📄 ercwellcheck.java
字号:
pointList.add(new EPoint(other.ctr.getX(), other.ctr.getY())); errorLogger.logError("Short circuit between well contacts", null, null, null, pointList, null, cell, 0); shortsInWC.add(otherNetNum); shortsInOther.add(wcNetNum); } } } } // more analysis boolean hasPCon = false, hasNCon = false; for(WellCon wc : wellCons) { if (wc.fun == PrimitiveNode.Function.WELL) hasPCon = true; else hasNCon = true; if (!wc.onProperRail) { if (wc.fun == PrimitiveNode.Function.WELL) { if (ERC.isMustConnectPWellToGround()) { errorLogger.logError("P-Well contact not connected to ground", new EPoint(wc.ctr.getX(), wc.ctr.getY()), cell, 0); } } else { if (ERC.isMustConnectNWellToPower()) { errorLogger.logError("N-Well contact not connected to power", new EPoint(wc.ctr.getX(), wc.ctr.getY()), cell, 0); } } } } // look for unconnected well areas if (ERC.getPWellCheck() != 2) findUnconnected(pWellRoot, pWellRoot, "P"); if (ERC.getNWellCheck() != 2) findUnconnected(nWellRoot, nWellRoot, "N"); if (ERC.getPWellCheck() == 1 && !hasPCon) { errorLogger.logError("No P-Well contact found in this cell", cell, 0); } if (ERC.getNWellCheck() == 1 && !hasNCon) { errorLogger.logError("No N-Well contact found in this cell", cell, 0); } endTime = System.currentTimeMillis(); System.out.println(" Additional analysis took " + TextUtils.getElapsedTime(endTime - startTime)); startTime = endTime; // make sure the wells are separated properly // Local storage of rules.. otherwise getSpacingRule is called too many times // THIS IS A DRC JOB .. not efficient if done here. if (ERC.isDRCCheck()) { DRCTemplate pRule = DRC.getSpacingRule(pWellLayer, null, pWellLayer, null, false, -1, 0, 0); DRCTemplate nRule = DRC.getSpacingRule(nWellLayer, null, nWellLayer, null, false, -1, 0, 0); if (pRule != null) findDRCViolations(pWellRoot, pRule.getValue(0)); if (nRule != null) findDRCViolations(nWellRoot, nRule.getValue(0)); endTime = System.currentTimeMillis(); System.out.println(" Design rule check took " + TextUtils.getElapsedTime(endTime - startTime)); startTime = endTime; } // compute edge distance if requested if (ERC.isFindWorstCaseWell()) { worstPWellDist = 0; worstPWellCon = null; worstPWellEdge = null; worstNWellDist = 0; worstNWellCon = null; worstNWellEdge = null; Map<Integer,WellNet> wellNets = new HashMap<Integer,WellNet>(); for(WellCon wc : wellCons) { if (wc.wellNum == null) continue; Integer netNUM = new Integer(wc.wellNum.getIndex()); WellNet wn = wellNets.get(netNUM); if (wn == null) { wn = new WellNet(); wn.pointsOnNet = new ArrayList<Point2D>(); wn.contactsOnNet = new ArrayList<WellCon>(); wn.fun = wc.fun; wellNets.put(netNUM, wn); } wn.contactsOnNet.add(wc); } findWellNetPoints(pWellRoot, wellNets); findWellNetPoints(nWellRoot, wellNets); for(Integer netNUM : wellNets.keySet()) { WellNet wn = wellNets.get(netNUM); for(Point2D pt : wn.pointsOnNet) { // find contact closest to this point double closestDist = Double.MAX_VALUE; Point2D closestCon = null; for(WellCon wc : wn.contactsOnNet) { double dist = wc.ctr.distance(pt); if (dist < closestDist) { closestDist = dist; closestCon = wc.ctr; } } // see if this distance is worst for the well type if (wn.fun == PrimitiveNode.Function.WELL) { // pWell if (closestDist > worstPWellDist) { worstPWellDist = closestDist; worstPWellCon = closestCon; worstPWellEdge = pt; } } else { // nWell if (closestDist > worstNWellDist) { worstNWellDist = closestDist; worstNWellCon = closestCon; worstNWellEdge = pt; } } } } endTime = System.currentTimeMillis(); System.out.println(" Worst-case distance analysis took " + TextUtils.getElapsedTime(endTime - startTime)); startTime = endTime; } errorLogger.termLogging(true); int errorCount = errorLogger.getNumErrors(); return errorCount; } private void assignWellContacts(int numberOfThreads) { wellConIterator = new Iterator[numberOfThreads]; wellConLists = new List[numberOfThreads]; // load the lists if (numberOfThreads == 1) { wellConLists[0] = wellCons; } else { for(int i=0; i<numberOfThreads; i++) wellConLists[i] = new ArrayList<WellCon>(); if (DISTANTSEEDS) { // the new way: cluster the well contacts together Rectangle2D cellBounds = cell.getBounds(); Point2D ctr = new Point2D.Double(cellBounds.getCenterX(), cellBounds.getCenterY()); Point2D [] farPoints = new Point2D[numberOfThreads]; for(int i=0; i<numberOfThreads; i++) { double farthest = 0; farPoints[i] = new Point2D.Double(0, 0); for(WellCon wc : wellCons) { double dist = 0; if (i == 0) dist += wc.ctr.distance(ctr); else { for(int j=0; j<i; j++) dist += wc.ctr.distance(farPoints[j]); } if (dist > farthest) { farthest = dist; farPoints[i].setLocation(wc.ctr); } } } // find the center of the cell for(WellCon wc : wellCons) { double minDist = Double.MAX_VALUE; int threadNum = 0; for(int j=0; j<numberOfThreads; j++) { double dist = wc.ctr.distance(farPoints[j]); if (dist < minDist) { minDist = dist; threadNum = j; } } wellConLists[threadNum].add(wc); }// for(int i=0; i<numberOfThreads; i++)// Collections.sort(wellConLists[i], new SortWellCons(farPoints[i])); } else { // old way where well contacts are analyzed in random order for(int i=0; i<wellCons.size(); i++) wellConLists[i%numberOfThreads].add(wellCons.get(i)); } } // create iterators over the lists for(int i=0; i<numberOfThreads; i++) wellConIterator[i] = wellConLists[i].iterator(); }// /**// * Comparator class for sorting Rectangle2D objects by their size.// */// private static class SortWellCons implements Comparator<WellCon>// {// private Point2D clusterPt;//// public SortWellCons(Point2D clusterPt)// {// super();// this.clusterPt = clusterPt;// }//// /**// * Method to sort Rectangle2D objects by their size.// */// public int compare(WellCon wc1, WellCon wc2)// {// double dist1 = wc1.ctr.distance(clusterPt);// double dist2 = wc2.ctr.distance(clusterPt);// if (dist1 > dist2) return 1;// if (dist1 < dist2) return -1;// return 0;// }// } private void findDRCViolations(RTNode rtree, double minDist) { for(int j=0; j<rtree.getTotal(); j++) { if (rtree.getFlag()) { WellBound child = (WellBound)rtree.getChild(j); if (child.netID == null) continue; // look all around this geometry for others in the well area Rectangle2D searchArea = new Rectangle2D.Double(child.bound.getMinX()-minDist, child.bound.getMinY()-minDist, child.bound.getWidth()+minDist*2, child.bound.getHeight()+minDist*2); for(RTNode.Search sea = new RTNode.Search(searchArea, rtree, true); sea.hasNext(); ) { WellBound other = (WellBound)sea.next(); if (other.netID.getIndex() <= child.netID.getIndex()) continue; if (child.bound.getMinX() > other.bound.getMaxX()+minDist || other.bound.getMinX() > child.bound.getMaxX()+minDist || child.bound.getMinY() > other.bound.getMaxY()+minDist || other.bound.getMinY() > child.bound.getMaxY()+minDist) continue; PolyBase pb = new PolyBase(child.bound); double trueDist = pb.polyDistance(other.bound); if (trueDist < minDist) { List<PolyBase> polyList = new ArrayList<PolyBase>(); polyList.add(new PolyBase(child.bound)); polyList.add(new PolyBase(other.bound)); errorLogger.logError("Well areas too close (are " + TextUtils.formatDouble(trueDist) + " but should be " + TextUtils.formatDouble(minDist, 1) + " apart)", null, null, null, null, polyList, cell, 0); } } } else { RTNode child = (RTNode)rtree.getChild(j); findDRCViolations(child, minDist); } } } private int getTreeSize(RTNode rtree) { int total = 0; if (rtree.getFlag()) total += rtree.getTotal(); else { for(int j=0; j<rtree.getTotal(); j++) { RTNode child = (RTNode)rtree.getChild(j); total += getTreeSize(child); } } return total; } private void findWellNetPoints(RTNode rtree, Map<Integer,WellNet> wellNets) { for(int j=0; j<rtree.getTotal(); j++) { if (rtree.getFlag()) { WellBound child = (WellBound)rtree.getChild(j); if (child.netID == null) continue; Integer netNUM = new Integer(child.netID.getIndex()); WellNet wn = wellNets.get(netNUM); if (wn == null) continue; wn.pointsOnNet.add(new Point2D.Double(child.bound.getMinX(), child.bound.getMinY())); wn.pointsOnNet.add(new Point2D.Double(child.bound.getMaxX(), child.bound.getMinY())); wn.pointsOnNet.add(new Point2D.Double(child.bound.getMaxX(), child.bound.getMaxY())); wn.pointsOnNet.add(new Point2D.Double(child.bound.getMinX(), child.bound.getMaxY())); } else { RTNode child = (RTNode)rtree.getChild(j); findWellNetPoints(child, wellNets); } } } private void findUnconnected(RTNode rtree, RTNode current, String title) { for(int j=0; j<current.getTotal(); j++) { if (current.getFlag()) { WellBound child = (WellBound)current.getChild(j); if (child.netID == null) { spreadWellSeed(child.bound.getCenterX(), child.bound.getCenterY(), new NetValues(), rtree, 0); errorLogger.logError("No " + title + "-Well contact in this area", new EPoint(child.bound.getCenterX(), child.bound.getCenterY()), cell, 0); } } else { RTNode child = (RTNode)current.getChild(j); findUnconnected(rtree, child, title); } } } private void spreadWellSeed(double cX, double cY, NetValues wellNum, RTNode rtree, int threadIndex) { RTNode allFound = null; Point2D ctr = new Point2D.Double(cX, cY); Rectangle2D searchArea = new Rectangle2D.Double(cX, cY, 0, 0); MutableBoolean keepSearching = new MutableBoolean(true); Rectangle2D[] sides = new Rectangle2D[4]; for(int i=0; i<4; i++) sides[i] = new Rectangle2D.Double(0, 0, 0, 0); int numSides = 1; sides[0].setRect(searchArea); while (keepSearching.booleanValue()) { if (INCREMENTALGROWTH) { // grow the search area incrementally double lX = sides[0].getMinX(), hX = sides[0].getMaxX(); double lY = sides[0].getMinY(), hY = sides[0].getMaxY(); for(int i=1; i<numSides; i++) { lX = Math.min(lX, sides[i].getMinX()); hX = Math.max(hX, sides[i].getMinX()); lY = Math.min(lY, sides[i].getMinY()); hY = Math.max(hY, sides[i].getMinY()); } double newLX = lX, newHX = hX; double newLY = lY, newHY = hY; boolean anySearchesGood = false; for(int i=0; i<numSides; i++) { allFound = searchInArea(sides[i], wellNum, rtree, allFound, ctr, keepSearching, threadIndex); if (keepSearching.booleanValue()) anySearchesGood = true; newLX = Math.min(newLX, sides[i].getMinX()); newHX = Math.max(newHX, sides[i].getMinX()); newLY = Math.min(newLY, sides[i].getMinY()); newHY = Math.max(newHY, sides[i].getMinY()); } keepSearching.setValue(anySearchesGood); // compute new bounds numSides = 0; if (newLX < lX) sides[numSides++].setRect(newLX, newLY, lX-newLX, newHY-newLY); if (newHX > hX) sides[numSides++].setRect(hX, newLY, newHX-hX, newHY-newLY); if (newLY < lY) sides[numSides++].setRect(newLX, newLY, newHX-newLX, lY-newLY); if (newHY > hY) sides[numSides++].setRect(newLX, hY, newHX-newLX, newHY-hY); } else { // just keep growing the search area allFound = searchInArea(searchArea, wellNum, rtree, allFound, ctr, keepSearching, threadIndex); } } } private RTNode searchInArea(Rectangle2D searchArea, NetValues wellNum, RTNode rtree, RTNode allFound, Point2D ctr, MutableBoolean keepSearching, int threadIndex) { keepSearching.setValue(false); for(RTNode.Search sea = new RTNode.Search(searchArea, rtree, true); sea.hasNext(); ) { WellBound wb = (WellBound)sea.next();if (GATHERSTATISTICS) numObjSearches++; // ignore if this object is already properly connected if (wb.netID != null && wb.netID.getIndex() == wellNum.getIndex()) continue; // see if this object actually touches something in the set if (allFound == null) { // start from center of contact if (!wb.bound.contains(ctr)) continue; } else { boolean touches = false; for(RTNode.Search subSea = new RTNode.Search(wb.bound, allFound, true); subSea.hasNext(); ) { WellBound subWB = (WellBound)subSea.next(); if (DBMath.rectsIntersect(subWB.bound, wb.bound)) { touches = true; break; } } if (!touches) continue; } // this touches what is gathered so far: add to it synchronized(wb) { if (wb.netID != null) wellNum.merge(wb.netID); else wb.netID = wellNum; }if (GATHERSTATISTICS) wellBoundSearchOrder.add(new WellBoundRecord(wb, threadIndex)); // expand the next search area by this added bound Rectangle2D.union(searchArea, wb.bound, searchArea); if (allFound == null) allFound = RTNode.makeTopLevel(); allFound = RTNode.linkGeom(null, allFound, wb); keepSearching.setValue(true); } return allFound; } private static class NetValues { private int index; private static int indexValues; static void reset() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -