📄 nccnetlist.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: NccNetlist.java * * Copyright (c) 2003 Sun Microsystems and 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.ncc.netlist;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Set;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.HierarchyEnumerator;import com.sun.electric.database.hierarchy.Nodable;import com.sun.electric.database.hierarchy.HierarchyEnumerator.CellInfo;import com.sun.electric.database.hierarchy.HierarchyEnumerator.NetNameProxy;import com.sun.electric.database.hierarchy.HierarchyEnumerator.NodableNameProxy;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.NodeProto;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.prototype.PortProto;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.Technology;import com.sun.electric.technology.TransistorSize;import com.sun.electric.technology.PrimitiveNode.Function;import com.sun.electric.tool.generator.layout.LayoutLib;import com.sun.electric.tool.ncc.NccGlobals;import com.sun.electric.tool.ncc.basic.NccCellAnnotations;import com.sun.electric.tool.ncc.basic.NccUtils;import com.sun.electric.tool.ncc.basic.TransitiveRelation;import com.sun.electric.tool.ncc.basic.NccCellAnnotations.NamePattern;import com.sun.electric.tool.ncc.netlist.NccNameProxy.PartNameProxy;import com.sun.electric.tool.ncc.netlist.NccNameProxy.WireNameProxy;import com.sun.electric.tool.ncc.processing.HierarchyInfo;import com.sun.electric.tool.ncc.processing.SubcircuitInfo;import com.sun.electric.tool.user.ncc.ExportConflict;import com.sun.electric.tool.user.ncc.NccGuiInfo;import com.sun.electric.tool.user.ncc.UnrecognizedPart;/** * NCC's representation of a netlist. */public class NccNetlist { public final static Netlist.ShortResistors SHORT_RESISTORS = Netlist.ShortResistors.PARASITIC; private final NccGlobals globals; private final Cell rootCell; private final VarContext rootContext; private ArrayList<Wire> wires; private ArrayList<Part> parts; private ArrayList<Port> ports; private boolean exportAssertionFailures; private boolean exportGlobalConflicts; private boolean badTransistorType; private boolean userAbort; // ---------------------------- public methods --------------------------- public NccNetlist(Cell root, VarContext context, HierarchyInfo hierInfo, boolean blackBox, NccGlobals globals) { this.globals = globals; rootCell = root; rootContext = context; try { Visitor v = new Visitor(globals, hierInfo, blackBox, context); HierarchyEnumerator.enumerateCell(root.getNetlist(SHORT_RESISTORS), context, v, true); wires = v.getWireList(); parts = v.getPartList(); ports = v.getPortList(); exportAssertionFailures = v.exportAssertionFailures(); badTransistorType = v.badTransistorType(); } catch (RuntimeException e) { if (e instanceof ExportGlobalConflict) { exportGlobalConflicts = true; } else if (e instanceof UserAbort) { userAbort = true; } else { throw e; } } // if there are net list errors then make net list look empty if (cantBuildNetlist()) { wires = new ArrayList<Wire>(); parts = new ArrayList<Part>(); ports = new ArrayList<Port>(); } } public ArrayList<Wire> getWireArray() {return wires;} public ArrayList<Part> getPartArray() {return parts;} public ArrayList<Port> getPortArray() {return ports;} public boolean cantBuildNetlist() { return exportAssertionFailures || exportGlobalConflicts || badTransistorType; } public boolean userAbort() {return userAbort;} public Cell getRootCell() {return rootCell;} public VarContext getRootContext() {return rootContext;}}class ExportGlobalConflict extends RuntimeException { static final long serialVersionUID = 0;}class UserAbort extends RuntimeException { static final long serialVersionUID = 0;}/** map from netID to NCC Wire */class Wires { private final ArrayList<Wire> wires = new ArrayList<Wire>(); private final String pathPrefix; private void growIfNeeded(int ndx) { while(ndx>wires.size()-1) wires.add(null); } /** Construct a Wire table. The mergedNetIDs argument specifies * sets of net IDs that should point to the same Wire. * @param mergedNetIDs contains sets of net IDs that must be merged * into the same Wire. */ public Wires(TransitiveRelation<Integer> mergedNetIDs, CellInfo info, String pathPrefix) { this.pathPrefix = pathPrefix; for (Iterator<Set<Integer>> it=mergedNetIDs.getSetsOfRelatives(); it.hasNext();) { Set<Integer> relatives = it.next(); Iterator<Integer> ni = relatives.iterator(); if (!ni.hasNext()) continue; int netId = ni.next().intValue(); Wire w = get(netId, info); while (ni.hasNext()) { netId = ni.next().intValue(); growIfNeeded(netId); wires.set(netId, w); } } } public Wire get(int netID, CellInfo info) { growIfNeeded(netID); Wire wire = wires.get(netID); if (wire==null) { NetNameProxy np = info.getUniqueNetNameProxy(netID, "/"); WireNameProxy wireNm = new WireNameProxy(np, pathPrefix); wire = new Wire(wireNm); wires.set(netID, wire); } return wire; } // return non-null entries of wires array // Eliminate duplicated Wires. public ArrayList<Wire> getWireArray() { Set<Wire> wireSet = new HashSet<Wire>(); wireSet.addAll(wires); wireSet.remove(null); ArrayList<Wire> nonNullWires = new ArrayList<Wire>(); nonNullWires.addAll(wireSet); return nonNullWires; }}class NccCellInfo extends CellInfo { private NccGlobals globals; // I'm caching the annotations because otherwise every Cell // instance is going to regenerate annotations for it's parent. private boolean gotAnnotations = false; private NccCellAnnotations annotations; // ----------------------------- public methods --------------------------- public NccCellInfo(NccGlobals globals) {this.globals=globals;} public NccCellAnnotations getAnnotations() { if (!gotAnnotations) annotations = NccCellAnnotations.getAnnotations(getCell()); gotAnnotations = true; return annotations; } // Subtle: Suppose a schematic network has an export on it named "gnd" // and suppose it is also attached to a global signal "gnd". Then we may // create two "Ports" for the network, one for the global and one for the // export. The problem is both these ports have the same name: "gnd". This // violates the invariant that no two Ports may have the same name. I // believe it's better to preserve the invariant by discarding the global // "gnd" if there is already an Export named "gnd". public Iterator<ExportGlobal> getExportsAndGlobals() { HashMap<String,ExportGlobal> nameToExport = new HashMap<String,ExportGlobal>(); // first collect all exports for (Iterator<PortProto> it=getCell().getPorts(); it.hasNext();) { Export e = (Export) it.next(); int[] expNetIDs = getExportNetIDs(e); for (int i=0; i<expNetIDs.length; i++) { String nm = e.getNameKey().subname(i).toString(); ExportGlobal eg = new ExportGlobal(nm, expNetIDs[i], e.getCharacteristic(), getNetlist().getNetwork(e,i), e); nameToExport.put(nm, eg); } } List<ExportGlobal> expGlob = new ArrayList<ExportGlobal>(); expGlob.addAll(nameToExport.values()); // next collect all the globals Global.Set globNets = getNetlist().getGlobals(); for (int i=0; i<globNets.size(); i++) { Global g = globNets.get(i); String nm = g.getName(); Network net = getNetlist().getNetwork(g); int netID = getNetID(net); PortCharacteristic type = globNets.getCharacteristic(g); ExportGlobal eg = nameToExport.get(nm); if (eg!=null) { // Name collision between an export and a global signal. // Discard the global. if (eg.netID!=netID || eg.type!=type) { if (eg.netID!=netID) { globals.prln( " Error! Cell: "+getCell().libDescribe()+ " has both an Export and a global signal "+ "named: "+nm+" but their networks differ"); // GUI ExportConflict.NetworkConflict conf = new ExportConflict.NetworkConflict(getCell(), getContext(), nm, eg.network, net); globals.getNccGuiInfo().addNetworkExportConflict(conf); } if (eg.type!=type) { globals.prln( " Error! Cell: "+getCell().libDescribe()+ " has both an Export and a global signal "+ "named: "+nm+" but their Characteristics differ"); // GUI ExportConflict.CharactConflict conf = new ExportConflict.CharactConflict(getCell(), getContext(), nm, type.getFullName(), eg.type.getFullName(), eg.getExport()); globals.getNccGuiInfo().addCharactExportConflict(conf); } throw new ExportGlobalConflict(); } } else { eg = new ExportGlobal(nm, netID, type, net); expGlob.add(eg); } } return expGlob.iterator(); }}/** Information from either an Export or a Global signal */class ExportGlobal { private final Export export; public final String name; public final int netID; public final PortCharacteristic type; public final Network network; /** For Export * @param export is needed because this ExportGlobal * might be a piece of bussed Export; for example if this ExportGlobal * is foo[1] but is only a part of the Export foo[1:3]. */ public ExportGlobal(String nm, int id, PortCharacteristic ty, Network net, Export export) { this.export=export; name=nm; netID=id; type=ty; network=net; } /** For Global */ public ExportGlobal(String nm, int id, PortCharacteristic ty, Network net) { export=null; name=nm; netID=id; type=ty; network=net; } public boolean isExport() {return export!=null;} public Export getExport() { LayoutLib.error(export==null, "this is a Global, not an Export!"); return export; }}class Visitor extends HierarchyEnumerator.Visitor { // --------------------------- private data ------------------------------- private static final boolean debug = false; private static final Technology SCHEMATIC = Technology.findTechnology("schematic"); private static final Function4PortTo3Port fourToThree = new Function4PortTo3Port(); private final NccGlobals globals; /** If I'm building a netlist from a node that isn't at the top of the * design hierarchy then Part and Wire names all share a common prefix. * This is VERY annoying to the user. Save the path prefix here so I can * remove it whenever I build Parts or Wires. */ private final String pathPrefix; private boolean exportAssertionFailures = false; private boolean badPartType = false; private int depth = 0; /** map from netID to Wire */ private Wires wires; /** all Parts in the net list */ private final ArrayList<Part> parts = new ArrayList<Part>(); /** all ports in the net list */ private final ArrayList<Port> ports = new ArrayList<Port>(); /** treat these Cells as primitives */ private final HierarchyInfo hierarchicalCompareInfo; /** generate only hierarchical comparison information */ private final boolean blackBox; // --------------------------- private methods ---------------------------- private void error(boolean pred, String msg) {globals.error(pred, msg);} private String spaces() { StringBuffer sp = new StringBuffer(); for (int i=0; i<depth; i++) sp.append(" "); return sp.toString(); } private void addMatchingNetIDs(List<Integer> netIDs, NamePattern pattern, NccCellInfo rootInfo) { for (Iterator<ExportGlobal> it=rootInfo.getExportsAndGlobals(); it.hasNext();) { ExportGlobal eg = it.next(); if (pattern.matches(eg.name)) netIDs.add(new Integer(eg.netID)); } } private void doExportsConnAnnot(TransitiveRelation<Integer> mergedNetIDs, List<NamePattern> connected, NccCellInfo rootInfo) { List<Integer> netIDs = new ArrayList<Integer>(); for (NamePattern np : connected) { addMatchingNetIDs(netIDs, np, rootInfo); } for (int i=1; i<netIDs.size(); i++) { mergedNetIDs.theseAreRelated(netIDs.get(0), netIDs.get(i)); } } private void doExportsConnAnnots(TransitiveRelation<Integer> mergedNetIDs, NccCellInfo rootInfo) { NccCellAnnotations ann = rootInfo.getAnnotations(); if (ann==null) return; for (Iterator<List<NamePattern>> it=ann.getExportsConnected(); it.hasNext();) { doExportsConnAnnot(mergedNetIDs, it.next(), rootInfo); } } private void initWires(NccCellInfo rootInfo) { TransitiveRelation<Integer> mergedNetIDs = new TransitiveRelation<Integer>(); doExportsConnAnnots(mergedNetIDs, rootInfo); wires = new Wires(mergedNetIDs, rootInfo, pathPrefix); } private void createPortsFromExports(NccCellInfo rootInfo) { boolean oneNamePerPort = globals.getOptions().oneNamePerPort; HashSet<Port> portSet = new HashSet<Port>(); for (Iterator<ExportGlobal> it=rootInfo.getExportsAndGlobals(); it.hasNext();) { ExportGlobal eg = it.next(); Wire wire = wires.get(eg.netID, rootInfo); portSet.add(wire.addExport(eg.name, eg.type, oneNamePerPort)); } for (Port p : portSet) ports.add(p); } /** Get the Wire that's attached to port pi. The Nodable must be an * instance of a PrimitiveNode. * @return the attached Wire. */ private Wire getWireForPortInst(PortInst pi, CellInfo info) { NodeInst ni = pi.getNodeInst(); error(ni.isCellInstance(), "not PrimitiveNode"); PortProto pp = pi.getPortProto(); int[] netIDs = info.getPortNetIDs(ni, pp); error(netIDs.length!=1, "Primitive Port connected to bus?"); return wires.get(netIDs[0], info); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -