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

📄 ercwellcheck.java

📁 The ElectricTM VLSI Design System is an open-source Electronic Design Automation (EDA) system that c
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
			indexValues = 0;		}		static synchronized int getFreeIndex()		{			return indexValues++;		}		public int getIndex() { return index; }		public NetValues()		{			index = getFreeIndex();		}		public synchronized void merge(NetValues other)		{			if (this.index == other.index) return;			other.index = this.index;		}	}	// well contacts	private static class WellCon	{		Point2D                ctr;		int                    netNum;		NetValues              wellNum;		boolean                onProperRail;		PrimitiveNode.Function fun;	}	/**	 * Class to define an R-Tree leaf node for geometry in the blockage data structure.	 */	private static class WellBound implements RTBounds	{		private Rectangle2D bound;		private NetValues netID;		WellBound(Rectangle2D bound)		{			this.bound = bound;			this.netID = null;		}		public Rectangle2D getBounds() { return bound; }		public NetValues getNetID() { return netID; }		public String toString() { return "Well Bound on net " + netID.getIndex(); }	}	private static class NetRails	{		boolean onGround;		boolean onPower;	}	private static class WellNet	{		List<Point2D> pointsOnNet;		List<WellCon> contactsOnNet;		PrimitiveNode.Function fun;	}	/**	 * Comparator class for sorting Rectangle2D objects by their size.	 */	private static class RectangleBySize implements Comparator<Rectangle2D>	{		/**		 * Method to sort Rectangle2D objects by their size.		 */		public int compare(Rectangle2D b1, Rectangle2D b2)		{			double s1 = b1.getWidth() * b1.getHeight();			double s2 = b2.getWidth() * b2.getHeight();			if (s1 > s2) return -1;			if (s1 < s2) return 1;			return 0;		}	}	private class NewWellCheckVisitor extends HierarchyEnumerator.Visitor	{		private Map<Cell,List<Rectangle2D>> essentialPWell;		private Map<Cell,List<Rectangle2D>> essentialNWell;		private Map<Network,NetRails> networkCache;		public NewWellCheckVisitor()		{			essentialPWell = new HashMap<Cell,List<Rectangle2D>>();			essentialNWell = new HashMap<Cell,List<Rectangle2D>>();			networkCache = new HashMap<Network,NetRails>();		}		public boolean enterCell(HierarchyEnumerator.CellInfo info)		{			// Checking if job is scheduled for abort or already aborted			if (job != null && job.checkAbort()) return false;			// make sure essential well areas are gathered			Cell cell = info.getCell();			ensureCellCached(cell);			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();			List<Rectangle2D> pWellsInCell = essentialPWell.get(cell);			List<Rectangle2D> nWellsInCell = essentialNWell.get(cell);			for(Rectangle2D b : pWellsInCell)			{				Rectangle2D bounds = new Rectangle2D.Double(b.getMinX(), b.getMinY(), b.getWidth(), b.getHeight());				DBMath.transformRect(bounds, info.getTransformToRoot());				pWellRoot = RTNode.linkGeom(null, pWellRoot, new WellBound(bounds));			}			for(Rectangle2D b : nWellsInCell)			{				Rectangle2D bounds = new Rectangle2D.Double(b.getMinX(), b.getMinY(), b.getWidth(), b.getHeight());				DBMath.transformRect(bounds, info.getTransformToRoot());				nWellRoot = RTNode.linkGeom(null, nWellRoot, new WellBound(bounds));			}		}		public boolean visitNodeInst(Nodable no, HierarchyEnumerator.CellInfo info)		{			NodeInst ni = no.getNodeInst();			// 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();				AffineTransform trans = ni.rotateOut();				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.onProperRail = false;				wc.wellNum = null;				if (net == null) wc.netNum = -1; else				{					wc.netNum = info.getNetID(net);					// 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)					{						NetRails nr = networkCache.get(parentNet);						if (nr == null)						{							nr = new NetRails();							networkCache.put(parentNet, nr);							for (Iterator<Export> it = parentNet.getExports(); it.hasNext(); )							{								Export exp = it.next();								if (exp.isGround()) nr.onGround = true;								if (exp.isPower()) nr.onPower = true;							}						}						boolean searchWell = (fun == PrimitiveNode.Function.WELL);						if ((searchWell && nr.onGround) || (!searchWell && nr.onPower))							wc.onProperRail = true;					}				}				wellCons.add(wc);			}			return true;		}		private void ensureCellCached(Cell cell)		{			List<Rectangle2D> pWellsInCell = essentialPWell.get(cell);			List<Rectangle2D> nWellsInCell = essentialNWell.get(cell);			if (pWellsInCell == null)			{				// gather all wells in the cell				pWellsInCell = new ArrayList<Rectangle2D>();				nWellsInCell = new ArrayList<Rectangle2D>();				for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); )				{					NodeInst ni = it.next();					if (ni.isCellInstance()) continue;					PrimitiveNode pn = (PrimitiveNode)ni.getProto();					if (!possiblePrimitives.contains(pn)) continue;					// Getting only ercLayers					Poly [] nodeInstPolyList = pn.getTechnology().getShapeOfNode(ni, true, true, ercLayers);					int tot = nodeInstPolyList.length;					for(int i=0; i<tot; i++)					{						Poly poly = nodeInstPolyList[i];						Layer layer = poly.getLayer();						AffineTransform trans = ni.rotateOut();						poly.transform(trans);						Rectangle2D bound = poly.getBounds2D();						int wellType = getWellLayerType(layer);						if (wellType == ERCPWell) pWellsInCell.add(bound);							else if (wellType == ERCNWell) nWellsInCell.add(bound);					}				}				for(Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); )				{					ArcInst ai = it.next();					ArcProto ap = ai.getProto();					if (!possiblePrimitives.contains(ap)) continue;					// Getting only ercLayers					Poly [] arcInstPolyList = ap.getTechnology().getShapeOfArc(ai, ercLayers);					int tot = arcInstPolyList.length;					for(int i=0; i<tot; i++)					{						Poly poly = arcInstPolyList[i];						Layer layer = poly.getLayer();						Rectangle2D bound = poly.getBounds2D();						int wellType = getWellLayerType(layer);						if (wellType == ERCPWell) pWellsInCell.add(bound);							else if (wellType == ERCNWell) nWellsInCell.add(bound);					}				}				// eliminate duplicates				eliminateDuplicates(pWellsInCell);				eliminateDuplicates(nWellsInCell);				// save results				essentialPWell.put(cell, pWellsInCell);				essentialNWell.put(cell, nWellsInCell);			}		}		private void eliminateDuplicates(List<Rectangle2D> wbList)		{			// first sort by size			Collections.sort(wbList, new RectangleBySize());			for(int i=0; i<wbList.size(); i++)			{				Rectangle2D b = wbList.get(i);				for(int j=0; j<i; j++)				{					Rectangle2D prevB = wbList.get(j);					if (prevB.contains(b))					{						wbList.remove(i);						i--;						break;					}				}			}		}	}	private static final int ERCPWell = 1;	private static final int ERCNWell = 2;	private static final int ERCPSEUDO = 0;	private static final Layer.Function[] ercLayersArray = {		Layer.Function.WELLP, Layer.Function.WELL, Layer.Function.WELLN, Layer.Function.SUBSTRATE,		Layer.Function.IMPLANTP, Layer.Function.IMPLANT, Layer.Function.IMPLANTN};	private static final Layer.Function.Set ercLayers = new Layer.Function.Set(ercLayersArray);	/**	 * Method to return nonzero if layer "layer" is a well/select layer.	 * @return 1: P-Well, 2: N-Well	 */	private static int getWellLayerType(Layer layer)	{		Layer.Function fun = layer.getFunction();		if (layer.isPseudoLayer()) return ERCPSEUDO;		if (fun == Layer.Function.WELLP) return ERCPWell;		if (fun == Layer.Function.WELL || fun == Layer.Function.WELLN) return ERCNWell;		return ERCPSEUDO;	}	// variables for the "old way"	private GeometryHandler.GHMode mode;	private Set<Cell> doneCells = new HashSet<Cell>(); // Mark if cells are done already.	private Map<Cell,GeometryHandler> cellMerges = new HashMap<Cell,GeometryHandler>(); // make a map of merge information in each cell	// well areas	private static class WellArea	{		PolyBase    poly;		int         netNum;		int         index;	}	private int doOldWay()	{		// enumerate the hierarchy below here		WellCheckVisitor wcVisitor = new WellCheckVisitor();		HierarchyEnumerator.enumerateCell(cell, VarContext.globalContext, wcVisitor);		// Checking if job is scheduled for abort or already aborted		if (job != null && job.checkAbort()) return 0;		// make a list of well and substrate areas		List<WellArea> wellAreas = new ArrayList<WellArea>();		int wellIndex = 0;		GeometryHandler topMerge = cellMerges.get(cell);		for (Layer layer : topMerge.getKeySet())		{			// Not sure if null goes here			Collection<PolyBase> set = topMerge.getObjects(layer, false, true);			for(PolyBase poly : set)			{				WellArea wa = new WellArea();				wa.poly = poly;				wa.poly.setLayer(layer);				wa.poly.setStyle(Poly.Type.FILLED);				wa.index = wellIndex++;				wellAreas.add(wa);			}		}		boolean foundPWell = false;		boolean foundNWell = false;		for(WellArea wa : wellAreas)		{			int wellType = getWellLayerType(wa.poly.getLayer());			if (wellType != ERCPWell && wellType != ERCNWell) continue;			// presume N-well			PrimitiveNode.Function desiredContact = PrimitiveNode.Function.SUBSTRATE;			String noContactError = "No N-Well contact found in this area";			int contactAction = ERC.getNWellCheck();			if (wellType == ERCPWell)			{				// P-well				desiredContact = PrimitiveNode.Function.WELL;				contactAction = ERC.getPWellCheck();				noContactError = "No P-Well contact found in this area";				foundPWell = true;			}			else				foundNWell = true;			// find a contact in the area			boolean found = false;			for(WellCon wc : wellCons)			{				if (wc.fun != desiredContact) continue;				if (!wa.poly.getBounds2D().contains(wc.ctr)) continue;				if (!wa.poly.contains(wc.ctr)) continue;				wa.netNum = wc.netNum;				found = true;				break;			}			// if no contact, issue appropriate errors			if (!found)			{				if (contactAction == 0)				{					errorLogger.logError(noContactError, wa.poly, cell, 0);				}			}		}		// make sure all of the contacts are on the same net		for(WellCon wc : wellCons)		{			// -1 means not connected in hierarchyEnumerator::numberNets()			if (wc.netNum == -1)			{				String errorMsg = "N-Well contact is floating";				if (wc.fun == PrimitiveNode.Function.WELL) errorMsg = "P-Well contact is floating";				errorLogger.logError(errorMsg, new EPoint(wc.ctr.getX(), wc.ctr.getY()), cell, 0);				continue;			}			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);					}				}			}		}		// if just 1 N-Well contact is needed, see if it is there		if (ERC.getNWellCheck() == 1 && foundNWell)		{			boolean found = false;			for(WellCon wc : wellCons)			{				if (wc.fun == PrimitiveNode.Function.SUBSTRATE) { found = true;   break; }			}			if (!found)			{				errorLogger.logError("No N-Well contact found in this cell", cell, 0);			}		}		// if just 1 P-Well contact is needed, see if it is there		if (ERC.getPWellCheck() == 1 && foundPWell)		{			boolean found = false;			for(WellCon wc : wellCons)			{				if (wc.fun == PrimitiveNode.Function.WELL) { found = true;   break; }			}			if (!found)			{				errorLogger.logError("No P-Well contact found in this cell", cell, 0);			}		}		// 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())		{			Map<Layer,DRCTemplate> rulesCon = new HashMap<Layer,DRCTemplate>();			Map<Layer,DRCTemplate> rulesNonCon = new HashMap<Layer,DRCTemplate>();			for(WellArea wa : wellAreas)			{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -