📄 circuitchangejobs.java
字号:
} System.out.println("Deleted " + arcsToDelete.size() + " arcs"); return true; } } /****************************** DELETE OBJECTS IN A LIST ******************************/ /** * Method to delete all of the Geometrics in a list. * @param cell the cell with the objects to be deleted. * @param list a List of Geometric or Highlight objects to be deleted. * @param reconstructArcsAndExports true to reconstruct arcs to deleted cell instances. * @param stuffToHighlight a set of objects to select (arcs and exports) if reconstruction is done. */ public static void eraseObjectsInList(Cell cell, List<Geometric> list, boolean reconstructArcsAndExports, Set<ElectricObject> stuffToHighlight) { // make sets of all of the arcs and nodes explicitly selected for deletion Set<ArcInst> arcsToDelete = new HashSet<ArcInst>(); Set<NodeInst> nodesToDelete = new HashSet<NodeInst>(); if (cantEdit(cell, null, true, false, true) != 0) return; for(Geometric geom : list) { if (geom instanceof ArcInst) { ArcInst ai = (ArcInst)geom; arcsToDelete.add(ai); } else if (geom instanceof NodeInst) { NodeInst ni = (NodeInst)geom; if (cantEdit(cell, ni, true, false, true) != 0) continue; nodesToDelete.add(ni); } } // make a set of additional nodes to potentially delete Set<NodeInst> alsoDeleteTheseNodes = new HashSet<NodeInst>(); // also (potentially) delete nodes on the end of deleted arcs for(ArcInst ai : arcsToDelete) { alsoDeleteTheseNodes.add(ai.getHeadPortInst().getNodeInst()); alsoDeleteTheseNodes.add(ai.getTailPortInst().getNodeInst()); } // also mark all nodes on the other end of arcs connected to erased nodes for(NodeInst ni : nodesToDelete) { for(Iterator<Connection> sit = ni.getConnections(); sit.hasNext(); ) { Connection con = sit.next(); ArcInst ai = con.getArc(); int otherEnd = 1 - con.getEndIndex(); NodeInst oNi = ai.getPortInst(otherEnd).getNodeInst(); alsoDeleteTheseNodes.add(oNi); } } // reconnect hair to cells (if requested) if (reconstructArcsAndExports) { for(NodeInst ni : nodesToDelete) { if (!ni.isCellInstance()) continue; // make a map of recreated ports Map<PortInst,PortInst> reassigned = new HashMap<PortInst,PortInst>(); // reconstruct exports to deleted cell instances for(Iterator<Export> eIt = ni.getExports(); eIt.hasNext(); ) { Export e = eIt.next(); AffineTransform trans = new AffineTransform(); Orientation orient = Orientation.IDENT; PortInst pi = e.getOriginalPort(); NodeInst subNi; PortProto subPP; for(;;) { subNi = pi.getNodeInst(); subPP = pi.getPortProto(); trans = subNi.rotateOut(trans); orient = orient.concatenate(subNi.getOrient()); if (!subNi.isCellInstance()) break; trans = subNi.translateOut(trans); pi = ((Export)subPP).getOriginalPort(); } NodeProto subNp = subNi.getProto(); Point2D ctr = new Point2D.Double(subNi.getTrueCenter().getX(), subNi.getTrueCenter().getY()); trans.transform(ctr, ctr); NodeInst eNi = NodeInst.makeInstance(subNp, ctr, subNi.getXSize(), subNi.getYSize(), cell, orient, null, 0); pi = eNi.findPortInstFromProto(subPP); reassigned.put(e.getOriginalPort(), pi); e.move(pi); if (stuffToHighlight != null) stuffToHighlight.add(e); } // reconstruct each connection to a deleted cell instance for(Iterator<Connection> cIt = ni.getConnections(); cIt.hasNext(); ) { Connection con = cIt.next(); ArcInst ai = con.getArc(); if (arcsToDelete.contains(ai)) continue; // recreate them int thisEnd = con.getEndIndex(); int otherEnd = 1 - thisEnd; PortInst thisPi = ai.getPortInst(thisEnd); PortInst otherPi = ai.getPortInst(otherEnd); NodeInst otherNi = otherPi.getNodeInst(); if (otherNi == ni) { // special case: arc from node to itself gets preserved? continue; } if (nodesToDelete.contains(otherNi)) continue; // reconnect a piece of hair to a cell instance PortInst alreadyPI = reassigned.get(thisPi); if (alreadyPI == null) { PrimitiveNode pinNp = ai.getProto().findPinProto(); NodeInst pin = NodeInst.makeInstance(pinNp, con.getLocation(), pinNp.getDefWidth(), pinNp.getDefHeight(), cell); alreadyPI = pin.getOnlyPortInst(); reassigned.put(thisPi, alreadyPI); } ArcInst newAI = ArcInst.makeInstanceBase(ai.getProto(), ai.getLambdaBaseWidth(), otherPi, alreadyPI, ai.getConnection(otherEnd).getLocation(), con.getLocation(), ai.getName()); if (stuffToHighlight != null) stuffToHighlight.add(newAI); } } } // now kill all of the arcs for(ArcInst ai : arcsToDelete) { ai.kill(); } // reconnect all nodes that are in the middle of two arcs for(NodeInst ni : nodesToDelete) { // see if any arcs can be reconnected as a result of this kill Reconnect re = Reconnect.erasePassThru(ni, false, false); if (re != null) re.reconnectArcs(); } // next kill all of the nodes cell.killNodes(nodesToDelete); // kill all pin nodes that touched an arc and no longer do Set<NodeInst> deleteTheseNodes = new HashSet<NodeInst>(); for(NodeInst ni : alsoDeleteTheseNodes) { if (!ni.isLinked()) continue; if (!ni.isCellInstance()) { if (ni.getProto().getFunction() != PrimitiveNode.Function.PIN) continue; if (ni.hasConnections() || ni.hasExports()) continue; deleteTheseNodes.add(ni); } } cell.killNodes(deleteTheseNodes); // kill all unexported pin or bus nodes left in the middle of arcs List<NodeInst> nodesToPassThru = new ArrayList<NodeInst>(); for(NodeInst ni : alsoDeleteTheseNodes) { if (!ni.isCellInstance()) { if (ni.getProto().getFunction() != PrimitiveNode.Function.PIN) continue; if (ni.hasExports()) continue; if (!ni.isInlinePin()) continue; nodesToPassThru.add(ni); } } for(NodeInst ni : nodesToPassThru) { Reconnect re = Reconnect.erasePassThru(ni, false, false); if (re != null) { re.reconnectArcs(); ni.kill(); } } int numArcsDeleted = arcsToDelete.size(); int numNodesDeleted = nodesToDelete.size(); String msg = "Deleted"; if (numNodesDeleted == 1) msg += " 1 node"; else if (numNodesDeleted > 1) msg += " " + numNodesDeleted + " nodes"; if (numNodesDeleted > 0 && numArcsDeleted > 0) msg += " and"; if (numArcsDeleted == 1) msg += " 1 arc"; else if (numArcsDeleted > 1) msg += " " + numArcsDeleted + " arcs"; System.out.println(msg); } /****************************** CLEAN-UP ******************************/ /** * This class implements the changes needed to cleanup pins in a Cell. */ public static class CleanupChanges extends Job { private Cell cell; private boolean justThis; private Set<NodeInst> pinsToRemove; private List<Reconnect> pinsToPassThrough; private Map<NodeInst,EPoint> pinsToScale; private List<NodeInst> textToMove; private Set<ArcInst> arcsToKill; private int zeroSize, negSize, overSizePins; public CleanupChanges(Cell cell, boolean justThis, Set<NodeInst> pinsToRemove, List<Reconnect> pinsToPassThrough, Map<NodeInst,EPoint> pinsToScale, List<NodeInst> textToMove, Set<ArcInst> arcsToKill, int zeroSize, int negSize, int overSizePins) { super("Cleanup " + cell, User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.cell = cell; this.justThis = justThis; this.pinsToRemove = pinsToRemove; this.pinsToPassThrough = pinsToPassThrough; this.pinsToScale = pinsToScale; this.textToMove = textToMove; this.arcsToKill = arcsToKill; this.zeroSize = zeroSize; this.negSize = negSize; this.overSizePins = overSizePins; startJob(); } public boolean doIt() throws JobException { // make sure moving the node is allowed if (cantEdit(cell, null, true, false, true) != 0) return false; // do the queued operations cell.killNodes(pinsToRemove); int pinsPassedThrough = 0; for(;;) { boolean found = false; for(Reconnect re : pinsToPassThrough) { if (!re.ni.isLinked()) continue; List created = re.reconnectArcs(); if (created.size() > 0) { re.ni.kill(); pinsPassedThrough++; found = true; } } if (!found) break; pinsToPassThrough = getPinsToPassThrough(cell); } for(NodeInst ni : pinsToScale.keySet()) { EPoint scale = pinsToScale.get(ni); ni.resize(scale.getX(), scale.getY()); } for(NodeInst ni : textToMove) { ni.invisiblePinWithOffsetText(true); } cell.killArcs(arcsToKill); // report what was cleaned StringBuffer infstr = new StringBuffer(); if (!justThis) infstr.append("Cell " + cell.describe(true) + ":"); boolean spoke = false; if ((pinsToRemove.size()+pinsPassedThrough) != 0) { int removed = pinsToRemove.size() + pinsPassedThrough; infstr.append("Removed " + removed + " pins"); spoke = true; } if (arcsToKill.size() != 0) { if (spoke) infstr.append("; "); infstr.append("Removed " + arcsToKill.size() + " duplicate arcs"); spoke = true; } if (pinsToScale.size() != 0) { if (spoke) infstr.append("; "); infstr.append("Shrunk " + pinsToScale.size() + " pins"); spoke = true; } if (zeroSize != 0) { if (spoke) infstr.append("; "); if (justThis) { infstr.append("Highlighted " + zeroSize + " zero-size pins"); } else { infstr.append("Found " + zeroSize + " zero-size pins"); } spoke = true; } if (negSize != 0) { if (spoke) infstr.append("; "); if (justThis) { infstr.append("Highlighted " + negSize + " negative-size pins"); } else { infstr.append("Found " + negSize + " negative-size pins"); } spoke = true; } if (overSizePins != 0) { if (spoke) infstr.append("; "); if (justThis) { infstr.append("Highlighted " + overSizePins + " oversize pins with arcs that don't touch"); } else { infstr.append("Found " + overSizePins + " oversize pins with arcs that don't touch"); } spoke = true; } if (textToMove.size() != 0) { if (spoke) infstr.append("; "); infstr.append("Moved text on " + textToMove.size() + " pins with offset text"); } System.out.println(infstr.toString()); return true; } } /** * This class implements the changes needed to shorten selected arcs. */ public static class ShortenArcs extends Job { private Cell cell; private List<ArcInst> selected; public ShortenArcs(Cell cell, List<ArcInst> selected) { super("Shorten selected arcs", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.cell = cell; this.selected = selected; startJob(); } public boolean doIt() throws JobException { // make sure shortening is allowed if (cantEdit(cell, null, true, false, true) != 0) return false; int l = 0; double [] dX = new double[2]; double [] dY = new double[2]; for(ArcInst ai : selected) { for(int j=0; j<2; j++) { Poly portPoly = ai.getPortInst(j).getPoly(); double wid = ai.getLambdaBaseWidth(); portPoly.reducePortPoly(ai.getPortInst(j), wid, ai.getAngle()); Point2D closest = portPoly.closestPoint(ai.getLocation(1-j)); dX[j] = closest.getX() - ai.getLocation(j).getX(); dY[j] = closest.getY() - ai.getLocation(j).getY(); } if (dX[0] != 0 || dY[0] != 0 || dX[1] != 0 || dY[1] != 0) { ai.modify(dX[ArcInst.HEADEND], dY[ArcInst.HEADEND], dX[ArcInst.TAILEND], dY[ArcInst.TAILEND]); l++; } } System.out.println("Shortened " + l + " arcs"); return true; } } /****************************** MOVE SELECTED OBJECTS ******************************/ public static class ManyMove extends Job { private static final boolean verbose = true; private Cell cell; private List<ElectricObject> highlightedObjs; private List<DisplayedText> highlightedText; private double dX, dY; private boolean updateStatusBar; public ManyMove(Cell cell, List<ElectricObject> highlightedObjs, List<DisplayedText> highlightedText, double dX, double dY) { super("Move", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER); this.cell = cell; this.highlightedObjs = highlightedObjs; this.highlightedText = highlightedText; this.dX = dX; this.dY = dY; startJob(); } public boolean doIt() throws JobException { // get information about what is highlighted if (highlightedObjs.size() + highlightedText.size() == 0) return false; // make sure moving is allowed if (cantEdit(cell, null, true, false, true) != 0) return false; // special case if moving only one node if (highlightedObjs.size() == 1 && highlightedText.size() == 0) { ElectricObject firstEObj = highlightedObjs.get(0); if (firstEObj instanceof NodeInst || firstEObj instanceof PortInst) { NodeInst ni;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -