📄 silos.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Silos.java * Input/output tool: Silos netlist output * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2004 Sun Microsystems and Static Free Software * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.tool.io.output;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Nodable;import com.sun.electric.database.network.Global;import com.sun.electric.database.network.Netlist;import com.sun.electric.database.network.Network;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.text.Version;import com.sun.electric.database.topology.Connection;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.database.variable.VarContext;import com.sun.electric.database.variable.Variable;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.technologies.Schematics;import com.sun.electric.tool.simulation.Simulation;import com.sun.electric.tool.user.User;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.util.Date;import java.util.Iterator;/** * This is the netlister for Silos. */public class Silos extends Topology{ /** split lines into 80 characters. */ private static final int MAXSTR = 79; /** Maximum macro name length. */ private static final int MAXNAME = 12; /** key of Variable holding node name. */ public static final Variable.Key SILOS_NODE_NAME_KEY = Variable.newKey("SIM_silos_node_name"); /** key of Variable holding global names. */ public static final Variable.Key SILOS_GLOBAL_NAME_KEY = Variable.newKey("SIM_silos_global_name"); /** key of Variable holding behavior file. */ public static final Variable.Key SILOS_BEHAVIOR_FILE_KEY = Variable.newKey("SIM_silos_behavior_file"); /** key of Variable holding model. */ public static final Variable.Key SILOS_MODEL_KEY = Variable.newKey("SC_silos"); /** * The main entry point for Silos deck writing. * @param cell the top-level cell to write. * @param context the hierarchical context to the cell. * @param filePath the disk file to create. */ public static void writeSilosFile(Cell cell, VarContext context, String filePath) { Silos out = new Silos(); if (out.openTextOutputStream(filePath)) return; if (out.writeCell(cell, context)) return; if (out.closeTextOutputStream()) return; System.out.println(filePath + " written"); } /** * Creates a new instance of the Silos netlister. */ Silos() { } protected void start() { // parameters to the output-line-length limit and how to break long lines setOutputWidth(MAXSTR, true); setContinuationString("+"); // write header information writeWidthLimited("\n$ CELL " + topCell.describe(false) + " FROM LIBRARY " + topCell.getLibrary().getName() + "\n"); emitCopyright("$ ", ""); if (User.isIncludeDateAndVersionInOutput()) { writeWidthLimited("$ CELL CREATED ON " + TextUtils.formatDate(topCell.getCreationDate()) + "\n"); writeWidthLimited("$ VERSION " + topCell.getVersion() + "\n"); writeWidthLimited("$ LAST REVISED " + TextUtils.formatDate(topCell.getRevisionDate()) + "\n"); writeWidthLimited("$ SILOS netlist written by Electric VLSI Design System, version " + Version.getVersion() + "\n"); writeWidthLimited("$ WRITTEN ON " + TextUtils.formatDate(new Date()) + "\n"); } else { writeWidthLimited("$ SILOS netlist written by Electric VLSI Design System\n"); } // First look for any global sources for(Iterator<NodeInst> it = topCell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (ni.isCellInstance()) continue; // only real sources PrimitiveNode.Function nodetype = ni.getFunction(); if (nodetype != PrimitiveNode.Function.SOURCE) continue; Variable var = ni.getVar(SILOS_GLOBAL_NAME_KEY); String name = ""; if (var != null) // is this a global source ? { name = var.getObject().toString(); writeWidthLimited(".GLOBAL " + convertSpecialNames(name) + "\n"); } // Get the source type var = ni.getVar(Spice.SPICE_MODEL_KEY); if (var == null) { System.out.println("Unspecified source:"); writeWidthLimited("$$$$$ Unspecified source: \n"); } else // There is more { boolean clktype = false; // Extra data required if variable there String msg = var.getObject().toString(); String line = ""; char lastChr = 0; for(int i=0; i<msg.length(); i++) { lastChr = msg.charAt(i); if (lastChr == '/') break; switch (lastChr) { case 'g': // a global clock (THIS IS WRONG!!!) line = name + " .CLK "; clktype = true; break; case 'h': // a fixed high source (THIS IS WRONG!!!) line = name + " .CLK 0 S1 $ HIGH LEVEL"; break; case 'l': // a fixed low source (THIS IS WRONG!!!) line = name + " .CLK 0 S0 $ LOW LEVEL"; break; } } if (lastChr == '/' && clktype) line += msg.substring(msg.indexOf('/')+1); writeWidthLimited(line + "\n"); } } } protected void done() { } /** * Method to write cellGeom */ protected void writeCellTopology(Cell cell, CellNetInfo cni, VarContext context, Topology.MyCellInfo info) { // Read a behavior file if it is available for(Iterator<Cell> it = cell.getCellGroup().getCells(); it.hasNext(); ) { Cell oCell = it.next(); Variable var = oCell.getVar(SILOS_BEHAVIOR_FILE_KEY); if (var != null) { String headerPath = TextUtils.getFilePath(cell.getLibrary().getLibFile()); String fileName = headerPath + var.getObject().toString(); File test = new File(fileName); if (!test.exists()) { System.out.println("Cannot find SILOS behavior file " + fileName + " on " + cell); } else { try { FileReader fr = new FileReader(test); BufferedReader br = new BufferedReader(fr); for(;;) { String line = br.readLine(); if (line == null) break; writeWidthLimited(line + "\n"); } br.close(); fr.close(); } catch (IOException e) {} return; } } } /* * There was no behavior file... * Get the SILOS model from the library if it exists */ for(Iterator<Cell> it = cell.getCellGroup().getCells(); it.hasNext(); ) { Cell oCell = it.next(); Variable var = oCell.getVar(SILOS_MODEL_KEY); if (var != null && var.getObject() instanceof String[]) { String [] model = (String [])var.getObject(); for(int i = 0; i < model.length; i++) writeWidthLimited(model[i] + "\n"); writeWidthLimited("\n"); return; } } // gather networks in the cell Netlist netList = cni.getNetList(); // write the module header if (cell != topCell) { writeWidthLimited("\n"); String name = cni.getParameterizedName(); if (name.length() > MAXNAME) { System.out.print(".MACRO name " + name + " is too long;"); name = name.substring(0, MAXNAME); System.out.println(" truncated to " + name); } writeWidthLimited(".MACRO " + convertName(name)); for(Iterator<CellAggregateSignal> it = cni.getCellAggregateSignals(); it.hasNext(); ) { CellAggregateSignal cas = it.next(); if (cas.getExport() == null) continue; if (cas.isSupply()) continue; writeWidthLimited(" " + convertSubscripts(cas.getNameWithIndices())); } writeWidthLimited("\n"); } else writeWidthLimited("\n"); // write the cell instances for(Iterator<Nodable> nIt = netList.getNodables(); nIt.hasNext(); ) { Nodable no = nIt.next(); if (no.isCellInstance()) { String nodeName = parameterizedName(no, context); CellNetInfo subCni = getCellNetInfo(nodeName); writeWidthLimited("(" + no.getName() + " " + convertName(nodeName)); for(Iterator<CellAggregateSignal> sIt = subCni.getCellAggregateSignals(); sIt.hasNext(); ) { CellAggregateSignal cas = sIt.next(); if (cas.isSupply()) continue; // ignore networks that aren't exported PortProto pp = cas.getExport(); if (pp == null) continue; int low = cas.getLowIndex(), high = cas.getHighIndex(); if (low > high) { // single signal Network net = netList.getNetwork(no, pp, cas.getExportIndex()); CellSignal cs = cni.getCellSignal(net); writeWidthLimited(" " + cs.getName()); } else { int total = high - low + 1; CellSignal [] outerSignalList = new CellSignal[total]; for(int j=low; j<=high; j++) { CellSignal cInnerSig = cas.getSignal(j-low); Network net = netList.getNetwork(no, cas.getExport(), cInnerSig.getExportIndex()); outerSignalList[j-low] = cni.getCellSignal(net); } writeBus(outerSignalList, low, high, cas.isDescending(), cas.getName(), cni.getPowerNet(), cni.getGroundNet()); } } writeWidthLimited("\n"); } } // write the primitives for(Iterator<Nodable> nIt = netList.getNodables(); nIt.hasNext(); ) { Nodable no = nIt.next(); // not interested in passive nodes (ports electrically connected) if (!no.isCellInstance()) { NodeInst ni = (NodeInst)no; PrimitiveNode.Function nodeType = getPrimitiveType(ni); if (nodeType == PrimitiveNode.Function.UNKNOWN) continue; if (nodeType.isFET()) { // Transistors need a part number writeWidthLimited(getNodeInstName(ni)); writeWidthLimited(" "); writeWidthLimited(getPrimitiveName(ni, false)); // write the names of the port(s) for(Iterator<PortProto> pIt = ni.getProto().getPorts(); pIt.hasNext(); ) { PortProto pp = pIt.next(); writeWidthLimited(getPortProtoName(cell == topCell, null, ni, pp, cell, netList, cni)); } writeWidthLimited("\n"); continue; } if (nodeType.isFlipFlop()) { // flip-flops need a part number writeWidthLimited(getNodeInstName(ni)); writeWidthLimited(" "); writeWidthLimited(getPrimitiveName(ni, false)); // write the names of the port(s) writeFlipFlop(cell == topCell, ni, cell, nodeType, netList, cni); continue; } if (nodeType == PrimitiveNode.Function.METER || nodeType == PrimitiveNode.Function.SOURCE) { if (cell != topCell) System.out.println("WARNING: Global Clock in a sub-cell"); continue; } if (nodeType == PrimitiveNode.Function.GATEAND || nodeType == PrimitiveNode.Function.GATEOR || nodeType == PrimitiveNode.Function.GATEXOR || nodeType == PrimitiveNode.Function.BUFFER) { // Gates use their output port as a name PortProto outPP = null; for(Iterator<PortProto> pIt = ni.getProto().getPorts(); pIt.hasNext(); ) { PortProto pp = pIt.next(); if (pp.getCharacteristic() == PortCharacteristic.OUT) { // find the name of the output port writeWidthLimited(getPortProtoName(cell == topCell, null, ni, pp, cell, netList, cni)); // record that we used it outPP = pp; // determine if this proto is negated Connection con = null; for(Iterator<Connection> aIt = ni.getConnections(); aIt.hasNext(); ) { Connection c = aIt.next(); if (c.getPortInst().getPortProto() == pp) { con = c; break; } } boolean negated = false; if (con != null && con.isNegated()) negated = true; writeWidthLimited(" " + getPrimitiveName(ni, negated)); break; } } if (outPP == null) System.out.println("Could not find an output connection on " + ni.getProto().getName()); // get the fall and rise times writeWidthLimited(getRiseTime(ni)); writeWidthLimited(getFallTime(ni)); // write the rest of the ports only if they're connected for(Iterator<Connection> aIt = ni.getConnections(); aIt.hasNext(); ) { Connection con = aIt.next(); PortProto pp = con.getPortInst().getPortProto(); if (pp == outPP) continue; writeWidthLimited(getPortProtoName(cell == topCell, con, ni, pp, cell, netList, cni)); } writeWidthLimited("\n"); continue; } if (nodeType == PrimitiveNode.Function.CAPAC) { // find a connected port for the node name for(Iterator<Connection> aIt = ni.getConnections(); aIt.hasNext(); ) { Connection con = aIt.next(); // write port name as output PortProto pp = con.getPortInst().getPortProto(); writeWidthLimited(getPortProtoName(cell == topCell, null, ni, pp, cell, netList, cni)); writeWidthLimited(" " + getPrimitiveName(ni, false)); double j = getCapacitanceInMicroFarads(ni, context); if (j >= 0) { writeWidthLimited(" " + TextUtils.formatDouble(j, 0)); } else { System.out.println("Warning: capacitor with no value on " + ni); } writeWidthLimited("\n"); break; } continue; } if (nodeType == PrimitiveNode.Function.RESIST) { // sorry! can't handle the resistive gate yet continue; } } } if (cell != topCell) writeWidthLimited(".EOM\n"); } /** * Method to add a bus of signals named "name" to the infinite string "infstr". If "name" is zero, * do not include the ".NAME()" wrapper. The signals are in "outerSignalList" and range in index from * "lowindex" to "highindex". They are described by a bus with characteristic "tempval" * (low bit is on if the bus descends). Any unconnected networks can be numbered starting at * "*unconnectednet". The power and grounds nets are "pwrnet" and "gndnet". */ private void writeBus(CellSignal [] outerSignalList, int lowIndex, int highIndex, boolean descending, String name, Network pwrNet, Network gndNet) { // presume writing the bus as a whole boolean breakBus = false; // see if all of the nets on this bus are distinct int j = lowIndex+1; for( ; j<=highIndex; j++) { CellSignal cs = outerSignalList[j-lowIndex]; int k = lowIndex; for( ; k<j; k++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -