📄 ercantenna.java
字号:
trans.concatenate(tTrans); AffineTransform rTrans = ao.hierstack[i].rotateOut(); trans.concatenate(rTrans); } Technology tech = ai.getProto().getTechnology(); if (tech != curTech) continue; Poly [] polyList = tech.getShapeOfArc(ai); for(int i=0; i<polyList.length; i++) { Poly poly = polyList[i]; if (poly.getLayer() != lay) continue; if (vmerge == null) vmerge = new PolyMerge(); poly.transform(trans); vmerge.addPolygon(poly.getLayer(), poly); } } } if (vmerge != null) { // get the area of the antenna double totalRegionPerimeterArea = 0.0; for (Layer oLay : vmerge.getKeySet()) { double thickness = oLay.getThickness(); if (thickness == 0) { if (oLay.getFunction().isMetal()) thickness = DEFMETALTHICKNESS; else if (oLay.getFunction().isPoly()) thickness = DEFPOLYTHICKNESS; } List<PolyBase> merges = vmerge.getMergedPoints(oLay, true); for(PolyBase merged : merges) { totalRegionPerimeterArea += merged.getPerimeter() * thickness; } } // see if it is an antenna violation double ratio = totalRegionPerimeterArea / totalGateArea; double neededratio = getAntennaRatio(lay); if (ratio > worstRatio) worstRatio = ratio; if (ratio >= neededratio) { // error String errMsg = "layer " + lay.getName() + " has perimeter-area " + totalRegionPerimeterArea + "; gates have area " + totalGateArea + ", ratio is " + ratio + " but limit is " + neededratio; List<PolyBase> polyList = new ArrayList<PolyBase>(); for (Layer oLay : vmerge.getKeySet()) { List<PolyBase> merges = vmerge.getMergedPoints(oLay, true); for(PolyBase merged : merges) { polyList.add(merged); } } errorLogger.logError(errMsg, null, null, null, null, polyList, cell, 0); } } } } } // now look at subcells fsCell.add(cell); for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (!ni.isCellInstance()) continue; Cell subCell = (Cell)ni.getProto(); if (fsCell.contains(subCell)) continue; if (checkThisCell(subCell, lay, job)) return true; } return false; } /** * Method to follow a node around the cell. * @param ni the NodeInst to follow. * @param pp the PortProto on the NodeInst. * @param lay the layer to consider. * @param trans a transformation to the top-level. * @return ERCANTPATHNULL if it found no gate or active on the path. * Returns ERCANTPATHGATE if it found gates on the path. * Returns ERCANTPATHACTIVE if it found active on the path. */ private int followNode(NodeInst ni, PortProto pp, Layer lay, AffineTransform trans, Job job) { // presume that nothing was found int ret = ERCANTPATHNULL; firstSpreadAntennaObj = new ArrayList<AntennaObject>(); NodeInst [] antstack = new NodeInst[200]; int depth = 0; // keep walking along the nodes and arcs for(;;) { if (job.checkAbort()) return ERCABORTED; // if this is a subcell, recurse on it fsGeom.add(ni); NodeInst thisni = ni; while (thisni.isCellInstance()) { antstack[depth] = thisni; depth++; thisni = ((Export)pp).getOriginalPort().getNodeInst(); pp = ((Export)pp).getOriginalPort().getPortProto(); } // see if we hit a transistor boolean seen = false; if (thisni.getFunction().isFET()) { // stop tracing if (thisni.getTransistorDrainPort().getPortProto() == pp || thisni.getTransistorSourcePort().getPortProto() == pp) { // touching the diffusion side of the transistor return ERCANTPATHACTIVE; } // touching the gate side of the transistor TransistorSize dim = thisni.getTransistorSize(VarContext.globalContext); totalGateArea += dim.getDoubleLength() * dim.getDoubleWidth(); ret = ERCANTPATHGATE; } else { // normal primitive: propagate if (hasDiffusion(thisni)) return ERCANTPATHACTIVE; AntennaObject ao = new AntennaObject(ni); if (haveAntennaObject(ao)) { // already in the list: free this object seen = true; } else { // not in the list: add it ao.loadAntennaObject(antstack, depth); addAntennaObject(ao); } } // look at all arcs on the node if (!seen) { int found = findArcs(thisni, pp, lay, depth, antstack); if (found == ERCANTPATHACTIVE) return found; if (depth > 0) { found = findExports(thisni, pp, lay, depth, antstack); if (found == ERCANTPATHACTIVE) return found; } } // look for an unspread antenna object and keep walking if (firstSpreadAntennaObj.size() == 0) break; AntennaObject ao = firstSpreadAntennaObj.get(0); firstSpreadAntennaObj.remove(0); ArcInst ai = (ArcInst)ao.geom; ni = ai.getPortInst(ao.otherend).getNodeInst(); pp = ai.getPortInst(ao.otherend).getPortProto(); depth = ao.hierstack.length; for(int i=0; i<depth; i++) antstack[i] = ao.hierstack[i]; } return ret; } /** * Method to tell whether a NodeInst has diffusion on it. * @param ni the NodeInst in question. * @return true if the NodeInst has diffusion on it. */ private boolean hasDiffusion(NodeInst ni) { // stop if this is a pin if (ni.getFunction() == PrimitiveNode.Function.PIN) return false; // analyze to see if there is diffusion here Technology tech = ni.getProto().getTechnology(); Poly [] polyList = tech.getShapeOfNode(ni); for(int i=0; i<polyList.length; i++) { Poly poly = polyList[i]; Layer.Function fun = poly.getLayer().getFunction(); if (fun.isDiff()) return true; } return false; } private int findArcs(NodeInst ni, PortProto pp, Layer lay, int depth, NodeInst [] antstack) { PortInst pi = ni.findPortInstFromProto(pp); for(Iterator<Connection> it = pi.getConnections(); it.hasNext(); ) { Connection con = it.next();// for(Iterator it = ni.getConnections(); it.hasNext(); )// {// Connection con = it.next();// PortInst pi = con.getPortInst();// if (pi.getPortProto() != pp) continue; ArcInst ai = con.getArc(); // see if it is the desired layer if (ai.getProto().getFunction().isDiffusion()) return ERCANTPATHACTIVE; Layer aLayer = arcProtoToLayer.get(ai.getProto()); if (aLayer == null) continue; if (ai.getProto().getFunction().isMetal() != aLayer.getFunction().isMetal()) continue; if (ai.getProto().getFunction().isPoly() != aLayer.getFunction().isPoly()) continue; if (ai.getProto().getFunction().getLevel() > aLayer.getFunction().getLevel()) continue; // make an antenna object for this arc fsGeom.add(ai); AntennaObject ao = new AntennaObject(ai); if (haveAntennaObject(ao)) continue; ao.loadAntennaObject(antstack, depth); int other = 0; if (ai.getPortInst(0) == pi) other = 1; ao.otherend = other; addAntennaObject(ao); // add to the list of "unspread" antenna objects firstSpreadAntennaObj.add(ao); } return ERCANTPATHNULL; } private int findExports(NodeInst ni, PortProto pp, Layer lay, int depth, NodeInst [] antstack) { depth--; for(Iterator<Export> it = ni.getExports(); it.hasNext(); ) { Export e = it.next(); if (e != pp) continue; ni = antstack[depth]; pp = e; int found = findArcs(ni, pp, lay, depth, antstack); if (found == ERCANTPATHACTIVE) return found; if (depth > 0) { found = findExports(ni, pp, lay, depth, antstack); if (found == ERCANTPATHACTIVE) return found; } } return ERCANTPATHNULL; } /** * Method to tell whether an AntennaObject is in the active list. * @param ao the AntennaObject. * @return true if the AntennaObject is already in the list. */ private boolean haveAntennaObject(AntennaObject ao) { for(AntennaObject oAo : pathList) { if (oAo.geom == ao.geom && oAo.depth == ao.depth) { boolean found = true; int len = 0; if (ao.hierstack != null) len = ao.hierstack.length; int oLen = 0; if (oAo.hierstack != null) oLen = oAo.hierstack.length; if (len != oLen) continue; for(int i=0; i<len; i++) { if (oAo.hierstack[i] != ao.hierstack[i]) { found = false; break; } } if (found) return true; } } return false; } /** * Method to add an AntennaObject to the list of antenna objects on this path. * @param ao the AntennaObject to add. */ private void addAntennaObject(AntennaObject ao) { pathList.add(ao); } /** * Method to return the maximum antenna ratio on a given Layer. * @param layer the layer in question. * @return the maximum antenna ratio for the Layer. */ private double getAntennaRatio(Layer layer) { // find the ArcProto that corresponds to this layer ArcProto ap = layerToArcProto.get(layer); if (ap == null) return 0; // return its ratio return ERC.tool.getAntennaRatio(ap); //return ap.getAntennaRatio(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -