/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: MOSSIM.java * Input/output tool: MOSSIM net list generator * 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.Export; 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.topology.ArcInst; 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 java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * This is the netlister for MOSSIM. * * A circuit can be augmented in a number of ways for MOSSIM output: * The variable "SIM_mossim_strength" may be placed on any node or arc. * On transistor nodes, it specifies the strength field to use for that * transistor declaration. On arcs, it specifies the strength field to * use for that network node (only works for internal nodes of a cell). */ public class MOSSIM extends Topology { /** key of Variable holding node or arc strength. */ public static final Variable.Key MOSSIM_STRENGTH_KEY = Variable.newKey("SIM_mossim_strength"); // private MOSSIMPreferences localPrefs; public static class MOSSIMPreferences extends OutputPreferences { public MOSSIMPreferences(boolean factory) { super(factory); } public Output doOutput(Cell cell, VarContext context, String filePath) { MOSSIM out = new MOSSIM(this); if (out.openTextOutputStream(filePath)) return out.finishWrite(); if (out.writeCell(cell, context)) return out.finishWrite(); if (out.closeTextOutputStream()) return out.finishWrite(); System.out.println(filePath + " written"); return out.finishWrite(); } } /** * Creates a new instance of the MOSSIM netlister. */ MOSSIM(MOSSIMPreferences mp) { /* localPrefs = mp; */ } protected void start() {} protected void done() {} /** * Method to write cellGeom */ protected void writeCellTopology(Cell cell, String cellName, CellNetInfo cni, VarContext context, Topology.MyCellInfo info) { if (cell == topCell) { // declare power and ground nodes if this is top cell printWriter.println("| Top-level cell " + cell.describe(false) + " ;"); printWriter.println("i VDD ;"); printWriter.println("i GND ;"); } else { // write ports if this cell is sub-cell printWriter.println("| Cell " + cell.describe(false) + " ;"); printWriter.print("c " + cell.getName()); for(Iterator<CellSignal> it = cni.getCellSignals(); it.hasNext(); ) { CellSignal cs = it.next(); if (cs.isExported()) printWriter.print(" " + cs.getName()); } printWriter.println(" ;"); } // gather strength information Netlist netList = cni.getNetList(); Map<Network,String> strengthMap = new HashMap<Network,String>(); for(Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); ) { ArcInst ai = it.next(); Variable var = ai.getVar(MOSSIM_STRENGTH_KEY); if (var == null) continue; Network net = netList.getNetwork(ai, 0); strengthMap.put(net, var.getPureValue(-1)); } // mark all ports that are equivalent for(Iterator<CellSignal> it = cni.getCellSignals(); it.hasNext(); ) { CellSignal cs = it.next(); if (cs.isPower()) { if (!cs.getName().equalsIgnoreCase("vdd")) printWriter.println("e VDD " + cs.getName() + " ;"); continue; } if (cs.isGround()) { if (!cs.getName().equalsIgnoreCase("gnd")) printWriter.println("e GND " + cs.getName() + " ;"); continue; } if (cs.isExported()) { if (cell == topCell) { Export e = cs.getExport(); if (e.getCharacteristic() == PortCharacteristic.IN) { printWriter.println("i " + cs.getName() + " ;"); } else { printWriter.println("s 1 " + cs.getName() + " ;"); } } } else { String strength = strengthMap.get(cs.getNetwork()); if (strength == null) strength = "1"; printWriter.println("s " + strength + " " + cs.getName()); } } // now write the transistors for(Iterator<Nodable> nIt = netList.getNodables(); nIt.hasNext(); ) { Nodable no = nIt.next(); if (no.isCellInstance()) { // complex node: make instance call String nodeName = parameterizedName(no, context); StringBuffer infstr = new StringBuffer(); infstr.append("h " + nodeName + " " + no.getName()); CellNetInfo subCni = getCellNetInfo(nodeName); for(Iterator<CellSignal> sIt = subCni.getCellSignals(); sIt.hasNext(); ) { CellSignal subCs = sIt.next(); if (!subCs.isExported()) continue; PortProto pp = subCs.getExport(); Network net = netList.getNetwork(no, pp, subCs.getExportIndex()); CellSignal cs = cni.getCellSignal(net); infstr.append(" " + cs.getName()); } infstr.append(" ;"); printWriter.println(infstr.toString()); } else { // handle primitives NodeInst ni = (NodeInst)no; PrimitiveNode.Function type = ni.getFunction(); // if it is a transistor, write the information if (!type.isFET()) continue; // gate is port 0 or 2, source is port 1, drain is port 3 PortInst gate = ni.getTransistorGatePort(); PortInst source = ni.getTransistorSourcePort(); PortInst drain = ni.getTransistorDrainPort(); // write the transistor StringBuffer infstr = new StringBuffer(); if (type.isNTypeTransistor()) infstr.append("n"); else if (type.isPTypeTransistor()) infstr.append("p"); else infstr.append("d"); // write the strength of the transistor Variable var = ni.getVar(MOSSIM_STRENGTH_KEY); if (var != null) { infstr.append(" " + var.getPureValue(-1)); } else { infstr.append(" 2"); } // write the gate/source/drain nodes CellSignal cs = cni.getCellSignal(netList.getNetwork(gate)); if (cs == null) reportError(ni.getParent() + " CANNOT DETERMINE GATE NETWORK ON " + ni); infstr.append(" " + cs.getName()); cs = cni.getCellSignal(netList.getNetwork(source)); if (cs == null) reportError(ni.getParent() + " CANNOT DETERMINE SOURCE NETWORK ON " + ni); infstr.append(" " + cs.getName()); cs = cni.getCellSignal(netList.getNetwork(drain)); if (cs == null) reportError(ni.getParent() + " CANNOT DETERMINE DRAIN NETWORK ON " + ni); infstr.append(" " + cs.getName()); infstr.append(" ; | " + ni.getName() + ";"); printWriter.println(infstr.toString()); } } // finish up printWriter.println("."); } /****************************** SUBCLASSED METHODS FOR THE TOPOLOGY ANALYZER ******************************/ /** * Method to adjust a cell name to be safe for MOSSIM output. * @param name the cell name. * @return the name, adjusted for MOSSIM output. */ protected String getSafeCellName(String name) { return name; } /** Method to return the proper name of Power */ protected String getPowerName(Network net) { return "VDD"; } /** Method to return the proper name of Ground */ protected String getGroundName(Network net) { return "GND"; } /** Method to return the proper name of a Global signal */ protected String getGlobalName(Global glob) { return glob.getName(); } /** Method to report that export names DO take precedence over * arc names when determining the name of the network. */ protected boolean isNetworksUseExportedNames() { return true; } /** Method to report that library names ARE always prepended to cell names. */ protected boolean isLibraryNameAlwaysAddedToCellName() { return false; } /** Method to report that aggregate names (busses) ARE used. */ protected boolean isAggregateNamesSupported() { return false; } /** Abstract method to decide whether aggregate names (busses) can have gaps in their ranges. */ protected boolean isAggregateNameGapsSupported() { return false; } /** Method to report whether input and output names are separated. */ protected boolean isSeparateInputAndOutput() { return true; } /** Abstract method to decide whether netlister is case-sensitive (Verilog) or not (Spice). */ protected boolean isCaseSensitive() { return true; } /** * Method to adjust a network name to be safe for MOSSIM output. */ protected String getSafeNetName(String name, boolean bus) { return name; } /** Tell the Hierarchy enumerator how to short resistors */ @Override protected Netlist.ShortResistors getShortResistors() { return Netlist.ShortResistors.ALL; } /** * Method to tell whether the topological analysis should mangle cell names that are parameterized. */ protected boolean canParameterizeNames() { return true; } }