📄 connectivity.java
字号:
} } } return touchingPi; } private static class Centerline { Point2D start, end; EPoint startUnscaled, endUnscaled; boolean startHub, endHub; double width; boolean handled; int angle; Centerline(double width, Point2D start, Point2D end) { this.width = width; this.start = start; this.startUnscaled = new EPoint(start.getX() / SCALEFACTOR, start.getY() / SCALEFACTOR); this.endUnscaled = new EPoint(end.getX() / SCALEFACTOR, end.getY() / SCALEFACTOR); this.end = end; startHub = endHub = false; if (start.equals(end)) angle = -1; else angle = GenMath.figureAngle(end, start); } void setStart(double x, double y) { start.setLocation(x, y); startUnscaled = new EPoint(x / SCALEFACTOR, y / SCALEFACTOR); } void setEnd(double x, double y) { end.setLocation(x, y); endUnscaled = new EPoint(x / SCALEFACTOR, y / SCALEFACTOR); } public String toString() { return "CENTERLINE from (" + TextUtils.formatDouble(start.getX()/SCALEFACTOR) + "," + TextUtils.formatDouble(start.getY()/SCALEFACTOR) + ") to (" + TextUtils.formatDouble(end.getX()/SCALEFACTOR) + "," + TextUtils.formatDouble(end.getY()/SCALEFACTOR) + ") wid=" + TextUtils.formatDouble(width/SCALEFACTOR) + ", len=" + TextUtils.formatDouble((start.distance(end)/SCALEFACTOR)); } } /** * Method to return the port and location to use for one end of a Centerline. * @param cl the Centerline to connect * @param loc1 it's location (values returned through this object!) * @param layer the layer associated with the Centerline. * @param ap the type of arc to create. * @param startSide true to * @param newCell the Cell in which to find ports. * @return the PortInst on the Centerline. */ private PortInst locatePortOnCenterline(Centerline cl, Point2D loc1, Layer layer, ArcProto ap, boolean startSide, Cell newCell) { PortInst piRet = null; boolean isHub = cl.endHub; EPoint startPoint = cl.endUnscaled; if (startSide) { isHub = cl.startHub; startPoint = cl.startUnscaled; } if (!isHub) { List<PortInst> possiblePorts = findPortInstsTouchingPoint(startPoint, layer, newCell, ap); for(PortInst pi : possiblePorts) { Poly portPoly = pi.getPoly(); Point2D [] points = portPoly.getPoints(); if (points.length == 1) { Point2D iPt = GenMath.intersect(cl.startUnscaled, cl.angle, points[0], (cl.angle+900)%3600); if (iPt != null) { loc1.setLocation(iPt.getX(), iPt.getY()); piRet = pi; break; } } else { if (portPoly.contains(startPoint)) { loc1.setLocation(startPoint); piRet = pi; break; } for(int i=0; i<points.length; i++) { int last = i-1; if (last < 0) last = points.length-1; Point2D portLineFrom = points[last]; Point2D portLineTo = points[i]; Point2D interPt = null; if (portLineFrom.equals(portLineTo)) { interPt = GenMath.intersect(cl.startUnscaled, cl.angle, portLineFrom, (cl.angle+900)%3600); } else { int angPortLine = GenMath.figureAngle(portLineFrom, portLineTo); interPt = GenMath.intersect(portLineFrom, angPortLine, cl.startUnscaled, cl.angle); if (interPt != null) { if (interPt.getX() < Math.min(portLineFrom.getX(), portLineTo.getX()) || interPt.getX() > Math.max(portLineFrom.getX(), portLineTo.getX()) || interPt.getY() < Math.min(portLineFrom.getY(), portLineTo.getY()) || interPt.getY() > Math.max(portLineFrom.getY(), portLineTo.getY())) interPt = null; } } if (interPt == null) continue; loc1.setLocation(interPt.getX(), interPt.getY()); if (!portPoly.contains(loc1)) continue; piRet = pi; break; } if (piRet != null) break; } } } if (piRet == null) { // shrink the end inward by half-width PrimitiveNode pin = ap.findPinProto(); int ang = GenMath.figureAngle(cl.start, cl.end); double xOff = GenMath.cos(ang) * cl.width/2; double yOff = GenMath.sin(ang) * cl.width/2; if (startSide) { if (!isHub && cl.start.distance(cl.end) > cl.width) cl.setStart(cl.start.getX() + xOff, cl.start.getY() + yOff); NodeInst ni = wantNodeAt(cl.startUnscaled, pin, cl.width / SCALEFACTOR, newCell); loc1.setLocation(cl.startUnscaled.getX(), cl.startUnscaled.getY()); piRet = ni.getOnlyPortInst(); } else { if (!isHub && cl.start.distance(cl.end) > cl.width) cl.setEnd(cl.end.getX() - xOff, cl.end.getY() - yOff); NodeInst ni = wantNodeAt(cl.endUnscaled, pin, cl.width / SCALEFACTOR, newCell); loc1.setLocation(cl.endUnscaled.getX(), cl.endUnscaled.getY()); piRet = ni.getOnlyPortInst(); } } return piRet; } private List<PortInst> findPortInstsTouchingPoint(Point2D pt, Layer layer, Cell newCell, ArcProto ap) { List<PortInst> touchingNodes = new ArrayList<PortInst>(); boolean mightCreateExports = false; Rectangle2D checkBounds = new Rectangle2D.Double(pt.getX(), pt.getY(), 0, 0); for(Iterator<RTBounds> it = newCell.searchIterator(checkBounds); it.hasNext(); ) { RTBounds geom = it.next(); if (!(geom instanceof NodeInst)) continue; NodeInst ni = (NodeInst)geom; if (ni.isCellInstance()) { boolean found = false; for(Iterator<PortInst> pIt = ni.getPortInsts(); pIt.hasNext(); ) { PortInst pi = pIt.next(); Poly portPoly = pi.getPoly(); if (portPoly.contains(pt)) { touchingNodes.add(pi); found = true; break; } } if (found) continue; // remember that a cell was found...might have to create exports on it mightCreateExports = true; continue; } // for pins, must be centered over the desired point if (ni.getFunction() == PrimitiveNode.Function.PIN) { if (!ni.getOnlyPortInst().getPortProto().connectsTo(ap)) continue; if (ni.getAnchorCenter().equals(pt)) { touchingNodes.add(ni.getOnlyPortInst()); } } else { // nonpins can have any touching and connecting layer Poly [] polys = tech.getShapeOfNode(ni, true, true, null); AffineTransform trans = ni.rotateOut(); for(int i=0; i<polys.length; i++) { Poly oPoly = polys[i]; Layer oLayer = geometricLayer(oPoly.getLayer()); if (layer != oLayer) continue; oPoly.transform(trans); // do the polys touch? if (oPoly.contains(pt)) { PortInst touchingPi = findPortInstClosestToPoly(ni, (PrimitivePort)oPoly.getPort(), pt); if (touchingPi == null) { addErrorLog(newCell, "Can't find port for "+ni+" and "+oPoly.getPort(), new EPoint(pt.getX(), pt.getY())); continue; } touchingNodes.add(touchingPi); break; } } } } // if no ports were found but there were cells, should create new exports in the cells if (touchingNodes.size() == 0 && mightCreateExports) { // can we create an export on the cell? PortInst pi = makePort(newCell, layer, pt); if (pi != null) touchingNodes.add(pi); } return touchingNodes; } /** * Method to connect to a given location and layer. * @param cell the cell in which this location/layer exists. * @param layer the layer on which to connect. * @param pt the location in the Cell for the connection. * @return a PortInst on a node in the Cell (null if it cannot be found). */ private PortInst makePort(Cell cell, Layer layer, Point2D pt) { Rectangle2D checkBounds = new Rectangle2D.Double(pt.getX(), pt.getY(), 0, 0); for(Iterator<RTBounds> it = cell.searchIterator(checkBounds); it.hasNext(); ) { RTBounds geom = it.next(); if (!(geom instanceof NodeInst)) continue; NodeInst subNi = (NodeInst)geom; PortInst foundPi = null; if (subNi.isCellInstance()) { AffineTransform transIn = subNi.rotateIn(subNi.translateIn()); Point2D inside = new Point2D.Double(); transIn.transform(pt, inside); Cell subCell = (Cell)subNi.getProto(); PortInst pi = makePort(subCell, layer, inside); if (pi != null) { // already exported? for(Iterator<Export> eIt = pi.getNodeInst().getExports(); eIt.hasNext(); ) { Export e = eIt.next(); if (e.getOriginalPort() == pi) { foundPi = subNi.findPortInstFromProto(e); return foundPi; } } // if not already exported, make the export now if (foundPi == null) { Netlist nl = subCell.acquireUserNetlist(); Network net = nl.getNetwork(pi); String exportName = null; for(Iterator<String> nIt = net.getExportedNames(); nIt.hasNext(); ) { String eName = nIt.next(); if (exportName == null || exportName.length() < eName.length()) exportName = eName; } if (exportName == null) exportName = "E"; exportName = ElectricObject.uniqueObjectName(exportName, subCell, PortProto.class, true); Export e = Export.newInstance(subCell, pi, exportName); foundPi = subNi.findPortInstFromProto(e); return foundPi; } } } else { Technology tech = subNi.getProto().getTechnology(); AffineTransform trans = subNi.rotateOut(); Poly [] polyList = tech.getShapeOfNode(subNi, true, true, null); for(int i=0; i<polyList.length; i++) { Poly poly = polyList[i]; if (poly.getPort() == null) continue; if (geometricLayer(poly.getLayer()) != layer) continue; poly.transform(trans); if (poly.contains(pt)) { // found polygon that touches the point. Make the export foundPi = findPortInstClosestToPoly(subNi, (PrimitivePort)poly.getPort(), pt); return foundPi; } } } } return null; } /********************************************** VIA/CONTACT EXTRACTION **********************************************/ private static class PossibleVia { PrimitiveNode pNp; int rotation; double minWidth, minHeight; double largestShrink; Technology.NodeLayer cutNodeLayer; Layer [] layers; double [] shrinkL, shrinkR, shrinkT, shrinkB; PossibleVia(PrimitiveNode pNp, int numLayers) { this.pNp = pNp; layers = new Layer[numLayers]; shrinkL = new double[numLayers]; shrinkR = new double[numLayers]; shrinkT = new double[numLayers]; shrinkB = new double[numLayers]; } } /** * Method to scan the geometric information for possible contacts and vias. * Any vias found are created in the new cell and removed from the geometric information. * @param merge * @param originalMerge * @param newCell * @return False if the job was aborted */ private boolean extractVias(PolyMerge merge, PolyMerge originalMerge, Cell newCell) { // make a list of all via/cut layers in the technology and count the number of vias/cuts int totalCuts = 0; List<Layer> layers = new ArrayList<Layer>(); for (Layer layer : allCutLayers.keySet()) { layers.add(layer); List<PolyBase> cutList = allCutLayers.get(layer); totalCuts += cutList.size(); } // initialize list of nodes that have been created List<NodeInst> contactNodes = new ArrayList<NodeInst>(); // examine all vias/cuts for possible contacts int soFar = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -