⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ercwellcheck.java

📁 The ElectricTM VLSI Design System is an open-source Electronic Design Automation (EDA) system that c
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
						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 + -