📄 nccnetlist.java
字号:
private boolean isSchematicPrimitive(NodeInst ni) { return ni.getProto().getTechnology()==SCHEMATIC; } private Function getMosType(NodeInst ni, NccCellInfo info) { Function func = ni.getFunction(); if (isSchematicPrimitive(ni)) { // This is a workaround to allow compatibility with the regression // suite. The old regressions use "transistorType" declarations. // Designer convention: // If the Cell containing a schematic transistor primitive has an // NCC declaration "transistorType" then get the type information // from that annotation. Otherwise use the type of the transistor // primitive. Cell parent = ni.getParent(); NccCellAnnotations ann = NccCellAnnotations.getAnnotations(parent); String typeNm = ann==null ? null : ann.getTransistorType(); if (typeNm!=null) { func = PrimitiveNameToFunction.nameToFunction(typeNm); if (func==null) { badPartType = true; prln(" Unrecognized transistor type: "+typeNm); // GUI globals.getNccGuiInfo().addUnrecognizedPart( new UnrecognizedPart(ni.getParent(), info.getContext(), typeNm, ni)); } } } else { // This is a workaround until we update the Technologies to utilize // NodeProto.Function. if (func==Function.TRANMOS || func==Function.TRAPMOS) { String protoNm = ni.getProto().getName(); Function funcOverride = PrimitiveNameToFunction.nameToFunction(protoNm); if (funcOverride!=null) func=funcOverride; } } func = fourToThree.translate(func); return func; } private void buildMos(NodeInst ni, NccCellInfo info) { NodableNameProxy np = info.getUniqueNodableNameProxy(ni, "/"); PartNameProxy name = new PartNameProxy(np, pathPrefix); double width=0, length=0; if (globals.getOptions().checkSizes) { TransistorSize dim = ni.getTransistorSize(info.getContext()); width = dim.getDoubleWidth(); length = dim.getDoubleLength(); } Wire s = getWireForPortInst(ni.getTransistorSourcePort(), info); Wire g = getWireForPortInst(ni.getTransistorGatePort(), info); Wire d = getWireForPortInst(ni.getTransistorDrainPort(), info); Function type = getMosType(ni, info); // if unrecognized transistor type then ignore MOS if (type!=null) { Part t = new Mos(type, name, width, length, s, g, d); parts.add(t); } } private void buildBipolar(NodeInst ni, NccCellInfo info) { NodableNameProxy np = info.getUniqueNodableNameProxy(ni, "/"); PartNameProxy name = new PartNameProxy(np, pathPrefix); double area=0; if (globals.getOptions().checkSizes) { TransistorSize dim = ni.getTransistorSize(info.getContext()); area = dim!=null ? dim.getDoubleArea() : 0; } Wire e = getWireForPortInst(ni.getTransistorEmitterPort(), info); Wire b = getWireForPortInst(ni.getTransistorBasePort(), info); Wire c = getWireForPortInst(ni.getTransistorCollectorPort(), info); Function f = ni.getFunction(); Part t = new Bipolar(f, name, area, e, b, c); parts.add(t); } private void buildTransistor(NodeInst ni, NccCellInfo info) { Function f = ni.getFunction(); if (f.isFET()) { buildMos(ni, info); } else if (f.isBipolar()) { buildBipolar(ni, info); } else { globals.error(true, "Unrecognized primitive transistor: "+f.getShortName()); } } private Function getResistorType(NodeInst ni, NccCellInfo info) { Function f = ni.getFunction(); if (isSchematicPrimitive(ni)) { // This is a work-around to allow compatibility with older // regressions. // Designer convention: // Cell containing a schematic transistor primitive may have an // NCC declaration "resistorType" with Primitive Node name. Cell parent = ni.getParent(); NccCellAnnotations ann = NccCellAnnotations.getAnnotations(parent); String typeNm = ann==null ? null : ann.getResistorType(); if (typeNm!=null) { Function funcOverride = PrimitiveNameToFunction.nameToFunction(typeNm); if (funcOverride!=null) { f = funcOverride; } else { badPartType = true; prln(" Unrecognized resistor type: "+typeNm); // GUI globals.getNccGuiInfo().addUnrecognizedPart( new UnrecognizedPart(ni.getParent(), info.getContext(), typeNm, ni)); } } } else { // This is a work-around until we update Technologies to specify // the correct resistor Function. if (f==Function.PRESIST || f==Function.WRESIST) { String typeNm = ni.getProto().getName(); if (typeNm!=null) { Function funcOverride = PrimitiveNameToFunction.nameToFunction(typeNm); if (funcOverride!=null) f = funcOverride; } } } return f; } private Wire[] getResistorWires(NodeInst ni, NccCellInfo info) { Wire a = getWireForPortInst(ni.getPortInst(0), info); Wire b = getWireForPortInst(ni.getPortInst(1), info); return new Wire[] {a, b}; } private double getDoubleVariableValue(String varName, NodeInst ni, VarContext context) { Variable var = ni.getParameterOrVariable(varName); if (var==null) return 0; Object obj = context==null ? var.getObject() : context.evalVar(var, ni); return VarContext.objectToDouble(obj, 0); } private double[] getResistorSize(NodeInst ni, VarContext context) { double w=0, l=0; if (isSchematicPrimitive(ni)) { w = getDoubleVariableValue("ATTR_width", ni, context); l = getDoubleVariableValue("ATTR_length", ni, context); } else { w = ni.getLambdaBaseYSize(); l = ni.getLambdaBaseXSize();// SizeOffset so = ni.getSizeOffset();// w = ni.getYSize() - so.getLowYOffset() - so.getHighYOffset();// l = ni.getXSize() - so.getLowXOffset() - so.getHighXOffset(); } return new double[] {w, l}; } private void buildResistor(NodeInst ni, NccCellInfo info) { NodableNameProxy np = info.getUniqueNodableNameProxy(ni, "/"); PartNameProxy name = new PartNameProxy(np, pathPrefix); double width=0, length=0; if (globals.getOptions().checkSizes) { double[] dim = getResistorSize(ni, info.getContext()); width = dim[0]; length = dim[1]; } Wire[] wires = getResistorWires(ni, info); Function type = getResistorType(ni, info); // if unrecognized resistor type then ignore if (type!=null) { Part t = new Resistor(type, name, width, length, wires[0], wires[1]); parts.add(t); } } private void doPrimitiveNode(NodeInst ni, NccCellInfo info) { Function f = ni.getFunction(); if (f.isTransistor()) { buildTransistor(ni, info); } else if (f.isResistor() && f!=Function.RESIST) { // We use normal resistors to model parasitic wire resistance. // NCC considers them to be "short circuits" and discards them. buildResistor(ni, info); } } private void addToPins(Wire[] pins, int pinNdx, Wire w) { if (pins[pinNdx]==null) { pins[pinNdx] = w; } else { globals.error(pins[pinNdx]!=w, "exports that should be connected aren't"); } } private void pr(String s) {System.out.print(s);} private void prln(String s) {System.out.println(s);} private void printExports(HashSet<ExportGlobal> exportNames) { pr("{ "); for (ExportGlobal eg : exportNames) pr(eg.name+" "); pr("}"); } private void printExportAssertionFailure(HashMap<Wire,HashSet<ExportGlobal>> wireToExportGlobals, NccCellInfo info) { String instPath = NccNameProxy.removePrefix(pathPrefix, info.getContext().getInstPath("/")); String cellName = NccUtils.fullName(info.getCell()); prln(" Assertion: exportsConnectedByParent in cell: "+ cellName+" fails. Instance path is: "+instPath); prln(" The exports are connected to "+ wireToExportGlobals.size()+" different networks"); for (Wire w : wireToExportGlobals.keySet()) { pr(" On network: "+w.getName()+" are exports: "); printExports(wireToExportGlobals.get(w)); prln(""); } // The GUI should put the following into one box VarContext context = info.getContext(); Cell cell = info.getCell(); NccGuiInfo cm = globals.getNccGuiInfo(); Object[][] items = new Object[wireToExportGlobals.keySet().size()][]; String[][] names = new String[wireToExportGlobals.keySet().size()][]; int j = 0; for (Iterator<Wire> it=wireToExportGlobals.keySet().iterator(); it.hasNext(); j++) { HashSet<ExportGlobal> exportGlobals = wireToExportGlobals.get(it.next()); items[j] = new Object[exportGlobals.size()]; names[j] = new String[exportGlobals.size()]; int i = 0; // The GUI should put the following on one line for (Iterator<ExportGlobal> it2=exportGlobals.iterator(); it2.hasNext(); i++) { ExportGlobal eg = it2.next(); names[j][i] = eg.name; if (eg.isExport()) items[j][i] = eg.getExport(); else items[j][i] = eg.network; } } cm.addExportAssertionFailure(cell,context,items, names); } private void matchExports(HashMap<Wire,HashSet<ExportGlobal>> wireToExportGlobals, NamePattern pattern, NccCellInfo info) { for (Iterator<ExportGlobal> it=info.getExportsAndGlobals(); it.hasNext();) { ExportGlobal eg = it.next(); if (!pattern.matches(eg.name)) continue; Wire wire = wires.get(eg.netID, info); HashSet<ExportGlobal> exportGlobals = wireToExportGlobals.get(wire); if (exportGlobals==null) { exportGlobals = new HashSet<ExportGlobal>(); wireToExportGlobals.put(wire, exportGlobals); } exportGlobals.add(eg); } } private boolean exportAssertionFailure(List<NamePattern> patterns, NccCellInfo info) { // map from Wire to Set of Export Names HashMap<Wire,HashSet<ExportGlobal>> wireToExportGlobals = new HashMap<Wire,HashSet<ExportGlobal>>(); for (NamePattern np : patterns) { matchExports(wireToExportGlobals, np, info); } if (wireToExportGlobals.size()<=1) return false; printExportAssertionFailure(wireToExportGlobals, info); return true; } private boolean exportAssertionFailures(NccCellInfo info) { NccCellAnnotations ann = info.getAnnotations(); if (ann==null) return false; boolean gotError = false; for (Iterator<List<NamePattern>> it=ann.getExportsConnected(); it.hasNext();) gotError |= exportAssertionFailure(it.next(), info); return gotError; } private void doSubcircuit(SubcircuitInfo subcktInfo, NccCellInfo info) { Wire[] pins = new Wire[subcktInfo.numPorts()]; for (Iterator<ExportGlobal> it=info.getExportsAndGlobals(); it.hasNext();) { ExportGlobal eg = it.next(); Wire wire = wires.get(eg.netID, info); int pinNdx = subcktInfo.getPortIndex(eg.name); if (pinNdx!=-1) addToPins(pins, pinNdx, wire); } for (int i=0; i<pins.length; i++) globals.error(pins[i]==null, "disconnected subcircuit pins!"); CellInfo parentInfo = info.getParentInfo(); Nodable parentInst = info.getParentInst(); NodableNameProxy np = parentInfo.getUniqueNodableNameProxy(parentInst, "/"); PartNameProxy name = new PartNameProxy(np, pathPrefix); parts.add(new Subcircuit(name, subcktInfo, pins)); } /** Check to see if the parent of the current Cell instance says to * flatten the current Cell instance */ private boolean parentSaysFlattenMe(NccCellInfo info) { if (info.isRootCell()) return false; NccCellInfo parentInfo = (NccCellInfo) info.getParentInfo(); //if (!parentInfo.isRootCell()) return false; NccCellAnnotations parentAnn = parentInfo.getAnnotations(); if (parentAnn==null) return false; Nodable no = info.getParentInst(); String instName = no.getName(); return parentAnn.flattenInstance(instName); } // --------------------------- public methods ----------------------------- @Override public CellInfo newCellInfo() { return new NccCellInfo(globals); } @Override public boolean enterCell(CellInfo ci) { if (globals.userWantsToAbort()) throw new UserAbort(); NccCellInfo info = (NccCellInfo) ci; if (debug) { globals.status2(spaces()+"Enter cell: " + info.getCell().getName()); depth++; } if (info.isRootCell()) { initWires(info); createPortsFromExports(info); // "black box" means only use Export information. Ignore contents. if (blackBox) return false; } else { // We need to test exportsConnectedByParent assertions here // because if assertions fail then doSubcircuit will attempt // to connect multiple wires to the same port. boolean exportAssertFail = exportAssertionFailures(info); exportAssertionFailures |= exportAssertFail; // Subtle! Suppose mux21{sch}, mux21{lay}, and mux21_r{lay} are in // the same compareList. Then we will first compare // mux21{sch} with mux21{lay}, and then with mux21_r{lay}. For the // second comparison hierarchicalCompareInfo will tell us to treat // mux21{sch} as a primitive. Ignore it. We NEVER want to treat // the root Cell as a primitive. Cell cell = info.getCell(); if (!parentSaysFlattenMe(info) &&// hierarchicalCompareInfo!=null && hierarchicalCompareInfo.treatAsPrimitive(cell) && !exportAssertFail) { SubcircuitInfo subcktInfo = hierarchicalCompareInfo.getSubcircuitInfo(cell); doSubcircuit(subcktInfo, info); return false; } } return true; } @Override public void exitCell(CellInfo info) { if (debug) { depth--; globals.status2(spaces()+"Exit cell: " + info.getCell().getName()); } } @Override public boolean visitNodeInst(Nodable no, CellInfo ci) { NccCellInfo info = (NccCellInfo) ci; if (!no.isCellInstance()) { doPrimitiveNode((NodeInst)no, info); return false; } else { error(!no.isCellInstance(), "expecting Cell");// boolean paralleled = info.isDiscardable(no);// return !paralleled; return true; } } // ---------------------- intended public interface ----------------------- public ArrayList<Wire> getWireList() {return wires.getWireArray();} public ArrayList<Part> getPartList() {return parts;} public ArrayList<Port> getPortList() {return ports;} /** Ensure that all subcircuits we instantiate have valid exportsConnectedByParent assertions. * If not then this netlist isn't valid. */ public boolean exportAssertionFailures() {return exportAssertionFailures;} public boolean badTransistorType() {return badPartType;} public Visitor(NccGlobals globals, HierarchyInfo hierarchicalCompareInfo, boolean blackBox, VarContext context) { this.globals = globals; this.hierarchicalCompareInfo = hierarchicalCompareInfo; this.blackBox = blackBox; this.pathPrefix = context.getInstPath("/"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -