📄 autostitch.java
字号:
PortProto rPp = mPp; while (rNi.isCellInstance()) { AffineTransform temp = rNi.translateOut(); temp.preConcatenate(trans); Export e = (Export)rPp; rNi = e.getOriginalPort().getNodeInst(); rPp = e.getOriginalPort().getPortProto(); trans = rNi.rotateOut(); trans.preConcatenate(temp); } // see how much geometry is on this node Poly [] polys = shapeOfNode(rNi); int tot = polys.length; if (tot == 0) { // not a geometric primitive: look for ports that touch Poly oPoly = oNi.getShapeOfPort(mPp); if (comparePoly(oNi, mPp, oPoly, oNet, ni, pp, poly, net, ap, stayInside, top, limitBound)) return true; } else { // a geometric primitive: look for ports on layers that touch Netlist subNetlist = rNi.getParent().getUserNetlist(); for(int j=0; j<tot; j++) { Poly oPoly = polys[j]; // only want electrically connected polygons if (oPoly.getPort() == null) continue; // only want polygons connected to correct part of nodeinst if (!subNetlist.portsConnected(rNi, rPp, oPoly.getPort())) continue; // if the polygon layer is pseudo, substitute real layer if (ni.getProto() != Generic.tech().simProbeNode) { Layer oLayer = oPoly.getLayer(); if (oLayer != null) oLayer = oLayer.getNonPseudoLayer(); Layer apLayer = arcLayers.get(ap); if (!oLayer.getTechnology().sameLayer(oLayer, apLayer)) continue; } // transform the polygon and pass it on to the next test oPoly.transform(trans); if (comparePoly(oNi, mPp, oPoly, oNet, ni, pp, poly, net, ap, stayInside, top, limitBound)) return true; } } } } } else { // primitive node: check its layers AffineTransform trans = oNi.rotateOut(); // determine target point double ox = poly.getCenterX(); double oy = poly.getCenterY(); // look at all polygons on nodeinst oNi Poly [] polys = shapeOfNode(oNi); int tot = polys.length; if (tot == 0) { // not a geometric primitive: look for ports that touch PortProto bestPp = null; double bestDist = 0; for(Iterator<PortProto> pIt = oNi.getProto().getPorts(); pIt.hasNext(); ) { PortProto rPp = pIt.next(); // compute best distance to the other node Poly portPoly = oNi.getShapeOfPort(rPp); double dist = Math.abs(portPoly.getCenterX()-ox) + Math.abs(portPoly.getCenterY()-oy); if (bestPp == null) { bestDist = dist; bestPp = rPp; } if (dist > bestDist) continue; bestPp = rPp; bestDist = dist; } if (bestPp != null) { PortProto rPp = bestPp; Network oNet = top.getPortNetwork(oNi.findPortInstFromProto(bestPp)); if (net == null || oNet != net) { // port must be able to connect to the arc if (rPp.getBasePort().connectsTo(ap)) { // transformed the polygon and pass it on to the next test Poly oPoly = oNi.getShapeOfPort(rPp); if (comparePoly(oNi, rPp, oPoly, oNet, ni, pp, poly, net, ap, stayInside, top, limitBound)) return true; } } } } else { // a geometric primitive: look for ports on layers that touch for(int j=0; j<tot; j++) { Poly oPoly = polys[j]; // only want electrically connected polygons if (oPoly.getPort() == null) continue; // if the polygon layer is pseudo, substitute real layer Layer oLayer = oPoly.getLayer(); if (oLayer != null) oLayer = oLayer.getNonPseudoLayer(); // this must be the smallest layer on the arc Layer apLayer = arcLayers.get(ap); if (!apLayer.getTechnology().sameLayer(apLayer, oLayer)) continue; // do not stitch where there is already an electrical connection PortInst oPi = oNi.findPortInstFromProto(oPoly.getPort()); Network oNet = top.getPortNetwork(oPi); if (net != null && oNet == net) continue; // search all ports for the closest connected to this layer PortProto bestPp = null; double bestDist = 0; for(Iterator<PortProto> pIt = oNi.getProto().getPorts(); pIt.hasNext(); ) { PortProto rPp = pIt.next(); if (!top.portsConnected(oNi, rPp, oPoly.getPort())) continue; // compute best distance to the other node Poly portPoly = oNi.getShapeOfPort(rPp); double dist = Math.abs(ox-portPoly.getCenterX()) + Math.abs(oy-portPoly.getCenterY()); if (bestPp == null) bestDist = dist; if (dist > bestDist) continue; bestPp = rPp; bestDist = dist; } if (bestPp == null) continue; PortProto rPp = bestPp; // port must be able to connect to the arc if (!rPp.getBasePort().connectsTo(ap)) continue; // transformed the polygon and pass it on to the next test oPoly.transform(trans); if (comparePoly(oNi, rPp, oPoly, oNet, ni, pp, poly, net, ap, stayInside, top, limitBound)) return true; } } } return false; } /** * Method to compare two polygons. If these polygons touch * or overlap then the two nodes should be connected. * @param oNi the NodeInst responsible for the first polygon. * @param opp the PortProto responsible for the first polygon. * @param oPoly the first polygon. * @param oNet the Network responsible for the first polygon. * @param ni the NodeInst responsible for the second polygon. * @param pp the PortProto responsible for the second polygon. * @param poly the second polygon. * @param net the Network responsible for the second polygon. * @param ap the type of arc to use when stitching the nodes. * @param stayInside is the area in which to route (null to route arbitrarily). * @param top the netlist for the Cell with the polygons. * @param limitBound if not null, only consider connections that occur in this area. * @return true if the connection is made. */ private boolean comparePoly(NodeInst oNi, PortProto opp, Poly oPoly, Network oNet, NodeInst ni, PortProto pp, Poly poly, Network net, ArcProto ap, PolyMerge stayInside, Topology top, Rectangle2D limitBound) { // find the bounding boxes of the polygons if (poly.separation(oPoly) >= DBMath.getEpsilon()) return false; // be sure the closest ports are being used Poly portPoly = ni.getShapeOfPort(pp); Point2D portCenter = new Point2D.Double(portPoly.getCenterX(), portPoly.getCenterY()); Poly oPortPoly = oNi.getShapeOfPort(opp); Point2D oPortCenter = new Point2D.Double(oPortPoly.getCenterX(), oPortPoly.getCenterY()); if (USEQTREE && stayInside == null) { if (ni.isCellInstance() || oNi.isCellInstance()) { Rectangle2D polyBounds = portPoly.getBounds2D(); Rectangle2D oPolyBounds = oPortPoly.getBounds2D(); // quit now if bounding boxes don't intersect if ((polyBounds.getMinX() > oPolyBounds.getMaxX() || oPolyBounds.getMinX() > polyBounds.getMaxX()) && (polyBounds.getMinY() > oPolyBounds.getMaxY() || oPolyBounds.getMinY() > polyBounds.getMaxY())) return false; } } double dist = portCenter.distance(oPortCenter); for(Iterator<PortProto> it = oNi.getProto().getPorts(); it.hasNext(); ) { PortProto tPp = it.next(); if (tPp == opp) continue; if (!top.portsConnected(oNi, tPp, opp)) continue; portPoly = oNi.getShapeOfPort(tPp); Point2D tPortCenter = new Point2D.Double(portPoly.getCenterX(), portPoly.getCenterY()); double tDist = portCenter.distance(tPortCenter); if (tDist >= dist) continue; dist = tDist; opp = tPp; oPortCenter.setLocation(tPortCenter); } for(Iterator<PortProto> it = ni.getProto().getPorts(); it.hasNext(); ) { PortProto tPp = it.next(); if (tPp == pp) continue; if (!top.portsConnected(ni, tPp, pp)) continue; portPoly = ni.getShapeOfPort(tPp); Point2D tPortCenter = new Point2D.Double(portPoly.getCenterX(), portPoly.getCenterY()); double tDist = oPortCenter.distance(tPortCenter); if (tDist >= dist) continue; dist = tDist; pp = tPp; portCenter.setLocation(tPortCenter); } // reject connection if it is out of the limit bounds if (limitBound != null) { if (!DBMath.pointInRect(portCenter, limitBound) && !DBMath.pointInRect(oPortCenter, limitBound)) return false; } // find some dummy position to help run the arc double x = (oPortCenter.getX() + portCenter.getX()) / 2; double y = (oPortCenter.getY() + portCenter.getY()) / 2; // run the wire PortInst pi = ni.findPortInstFromProto(pp); PortInst opi = oNi.findPortInstFromProto(opp); return connectObjects(pi, net, opi, oNet, ni.getParent(), new Point2D.Double(x,y), stayInside, top); } /** * Method to connect two objects if they touch. * @param eobj1 the first object (either an ArcInst or a PortInst). * @param net1 the network on which the first object resides. * @param eobj2 the second object (either an ArcInst or a PortInst). * @param net2 the network on which the second object resides. * @param cell the Cell in which these objects reside. * @param ctr bend point suggestion when making "L" connection. * @param stayInside is the area in which to route (null to route arbitrarily). * @param top the topology of the cell. * @return true if a connection is made. */ private boolean connectObjects(ElectricObject eobj1, Network net1, ElectricObject eobj2, Network net2, Cell cell, Point2D ctr, PolyMerge stayInside, Topology top) { // run the wire NodeInst ni1 = null; if (eobj1 instanceof NodeInst) ni1 = (NodeInst)eobj1; else if (eobj1 instanceof PortInst) ni1 = ((PortInst)eobj1).getNodeInst(); NodeInst ni2 = null; if (eobj2 instanceof NodeInst) ni2 = (NodeInst)eobj2; else if (eobj2 instanceof PortInst) ni2 = ((PortInst)eobj2).getNodeInst(); Route route = router.planRoute(cell, eobj1, eobj2, ctr, stayInside, true, true); if (route.size() == 0) return false;// // see if this caused an arc to be deleted// boolean deletedArc = false;// for (RouteElement e : route)// if (e.getAction() == RouteElement.RouteElementAction.deleteArc) { deletedArc = true; break; } allRoutes.add(route); top.connect(net1, net2); // if either ni or oNi is a pin primitive, see if it is a candidate for clean-up if (ni1 != null) { if (ni1.getFunction() == PrimitiveNode.Function.PIN && !ni1.hasExports() && !ni1.hasConnections()) { possibleInlinePins.add(ni1); } } if (ni2 != null) { if (ni2.getFunction() == PrimitiveNode.Function.PIN && !ni2.hasExports() && !ni2.hasConnections()) { possibleInlinePins.add(ni2); } } return true; } /****************************************** EXPORT-CREATION STITCHING ******************************************/ /** * Method to check an object for possible stitching to neighboring objects with export creation. * Actual stitching is not done, but necessary exports are created. * @param geom the object to check for stitching. */ private void checkExportCreationStitching(Geometric geom) { Cell cell = geom.getParent(); NodeInst ni = null; if (geom instanceof NodeInst) ni = (NodeInst)geom; // make a list of other geometrics that touch or overlap this one (copy it because the main list will change) List<Geometric> geomsInArea = new ArrayList<Geometric>(); Rectangle2D geomBounds = geom.getBounds(); double epsilon = DBMath.getEpsilon(); Rectangle2D searchBounds = new Rectangle2D.Double(geomBounds.getMinX()-epsilon, geomBounds.getMinY()-epsilon, geomBounds.getWidth()+epsilon*2, geomBounds.getHeight()+epsilon*2); for(Iterator<RTBounds> it = cell.searchIterator(searchBounds); it.hasNext(); ) { Geometric oGeom = (Geometric)it.next(); if (oGeom != geom) geomsInArea.add(oGeom); } for(Geometric oGeom : geomsInArea) { // find another node in this area if (oGeom instanceof ArcInst) { // other geometric is an ArcInst ArcInst oAi = (ArcInst)oGeom; if (ni == null) continue; // compare node "ni" against arc "oAi" if (ni.isCellInstance()) compareNodeInstWithArcMakeExport(ni, oAi); } else { // other geometric a NodeInst NodeInst oNi = (NodeInst)oGeom; if (!oNi.isCellInstance()) { PrimitiveNode pnp = (PrimitiveNode)oNi.getProto(); if (pnp.getTechnology() == Generic.tech()) continue; if (pnp.getFunction() == PrimitiveNode.Function.NODE) continue; } if (ni == null) { // compare arc "geom" against node "oNi" if (oNi.isCellInstance()) compareNodeInstWithArcMakeExport(oNi, (ArcInst)geom); continue; } // compare node "ni" against node "oNi" if (oNi.isCellInstance() && ni.isCellInstance()) { compareTwoNodesMakeExport(ni, oNi); } } } } /** * Method to compare a node instance and an arc to see if they touch and should be connected and an export created. * @param ni the NodeInst to compare. * @param ai the ArcInst to compare. */ private void compareNodeInstWithArcMakeExport(NodeInst ni, ArcInst ai) { // get the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -