📄 topology.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Topology.java * Input/output tool: superclass for output modules that write connectivity. * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2003 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.HierarchyEnumerator;import com.sun.electric.database.hierarchy.Nodable;import com.sun.electric.database.hierarchy.View;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.network.NetworkTool;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.topology.ArcInst;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.ArcProto;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.PrimitivePort;import com.sun.electric.technology.Technology;import com.sun.electric.technology.technologies.Generic;import com.sun.electric.tool.generator.sclibrary.SCLibraryGen;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;/** * This is the Simulation Interface tool. */public abstract class Topology extends Output{ private static final boolean DEBUGTOPOLOGY = false; /** top-level cell being processed */ protected Cell topCell; /** Map of all CellTopologies */ private Map<String,CellNetInfo> cellTopos; /** Map of all Cell names */ private Map<Cell,String> cellNameMap; private HierarchyEnumerator.CellInfo lastInfo; /** Creates a new instance of Topology */ public Topology() {} /** * Write cell to file * @return true on error */ public boolean writeCell(Cell cell, VarContext context) { writeCell(cell, context, new Visitor(this)); return false; } /** * Write cell to file * @return true on error */ public boolean writeCell(Cell cell, VarContext context, Visitor visitor) { // remember the top-level cell topCell = cell; // clear the map of CellNetInfo for each processed cell cellTopos = new HashMap<String,CellNetInfo>(); // make a map of cell names to use (unique across libraries) cellNameMap = makeCellNameMap(topCell); // write out cells start(); HierarchyEnumerator.enumerateCell(cell, context, visitor, getShortResistors()); done(); return false; } /** Abstract method called before hierarchy traversal */ protected abstract void start(); /** Abstract method called after traversal */ protected abstract void done(); /** Called at the end of the enter cell phase of hierarchy enumeration */ protected void enterCell(HierarchyEnumerator.CellInfo info) { } /** Abstract method to write CellGeom to disk */ protected abstract void writeCellTopology(Cell cell, CellNetInfo cni, VarContext context, Topology.MyCellInfo info); /** Abstract method to convert a network name to one that is safe for this format */ protected abstract String getSafeNetName(String name, boolean bus); /** Abstract method to convert a cell name to one that is safe for this format */ protected abstract String getSafeCellName(String name); /** Abstract method to return the proper name of Power (or null to use existing name) */ protected abstract String getPowerName(Network net); /** Abstract method to return the proper name of Ground (or null to use existing name) */ protected abstract String getGroundName(Network net); /** Abstract method to return the proper name of a Global signal */ protected abstract String getGlobalName(Global glob); /** * Abstract method to decide whether export names take precedence over * arc names when determining the name of the network. */ protected abstract boolean isNetworksUseExportedNames(); /** Abstract method to decide whether library names are always prepended to cell names. */ protected abstract boolean isLibraryNameAlwaysAddedToCellName(); /** Abstract method to decide whether aggregate names (busses) are used. */ protected abstract boolean isAggregateNamesSupported(); /** Abstract method to decide whether aggregate names (busses) can have gaps in their ranges. */ protected abstract boolean isAggregateNameGapsSupported(); /** Method to decide whether to choose best export name among exports connected to signal. */ protected boolean isChooseBestExportName() { return true; } /** Abstract method to decide whether aggregate names (busses) are used. */ protected abstract boolean isSeparateInputAndOutput(); /** Abstract method to decide whether netlister is case-sensitive (Verilog) or not (Spice). */ protected abstract boolean isCaseSensitive(); /** * If the netlister has requirments not to netlist certain cells and their * subcells, override this method. */ protected boolean skipCellAndSubcells(Cell cell) { return false; } /** * If a cell is skipped, this method can perform any checking to * validate that no error occurs */ protected void validateSkippedCell(HierarchyEnumerator.CellInfo info) { } /** * Method to tell whether the topological analysis should mangle cell names that are parameterized. */ protected boolean canParameterizeNames() { return false; } /** Tell the Hierarchy enumerator how to short resistors */ protected Netlist.ShortResistors getShortResistors() { return Netlist.ShortResistors.NO; } /** Tell the Hierarchy enumerator whether or not to short parasitic resistors */ protected boolean isShortResistors() { return getShortResistors() != Netlist.ShortResistors.NO; } /** Tell the Hierarchy enumerator whether or not to short explicit (poly) resistors */ protected boolean isShortExplicitResistors() { return getShortResistors() == Netlist.ShortResistors.ALL; } /** * Method to tell set a limit on the number of characters in a name. * @return the limit to name size (0 if no limit). */ protected int maxNameLength() { return 0; } /** Abstract method to convert a cell name to one that is safe for this format */ protected CellNetInfo getCellNetInfo(String cellName) { CellNetInfo cni = cellTopos.get(cellName); return cni; } /** Used to switch from schematic enumeration to layout enumeration */ protected boolean enumerateLayoutView(Cell cell) { return false; } //------------------ override for HierarchyEnumerator.Visitor ---------------------- public class MyCellInfo extends HierarchyEnumerator.CellInfo { String currentInstanceParametizedName; } public class Visitor extends HierarchyEnumerator.Visitor { /** Topology object this Visitor is enumerating for */ private Topology outGeom; public Visitor(Topology outGeom) { this.outGeom = outGeom; } public boolean enterCell(HierarchyEnumerator.CellInfo info) { if (skipCellAndSubcells(info.getCell())) { if (!info.isRootCell()) { // save subcell topology, even though the cell isn't being written HierarchyEnumerator.CellInfo parentInfo = info.getParentInfo(); Nodable no = info.getParentInst(); String parameterizedName = parameterizedName(no, parentInfo.getContext()); CellNetInfo cni = getNetworkInformation(info.getCell(), false, parameterizedName, isNetworksUseExportedNames(), info); cellTopos.put(parameterizedName, cni); } validateSkippedCell(info); return false; } outGeom.enterCell(info); return true; } public void exitCell(HierarchyEnumerator.CellInfo info) { // write cell Cell cell = info.getCell(); CellNetInfo cni = null; if (info.isRootCell()) { cni = getNetworkInformation(cell, false, getSafeCellName(cell.getName()), isNetworksUseExportedNames(), info); cellTopos.put(cell.getName(), cni); } else { // derived parameterized name of instance of this cell in parent HierarchyEnumerator.CellInfo parentInfo = info.getParentInfo(); Nodable no = info.getParentInst(); String parameterizedName = parameterizedName(no, parentInfo.getContext()); cni = getNetworkInformation(info.getCell(), false, parameterizedName, isNetworksUseExportedNames(), info); cellTopos.put(parameterizedName, cni); } outGeom.writeCellTopology(cell, cni, info.getContext(), (MyCellInfo)info); lastInfo = info; } public boolean visitNodeInst(Nodable no, HierarchyEnumerator.CellInfo info) { if (!no.isCellInstance()) return false; VarContext context = info.getContext(); String parameterizedName = parameterizedName(no, context); if (cellTopos.containsKey(parameterizedName)) return false; // already processed this Cell Cell cell = (Cell)no.getProto(); Cell schcell = cell.contentsView(); if (schcell == null) schcell = cell; if (cell.isSchematic() && enumerateLayoutView(schcell)) { Cell layCell = null; for (Iterator<Cell> it = cell.getCellGroup().getCells(); it.hasNext(); ) { Cell c = it.next(); if (c.getView() == View.LAYOUT) { layCell = c; break; } } if (layCell != null) { HierarchyEnumerator.enumerateCell(layCell, context, this); // save subcell topology, even though the cell isn't being written CellNetInfo cni = getNetworkInformation(layCell, false, layCell.getName(), isNetworksUseExportedNames(), lastInfo); cellTopos.put(parameterizedName, cni); return false; } } // else just a cell return true; } public HierarchyEnumerator.CellInfo newCellInfo() { return new MyCellInfo(); } } //---------------------------- Utility Methods -------------------------------------- /** * Class to describe a single signal in a Cell. */ protected static class CellSignal { /** name to use for this network. */ private String name; /** Network for this signal. */ private Network net; /** CellAggregate that this is part of. */ private CellAggregateSignal aggregateSignal; /** export that this is part of. */ private Export pp; /** if export is bussed, index of signal */ private int ppIndex; /** true if part of a descending bus */ private boolean descending; /** true if a power signal */ private boolean power; /** true if a ground signal */ private boolean ground; /** true if from a global signal */ private Global globalSignal; protected String getName() { return name; } protected Network getNetwork() { return net; } protected Export getExport() { return pp; } protected int getExportIndex() { return ppIndex; } protected CellAggregateSignal getAggregateSignal() { return aggregateSignal; } protected boolean isDescending() { return descending; } protected boolean isGlobal() { return globalSignal != null; } protected Global getGlobal() { return globalSignal; } protected boolean isPower() { return power; } protected boolean isGround() { return ground; } protected boolean isExported() { return pp != null; } } /** * Class to describe an aggregate signal (a bus) in a Cell. * The difference between aggregate signals and busses is that aggregate signals * are more sensitive to variations. For example, a bus may be X[1,2,4,5] but * there may be two aggregate signals describing it because of the noncontinuity * of the indices (thus, the aggregate signals will be X[1:2] and X_1[4:5]). * Some netlisters allow for gaps, in which case they will be described with a * single aggregate signal. Other factors that cause busses to be broken into * multiple aggregate signals are: * (1) differences in port direction (mixes of input and output, for example) * (2) differences in port type (power, ground, global, etc.) */ protected static class CellAggregateSignal { private String name; private Export pp; private int ppIndex; private int low; private int high; private int[] indices; private boolean supply; private boolean descending; private CellSignal [] signals; /** scratch word for the subclass */ private int flags; protected String getName() { return name; } protected String getNameWithIndices() { if (low > high) return name; if (indices != null) { StringBuffer sb = new StringBuffer(); sb.append(name); sb.append('['); for(int i=0; i<indices.length; i++) { if (i != 0) sb.append(','); sb.append(indices[i]); } sb.append(']'); return sb.toString(); } int lowIndex = low, highIndex = high; if (descending) { lowIndex = high; highIndex = low; } return name + "[" + lowIndex + ":" + highIndex + "]"; } protected int getNumSignals() { return signals.length; } protected CellSignal getSignal(int index) { return signals[index]; } protected boolean isDescending() { return descending; } protected boolean isSupply() { return supply; } protected Export getExport() { return pp; } protected int getExportIndex() { return ppIndex; } protected int [] getIndices() { return indices; } protected int getLowIndex() { return low; } protected int getHighIndex() { return high; } protected int getFlags() { return flags; } protected void setFlags(int flags) { this.flags = flags; } protected boolean isGlobal() { int numGlobal = 0; for(int i=0; i<signals.length; i++) { CellSignal cs = signals[i]; if (cs.isGlobal()) numGlobal++; } if (numGlobal > 0 && numGlobal == signals.length) return true; return false; } } /** * Class to describe the networks in a Cell. * This contains all of the CellSignal and CellAggregateSignal information. */ protected static class CellNetInfo { private Cell cell; private String paramName; private Map<Network,CellSignal> cellSignals; private List<CellSignal> cellSignalsSorted; private List<CellAggregateSignal> cellAggregateSignals; private Network pwrNet; private Network gndNet; private Netlist netList; protected CellSignal getCellSignal(Network net) { return cellSignals.get(net); } protected Iterator<CellSignal> getCellSignals() { return cellSignalsSorted.iterator(); } protected Iterator<CellAggregateSignal> getCellAggregateSignals() { return cellAggregateSignals.iterator(); } protected String getParameterizedName() { return paramName; } protected Network getPowerNet() { return pwrNet; } protected Network getGroundNet() { return gndNet; } protected Netlist getNetList() { return netList; } protected Cell getCell() { return cell; } } private CellNetInfo getNetworkInformation(Cell cell, boolean quiet, String paramName, boolean useExportedName, HierarchyEnumerator.CellInfo info) { CellNetInfo cni = doGetNetworks(cell, quiet, paramName, useExportedName, info); if (DEBUGTOPOLOGY) { printWriter.println("********Decomposition of " + cell); printWriter.println("** Have " + cni.cellSignalsSorted.size() + " signals:"); for(Iterator<CellSignal> it = cni.getCellSignals(); it.hasNext(); ) { CellSignal cs = it.next(); printWriter.println("** Name="+cs.name+" export="+cs.pp+" index="+cs.ppIndex+" descending="+cs.descending+" power="+cs.power+" ground="+cs.ground+" global="+cs.globalSignal);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -