📄 ercwellcheck.java
字号:
for(WellArea oWa : wellAreas) { // Checking if job is scheduled for abort or already aborted if (job != null && job.checkAbort()) return (0); if (wa.index <= oWa.index) continue; Layer waLayer = wa.poly.getLayer(); if (waLayer != oWa.poly.getLayer()) continue; boolean con = false; if (wa.netNum == oWa.netNum && wa.netNum >= 0) con = true; DRCTemplate rule = (con)? rulesCon.get(waLayer): rulesNonCon.get(waLayer); // @TODO Might still return NULL the first time!!. Need another array or aux class? if (rule == null) { rule = DRC.getSpacingRule(waLayer, null, waLayer, null, con, -1, 0, 0); if (rule != null) { if (con) rulesCon.put(waLayer, rule); else rulesNonCon.put(waLayer, rule); } } double ruleValue = -1; if (rule != null) ruleValue = rule.getValue(0); if (ruleValue < 0) continue; if (wa.poly.getBounds2D().getMinX() > oWa.poly.getBounds2D().getMaxX()+ruleValue || oWa.poly.getBounds2D().getMinX() > wa.poly.getBounds2D().getMaxX()+ruleValue || wa.poly.getBounds2D().getMinY() > oWa.poly.getBounds2D().getMaxY()+ruleValue || oWa.poly.getBounds2D().getMinY() > wa.poly.getBounds2D().getMaxY()+ruleValue) continue; double dist = wa.poly.separation(oWa.poly); // dist == 0 -> intersect or inner loops if (dist > 0 && dist < ruleValue) { int layertype = getWellLayerType(waLayer); if (layertype == ERCPSEUDO) continue; List<PolyBase> polyList = new ArrayList<PolyBase>(); polyList.add(wa.poly); polyList.add(oWa.poly); errorLogger.logError(waLayer.getName() + " areas too close (are " + TextUtils.formatDouble(dist, 1) + ", should be " + TextUtils.formatDouble(ruleValue, 1) + ")", null, null, null, null, polyList, cell, 0); } } } } // compute edge distance if requested if (ERC.isFindWorstCaseWell()) { worstPWellDist = 0; worstPWellCon = null; worstPWellEdge = null; worstNWellDist = 0; worstNWellCon = null; worstNWellEdge = null; for(WellArea wa : wellAreas) { int wellType = getWellLayerType(wa.poly.getLayer()); if (wellType == ERCPSEUDO) continue; PrimitiveNode.Function desiredContact = PrimitiveNode.Function.SUBSTRATE; if (wellType == ERCPWell) desiredContact = PrimitiveNode.Function.WELL; // find the worst distance to the edge of the area Point2D [] points = wa.poly.getPoints(); int count = points.length; for(int i=0; i<count*2; i++) { // figure out which point is being analyzed Point2D testPoint = null; if (i < count) { int prev = i-1; if (i == 0) prev = count-1; testPoint = new Point2D.Double((points[prev].getX() + points[i].getX()) / 2, (points[prev].getY() + points[i].getY()) / 2); } else { testPoint = points[i-count]; } // find the closest contact to this point boolean first = true; double bestDist = 0; WellCon bestWc = null; for(WellCon wc : wellCons) { if (wc.fun != desiredContact) continue; if (!wa.poly.getBounds2D().contains(wc.ctr)) continue; if (!wa.poly.contains(wc.ctr)) continue; double dist = testPoint.distance(wc.ctr); if (first || dist < bestDist) { bestDist = dist; bestWc = wc; } first = false; } if (first) continue; // accumulate worst distances to edges if (wellType == 1) { if (bestDist > worstPWellDist) { worstPWellDist = bestDist; worstPWellCon = bestWc.ctr; worstPWellEdge = testPoint; } } else { if (bestDist > worstNWellDist) { worstNWellDist = bestDist; worstNWellCon = bestWc.ctr; worstNWellEdge = testPoint; } } } } } // clean up wellCons.clear(); doneCells.clear(); cellMerges.clear(); errorLogger.termLogging(true); int errorCount = errorLogger.getNumErrors(); return errorCount; } private class WellCheckVisitor extends HierarchyEnumerator.Visitor { public WellCheckVisitor() {} public boolean enterCell(HierarchyEnumerator.CellInfo info) { // Checking if job is scheduled for abort or already aborted if (job != null && job.checkAbort()) return false; // make an object for merging all of the wells in this cell Cell cell = info.getCell(); if (cellMerges.get(cell) == null) { GeometryHandler thisMerge = GeometryHandler.createGeometryHandler(mode, ercLayersArray.length); cellMerges.put(cell, thisMerge); } return true; } public void exitCell(HierarchyEnumerator.CellInfo info) { // Checking if job is scheduled for abort or already aborted if (job != null && job.checkAbort()) return; // get the object for merging all of the wells in this cell Cell cell = info.getCell(); GeometryHandler thisMerge = cellMerges.get(cell); if (thisMerge == null) throw new Error("wrong condition in ERCWellCheck.enterCell()"); if (!doneCells.contains(cell)) { for(Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); ) { ArcInst ai = it.next(); Technology tech = ai.getProto().getTechnology(); // Getting only ercLayers Poly [] arcInstPolyList = tech.getShapeOfArc(ai, ercLayers); int tot = arcInstPolyList.length; for(int i=0; i<tot; i++) { Poly poly = arcInstPolyList[i]; Layer layer = poly.getLayer(); // Only interested in well/select Shape newElem = poly; thisMerge.add(layer, newElem); } } thisMerge.postProcess(true); // merge everything sub trees for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (!ni.isCellInstance()) continue; // get sub-merge information for the cell instance GeometryHandler subMerge = cellMerges.get(ni.getProto()); if (subMerge != null) { AffineTransform tTrans = ni.translateOut(ni.rotateOut()); thisMerge.addAll(subMerge, tTrans); } } // To mark if cell is already done doneCells.add(cell); } } public boolean visitNodeInst(Nodable no, HierarchyEnumerator.CellInfo info) { NodeInst ni = no.getNodeInst(); if (NodeInst.isSpecialNode(ni)) return false; // Nothing to do, Dec 9; // merge everything AffineTransform trans = null; // Not done yet Cell cell = info.getCell(); if (!doneCells.contains(cell)) { if (!ni.isCellInstance()) { GeometryHandler thisMerge = cellMerges.get(cell); PrimitiveNode pNp = (PrimitiveNode)ni.getProto(); Technology tech = pNp.getTechnology(); // Getting only ercLayers Poly [] nodeInstPolyList = tech.getShapeOfNode(ni, true, true, ercLayers); int tot = nodeInstPolyList.length; for(int i=0; i<tot; i++) { Poly poly = nodeInstPolyList[i]; Layer layer = poly.getLayer(); // Only interested in well/select regions if (trans == null) trans = ni.rotateOut(); // transformation only calculated when required. poly.transform(trans); Shape newElem = poly; thisMerge.add(layer, newElem); } } } // look for well and substrate contacts PrimitiveNode.Function fun = ni.getFunction(); if (fun == PrimitiveNode.Function.WELL || fun == PrimitiveNode.Function.SUBSTRATE) { WellCon wc = new WellCon(); wc.ctr = ni.getTrueCenter(); if (trans == null) trans = ni.rotateOut(); // transformation only calculated when required. trans.transform(wc.ctr, wc.ctr); info.getTransformToRoot().transform(wc.ctr, wc.ctr); wc.fun = fun; PortInst pi = ni.getOnlyPortInst(); Netlist netList = info.getNetlist(); Network net = netList.getNetwork(pi); wc.netNum = info.getNetID(net); wc.onProperRail = false; if (net != null) { boolean searchWell = (fun == PrimitiveNode.Function.WELL); // PWell: must be on ground or NWell: must be on power Network parentNet = net; HierarchyEnumerator.CellInfo cinfo = info; while (cinfo.getParentInst() != null) { parentNet = cinfo.getNetworkInParent(parentNet); cinfo = cinfo.getParentInfo(); } if (parentNet != null) { for (Iterator<Export> it = parentNet.getExports(); !wc.onProperRail && it.hasNext();) { Export exp = it.next(); if ((searchWell && exp.isGround()) || (!searchWell && exp.isPower())) wc.onProperRail = true; } } } wellCons.add(wc); } return true; } } // **************************************** STATISTICS **************************************** private List<WellBoundRecord> wellBoundSearchOrder; private int numObjSearches; private void initStatistics() { if (GATHERSTATISTICS) { numObjSearches = 0; wellBoundSearchOrder = Collections.synchronizedList(new ArrayList<WellBoundRecord>()); } } private void showStatistics() { if (GATHERSTATISTICS) { System.out.println("SEARCHED "+numObjSearches+" OBJECTS"); new ShowWellBoundOrder(); } } private static class WellBoundRecord { WellBound wb; int processor; private WellBoundRecord(WellBound w, int p) { wb = w; processor = p; } } private class ShowWellBoundOrder extends EModelessDialog { private Timer vcrTimer; private long vcrLastAdvance; private int wbIndex; private int speed; private JTextField tf; private Highlighter h; private Color[] hColors = new Color[] {Color.WHITE, Color.RED, Color.GREEN, Color.BLUE}; public ShowWellBoundOrder() { super(TopLevel.isMDIMode() ? TopLevel.getCurrentJFrame() : null, false); initComponents(); finishInitialization(); setVisible(true); wbIndex = 0; EditWindow wnd = EditWindow.getCurrent(); h = wnd.getHighlighter(); h.clear(); } private void initComponents() { getContentPane().setLayout(new GridBagLayout()); setTitle("Show ERC Progress"); setName(""); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { closeDialog(); } }); GridBagConstraints gridBagConstraints; JButton go = new JButton("Go"); go.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { goNow(); } }); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.insets = new Insets(4, 4, 4, 4); getContentPane().add(go, gridBagConstraints); JButton stop = new JButton("Stop"); stop.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { stopNow(); } }); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.insets = new Insets(4, 4, 4, 4); getContentPane().add(stop, gridBagConstraints); JLabel lab = new JLabel("Speed:"); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.insets = new Insets(4, 4, 4, 4); getContentPane().add(lab, gridBagConstraints); speed = 1; tf = new JTextField(Integer.toString(speed)); tf.getDocument().addDocumentListener(new BoundsPlayerDocumentListener()); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.insets = new Insets(4, 4, 4, 4); getContentPane().add(tf, gridBagConstraints); pack(); } private void updateSpeed() { speed = TextUtils.atoi(tf.getText()); if (vcrTimer != null) vcrTimer.setDelay(speed); } private void goNow() { if (vcrTimer == null) { ActionListener taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { tick(); } }; vcrTimer = new Timer(speed, taskPerformer); vcrLastAdvance = System.currentTimeMillis(); vcrTimer.start(); } } private void stopNow() { if (vcrTimer == null) return; vcrTimer.stop(); vcrTimer = null; } private void tick() { // see if it is time to advance the VCR long curtime = System.currentTimeMillis(); if (curtime - vcrLastAdvance < speed) return; vcrLastAdvance = curtime; if (wbIndex >= wellBoundSearchOrder.size()) stopNow(); else { WellBoundRecord wbr = wellBoundSearchOrder.get(wbIndex++); h.addPoly(new Poly(wbr.wb.bound), cell, hColors[wbr.processor]); h.finished(); } } private class BoundsPlayerDocumentListener implements DocumentListener { BoundsPlayerDocumentListener() {} public void changedUpdate(DocumentEvent e) { updateSpeed(); } public void insertUpdate(DocumentEvent e) { updateSpeed(); } public void removeUpdate(DocumentEvent e) { updateSpeed(); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -