200
201
* @param createExports true to create exports in subcells where necessary.
201
202
* @param showProgress true to show progress.
203
public static void runAutoStitch(Cell cell, List<NodeInst> nodesToStitch, List<ArcInst> arcsToStitch,
204
public static void runAutoStitch(Cell cell, List<NodeInst> nodesToStitch, List<ArcInst> arcsToStitch, Job job,
204
205
PolyMerge stayInside, Rectangle2D limitBound, boolean forced, boolean createExports, boolean showProgress)
208
if (cell.isAllLocked())
210
System.out.println("WARNING: Cell " + cell.describe(false) + " is locked: no changes can be made");
206
214
AutoStitch as = new AutoStitch();
207
as.runNow(cell, nodesToStitch, arcsToStitch, stayInside, limitBound, forced, createExports, showProgress);
215
as.runNow(cell, nodesToStitch, arcsToStitch, job, stayInside, limitBound, forced, createExports, showProgress);
210
218
private AutoStitch()
217
225
* @param cell the cell in which to stitch.
218
226
* @param nodesToStitch a list of NodeInsts to stitch (null to use all in the cell).
219
227
* @param arcsToStitch a list of ArcInsts to stitch (null to use all in the cell).
228
* @param job the Job running this, for aborting.
220
229
* @param stayInside is the area in which to route (null to route arbitrarily).
221
230
* @param limitBound if not null, only consider connections that occur in this area.
222
231
* @param forced true if the stitching was explicitly requested (and so results should be printed).
223
232
* @param createExports true to create exports in subcells where necessary.
224
233
* @param showProgress true to show progress.
226
private void runNow(Cell cell, List<NodeInst> nodesToStitch, List<ArcInst> arcsToStitch,
235
private void runNow(Cell cell, List<NodeInst> nodesToStitch, List<ArcInst> arcsToStitch, Job job,
227
236
PolyMerge stayInside, Rectangle2D limitBound, boolean forced, boolean createExports, boolean showProgress)
230
if (cell.isAllLocked())
232
System.out.println("WARNING: Cell " + cell.describe(false) + " is locked: no changes can be made");
235
238
if (showProgress) Job.getUserInterface().setProgressNote("Initializing routing");
236
239
ArcProto preferredArc = Routing.getPreferredRoutingArcProto();
358
372
// get the topology object for knowing what is connected
359
373
Topology top = new Topology(cell);
362
375
if (showProgress) Job.getUserInterface().setProgressNote("Routing " + totalToStitch + " objects...");
377
// first check for arcs that daisy-chain many nodes
378
for(ArcInst ai : arcsToStitch)
381
if (showProgress && (soFar%100) == 0)
383
if (job != null && job.checkAbort()) return;
384
Job.getUserInterface().setProgressValue(soFar * 100 / totalToStitch);
386
checkDaisyChain(ai, nodePortBounds, stayInside, top);
388
if (allRoutes.size() > 0)
390
// found daisy-chain elements: do them now
391
System.out.println("Auto-routing detected " + allRoutes.size() + " daisy-chained arcs");
392
for(Route route : allRoutes)
394
Router.createRouteNoJob(route, cell, false, arcsCreatedMap, nodesCreatedMap);
397
// reset for the rest of the analysis
398
allRoutes = new ArrayList<Route>();
399
top = new Topology(cell);
364
402
// now run through the nodeinsts to be checked for stitching
365
403
for(NodeInst ni : nodesToStitch)
368
406
if (showProgress && (soFar%100) == 0)
408
if (job != null && job.checkAbort()) return;
369
409
Job.getUserInterface().setProgressValue(soFar * 100 / totalToStitch);
370
411
checkStitching(ni, nodeBounds, nodePortBounds, arcLayers, stayInside, top, limitBound, preferredArc);
517
/****************************************** ARCS THAT DAISY-CHAIN ******************************************/
519
private static class DaisyChainPoint
524
DaisyChainPoint(PortInst p, Point2D loc)
527
location = new EPoint(loc.getX(), loc.getY());
532
* Class to sort DaisyChainPoints.
534
private static class SortDaisyPoints implements Comparator<DaisyChainPoint>
536
public int compare(DaisyChainPoint dcp1, DaisyChainPoint dcp2)
538
if (dcp1.location.getX() < dcp2.location.getX()) return 1;
539
if (dcp1.location.getX() > dcp2.location.getX()) return -1;
540
if (dcp1.location.getY() < dcp2.location.getY()) return 1;
541
if (dcp1.location.getY() > dcp2.location.getY()) return -1;
547
* Method to see if an ArcInst daisy-chains over multiple ports.
548
* @param ai the ArcInst in question.
549
* @param nodePortBounds quad-tree bounds information for all nodes in the Cell.
550
* @param stayInside is the area in which to route (null to route arbitrarily).
551
* @param top network information for the Cell with these objects.
553
private void checkDaisyChain(ArcInst ai, Map<NodeInst, ObjectQTree> nodePortBounds, PolyMerge stayInside, Topology top)
555
// make a list of PortInsts that are on the centerline of this arc
556
Cell cell = ai.getParent();
557
Network arcNet = top.getArcNetwork(ai);
558
Point2D e1 = ai.getHeadLocation();
559
Point2D e2 = ai.getTailLocation();
560
List<DaisyChainPoint> daisyPoints = new ArrayList<DaisyChainPoint>();
561
Rectangle2D searchBounds = ai.getBounds();
562
for(Iterator<RTBounds> it = cell.searchIterator(searchBounds); it.hasNext(); )
564
Geometric geom = (Geometric)it.next();
565
if (geom instanceof NodeInst)
567
NodeInst ni = (NodeInst)geom;
570
// find ports on this arc
571
ObjectQTree oqt = nodePortBounds.get(ni);
572
Set set = oqt.find(searchBounds);
575
for (Object obj : set)
577
PortInst pi = (PortInst)obj;
578
if (!pi.getPortProto().getBasePort().connectsTo(ai.getProto())) continue;
579
PolyBase portPoly = pi.getPoly();
580
Point2D closest = GenMath.closestPointToSegment(e1, e2, portPoly.getCenter());
582
// if this port can connect, save it
583
if (DBMath.pointInRect(closest, portPoly.getBounds2D()))
585
// ignore if they are already connected
586
Network portNet = top.getPortNetwork(pi);
587
if (portNet == arcNet) continue;
588
daisyPoints.add(new DaisyChainPoint(pi, closest));
594
// can't handle this yet
600
// now see if there are multiple intermediate daisy-chain points
601
if (daisyPoints.size() <= 1) return;
602
Collections.sort(daisyPoints, new SortDaisyPoints());
604
Route route = new Route();
605
route.add(RouteElementArc.deleteArc(ai));
607
RouteElementPort headRE = RouteElementPort.existingPortInst(ai.getHeadPortInst(), ai.getHeadLocation());
608
RouteElementPort tailRE = RouteElementPort.existingPortInst(ai.getTailPortInst(), ai.getTailLocation());
609
DaisyChainPoint firstDCP = daisyPoints.get(0);
610
DaisyChainPoint lastDCP = daisyPoints.get(daisyPoints.size()-1);
611
if (firstDCP.location.distance(ai.getHeadLocation()) > firstDCP.location.distance(ai.getTailLocation()))
613
RouteElementPort swap = headRE; headRE = tailRE; tailRE = swap;
615
if (headRE.getNodeInst().getNumConnections() == 1 && headRE.getLocation().equals(firstDCP.location))
617
route.add(RouteElementPort.deleteNode(headRE.getNodeInst()));
620
if (tailRE.getNodeInst().getNumConnections() == 1 && tailRE.getLocation().equals(lastDCP.location))
622
route.add(RouteElementPort.deleteNode(tailRE.getNodeInst()));
625
String name = ai.getName();
626
for(DaisyChainPoint dcp : daisyPoints)
628
RouteElementPort dcpRE = RouteElementPort.existingPortInst(dcp.pi, dcp.location);
631
RouteElement re = RouteElementArc.newArc(cell, ai.getProto(), ai.getLambdaBaseWidth(), headRE, dcpRE,
632
headRE.getLocation(), dcpRE.getLocation(), name, ai.getTextDescriptor(ArcInst.ARC_NAME),
633
ai, ai.isHeadExtended(), ai.isTailExtended(), stayInside);
641
RouteElement re = RouteElementArc.newArc(cell, ai.getProto(), ai.getLambdaBaseWidth(), headRE, tailRE,
642
headRE.getLocation(), tailRE.getLocation(), name, ai.getTextDescriptor(ArcInst.ARC_NAME),
643
ai, ai.isHeadExtended(), ai.isTailExtended(), stayInside);
646
allRoutes.add(route);
472
649
/****************************************** NORMAL STITCHING ******************************************/
2006
2193
Rectangle2D intersectArea = bound1.createIntersection(bound2);
2008
2195
// now find all polygons in Node 1 that are in the intersection area
2009
List<SubPolygon> polygons = new ArrayList<SubPolygon>();
2196
RTNode rtree = null;
2010
2197
if (ni1.isCellInstance())
2012
GatherPolygonVisitor gpv = new GatherPolygonVisitor(polygons, intersectArea, ni1);
2199
GatherPolygonVisitor gpv = new GatherPolygonVisitor(intersectArea, ni1);
2013
2200
HierarchyEnumerator.enumerateCell(ni1.getParent(), VarContext.globalContext, gpv);
2201
rtree = gpv.getRTree();
2204
rtree = RTNode.makeTopLevel();
2016
2205
Technology tech = ni1.getProto().getTechnology();
2017
2206
Poly[] polys = tech.getShapeOfNode(ni1, true, true, null);
2018
2207
AffineTransform trans = ni1.rotateOut();
2021
2210
Poly poly = polys[i];
2022
2211
poly.transform(trans);
2023
2212
if (!DBMath.rectsIntersect(poly.getBounds2D(), intersectArea)) continue;
2024
polygons.add(new SubPolygon(poly, VarContext.globalContext, -1, ni1, null));
2213
rtree = RTNode.linkGeom(null, rtree, new SubPolygon(poly, VarContext.globalContext, -1, ni1, null));
2028
2217
// now take the list into the second node and look for connections
2029
CheckPolygonVisitor cpv = new CheckPolygonVisitor(polygons, intersectArea, ni2);
2218
CheckPolygonVisitor cpv = new CheckPolygonVisitor(rtree, intersectArea, ni2);
2030
2219
HierarchyEnumerator.enumerateCell(ni2.getParent(), VarContext.globalContext, cpv);
2031
2220
List<PolyConnection> polysFound = cpv.getFoundConnections();
2172
2363
private class GatherPolygonVisitor extends HierarchyEnumerator.Visitor
2174
private List<SubPolygon> polygons;
2365
private RTNode rtree;
2175
2366
private Rectangle2D intersectArea;
2176
2367
private NodeInst cellOfInterest;
2178
public GatherPolygonVisitor(List<SubPolygon> polygons, Rectangle2D intersectArea, NodeInst cellOfInterest)
2369
public GatherPolygonVisitor(Rectangle2D intersectArea, NodeInst cellOfInterest)
2180
this.polygons = polygons;
2371
rtree = RTNode.makeTopLevel();
2181
2372
this.intersectArea = intersectArea;
2182
2373
this.cellOfInterest = cellOfInterest;
2376
public RTNode getRTree() { return rtree; }
2185
2378
public boolean enterCell(HierarchyEnumerator.CellInfo info) { return true; }
2187
2380
public void exitCell(HierarchyEnumerator.CellInfo info)
2439
2632
if (res != 0) return res;
2440
2633
res = r1e.getPortInst().getPortProto().getName().compareTo(r2e.getPortInst().getPortProto().getName());
2441
2634
if (res != 0) return res;
2443
// // sort by the starting and ending port locations
2444
// Poly p1s = r1s.getPortInst().getPoly();
2445
// Poly p2s = r2s.getPortInst().getPoly();
2446
// double x1 = p1s.getCenterX();
2447
// double y1 = p1s.getCenterY();
2448
// double x2 = p2s.getCenterX();
2449
// double y2 = p2s.getCenterY();
2450
// if (x1 < x2) return 1;
2451
// if (x1 > x2) return -1;
2452
// if (y1 < y2) return 1;
2453
// if (y1 > y2) return -1;
2455
// Poly p1e = r1e.getPortInst().getPoly();
2456
// Poly p2e = r2e.getPortInst().getPoly();
2457
// x1 = p1e.getCenterX();
2458
// y1 = p1e.getCenterY();
2459
// x2 = p2e.getCenterX();
2460
// y2 = p2e.getCenterY();
2461
// if (x1 < x2) return 1;
2462
// if (x1 > x2) return -1;
2463
// if (y1 < y2) return 1;
2464
// if (y1 > y2) return -1;