📄 connectivity.java
字号:
private void addErrorLog(Cell cell, String msg, EPoint... pList) { List<EPoint> pointList = new ArrayList<EPoint>(); for(EPoint p : pList) pointList.add(p); errorLogger.logError(msg, null, null, null, pointList, null, cell, -1); System.out.println(msg); } /** * Top-level method in extracting connectivity from a Cell. * A new version of the cell is created that has real nodes (transistors, contacts) and arcs. * This cell should have pure-layer nodes which will be converted. */ private Cell doExtract(Cell oldCell, boolean recursive, Pattern pat, boolean top, Job job, List<List<ERectangle>> addedBatchRectangles, List<List<ERectangle>> addedBatchLines, List<String> addedBatchNames) { if (recursive) { // first see if subcells need to be converted for(Iterator<NodeInst> it = oldCell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (ni.isCellInstance()) { Cell subCell = (Cell)ni.getProto(); // do not recurse if this subcell will be expanded if (pat != null) { Matcher mat = pat.matcher(subCell.noLibDescribe()); if (mat.find()) continue; } Cell convertedCell = convertedCells.get(subCell); if (convertedCell == null) { doExtract(subCell, recursive, pat, false, job, addedBatchRectangles, addedBatchLines, addedBatchNames); } } } } // create the new version of the cell String newCellName = oldCell.getName() + oldCell.getView().getAbbreviationExtension(); Cell newCell = Cell.makeInstance(oldCell.getLibrary(), newCellName); if (newCell == null) { System.out.println("Cannot create new cell: " + newCellName); return null; } convertedCells.put(oldCell, newCell); // create a merge for the geometry in the cell PolyMerge merge = new PolyMerge(); // convert the nodes if (!startSection("Gathering geometry in " + oldCell + "...")) // HAS PROGRESS IN IT return null; // aborted Set<Cell> expandedCells = new HashSet<Cell>(); exportsToRestore = new ArrayList<Export>(); pinsForLater = new ArrayList<ExportedPin>(); allCutLayers = new HashMap<Layer,List<PolyBase>>(); extractCell(oldCell, newCell, pat, expandedCells, merge, GenMath.MATID); if (expandedCells.size() > 0) { System.out.print("These cells were expanded:"); for(Cell c : expandedCells) System.out.print(" " + c.describe(false)); System.out.println(); } // determine if this is a "P-well" or "N-well" process findMissingWells(merge); // now remember the original merge PolyMerge originalMerge = new PolyMerge(); originalMerge.addMerge(merge, new AffineTransform()); // start by extracting vias initDebugging(); if (!startSection("Extracting vias...")) return null; // aborted if (!extractVias(merge, originalMerge, newCell)) return null; // aborted termDebugging(addedBatchRectangles, addedBatchLines, addedBatchNames, "Vias"); // now extract transistors initDebugging(); if (!startSection("Extracting transistors...")) return null; // aborted extractTransistors(merge, originalMerge, newCell); termDebugging(addedBatchRectangles, addedBatchLines, addedBatchNames, "Transistors"); // extend geometry that sticks out in space initDebugging(); if (!startSection("Extracting extensions...")) return null; // aborted extendGeometry(merge, originalMerge, newCell, true); termDebugging(addedBatchRectangles, addedBatchLines, addedBatchNames, "StickOuts"); // look for wires and pins initDebugging(); if (!startSection("Extracting wires...")) return null; // aborted if (makeWires(merge, originalMerge, newCell)) return newCell; termDebugging(addedBatchRectangles, addedBatchLines, addedBatchNames, "Wires"); // convert any geometry that connects two networks initDebugging(); if (!startSection("Extracting connections...")) return null; // aborted extendGeometry(merge, originalMerge, newCell, false); termDebugging(addedBatchRectangles, addedBatchLines, addedBatchNames, "Bridges"); // dump any remaining layers back in as extra pure layer nodes initDebugging(); if (!startSection("Extracting leftover geometry...")) return null; // aborted convertAllGeometry(merge, originalMerge, newCell); termDebugging(addedBatchRectangles, addedBatchLines, addedBatchNames, "Pures"); // reexport any that were there before if (!startSection("Adding connecting wires...")) return null; // aborted restoreExports(oldCell, newCell); // cleanup by auto-stitching PolyMerge originalUnscaledMerge = new PolyMerge(); double shrinkage = 1.0 / SCALEFACTOR; AffineTransform shrink = new AffineTransform(shrinkage, 0, 0, shrinkage, 0, 0); originalUnscaledMerge.addMerge(originalMerge, shrink); Set<ArcInst> allArcs = null; if (DEBUGSTEPS) { allArcs = new HashSet<ArcInst>(); for(Iterator<ArcInst> it = newCell.getArcs(); it.hasNext(); ) allArcs.add(it.next()); } AutoStitch.runAutoStitch(newCell, null, null, job, originalUnscaledMerge, null, false, true, true); if (DEBUGSTEPS) { initDebugging(); for(Iterator<ArcInst> it = newCell.getArcs(); it.hasNext(); ) { ArcInst ai = it.next(); if (allArcs.contains(ai)) continue; Poly arcPoly = ai.makeLambdaPoly(ai.getGridBaseWidth(), Poly.Type.CLOSED); addedRectangles.add(ERectangle.fromLambda(arcPoly.getBounds2D())); } termDebugging(addedBatchRectangles, addedBatchLines, addedBatchNames, "Stitches"); } System.out.println("Extraction done."); return newCell; } /** * Method to start a new connection section. * @param msg message to display in progress window * @return False if the job is scheduled for abort or was aborted */ private boolean startSection(String msg) { System.out.println(msg); if (job.checkAbort()) return false; Job.getUserInterface().setProgressNote(msg); Job.getUserInterface().setProgressValue(0); return true; } private void initDebugging() { if (DEBUGSTEPS) { addedRectangles = new ArrayList<ERectangle>(); addedLines = new ArrayList<ERectangle>(); } } private void termDebugging(List<List<ERectangle>> addedBatchRectangles, List<List<ERectangle>> addedBatchLines, List<String> addedBatchNames, String descr) { if (DEBUGSTEPS) { addedBatchRectangles.add(addedRectangles); addedBatchLines.add(addedLines); addedBatchNames.add(descr); } } private static class ExportedPin { Point2D location; NodeInst ni; AffineTransform trans; ExportedPin(NodeInst ni, Point2D location, AffineTransform trans) { this.ni = ni; this.location = location; this.trans = trans; } } /** * Method to extract a cell's contents into the merge. * @param oldCell the cell being extracted. * @param newCell the new cell being created. * @param pat a pattern of subcell names that will be expanded. * @param expandedCells a set of cells that matched the pattern and were expanded. * @param merge the merge to be filled. * @param prevTrans the transformation coming into this cell. */ private void extractCell(Cell oldCell, Cell newCell, Pattern pat, Set<Cell> expandedCells, PolyMerge merge, AffineTransform prevTrans) { Map<NodeInst,NodeInst> newNodes = new HashMap<NodeInst,NodeInst>(); int totalNodes = oldCell.getNumNodes(); int soFar = 0; for(Iterator<NodeInst> nIt = oldCell.getNodes(); nIt.hasNext(); ) { NodeInst ni = nIt.next(); soFar++; if ((soFar % 100) == 0) Job.getUserInterface().setProgressValue(soFar * 100 / totalNodes); if (ni.getProto() == Generic.tech().cellCenterNode) continue; // see if the node can be copied or must be extracted NodeProto copyType = null; if (ni.isCellInstance()) { Cell subCell = (Cell)ni.getProto(); // if subcell is expanded, do it now if (pat != null) { Matcher mat = pat.matcher(subCell.noLibDescribe()); if (mat.find()) { // expanding the subcell expandedCells.add(subCell); AffineTransform subTrans = ni.translateOut(ni.rotateOut(prevTrans)); extractCell(subCell, newCell, pat, expandedCells, merge, subTrans); continue; } } // subcell not expanded, figure out what gets placed in the new cell copyType = convertedCells.get(subCell); if (copyType == null) copyType = subCell; } else { PrimitiveNode np = (PrimitiveNode)ni.getProto(); // special case for exported but unconnected pins: save for later if (np.getFunction() == PrimitiveNode.Function.PIN) { if (ni.hasExports() && !ni.hasConnections()) { ExportedPin ep = new ExportedPin(ni, ni.getTrueCenter(), prevTrans); pinsForLater.add(ep); continue; } } if (np.getFunction() != PrimitiveNode.Function.NODE) copyType = ni.getProto(); else { if (ignoreNodes.contains(np)) copyType = ni.getProto(); } } // copy it now if requested if (copyType != null) { double sX = ni.getXSize(); double sY = ni.getYSize(); if (copyType instanceof Cell) { Rectangle2D cellBounds = ((Cell)copyType).getBounds(); sX = cellBounds.getWidth(); sY = cellBounds.getHeight(); } Point2D instanceAnchor = new Point2D.Double(0, 0); prevTrans.transform(ni.getAnchorCenter(), instanceAnchor); NodeInst newNi = NodeInst.makeInstance(copyType, instanceAnchor, sX, sY, newCell, ni.getOrient(), ni.getName(), ni.getTechSpecific()); if (newNi == null) { addErrorLog(newCell, "Problem creating new instance of " + ni.getProto(), new EPoint(sX, sY)); return; } newNodes.put(ni, newNi); // copy exports too for(Iterator<Export> it = ni.getExports(); it.hasNext(); ) { Export e = it.next(); PortInst pi = newNi.findPortInstFromProto(e.getOriginalPort().getPortProto()); Export.newInstance(newCell, pi, e.getName()); } continue; } // see if the size is at an odd coordinate (and may suffer rounding problems) boolean growABit = false; if (((int)(ni.getXSize() * DBMath.GRID) % 2) != 0 || ((int)(ni.getYSize() * DBMath.GRID) % 2) != 0) growABit = true; // extract the geometry from the pure-layer node AffineTransform trans = ni.rotateOut(prevTrans); Poly [] polys = tech.getShapeOfNode(ni); for(int j=0; j<polys.length; j++) { Poly poly = polys[j]; // get the layer for the geometry Layer layer = poly.getLayer(); if (layer == null) continue; // make sure the geometric database is made up of proper layers layer = geometricLayer(layer); // finally add the geometry to the merge poly.transform(trans); Point2D [] points = poly.getPoints(); if (Extract.isGridAlignExtraction()) { Point2D hold = new Point2D.Double(); for(int i=0; i<points.length; i++) { hold.setLocation(points[i]); Job.getUserInterface().alignToGrid(hold); poly.setPoint(i, hold.getX(), hold.getY()); } } else { // grow the polygon to account for rounding problems if (growABit) { double growth = DBMath.getEpsilon()/2; Point2D polyCtr = poly.getCenter(); for(int i=0; i<points.length; i++) { double x = points[i].getX(); double y = points[i].getY(); if (x < polyCtr.getX()) x -= growth; else x += growth; if (y < polyCtr.getY()) y -= growth; else y += growth; poly.setPoint(i, x, y); } } } for(int i=0; i<points.length; i++) poly.setPoint(i, scaleUp(points[i].getX()), scaleUp(points[i].getY())); if (layer.getFunction().isContact()) { // cut layers are stored in lists because merging them is too expensive and pointless List<PolyBase> cutsOnLayer = allCutLayers.get(layer); if (cutsOnLayer == null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -