📄 spice.java
字号:
case SPICE_ENGINE_2: preferedEngineTemplateKey = SPICE_2_TEMPLATE_KEY; break; case SPICE_ENGINE_3: preferedEngineTemplateKey = SPICE_3_TEMPLATE_KEY; break; case SPICE_ENGINE_H: preferedEngineTemplateKey = SPICE_H_TEMPLATE_KEY; break; case SPICE_ENGINE_P: preferedEngineTemplateKey = SPICE_P_TEMPLATE_KEY; break; case SPICE_ENGINE_G: preferedEngineTemplateKey = SPICE_GC_TEMPLATE_KEY; break; case SPICE_ENGINE_S: preferedEngineTemplateKey = SPICE_SM_TEMPLATE_KEY; break; case SPICE_ENGINE_H_ASSURA: preferedEngineTemplateKey = SPICE_A_TEMPLATE_KEY; assuraHSpice = true; break; case SPICE_ENGINE_H_CALIBRE: preferedEngineTemplateKey = SPICE_C_TEMPLATE_KEY; assuraHSpice = true; break; } if (useCDL) { preferedEngineTemplateKey = CDL_TEMPLATE_KEY; } if (assuraHSpice || (useCDL && !CDLWRITESEMPTYSUBCKTS) || (!useCDL && !Simulation.isSpiceWriteEmtpySubckts())) { writeEmptySubckts = false; } // get the mask scale maskScale = 1.0;// Variable scaleVar = layoutTechnology.getVar("SIM_spice_mask_scale");// if (scaleVar != null) maskScale = TextUtils.atof(scaleVar.getObject().toString()); // set up the parameterized cells uniquifyCells = new HashMap<Cell,Cell>(); uniqueID = 0; uniqueNames = new HashMap<String,Integer>(); markCellsToUniquify(topCell); // setup the legal characters legalSpiceChars = SPICELEGALCHARS; if (spiceEngine == Simulation.SpiceEngine.SPICE_ENGINE_P || spiceEngine == Simulation.SpiceEngine.SPICE_ENGINE_G) legalSpiceChars = PSPICELEGALCHARS; // start writing the spice deck if (useCDL) { // setup bracket conversion for CDL if (Simulation.isCDLConvertBrackets()) legalSpiceChars = CDLNOBRACKETLEGALCHARS; multiLinePrint(true, "* First line is ignored\n"); // see if include file specified String headerPath = TextUtils.getFilePath(topCell.getLibrary().getLibFile()); String filePart = Simulation.getCDLIncludeFile(); if (!filePart.equals("")) { String fileName = headerPath + filePart; File test = new File(fileName); if (test.exists()) { multiLinePrint(true, "* Primitives described in this file:\n"); addIncludeFile(filePart); } else { System.out.println("Warning: CDL Include file not found: "+fileName); } } } else { writeHeader(topCell); spiceCodeFlat = new FlatSpiceCodeVisitor(filePath+".flatcode", this); HierarchyEnumerator.enumerateCell(topCell, VarContext.globalContext, spiceCodeFlat, getShortResistorsFlat()); spiceCodeFlat.close(); } if (Simulation.isParasiticsUseExemptedNetsFile()) { String headerPath = TextUtils.getFilePath(topCell.getLibrary().getLibFile()); exemptedNets = new SpiceExemptedNets(new File(headerPath + File.separator + "exemptedNets.txt")); } } /** * Method called once at the end of netlisting. */ protected void done() { if (!useCDL) { writeTrailer(topCell); if (Simulation.isSpiceWriteFinalDotEnd()) multiLinePrint(false, ".END\n"); } } /** * Method called by traversal mechanism to write one level of hierarchy in the Spice netlist. * This could be the top level or a subcircuit. * The bulk of the Spice netlisting happens here. */ protected void writeCellTopology(Cell cell, CellNetInfo cni, VarContext context, Topology.MyCellInfo info) { // if this is the top level cell, write globals if (cell == topCell) { Netlist netList = cni.getNetList(); Global.Set globals = netList.getGlobals(); int globalSize = globals.size(); if (Simulation.getSpiceGlobalTreatment() == Simulation.SpiceGlobal.USEGLOBALBLOCK) { if (globalSize > 0) { StringBuffer infstr = new StringBuffer(); infstr.append("\n.global"); for(int i=0; i<globalSize; i++) { Global global = globals.get(i); String name = global.getName(); if (global == Global.power) { if (getPowerName(null) != null) name = getPowerName(null); } if (global == Global.ground) { if (getGroundName(null) != null) name = getGroundName(null); } infstr.append(" " + name); } infstr.append("\n"); multiLinePrint(false, infstr.toString()); } } else { // make sure power and ground appear at the top level if (cni.getPowerNet() == null) System.out.println("WARNING: cannot find power at top level of circuit"); if (cni.getGroundNet() == null) System.out.println("WARNING: cannot find ground at top level of circuit"); } } // create electrical nets (SpiceNet) for every Network in the cell Netlist netList = cni.getNetList(); Map<Network,SpiceNet> spiceNetMap = new HashMap<Network,SpiceNet>(); for(Iterator<Network> it = netList.getNetworks(); it.hasNext(); ) { Network net = it.next(); SpiceNet spNet = new SpiceNet(net); spiceNetMap.put(net, spNet); } // for non-simple parasitics, create a SpiceSegmentedNets object to deal with them Simulation.SpiceParasitics spLevel = Simulation.getSpiceParasiticsLevel(); if (useCDL || cell.getView() != View.LAYOUT) spLevel = Simulation.SpiceParasitics.SIMPLE; SpiceSegmentedNets segmentedNets = null; if (spLevel != Simulation.SpiceParasitics.SIMPLE) { // make the parasitics info object if it does not already exist if (parasiticInfo == null) { if (spLevel == Simulation.SpiceParasitics.RC_PROXIMITY) { parasiticInfo = new SpiceParasitic(); } else if (spLevel == Simulation.SpiceParasitics.RC_CONSERVATIVE) { parasiticInfo = new SpiceRCSimple(); } } segmentedNets = parasiticInfo.initializeSegments(cell, cni, layoutTechnology, exemptedNets, info); } // count the number of different transistor types int bipolarTrans = 0, nmosTrans = 0, pmosTrans = 0; for(Iterator<NodeInst> aIt = cell.getNodes(); aIt.hasNext(); ) { NodeInst ni = aIt.next(); addNodeInformation(netList, spiceNetMap, ni); PrimitiveNode.Function fun = ni.getFunction(); if (fun == PrimitiveNode.Function.TRANPN || fun == PrimitiveNode.Function.TRA4NPN || fun == PrimitiveNode.Function.TRAPNP || fun == PrimitiveNode.Function.TRA4PNP || fun == PrimitiveNode.Function.TRANS) bipolarTrans++; else if (fun.isNTypeTransistor()) nmosTrans++; else if (fun.isPTypeTransistor()) pmosTrans++; } // accumulate geometry of all arcs for(Iterator<ArcInst> aIt = cell.getArcs(); aIt.hasNext(); ) { ArcInst ai = aIt.next(); // don't count non-electrical arcs if (ai.getProto().getFunction() == ArcProto.Function.NONELEC) continue; // ignore busses// if (ai->network->buswidth > 1) continue; Network net = netList.getNetwork(ai, 0); SpiceNet spNet = spiceNetMap.get(net); if (spNet == null) continue; addArcInformation(spNet.merge, ai); } // get merged polygons so far for(Iterator<Network> it = netList.getNetworks(); it.hasNext(); ) { Network net = it.next(); SpiceNet spNet = spiceNetMap.get(net); for (Layer layer : spNet.merge.getKeySet()) { List<PolyBase> polyList = spNet.merge.getMergedPoints(layer, true); if (polyList == null) continue; if (polyList.size() > 1) Collections.sort(polyList, GeometryHandler.shapeSort); for(PolyBase poly : polyList) { // compute perimeter and area double perim = poly.getPerimeter(); double area = poly.getArea(); // accumulate this information double scale = layoutTechnology.getScale(); // scale to convert units to nanometers if (layer.isDiffusionLayer()) { spNet.diffArea += area * maskScale * maskScale; spNet.diffPerim += perim * maskScale; } else { area = area * scale * scale / 1000000; // area in square microns perim = perim * scale / 1000; // perim in microns spNet.nonDiffCapacitance += layer.getCapacitance() * area * maskScale * maskScale; spNet.nonDiffCapacitance += layer.getEdgeCapacitance() * perim * maskScale; } } } } // make sure the ground net is number zero Network groundNet = cni.getGroundNet(); Network powerNet = cni.getPowerNet(); if (pmosTrans != 0 && powerNet == null) { String message = "WARNING: no power connection for P-transistor wells in " + cell; dumpErrorMessage(message); } if (nmosTrans != 0 && groundNet == null) { String message = "WARNING: no ground connection for N-transistor wells in " + cell; dumpErrorMessage(message); } // generate header for subckt or top-level cell boolean forceEval = useCDL || !Simulation.isSpiceUseCellParameters() || detectSpiceParams(cell) == UNIQUIFY_MARK; String topLevelInstance = ""; if (cell == topCell && !useCDL && !Simulation.isSpiceWriteSubcktTopCell()) { multiLinePrint(true, "\n*** TOP LEVEL CELL: " + cell.describe(false) + "\n"); } else { if (!writeEmptySubckts) { if (cellIsEmpty(cell)) return; } String cellName = cni.getParameterizedName(); multiLinePrint(true, "\n*** CELL: " + cell.describe(false) + "\n"); StringBuffer infstr = new StringBuffer(); infstr.append(".SUBCKT " + cellName); for(Iterator<CellSignal> sIt = cni.getCellSignals(); sIt.hasNext(); ) { CellSignal cs = sIt.next(); if (ignoreSubcktPort(cs)) continue; if (!cs.isGlobal() && cs.getExport() == null) continue; // special case for parasitic extraction if (parasiticInfo != null && !cs.isGlobal() && cs.getExport() != null) { parasiticInfo.writeSubcircuitHeader(cs, infstr); } else { infstr.append(" " + cs.getName()); } } Global.Set globals = netList.getGlobals(); int globalSize = globals.size(); if (cell == topCell && Simulation.isSpiceWriteSubcktTopCell()) { // create top level instantiation if (Simulation.isSpiceWriteTopCellInstance()) topLevelInstance = infstr.toString().replaceFirst("\\.SUBCKT ", "X") + " " + cellName; } if (!useCDL && Simulation.isSpiceUseCellParameters()) { // add in parameters to this cell Set<Variable.Key> spiceParams = detectSpiceParams(cell); for(Iterator<Variable> it = cell.getParameters(); it.hasNext(); ) { Variable paramVar = it.next(); if (DETECT_SPICE_PARAMS && !spiceParams.contains(paramVar.getKey())) continue; String value = paramVar.getPureValue(-1); if (USE_JAVA_CODE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -