/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Netlist.java
* Written by: Dmitry Nadezhin, Sun Microsystems.
*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
*
* 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.database.network;
import com.sun.electric.database.CellTree;
import com.sun.electric.database.Snapshot;
import com.sun.electric.database.hierarchy.Export;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.Nodable;
import com.sun.electric.database.prototype.PortProto;
import com.sun.electric.database.text.Name;
import com.sun.electric.database.topology.ArcInst;
import com.sun.electric.database.topology.IconNodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.user.ActivityLogger;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* This is the Netlist class. It contains information about electric
* networks of a cell for a given set of options. Networks are 0-based
* indices. First positions occupies indices of networks connected to
* global signals, then networks connected to exports, and then local
* networks.
*/
public abstract class Netlist {
/** Enumaration defines mode of short resistors in Netlist. */
public enum ShortResistors {
/** No resistors are shortened */
NO,
/** Resistors are shortened except poly resistors */
PARASITIC,
/** All resistors are shortened */
ALL
};
// -------------------------- private data ---------------------------------
/** NetCell which owns this Netlist. */
final NetCell netCell;
final ShortResistors shortResistors;
// HashMap/*<Cell,Netlist>*/ subNetlists;
/**
* The modCount value that the netlist believes that the backing
* netCell should have. If this expectation is violated, the netlist
* has detected concurrent modification.
*/
WeakReference<Snapshot> expectedSnapshot; // for Schem netlists
WeakReference<CellTree> expectedCellTree; // for Layout netlisits
// int expectedModCount;
/** An equivalence map of PortInsts and NetNames. */
final int[] netMap;
final int[] nm_net;
/** An array of Networks in this Cell. */
private Network[] networks;
int numExternalEntries;
int numExternalNets;
// ---------------------- package methods -----------------
/**
* The constructor of Netlist object..
*/
Netlist(NetCell netCell, ShortResistors shortResistors, int numExternals, int[] map) {
this.netCell = netCell;
this.shortResistors = shortResistors;
// this.subNetlists = subNetlists;
// expectedModCount = netCell.modCount;
netMap = map;
nm_net = new int[netMap.length];
closureMap(netMap);
int k = 0;
for (int i = 0; i < netMap.length; i++) {
if (netMap[i] == i) {
k++;
}
}
networks = new Network[k];
numExternalEntries = numExternals;
k = 0;
for (int i = 0; i < netMap.length; i++) {
if (netMap[i] == i) {
nm_net[i] = k;
k++;
if (i < numExternals) {
numExternalNets++;
}
} else {
nm_net[i] = nm_net[netMap[i]];
}
}
}
/**
* Init equivalence map.
* @param size numeber of elements in equivalence map
* @return integer array representing equivalence map consisting of disjoint elements.
*/
static int[] initMap(int size) {
int[] map = new int[size];
for (int i = 0; i < map.length; i++) {
map[i] = i;
}
return map;
}
/**
* Merge classes of equivalence map to which elements a1 and a2 belong.
*/
static void connectMap(int[] map, int a1, int a2) {
int m1, m2, m;
for (m1 = a1; map[m1] != m1; m1 = map[m1]);
for (m2 = a2; map[m2] != m2; m2 = map[m2]);
m = m1 < m2 ? m1 : m2;
for (;;) {
int k = map[a1];
map[a1] = m;
if (a1 == k) {
break;
}
a1 = k;
}
for (;;) {
int k = map[a2];
map[a2] = m;
if (a2 == k) {
break;
}
a2 = k;
}
}
/**
* Obtain canonical representation of equivalence map.
*/
static void closureMap(int[] map) {
for (int i = 0; i < map.length; i++) {
map[i] = map[map[i]];
}
}
/**
* Obtain canonical representation of equivalence map.
*/
// private static boolean equalMaps(int[] map1, int[] map2)
// {
// if (map1.length != map2.length) return false;
// for (int i = 0; i < map1.length; i++)
// {
// if (map1[i] != map2[i]) return false;
// }
// return true;
// }
/** A cell of this netlist. */
public Cell getCell() {
return netCell.cell;
}
/** A net can have multiple names. Return alphabetized list of names. */
abstract Iterator<String> getNames(int netIndex);
/** A net can have multiple names. Return alphabetized list of names. */
abstract Iterator<String> getExportedNames(int netIndex);
/**
* Returns most appropriate name of the net.
* Intitialized net has at least one name - user-defiend or temporary.
*/
abstract String getName(int netIndex);
/** Returns true if nm is one of Network's names */
abstract boolean hasName(int netIndex, String nm);
/**
* Add names of this net to two Collections. One for exported, and other for unexported names.
* @param exportedNames Collection for exported names.
* @param privateNames Collection for unexported names.
*/
abstract void fillNames(int netIndex, Collection<String> exportedNames, Collection<String> privateNames);
/**
* Method to tell whether this network has any exports or globals on it.
* @return true if there are exports or globals on this Network.
*/
boolean isExported(int netIndex) {
return netIndex < numExternalNets;
}
/**
* Method to tell whether this network has user-defined name.
* @return true if this Network has user-defined name.
*/
abstract boolean isUsernamed(int netIndex);
int getNetIndexByMap(int mapOffset) {
return nm_net[mapOffset];
}
abstract int getEquivPortIndexByNetIndex(int netIndex);
private final void checkForModification() {
if (expectedCellTree != null) {
if (netCell.cell.tree() != expectedCellTree.get() && netCell.obsolete(this)) {
throw new ConcurrentModificationException();
}
} else {
if (netCell.database.backup() != expectedSnapshot.get() && netCell.obsolete(this)) {
throw new ConcurrentModificationException();
}
}
netCell.database.checkExamine();
}
// ---------------------- public methods -----------------
// JKG: trying this out
/**
* Returns Nodable for given NodeInst and array index.
* The Nodable is NodeInst itself for primitives and layout subcells.
* The Nodable is a proxy nodable for icon instances.
* @param ni node instance
* @param arrayIndex array index for arrayed icons or zero.
* @return Nodable for given NodeInst and array index.
*/
public static Nodable getNodableFor(NodeInst ni, int arrayIndex) {
Cell parent = ni.getParent();
if (ni instanceof IconNodeInst) {
if (ni.isIconOfParent() || arrayIndex < 0 || arrayIndex >= ni.getNameKey().busWidth()) {
return null;
}
return ((IconNodeInst) ni).getNodable(arrayIndex);
} else {
return ni;
}
}
/**
* Get an iterator over all of the Nodables of this Cell.
* <p> Warning: before getNodables() is called, Networks must be
* build by calling Cell.rebuildNetworks()
*/
public Iterator<Nodable> getNodables() {
checkForModification();
return netCell.getNodables();
}
/**
* Returns subnetlist for a given Nodable.
* @param no Nadable in this Netlist
* @return subnetlist for a given Nidable.
*/
public Netlist getNetlist(Nodable no) {
if (!no.isCellInstance()) {
return null;
}
return ((Cell) no.getProto()).getNetlist(shortResistors);
// return subNetlists.get(no.getProto());
}
/**
* Returns set of global signals in this Netlist.
* @return set of global signals in this Netlist.
*/
public Global.Set getGlobals() {
checkForModification();
return netCell.getGlobals();
}
/**
* Returns number of drawn networks in this Netlist.
* Drawn networks are computed from this Cell only.
* They doesn't consider buses or shortcuts in subcells.
* @return set of number of drawn networks in this Netlist.
*/
public int getNumDrawns() {
return netCell.numDrawns;
}
/**
* Get number of networks in this Netlist.
* @return number of networks in this Netlist.
*/
public int getNumNetworks() {
checkForModification();
return networks.length;
}
/**
* Get number of networks in this Netlist, which are
* connected to exports or globals.
* @return number of external networks in this Netlist.
*/
public int getNumExternalNetworks() {
checkForModification();
return numExternalNets;
}
/**
* Get Network with specified index.
* @param netIndex index of Network
* @return Network with specified index.
*/
public Network getNetwork(int netIndex) {
checkForModification();
return getNetworkRaw(netIndex);
}
/**
* Get Network with specified index.
* If Network was not allocated yet, allocate it.
* @param netIndex index of Network
* @return Network with specified index.
*/
private Network getNetworkRaw(int netIndex) {
if (netIndex < 0) {
return null;
}
Network network = networks[netIndex];
if (network != null) {
return network;
}
network = new Network(this, netIndex);
// Check if concurrent thread allocated this network also
// This code is not properly synchronized !!!!!!
if (networks[netIndex] != null) {
return networks[netIndex];
}
networks[netIndex] = network;
return network;
}
/**
* Get an iterator over all of the Networks of this Netlist.
*/
public Iterator<Network> getNetworks() {
checkForModification();
for (int netIndex = 0; netIndex < networks.length; netIndex++) {
if (networks[netIndex] == null) {
getNetworkRaw(netIndex);
}
}
return Arrays.asList(networks).iterator();
}
/**
* Get net index of a global signal.
* @param global global signal.
* @return net index of a gloabal signal.
*/
int getNetIndex(Global global) {
checkForModification();
int netMapIndex = netCell.getNetMapOffset(global);
if (netMapIndex < 0) {
return -1;
}
return nm_net[netMapIndex];
}
/**
* Get net index of a global signal of nodable.
* @param no nodable.
* @param global global signal.
* @return net index of a global signal of nodable.
*/
int getNetIndex(Nodable no, Global global) {
checkForModification();
int netMapIndex = netCell.getNetMapOffset(no, global);
if (netMapIndex < 0) {
return -1;
}
return nm_net[netMapIndex];
}
/**
* Get net index of signal connected to specified external network of nodable.
* Nodable must be subcell
* @param no nodable (subcell)
* @param subNetwork a network
* @return network.
*/
int getNetIndex(Nodable no, Network subNetwork) {
checkForModification();
Netlist subNetlist = subNetwork.getNetlist();
assert subNetlist.shortResistors == shortResistors;
if (no.getParent() == netCell.cell && subNetlist.getCell() == no.getProto() && subNetwork.isExported()) {
int equivPortIndex = subNetlist.getEquivPortIndexByNetIndex(subNetwork.getNetIndex());
assert equivPortIndex >= 0 && equivPortIndex < subNetlist.netCell.equivPortsN.length;
int netMapIndex = netCell.getNetMapOffset(no, equivPortIndex);
if (netMapIndex >= 0) {
return nm_net[netMapIndex];
}
}
return -1;
}
/**
* Get net index of signal in a port instance of nodable.
* @param no nodable
* @param portProto port of nodable
* @param busIndex index of signal in a bus or zero.
* @return net index
*/
int getNetIndex(Nodable no, PortProto portProto, int busIndex) {
checkForModification();
// if (no instanceof IconNodeInst) {
// Nodable no1 = ((IconNodeInst)no).getNodable(0);
// if (Job.getDebug()) {
// System.out.println("IconNodeInst " + no + " is passed to getNodeIndex. Replaced by IconNodeable " + no1);
// }
// if (no1.getProto() != no.getProto()) {
// portProto = ((Export)portProto).getEquivalent();
// if (portProto == null) {
// return -1;
// }
// }
// no = no1;
// }
if (no.getParent() != netCell.cell) {
return -1;
}
if (portProto.getParent() != no.getProto()) {
System.out.println("Netlist.getNetwork: invalid argument portProto");
return -1;
}
if (busIndex < 0 || busIndex >= netCell.getBusWidth(no, portProto)) {
// System.out.println("Nodable.getNetwork: invalid arguments busIndex="+busIndex+" portProto="+portProto);
return -1;
}
int netMapIndex = netCell.getNetMapOffset(no, portProto, busIndex);
if (netMapIndex < 0) {
return -1;
}
return nm_net[netMapIndex];
}
/**
* Get net index of signal in a port instance of nodable.
* @param no nodable
* @param portName scalar port name
* @return net index
*/
int getNetIndex(Nodable no, Name portName) {
checkForModification();
if (no.getParent() != netCell.cell) {
return -1;
}
if (portName.isBus()) {
throw new IllegalArgumentException("Scalar export name expected");
}
int netMapIndex = netCell.getNetMapOffset(no, portName);
if (netMapIndex < 0) {
return -1;
}
return nm_net[netMapIndex];
}
/**
* Get net index of signal in export.
* @param export given Export.
* @param busIndex index of signal in a bus or zero.
* @return net index.
*/
int getNetIndex(Export export, int busIndex) {
checkForModification();
if (export.getParent() != netCell.cell) {
return -1;
}
if (busIndex < 0 || busIndex >= export.getNameKey().busWidth()) {
System.out.println("Nodable.getNetwork: invalid arguments busIndex=" + busIndex + " export=" + export);
return -1;
}
int netMapIndex = netCell.getNetMapOffset(export, busIndex);
int netIndex = netMapIndex >= 0 ? nm_net[netMapIndex] : -1;
if (Job.getDebug()) {
Name exportName = export.getNameKey().subname(busIndex);
if (netIndex != getNetIndex(exportName)) {
String msg = "Export Name network mismatch in Cell " + netCell.cell.libDescribe()
+ ": getNetIndex(" + export + "," + busIndex + ")=" + netIndex
+ " getNetIndex(" + exportName + ")" + "=" + getNetIndex(exportName);
System.out.println(msg);
ActivityLogger.logException(new AssertionError(msg));
}
}
return netIndex;
}
/**
* Get net index of signal in export name.
* @param exportName given Export name.
* @return net index.
*/
int getNetIndex(Name exportName) {
checkForModification();
if (exportName.isBus()) {
throw new IllegalArgumentException("Scalar export name expected");
}
int netMapIndex = netCell.getNetMapOffset(exportName);
if (netMapIndex < 0) {
return -1;
}
return nm_net[netMapIndex];
}
/**
* Get net index of signal on arc.
* @param ai arc instance
* @param busIndex index of signal in a bus or zero.
* @return net index.
*/
int getNetIndex(ArcInst ai, int busIndex) {
checkForModification();
if (ai.getParent() != netCell.cell) {
return -1;
}
int netMapIndex = netCell.getNetMapOffset(ai, busIndex);
if (netMapIndex < 0) {
return -1;
}
return nm_net[netMapIndex];
}
/**
* Get network of a global signal.
* @param global global signal.
* @return net index of a gloabal signal.
*/
public Network getNetwork(Global global) {
return getNetworkRaw(getNetIndex(global));
}
/**
* Get network of a global signal of nodable.
* @param no nodable.
* @param global global signal.
* @return net index of a gloabal signal of nodable.
*/
public Network getNetwork(Nodable no, Global global) {
return getNetworkRaw(getNetIndex(no, global));
}
/**
* Get network of signal connected to specified external network of nodable.
* Nodable must be subcell
* @param no nodable (subcell)
* @param subNetwork a network
* @return network.
* @throws IllegalArgumentException if nodable is not subcell
*/
public Network getNetwork(Nodable no, Network subNetwork) {
return getNetworkRaw(getNetIndex(no, subNetwork));
}
/**
* Get network of signal in a port instance of nodable.
* @param no nodable
* @param portProto port of nodable
* @param busIndex index of signal in a bus or zero.
* @return network.
*/
public Network getNetwork(Nodable no, PortProto portProto, int busIndex) {
if (no == null || portProto == null) {
return null;
}
if (no instanceof NodeInst && !((NodeInst) no).isLinked()) {
return null;
}
if (portProto instanceof Export && !((Export) portProto).isLinked()) {
return null;
}
return getNetworkRaw(getNetIndex(no, portProto, busIndex));
}
/**
* Get network of signal in a port instance of nodable.
* @param no nodable
* @param portName given port name.
* @return network.
*/
public Network getNetwork(Nodable no, Name portName) {
if (no == null || portName == null) {
return null;
}
if (no instanceof NodeInst && !((NodeInst) no).isLinked()) {
return null;
}
return getNetworkRaw(getNetIndex(no, portName));
}
/**
* Method to tell whether two PortProtos are electrically connected.
* @param no the Nodable on which the PortProtos reside.
* @param port1 the first PortProto.
* @param port2 the second PortProto.
* @return true if the two PortProtos are electrically connected.
*/
public boolean portsConnected(Nodable no, PortProto port1, PortProto port2) {
if (no == null || port1 == null || port2 == null) {
return false;
}
if (no instanceof NodeInst && !((NodeInst) no).isLinked()) {
return false;
}
if (port1 instanceof Export && !((Export) port1).isLinked()) {
return false;
}
if (port2 instanceof Export && !((Export) port2).isLinked()) {
return false;
}
int busWidth = netCell.getBusWidth(no, port1);
if (netCell.getBusWidth(no, port2) != busWidth) {
return false;
}
for (int i = 0; i < busWidth; i++) {
if (getNetIndex(no, port1, i) != getNetIndex(no, port2, i)) {
return false;
}
}
return true;
}
/**
* Get network of port instance.
* @param pi port instance.
* @return signal on port index or null.
*/
public Network getNetwork(PortInst pi) {
if (!pi.isLinked()) {
return null;
}
PortProto portProto = pi.getPortProto();
if (portProto.getNameKey().isBus()) {
NodeInst ni = pi.getNodeInst();
System.out.println("Internal error: getNetwork(PortInst) called for bus port on " + ni.describe(false) +
" in cell " + ni.getParent().describe(false));
return null;
}
return getNetwork(pi.getNodeInst(), portProto, 0);
}
/**
* Return a map from Networks to array of their PortInsts.
* Works only for layout cells.
* @return a map from Networks to array of their PortInsts.
* @throws IllegalArgumentException for schematic Netlists
*/
public Map<Network, PortInst[]> getPortInstsByNetwork() {
if (netCell instanceof NetSchem) {
throw new IllegalArgumentException();
}
Cell cell = netCell.cell;
int[] networkCounts = new int[getNumNetworks()];
for (Iterator<NodeInst> nit = cell.getNodes(); nit.hasNext();) {
NodeInst ni = nit.next();
for (Iterator<PortInst> pit = ni.getPortInsts(); pit.hasNext();) {
PortInst pi = pit.next();
Network net = getNetwork(pi);
if (net == null) {
continue;
}
networkCounts[net.getNetIndex()]++;
}
}
LinkedHashMap<Network, PortInst[]> map = new LinkedHashMap<Network, PortInst[]>();
PortInst[][] portInsts = new PortInst[getNumNetworks()][];
for (int netIndex = 0; netIndex < getNumNetworks(); netIndex++) {
map.put(getNetwork(netIndex), portInsts[netIndex] = new PortInst[networkCounts[netIndex]]);
}
Arrays.fill(networkCounts, 0);
for (Iterator<NodeInst> nit = cell.getNodes(); nit.hasNext();) {
NodeInst ni = nit.next();
for (Iterator<PortInst> pit = ni.getPortInsts(); pit.hasNext();) {
PortInst pi = pit.next();
Network net = getNetwork(pi);
if (net == null) {
continue;
}
int netIndex = net.getNetIndex();
portInsts[netIndex][networkCounts[netIndex]++] = pi;
}
}
return map;
}
/**
* Return a map from Networks to array of their ArcInsts.
* Works only for layout cells.
* @return a map from Networks to array of their ArcInsts.
* @throws IllegalArgumentException for schematic Netlists
*/
public Map<Network, ArcInst[]> getArcInstsByNetwork() {
if (netCell instanceof NetSchem) {
throw new IllegalArgumentException();
}
Cell cell = netCell.cell;
int[] networkCounts = new int[getNumNetworks()];
for (Iterator<ArcInst> ait = cell.getArcs(); ait.hasNext();) {
ArcInst ai = ait.next();
Network net = getNetwork(ai, 0);
if (net == null) {
continue;
}
networkCounts[net.getNetIndex()]++;
}
LinkedHashMap<Network, ArcInst[]> map = new LinkedHashMap<Network, ArcInst[]>();
ArcInst[][] arcInsts = new ArcInst[getNumNetworks()][];
for (int netIndex = 0; netIndex < getNumNetworks(); netIndex++) {
int numArcs = networkCounts[netIndex];
ArcInst[] arcs = numArcs > 0 ? new ArcInst[numArcs] : ArcInst.NULL_ARRAY;
map.put(getNetwork(netIndex), arcs);
arcInsts[netIndex] = arcs;
}
Arrays.fill(networkCounts, 0);
for (Iterator<ArcInst> ait = cell.getArcs(); ait.hasNext();) {
ArcInst ai = ait.next();
Network net = getNetwork(ai, 0);
if (net == null) {
continue;
}
int netIndex = net.getNetIndex();
arcInsts[netIndex][networkCounts[netIndex]++] = ai;
}
return map;
}
/**
* Get network of signal in export.
* @param export given Export.
* @param busIndex index of signal in a bus or zero.
* @return network.
*/
public Network getNetwork(Export export, int busIndex) {
if (!export.isLinked()) {
return null;
}
return getNetworkRaw(getNetIndex(export, busIndex));
}
/**
* Get network of signal in export name.
* @param exportName given Export name.
* @return network.
*/
public Network getNetwork(Name exportName) {
return getNetworkRaw(getNetIndex(exportName));
}
/**
* Get network of signal on arc.
* @param ai arc instance
* @param busIndex index of signal in a bus or zero.
* @return network.
*/
public Network getNetwork(ArcInst ai, int busIndex) {
if (!ai.isLinked()) {
return null;
}
return getNetworkRaw(getNetIndex(ai, busIndex));
}
/**
* Method to tell whether two ArcInsts are electrically equivalent.
* This considers individual elements of busses.
* @param ai1 the first ArcInst.
* @param ai2 the second ArcInst.
* @return true if the arcs are electrically connected.
*/
public boolean sameNetwork(ArcInst ai1, ArcInst ai2) {
if (ai1 == null || ai2 == null) {
return false;
}
if (!ai1.isLinked()) {
return false;
}
if (!ai2.isLinked()) {
return false;
}
checkForModification();
int busWidth1 = netCell.getBusWidth(ai1);
int busWidth2 = netCell.getBusWidth(ai2);
if (busWidth1 != busWidth2) {
return false;
}
for (int i = 0; i < busWidth1; i++) {
if (getNetIndex(ai1, i) != getNetIndex(ai2, i)) {
return false;
}
}
return true;
}
/**
* Method to tell whether a PortProto on a Nodable is electrically equivalent to an ArcInst.
* This considers individual elements of busses.
* @param no the Nodable.
* @param pp the PortProto on the Nodable.
* @param ai the ArcInst.
* @return true if they are electrically connected.
*/
public boolean sameNetwork(Nodable no, PortProto pp, ArcInst ai) {
if (no == null || pp == null || ai == null) {
return false;
}
if (no instanceof NodeInst && !((NodeInst) no).isLinked()) {
return false;
}
if (pp instanceof Export && !((Export) pp).isLinked()) {
return false;
}
if (!ai.isLinked()) {
return false;
}
checkForModification();
int busWidth1 = netCell.getBusWidth(no, pp);
int busWidth2 = netCell.getBusWidth(ai);
if (busWidth1 != busWidth2) {
return false;
}
for (int i = 0; i < busWidth1; i++) {
if (getNetIndex(no, pp, i) != getNetIndex(ai, i)) {
return false;
}
}
return true;
}
/**
* Method to tell whether two PortProto / Nodable pairs are electrically equivalent.
* This considers individual elements of busses.
* @param no1 the first Nodable.
* @param pp1 the PortProto on the first Nodable.
* @param no2 the second Nodable.
* @param pp2 the PortProto on the second Nodable.
* @return true if they are electrically connected.
*/
public boolean sameNetwork(Nodable no1, PortProto pp1, Nodable no2, PortProto pp2) {
if (no1 == null || pp1 == null || no2 == null || pp2 == null) {
return false;
}
if (no1 instanceof NodeInst && !((NodeInst) no1).isLinked()) {
return false;
}
if (pp1 instanceof Export && !((Export) pp1).isLinked()) {
return false;
}
if (no2 instanceof NodeInst && !((NodeInst) no2).isLinked()) {
return false;
}
if (pp2 instanceof Export && !((Export) pp2).isLinked()) {
return false;
}
int busWidth1 = netCell.getBusWidth(no1, pp1);
int busWidth2 = netCell.getBusWidth(no2, pp2);
if (busWidth1 != busWidth2) {
return false;
}
for (int i = 0; i < busWidth1; i++) {
if (getNetIndex(no1, pp1, i) != getNetIndex(no2, pp2, i)) {
return false;
}
}
return true;
}
/**
* Method to return either the network name or the bus name on this ArcInst.
* @return the either the network name or the bus name on this ArcInst.
*/
public String getNetworkName(ArcInst ai) {
if (ai == null || !ai.isLinked()) {
return null;
}
checkForModification();
if (ai.getParent() != netCell.cell) {
return null;
}
int busWidth = netCell.getBusWidth(ai);
if (busWidth > 1) {
return netCell.getBusName(ai).toString();
}
Network network = getNetwork(ai, 0);
if (network == null) {
return null;
}
return network.describe(false);
}
/**
* Method to return the name of the bus on this ArcInst.
* @return the name of the bus on this ArcInst.
*/
public Name getBusName(ArcInst ai) {
if (ai == null || !ai.isLinked()) {
return null;
}
checkForModification();
if (ai.getParent() != netCell.cell) {
return null;
}
int busWidth = netCell.getBusWidth(ai);
if (busWidth <= 1) {
return null;
}
return netCell.getBusName(ai);
}
/**
* Method to return the bus width on an Export.
* @param e the Export to examine.
* @return the bus width of the Export.
*/
public int getBusWidth(Export e) {
if (e == null || !e.isLinked()) {
return 0;
}
return e.getNameKey().busWidth();
}
/**
* Method to return the bus width on this ArcInst.
* @return the either the bus width on this ArcInst.
*/
public int getBusWidth(ArcInst ai) {
if (ai == null || !ai.isLinked()) {
return 0;
}
checkForModification();
if (ai.getParent() != netCell.cell) {
return 0;
}
return netCell.getBusWidth(ai);
}
public ShortResistors getShortResistors() {
return shortResistors;
}
/**
* Returns a printable version of this Netlist.
* @return a printable version of this Netlist.
*/
@Override
public String toString() {
return "Netlist of " + netCell.cell;
}
}