1
/* -*- tab-width: 4 -*-
3
* Electric(tm) VLSI Design System
5
* File: StitchFillJob.java
7
* Copyright (c) 2008 Sun Microsystems and Static Free Software
9
* Electric(tm) is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 3 of the License, or
12
* (at your option) any later version.
14
* Electric(tm) is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with Electric(tm); see the file COPYING. If not, write to
21
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22
* Boston, Mass 02111-1307, USA.
24
package com.sun.electric.tool.generator.layout.fill;
26
import com.sun.electric.tool.Job;
27
import com.sun.electric.tool.JobException;
28
import com.sun.electric.tool.user.CellChangeJobs;
29
import com.sun.electric.tool.user.ExportChanges;
30
import com.sun.electric.tool.user.ui.WindowFrame;
31
import com.sun.electric.tool.routing.*;
32
import com.sun.electric.database.hierarchy.Cell;
33
import com.sun.electric.database.hierarchy.Export;
34
import com.sun.electric.database.hierarchy.Library;
35
import com.sun.electric.database.hierarchy.View;
36
import com.sun.electric.database.topology.*;
37
import com.sun.electric.database.geometry.EPoint;
38
import com.sun.electric.database.geometry.DBMath;
39
import com.sun.electric.database.geometry.PolyBase;
40
import com.sun.electric.database.geometry.Orientation;
41
import com.sun.electric.database.prototype.NodeProto;
42
import com.sun.electric.database.prototype.PortCharacteristic;
43
import com.sun.electric.database.prototype.PortProto;
44
import com.sun.electric.database.network.Network;
45
import com.sun.electric.database.network.Netlist;
46
import com.sun.electric.technology.Layer;
47
import com.sun.electric.technology.ArcProto;
48
import com.sun.electric.technology.Technology;
49
import com.sun.electric.technology.PrimitiveNode;
52
import java.awt.geom.Rectangle2D;
53
import java.awt.geom.Area;
54
import java.awt.geom.Point2D;
57
* Fill Generator working on unconnected arcs
58
* User: Gilda Garreton
61
public class StitchFillJob extends Job
64
private Library outLibrary;
65
private List<Cell> generatedCells = new ArrayList<Cell>();
67
// private static final boolean doFill = false;
69
public StitchFillJob(Cell cell, Library lib, boolean doItNow)
71
super("Fill generator job", null, Type.CHANGE, null, null, Priority.USER);
73
this.outLibrary = lib;
75
if (doItNow) // call from regressions
82
} catch (JobException e)
88
startJob(); // queue the job
91
public boolean doIt() throws JobException
93
Point2D center = new Point2D.Double(0, 0);
95
// Get cells from EditWindows
98
Technology tech = null;
99
List<NodeInst> fillCells = new ArrayList<NodeInst>();
100
List<Geometric> fillGeoms = new ArrayList<Geometric>();
101
String fillCellName = "NewFill{lay}";
103
Library lib = Library.getCurrent();
106
System.out.println("No current library available.");
111
Cell oldCell = lib.findNodeProto(fillCellName);
112
// Delete previous version
115
Cell newCell = Cell.makeInstance(lib, fillCellName);
117
for (Iterator<WindowFrame> itW = WindowFrame.getWindows(); itW.hasNext();)
119
WindowFrame w = itW.next();
120
Cell c = w.getContent().getCell();
124
System.out.println("No cell in window '" + w.getTitle() + "'");
127
if (c.getView() != View.LAYOUT)
129
System.out.println("Cell '" + c + "' is not a layout cell");
133
Technology t = c.getTechnology();
134
if (tech == null) tech = t;
136
System.out.println("Mixing technologies in fill generator: " +
137
tech.getTechName() + " " + t.getTechName());
139
NodeInst ni = NodeInst.makeInstance(c, center, c.getDefWidth(), c.getDefHeight(), newCell);
144
doTheJob(newCell, fillCellName, fillCells, fillGeoms, null, false, this);
145
return true; // done at this point
148
String[] instructions = topCell.getTextViewContents();
150
if (instructions == null)
152
System.out.println("No fill instructions found.");
155
for (String line : instructions)
157
if (line.startsWith("//"))
158
continue; // commented line
160
StringTokenizer parse = new StringTokenizer(line, ":", false);
162
String fillCellName = null, rest = null;
164
while (parse.hasMoreTokens())
167
String value = parse.nextToken();
170
case 0: fillCellName = value;
178
if (fillCellName == null) continue; // no parsing matching
180
// getting possible options like "w" or "2x4"
181
int index = fillCellName.indexOf("(");
182
boolean wideOption = false;
183
List<TileInfo> tileList = new ArrayList<TileInfo>();
187
// Getting options like (W)
188
String options = fillCellName.substring(index);
189
fillCellName = fillCellName.substring(0, index);
190
parse = new StringTokenizer(options, "(), ", false);
191
while (parse.hasMoreTokens())
193
String option = parse.nextToken();
194
String lowerCase = option.toLowerCase();
195
// wide option where exports are added in lowest layer
196
if (lowerCase.equals("w"))
201
else if (lowerCase.contains("x"))
203
index = lowerCase.indexOf("x");
204
String str = lowerCase.substring(0, index);
205
int x = Integer.valueOf(str);
206
str = lowerCase.substring(index+1, lowerCase.length());
207
int y = Integer.valueOf(str);
209
TileInfo tile = new TileInfo(x, y);
215
// Library lib = topCell.getLibrary();
217
// extracting fill subcells
218
parse = new StringTokenizer(rest, " ,", false);
219
String newName = fillCellName+"{lay}";
220
Cell oldCell = outLibrary.findNodeProto(newName);
221
// Delete previous version
226
Cell newCell = Cell.makeInstance(outLibrary, newName);
227
Technology tech = null;
228
List<NodeInst> fillCells = new ArrayList<NodeInst>();
229
List<Geometric> fillGeoms = new ArrayList<Geometric>();
231
while (parse.hasMoreTokens())
233
String fillCell = parse.nextToken();
234
index = fillCell.indexOf("("); // options like (I)
235
boolean instanceFlag = false;
238
instanceFlag = fillCell.toLowerCase().indexOf("(i") != -1; // only (I) option for now
239
fillCell = fillCell.substring(0, index);
241
Cell c = topCell.getLibrary().findNodeProto(fillCell); // +"{lay}");
245
System.out.println("Cell '" + fillCell + "' does not exist");
248
if (c.getView() != View.LAYOUT)
250
System.out.println("Cell '" + c + "' is not a layout cell");
253
Technology t = c.getTechnology();
255
if (tech == null) tech = t;
257
System.out.println("Mixing technologies in fill generator: " + tech.getTechName() + " " + t.getTechName());
258
NodeInst ni = NodeInst.makeInstance(c, center, c.getDefWidth(), c.getDefHeight(), newCell);
263
newCell.setTechnology(tech);
264
generatedCells.add(newCell);
267
doTheJob(newCell, fillCellName, fillCells, fillGeoms, tileList, wideOption, this);
272
public List<Cell> getGeneratedCells() {return generatedCells;}
275
* Method that executes the different functions to get the tool working
277
* @param fillCellName
284
private static void doTheJob(Cell newCell, String fillCellName, List<NodeInst> fillCells,
285
List<Geometric> fillGeoms, List<TileInfo> tileList, boolean wideOption, Job job)
288
ExportChanges.reExportNodes(newCell, fillGeoms, false, true, false, true);
289
// if (!doFill) return;
292
new CellChangeJobs.ExtractCellInstances(newCell, fillCells, Integer.MAX_VALUE, true, true);
294
// generation of master fill
295
generateFill(newCell, wideOption);
297
// tiles generation. Flat generation for now
298
generateTiles(newCell, fillCellName, tileList, job);
302
* Class to store tile information
304
private class TileInfo
306
int x, y; // size in x and y axes
308
TileInfo(int a, int b)
316
* Method to generate tiles of a given cell according to the description provided.
317
* The function will use the auto stitch tool so no hierarchy is expected.
318
* @param template Cell to use as template
319
* @param fillCellName Root name of the template cell
320
* @param tileList List of dimensions to create
321
* @param job Job running the task
323
private static void generateTiles(Cell template, String fillCellName, List<TileInfo> tileList, Job job)
325
if (tileList == null) return; // nothing to tile
327
// tiles generation. Flat generation for now
328
for (TileInfo info : tileList)
330
String newTileName = fillCellName + info.x + "x" + info.y + "{lay}";
331
Cell newTile = Cell.makeInstance(template.getLibrary(), newTileName);
332
// generate the array
333
List<NodeInst> niList = new ArrayList<NodeInst>();
334
Rectangle2D rect = template.getBounds();
335
double width = rect.getWidth();
336
double height = rect.getHeight();
337
double xPos = 0, yPos;
339
for (int i = 0; i < info.x; i++)
342
for (int j = 0; j < info.y; j++)
344
NodeInst newNi = NodeInst.makeInstance(template,
345
new Point2D.Double(xPos, yPos), width, height, newTile, Orientation.IDENT, null, 0);
351
AutoStitch.runAutoStitch(newTile, niList, null, job, null, null, true, true, true);
356
* Main class to auto-stitch metal layers found in given cell
357
* @param theCell Cell with the metal layer information
358
* @param wideOption True if exports in the lowest layer will be added
359
* @return True if auto-stitch ran without errors
361
private static boolean generateFill(Cell theCell, boolean wideOption)
363
InteractiveRouter router = new SimpleWirer();
364
List<Layer> listOfLayers = new ArrayList<Layer>(12);
366
for (Iterator<Layer> itL = theCell.getTechnology().getLayers(); itL.hasNext(); )
368
Layer l = itL.next();
369
if (!l.getFunction().isMetal()) continue; // only metals
373
Collections.sort(listOfLayers, Layer.layerSortByName);
374
Map<ArcProto,Integer> arcsCreatedMap = new HashMap<ArcProto,Integer>();
375
Map<NodeProto,Integer> nodesCreatedMap = new HashMap<NodeProto,Integer>();
376
boolean evenHorizontal = true; // even metal layers are horizontal. Basic assumption
377
List<Route> routeList = new ArrayList<Route>();
378
Layer[] topLayers = new Layer[2];
379
Layer bottomLayer = null;
380
Map<String,Area> totalAreas = new HashMap<String,Area>();
382
for (int i = 0; i < listOfLayers.size() - 1; i++)
384
Layer bottom = listOfLayers.get(i);
385
boolean horizontal = isLayerHorizontal(bottom, evenHorizontal);
387
List<ArcInst> arcs = getArcsInGivenLayer(theCell.getArcs(), horizontal, bottom, null, null);
388
Layer top = listOfLayers.get(i+1);
389
Map<String,Area> remainingGeos = new HashMap<String,Area>();
391
for (ArcInst ai : arcs)
393
// Picking only 1 export and considering the root name`
394
Netlist netlist = theCell.getNetlist(); // getting new version of netlist after every routing.
395
String bottomName = getExportRootName(ai, netlist);
397
if (bottomName == null) continue; // nothing to export
399
List<PinsArcPair> pairs = new ArrayList<PinsArcPair>();
400
Rectangle2D bounds = ai.getBounds();
401
Area bottomA = new Area(bounds);
403
if (bottomLayer == null || bottom == bottomLayer) // only for the bottom layer, the first one
405
Area totalA = totalAreas.get(bottomName);
409
totalAreas.put(bottomName, totalA);
414
for(Iterator<RTBounds> it = theCell.searchIterator(bounds); it.hasNext(); )
416
Geometric nGeom = (Geometric)it.next();
418
if (!(nGeom instanceof ArcInst))
420
continue; // only arcs
423
ArcInst nai = (ArcInst)nGeom;
425
// Checking arc orientation with respect to layer
426
// If the orientation is not correct, then ignore it
427
// Must be perpendicular to the reference layer (bottom)
428
if (!isArcAligned(nai, !horizontal))
431
Layer nl = nai.getProto().getLayer(0);
433
if (nl != top) continue; // ascending order is easy
435
String topName = getExportRootName(nai, netlist);
437
if (topName == null || !topName.equals(bottomName)) continue; // no export matching
439
Rectangle2D nBnds = nai.getBounds();
440
Area topA = new Area(nBnds);
441
topA.intersect(bottomA);
442
Rectangle2D resultBnd = topA.getBounds2D();
444
// checking for full overlap. If horizontal -> width must be 100%
445
boolean fullCoverageX = (horizontal) ? DBMath.areEquals(resultBnd.getWidth(), nBnds.getWidth()) :
446
DBMath.areEquals(resultBnd.getHeight(), nBnds.getHeight());
447
boolean fullCoverageY = (horizontal) ? DBMath.areEquals(resultBnd.getHeight(), bounds.getHeight()) :
448
DBMath.areEquals(resultBnd.getWidth(), bounds.getWidth());
450
if (!fullCoverageX || !fullCoverageY)
452
// adding to list of pieces of geometries
453
Area a = remainingGeos.get(bottomName);
457
remainingGeos.put(bottomName, a);
460
continue; // skipping this case
463
EPoint insert = new EPoint(resultBnd.getCenterX(), resultBnd.getCenterY());
464
pairs.add(new PinsArcPair(nai, insert, resultBnd));
467
Collections.sort(pairs, pinsArcSort);
468
ArcInst mostLeft = ai;
471
if (bottomLayer == null)
472
bottomLayer = bottom;
474
// Mark the layer as possible one of the top ones
475
if (!pairs.isEmpty())
477
topLayers[0] = bottom;
481
Area a = remainingGeos.get(bottomName);
482
for (PinsArcPair pair : pairs)
484
//SplitContainter bottomSplit = splitArcAtPoint(mostLeft, pair.insert);
485
//SplitContainter topSplit = splitArcAtPoint(pair.topArc, pair.insert);
486
Route r = router.planRoute(theCell, mostLeft, pair.topArc, pair.insert, null, true, true, pair.cut);
487
//mostLeft = bottomSplit.rightArc;
490
// Extract area from possible remaining geometry. This will happen
491
// when the wires are in zig-zag
492
if (a != null) // there is a remainig area
494
Area remove = new Area(pair.cut);
498
for (Route r : routeList)
500
Router.createRouteNoJob(r, theCell, false, arcsCreatedMap, nodesCreatedMap);
504
// Adding remaining contacts due to non-100% overlap with original arcs
505
for (Map.Entry<String,Area> e : remainingGeos.entrySet())
507
Area a = e.getValue();
508
Netlist netlist = theCell.getNetlist();
509
List<PolyBase> list = PolyBase.getPointsInArea(a, bottom, false, false);
510
List<ArcInst> at = getArcsInGivenLayer(theCell.getArcs(), !horizontal, top, e.getKey(), netlist);
511
List<PinsArcPair> pairs = new ArrayList<PinsArcPair>(2);
513
// Add extra contacts. All points should be aligned in same horizontal or vertical line
514
// first the top arcs. They should be less in number (less number of splits)
515
for (PolyBase p : list)
517
Rectangle2D resultBnd = p.getBounds2D();
519
// look for the first pair of arcs in bottom/top arcs that overlap with geometry
520
ArcInst topA = getArcInstOverlappingWithArea(resultBnd, at, horizontal, true); // perferct if fully contains the arc
524
EPoint insert = new EPoint(resultBnd.getCenterX(), resultBnd.getCenterY());
525
pairs.add(new PinsArcPair(topA, insert, resultBnd));
528
// Sort the new pairs from left/top to right/bottom
529
Collections.sort(pairs, pinsArcSort);
531
// Look for bottomLayer arcs for those given positions
532
List<ArcInst> ab = getArcsInGivenLayer(theCell.getArcs(), horizontal, bottom, e.getKey(), netlist);
535
for (PinsArcPair pair : pairs)
537
ArcInst bottomA = getArcInstOverlappingWithArea(pair.cut, ab, horizontal, false);
540
//SplitContainter bottomSplit = splitArcAtPoint(bottomA, pair.insert);
541
//SplitContainter topSplit = splitArcAtPoint(pair.topArc, pair.insert);
542
Route r = router.planRoute(theCell, bottomA, pair.topArc, pair.insert, null, true, true, pair.cut);
543
// remove the old one and add new arc
545
//ab.add(bottomSplit.rightArc);
546
topLayers[0] = bottom;
550
else if (Job.getDebug())
552
bottomA = getArcInstOverlappingWithArea(pair.cut, ab, horizontal, false);
553
System.out.println("AFG: It couldn't find bottom layer for " + pair.cut);
556
for (Route r : routeList)
558
Router.createRouteNoJob(r, theCell, false, arcsCreatedMap, nodesCreatedMap);
563
Netlist netlist = theCell.getNetlist();
564
// Connect cell instances
565
for (Iterator<NodeInst> itNi = theCell.getNodes(); itNi.hasNext();)
567
NodeInst ni = itNi.next();
569
// only cell instances
570
if (!ni.isCellInstance()) continue;
572
// Checking if the export overlaps with
573
// Checking if there are exports overlapping with the arc
574
List<String> doneExports = new ArrayList<String>();
576
SimpleWirer niRouter = new SimpleWirer();
578
for (Iterator<Export> itE = ni.getExports(); itE.hasNext(); )
580
Export ex = itE.next();
581
String exportName = ex.getName();
582
String rootName = extractRootName(exportName);
584
if (doneExports.contains(rootName)) // exportName
585
continue; // export for this given NodeInst was done
587
PrimitiveNode n = ex.getBasePort().getParent();
588
Layer layer = n.getLayerIterator().next(); // assuming only 1
589
PortInst pi = ex.getOriginalPort();
590
PortProto epi = pi.getPortProto();
591
EPoint exportCenter = pi.getCenter();
592
NodeProto np = epi.getParent();
593
if (!(np instanceof Cell))
594
continue; // not good for now.
596
Netlist netl = c.getNetlist();
597
Network jExp = netl.getNetwork((Export)epi, 0);
598
Area expA = new Area();
600
// Look for all arcs in the cell instances that are on the given layer and netwoek
601
for (Iterator<ArcInst> itA = jExp.getArcs(); itA.hasNext();)
603
ArcInst ai = itA.next();
604
Layer l = ai.getProto().getLayer(0);
606
if (l != layer) continue;
607
expA.add(new Area(ai.getBounds()));
610
// Algorithm will look for the closest connection.
611
Rectangle2D bestCut = null; // represents the best cut
612
ArcInst bestArc = null;
613
Point2D bestCenter = null;
614
double bestDistance = Double.MAX_VALUE;
615
List<Network> netList = getNetworkFromName(netlist, rootName);
616
// jNet = getNetworkFromName(netlist, rootName);
618
for (Network jNet : netList)
620
for (Iterator<ArcInst> itA = jNet.getArcs(); itA.hasNext();)
622
ArcInst ai = itA.next();
623
Layer l = ai.getProto().getLayer(0);
626
System.out.println("found in same layer");
627
else if (Math.abs(l.getIndex() - layer.getIndex()) <=1)
629
// Not selecting the closest element yet
630
Area bnd = new Area(ai.getBounds());
634
Rectangle2D cut = bnd.getBounds2D();
635
Point2D center = new EPoint(cut.getCenterX(), cut.getCenterY());
636
double dist = DBMath.distBetweenPoints(center, exportCenter);
637
if (bestCenter == null || DBMath.isLessThan(dist, bestDistance))
639
// first time or the new distance is shorter
649
if (bestCut != null) // best location found
651
Route r = niRouter.planRoute(theCell, bestArc, pi, bestCenter, null, true, true, bestCut);
653
doneExports.add(rootName);
658
for (Route r : routeList)
660
Router.createRouteNoJob(r, theCell, false, arcsCreatedMap, nodesCreatedMap);
664
// Remove exports in lower layers
665
Set<Export> toDelete = new HashSet<Export>();
666
Map<String,Export> inBottomLayer = new HashMap<String,Export>(); // enough with 1 export stored
668
// find the highest level metal for a given network
669
Map<Network,Layer> maximumLayer = new HashMap<Network,Layer>();
670
for (Iterator<Export> itE = theCell.getExports(); itE.hasNext();) {
671
Export exp = itE.next();
672
PrimitiveNode n = exp.getBasePort().getParent();
673
Network net = netlist.getNetwork(exp, 0);
674
Layer l = maximumLayer.get(net);
675
for (Iterator<Layer> itL = n.getLayerIterator(); itL.hasNext();)
677
Layer lnew = itL.next();
682
if (lnew.getFunction().getLevel() > l.getFunction().getLevel()) {
686
maximumLayer.put(net, l);
689
for (Iterator<Export> itE = theCell.getExports(); itE.hasNext();)
691
Export exp = itE.next();
692
PrimitiveNode n = exp.getBasePort().getParent();
693
boolean found = false;
694
String rootName = extractRootName(exp.getName());
696
Layer topLayer = maximumLayer.get(netlist.getNetwork(exp, 0));
697
int levelMax = topLayer.getFunction().getLevel();
698
for (Iterator<Layer> itL = n.getLayerIterator(); itL.hasNext();)
700
Layer l = itL.next();
701
int level = l.getFunction().getLevel();
702
if (level == levelMax || level == (levelMax-1)) {
705
inBottomLayer.put(rootName, exp); // put the last one in the network.
708
if (!found) // delete the export
712
// Add extra export in the middle of the botoom layer.
715
Map<String,List<PinsArcPair>> newExports = new HashMap<String,List<PinsArcPair>>();
716
boolean horizontal = isLayerHorizontal(bottomLayer, evenHorizontal);
718
// For each export 1 export in the bottom layer should be insert
719
for (Map.Entry<String,Export> e : inBottomLayer.entrySet())
721
Export exp = e.getValue();
722
String rootName = extractRootName(exp.getName());
723
Network net = netlist.getNetwork(exp, 0);
724
// Collect first all the arcs in that layer
725
List<ArcInst> arcs = getArcsInGivenLayer(net.getArcs(), horizontal, bottomLayer, null, null);
726
Area area = totalAreas.get(rootName);
727
List<PinsArcPair> l = new ArrayList<PinsArcPair>();
729
// It could be multiple areas disconnected.
730
List<PolyBase> list = PolyBase.getPointsInArea(area, bottomLayer, false, false);
731
if (list == null) continue; // no matching export on bottom level
732
for (PolyBase b : list)
734
Rectangle2D resultBnd = b.getBounds2D();
735
EPoint insert = new EPoint(resultBnd.getCenterX(), resultBnd.getCenterY());
736
PinsArcPair split; // looking for the first arc where the center is contained.
737
for (ArcInst ai : arcs)
739
Rectangle2D bnd = ai.getBounds();
740
if (bnd.contains(insert.getX(), insert.getY()))
742
split = new PinsArcPair(ai, insert, null);
748
newExports.put(rootName, l);
751
for (Map.Entry<String,List<PinsArcPair>> e : newExports.entrySet())
753
List<PinsArcPair> pairs = e.getValue();
754
for (PinsArcPair pair : pairs)
756
SplitContainter split = splitArcAtPoint(pair.topArc, pair.insert);
757
Export.newInstance(theCell, split.splitPin.getPortInst(0), e.getKey(), PortCharacteristic.UNKNOWN);
762
// Delete after dealing with the wide option
763
// At least one connection was done otherwise it will keep the original exports.
764
// Option is mostly for debugging purposes.
765
if (topLayers[0] != null || topLayers[1] != null)
766
theCell.killExports(toDelete);
768
// make sure at least one export on a network is the root name
769
netlist = theCell.getNetlist();
770
for (Iterator<Network> itN = netlist.getNetworks(); itN.hasNext(); ) {
771
Network net = itN.next();
772
if (!net.isExported()) continue;
773
String name = net.getName();
774
String rootName = extractRootName(name);
775
if (!name.equals(rootName)) {
776
Export exp = net.getExports().next();
777
exp.rename(rootName);
783
private static ArcInst getArcInstOverlappingWithArea(Rectangle2D resultBnd, List<ArcInst> at, boolean horizontal, boolean topLayer)
785
Area topArea = new Area(resultBnd);
786
for (ArcInst ai : at)
788
Rectangle2D r = ai.getBounds();
790
// test if the current ai inserts with the given area
791
// and it is fully contained along the axis the arc is aligned
792
if (r.intersects(resultBnd))
794
Area rArea = new Area(r);
795
rArea.intersect(topArea);
796
Rectangle2D rect = rArea.getBounds2D();
799
if (horizontal && topLayer || !horizontal && !topLayer) // top arc is aligned along Y or bottom arc along Y
801
validArc = DBMath.areEquals(rect.getWidth(), r.getWidth());
803
else // top arc is aligned along X
805
validArc = DBMath.areEquals(rect.getHeight(), r.getHeight());
819
* Method to get Network from a given network root name
820
* @param netlist Netlist containing the network information
821
* @param rootName Root name of the network
824
private static List<Network> getNetworkFromName(Netlist netlist, String rootName)
826
List<Network> list = new ArrayList<Network>();
828
for (Iterator<Network> it = netlist.getNetworks(); it.hasNext();)
830
Network net = it.next();
831
if (net.getName().startsWith(rootName))
838
* Method to determine if Layer is aligned horizontally
839
* @param layer Given Layer
840
* @param evenHorizontal True if even layers are horizontal
841
* @return True of layer is horizontal
843
private static boolean isLayerHorizontal(Layer layer, boolean evenHorizontal)
845
int metalNumber = layer.getFunction().getLevel();
846
return (evenHorizontal && metalNumber%2==0) || (!evenHorizontal && metalNumber%2==1);
850
* Method to collect arcs in a given layer with a given export name from an iterator
851
* @param itAi Arcs iterator
852
* @param horizontal Variable to determine if the arc mus be aligned horizontally
853
* @param layer Given layer
854
* @param exportName Given export name. If null, any export name is valid
855
* @param netlist Given Netlist to find exports
856
* @return List of ArcInsts
858
private static List<ArcInst> getArcsInGivenLayer(Iterator<ArcInst> itAi, boolean horizontal,
859
Layer layer, String exportName, Netlist netlist)
861
List<ArcInst> arcs = new ArrayList<ArcInst>();
863
for (; itAi.hasNext();)
865
ArcInst ai = itAi.next();
867
// Checking arc orientation with respect to layer
868
// If the orientation is not correct, then ignore it
869
if (!isArcAligned(ai, horizontal))
872
Layer l = ai.getProto().getLayer(0);
875
if (exportName != null)
877
Network jNet = netlist.getNetwork(ai, 0);
878
Iterator<Export> itE = jNet.getExports();
882
System.out.println("AFG: No export name associated to ArcInst '" + ai.getName() + "'");
883
continue; // no export
885
Export exp = itE.next(); // first is enough
886
String expName = extractRootName(exp.getName());
887
if (!expName.equals(exportName))
888
continue; // no match
896
* Method to check whether a given arc is properly oriented with respect to the expected input
897
* @param ai the given ArcInst
898
* @param horizontal True if the arc must be horizontal
899
* @return True if the arc is aligned with the given direction
901
private static boolean isArcAligned(ArcInst ai, boolean horizontal)
903
EPoint head = ai.getHeadLocation();
904
EPoint tail = ai.getTailLocation();
906
return (DBMath.areEquals(head.getY(), tail.getY()));
907
return (DBMath.areEquals(head.getX(), tail.getX()));
911
* Method to extract the export root name from a given name
912
* @param name String containing the export name
913
* @return String containing the root name of the export
915
private static String extractRootName(String name)
917
int index = name.indexOf("_");
918
if (index != -1) // remove any character after _
919
name = name.substring(0, index);
924
* Methot to extrac root name of the export in a given arc
925
* @param ai arc with the export
926
* @param netlist Given network to search in
927
* @return Non-null string with the root name. Null if no export was found.
929
private static String getExportRootName(ArcInst ai, Netlist netlist)
931
Network jNet = netlist.getNetwork(ai, 0);
932
// Picking only 1 export and considering the root name`
933
// Assuming at 1 export per arc
936
assert(jNet != null);
937
Iterator<String> exportNames = jNet.getExportedNames();
938
if (!exportNames.hasNext())
939
return null; // no export
940
return extractRootName(exportNames.next());
944
* Method to split an arc at a given point
945
* @param ai arc to split
946
* @param insert point to split at
947
* @return SplitContainter representing the split pin and new arcs
949
private static SplitContainter splitArcAtPoint(ArcInst ai, EPoint insert)
951
// create the break pins
952
ArcProto ap = ai.getProto();
953
NodeProto np = ap.findPinProto();
954
if (np == null) return null;
955
NodeInst ni = NodeInst.makeInstance(np, insert, np.getDefWidth(), np.getDefHeight(), ai.getParent());
958
System.out.println("Cannot create pin " + np.describe(true));
962
SplitContainter container = new SplitContainter();
963
container.splitPin = ni;
965
// get location of connection to these pins
966
PortInst pi = ni.getOnlyPortInst();
968
// now save the arc information and delete it
969
PortInst headPort = ai.getHeadPortInst();
970
PortInst tailPort = ai.getTailPortInst();
971
Point2D headPt = ai.getHeadLocation();
972
Point2D tailPt = ai.getTailLocation();
973
double width = ai.getLambdaBaseWidth();
974
// String arcName = ai.getName();
976
// create the new arcs
977
ArcInst newAi1 = ArcInst.makeInstanceBase(ap, width, headPort, pi, headPt, insert, null);
978
ArcInst newAi2 = ArcInst.makeInstanceBase(ap, width, pi, tailPort, insert, tailPt, null);
979
newAi1.setHeadNegated(ai.isHeadNegated());
980
newAi1.setHeadExtended(ai.isHeadExtended());
981
newAi1.setHeadArrowed(ai.isHeadArrowed());
982
newAi1.setTailNegated(ai.isTailNegated());
983
newAi1.setTailExtended(ai.isTailExtended());
984
newAi1.setTailArrowed(ai.isTailArrowed());
986
newAi2.setHeadNegated(ai.isHeadNegated());
987
newAi2.setHeadExtended(ai.isHeadExtended());
988
newAi2.setHeadArrowed(ai.isHeadArrowed());
989
newAi2.setTailNegated(ai.isTailNegated());
990
newAi2.setTailExtended(ai.isTailExtended());
991
newAi2.setTailArrowed(ai.isTailArrowed());
993
// Determining which arc is left/top
994
if (isLeftTop(headPt, tailPt))
996
container.leftArc = newAi1;
997
container.rightArc = newAi2;
1001
container.leftArc = newAi2;
1002
container.rightArc = newAi1;
1005
// if (arcName != null)
1007
// if (headPt.distance(insert) > tailPt.distance(insert))
1009
// newAi1.setName(arcName);
1010
// newAi1.copyTextDescriptorFrom(ai, ArcInst.ARC_NAME);
1013
// newAi2.setName(arcName);
1014
// newAi2.copyTextDescriptorFrom(ai, ArcInst.ARC_NAME);
1021
* Internal class to keep potential connections
1023
private static class PinsArcPair
1025
private ArcInst topArc;
1026
private EPoint insert;
1027
private Rectangle2D cut;
1029
PinsArcPair(ArcInst topA, EPoint point, Rectangle2D c)
1037
private static boolean isLeftTop(Point2D p1, Point2D p2)
1039
if (DBMath.areEquals(p1.getX(), p2.getX()))
1041
return (!DBMath.isGreaterThan(p1.getY(), p2.getY()));
1043
else if (DBMath.areEquals(p1.getY(), p2.getY()))
1045
return (!DBMath.isGreaterThan(p1.getX(), p2.getX()));
1048
System.out.println("Case not considered in FillJob:isLeftTop");
1049
// assert(false); // not considered yet
1054
* Class to store temp info
1056
private static class SplitContainter
1059
ArcInst leftArc, rightArc; // to keep track of new arcs after the original one was split
1063
* To sort PinsArcPair
1065
private static final PinsArcPairSort pinsArcSort = new PinsArcPairSort();
1068
* Comparator class for sorting PinsArcPair by their insertion point
1070
private static class PinsArcPairSort implements Comparator<PinsArcPair>
1073
* Method to compare two PinsArcPair objects by their insertion point.
1074
* @param l1 one PinsArcPair.
1075
* @param l2 another PinsArcPair.
1076
* @return an integer indicating their sorting order.
1078
public int compare(PinsArcPair l1, PinsArcPair l2)
1080
EPoint p1 = l1.insert;
1081
EPoint p2 = l2.insert;
1082
return (isLeftTop(p2, p1)?1:-1);