/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: NetCell.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.EquivPorts;
import com.sun.electric.database.Snapshot;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.EDatabase;
import com.sun.electric.database.hierarchy.Export;
import com.sun.electric.database.hierarchy.Nodable;
import com.sun.electric.database.prototype.NodeProto;
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.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.technology.ArcProto;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.PrimitivePort;
import com.sun.electric.technology.technologies.Artwork;
import com.sun.electric.technology.technologies.Generic;
import com.sun.electric.technology.technologies.Schematics;
import com.sun.electric.util.math.GenMath;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* This is the Cell mirror in Network tool.
*/
public class NetCell {
/** Check immutable algorithm which computes equivalent ports */
private static final boolean CHECK_EQUIV_PORTS = true;
/** If bit set, netlist is valid for cell tree.*/
static final int VALID = 1;
/** If bit set, netlist is valid with current equivPorts of subcells.*/
static final int LOCALVALID = 2;
/** Separator for net names of unconnected port instances */
static final char PORT_SEPARATOR = '.';
/** Network manager to which this NetCell belongs. */
final NetworkManager networkManager;
/** Database to which this NetCell belongs. */
final EDatabase database;
/** This NetCell is schematic */
final boolean isSchem;
/** Cell from database. */
final Cell cell;
/** Flags of this NetCell. */
int flags;
/** The number of times this NetCell has been <i>structurally modified</i>.
* Structural modifications are those that change the number of networks in
* its netlists, or otherwise perturb them in such a fashion that iterations in
* progress may yield incorrect results.<p>
*
* This field is used by the netlist implementation returned by the
* <tt>getNetlist</tt> methods. If the value of this field changes unexpectedly,
* the netlist will throw a <tt>ConcurrentModificationException</tt> in
* response to the <tt>getNetwork</tt> and other operations. This provides
* <i>fail-fast</i> behavior, rather than non-deterministic behavior in
* the face of concurrent modification during netlist examination.<p>
*/
// int modCount = 0;
WeakReference<Snapshot> expectedSnapshot; // for Schem netlists
WeakReference<CellTree> expectedCellTree; // for Layout netlisits
/**
* Equivalence of ports.
* equivPorts.size == ports.size.
* equivPorts[i] contains minimal index among ports of its group.
*/
int[] equivPortsN;
int[] equivPortsP;
int[] equivPortsA;
/** Node offsets. */
int[] ni_pi;
/** */
int arcsOffset;
/** */
private int[] headConn;
/** */
private int[] tailConn;
/** */
int[] drawns;
/** */
int numDrawns;
/** */
int numExportedDrawns;
/** */
int numConnectedDrawns;
/** A map from canonic String to NetName. */
HashMap<Name, GenMath.MutableInteger> netNames = new HashMap<Name, GenMath.MutableInteger>();
/** Counter for enumerating NetNames. */
private int netNameCount;
/** Counter for enumerating NetNames. */
int exportedNetNameCount;
/** Netlist for ShortResistors.NO option. */
NetlistImpl netlistN;
/** Netlist for true ShortResistors.PARASITIC option. */
NetlistShorted netlistP;
/** Netlist for true ShortResistors.ALL option. */
NetlistShorted netlistA;
/** */
private static PortProto busPinPort = Schematics.tech().busPinNode.getPort(0);
/** */
private static ArcProto busArc = Schematics.tech().bus_arc;
NetCell(Cell cell) {
// System.out.println("Create NetCell " + cell.libDescribe());
this.database = cell.getDatabase();
this.networkManager = database.getNetworkManager();
this.isSchem = this instanceof NetSchem;
if (isSchem) {
expectedSnapshot = new WeakReference<Snapshot>(null);
} else {
expectedCellTree = new WeakReference<CellTree>(null);
}
this.cell = cell;
}
public static NetCell newInstance(Cell cell) {
return cell.isIcon() || cell.isSchematic() ? new NetSchem(cell) : new NetCell(cell);
}
public Netlist getNetlist(Netlist.ShortResistors shortResistors) {
if (isSchem) {
if (database.backup() != expectedSnapshot.get()) {
((NetSchem) this).updateSchematic();
}
} else {
if (cell.tree() != expectedCellTree.get()) {
updateLayout();
}
}
switch (shortResistors) {
case NO:
return netlistN;
case PARASITIC:
return netlistP;
case ALL:
return netlistA;
default:
throw new AssertionError();
}
}
/**
* Get an iterator over all of the Nodables of this Cell.
*/
Iterator<Nodable> getNodables() {
return cell.getNodables();
}
/**
* Get a set of global signal in this Cell and its descendants.
*/
Global.Set getGlobals() {
return Global.Set.empty;
}
/*
* Get offset in networks map for given global signal.
*/
int getNetMapOffset(Global global) {
return -1;
}
/**
* Get offset in networks map for given global of nodable.
* @param no nodable.
* @param global global signal.
* @return offset in networks map.
*/
int getNetMapOffset(Nodable no, Global global) {
return -1;
}
/**
* Get offset in networks map for given subnetwork of nodable.
* @param no nodable.
* @param equivPortIndex index of entry in equivPortsX
* @return offset in networks map.
*/
int getNetMapOffset(Nodable no, int equivPortIndex) {
NodeInst ni = (NodeInst) no;
return drawns[ni_pi[ni.getNodeIndex()] + equivPortIndex];
}
/*
* Get offset in networks map for given port instance.
*/
int getNetMapOffset(Nodable no, PortProto portProto, int busIndex) {
NodeInst ni = (NodeInst) no;
return drawns[ni_pi[ni.getNodeIndex()] + portProto.getPortIndex()];
}
/*
* Get offset in networks map for given port instance.
*/
int getNetMapOffset(Nodable no, Name portName) {
NodeInst ni = (NodeInst) no;
if (ni.isCellInstance()) {
Cell subCell = (Cell) ni.getProto();
assert !subCell.isIcon() && !subCell.isSchematic();
}
PortProto portProto = ni.getProto().findPortProto(portName);
if (portProto == null) {
return -1;
}
return drawns[ni_pi[ni.getNodeIndex()] + portProto.getPortIndex()];
}
/**
* Method to return the port width of port of the Nodable.
* @return the either the port width.
*/
int getBusWidth(Nodable no, PortProto portProto) {
return 1;
}
/*
* Get offset in networks map for given export..
*/
int getNetMapOffset(Export export, int busIndex) {
return drawns[export.getPortIndex()];
}
/*
* Get offset in networks map for given export name.
*/
int getNetMapOffset(Name exportName) {
Export export = cell.findExport(exportName);
return export != null ? drawns[export.getPortIndex()] : -1;
}
/*
* Get offset in networks map for given arc.
*/
int getNetMapOffset(ArcInst ai, int busIndex) {
return getArcDrawn(ai);
}
/**
* 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.
*/
Name getBusName(ArcInst ai) {
return null;
}
/**
* Method to return the bus width on this ArcInst.
* @return the either the bus width on this ArcInst.
*/
int getBusWidth(ArcInst ai) {
int drawn = getArcDrawn(ai);
if (drawn < 0) {
return 0;
}
return 1;
}
int getArcDrawn(ArcInst ai) {
assert ai.getParent() == cell;
int arcIndex = cell.getMemoization().getArcIndex(ai.getD());
return drawns[arcsOffset + arcIndex];
}
private void initConnections() {
int numPorts = cell.getNumPorts();
int numNodes = cell.getNumNodes();
int numArcs = cell.getNumArcs();
if (ni_pi == null || ni_pi.length != numNodes) {
ni_pi = new int[numNodes];
}
int offset = numPorts;
for (int i = 0; i < numNodes; i++) {
NodeInst ni = cell.getNode(i);
ni_pi[i] = offset;
offset += ni.getProto().getNumPorts();
}
arcsOffset = offset;
offset += numArcs;
if (headConn == null || headConn.length != offset) {
headConn = new int[offset];
tailConn = new int[offset];
drawns = new int[offset];
}
for (int i = numPorts; i < arcsOffset; i++) {
headConn[i] = i;
tailConn[i] = i;
}
for (int i = 0; i < numPorts; i++) {
int portOffset = i;
Export export = cell.getPort(i);
int orig = getPortInstOffset(export.getOriginalPort());
headConn[portOffset] = headConn[orig];
headConn[orig] = portOffset;
tailConn[portOffset] = -1;
}
int arcIndex = 0;
for (Iterator<ArcInst> it = cell.getArcs(); arcIndex < numArcs; arcIndex++) {
ArcInst ai = it.next();
int arcOffset = arcsOffset + arcIndex;
int head = getPortInstOffset(ai.getHeadPortInst());
headConn[arcOffset] = headConn[head];
headConn[head] = arcOffset;
int tail = getPortInstOffset(ai.getTailPortInst());
tailConn[arcOffset] = tailConn[tail];
tailConn[tail] = arcOffset;
}
//showConnections();
}
// private void showConnections() {
// int numNodes = cell.getNumNodes();
// for (int i = 0; i < numNodes; i++) {
// NodeInst ni = cell.getNode(i);
// int numPortInsts = ni.getProto().getNumPorts();
// for (int j = 0; j < numPortInsts; j++) {
// PortInst pi = ni.getPortInst(j);
// System.out.println("Connections of " + pi);
// int piOffset = getPortInstOffset(pi);
// for (int k = piOffset; headConn[k] != piOffset; ) {
// k = headConn[k];
// if (k >= arcsOffset)
// System.out.println("\thead_arc\t" + cell.getArc(k - arcsOffset).describe(true));
// else
// System.out.println("\tport\t" + cell.getPort(k));
// }
// for (int k = piOffset; tailConn[k] != piOffset; ) {
// k = tailConn[k];
// System.out.println("\ttail_arc\t" + cell.getArc(k - arcsOffset).describe(true));
// }
// }
// }
// }
private ArrayList<PortInst> stack;
private void addToDrawn1(PortInst pi) {
int piOffset = getPortInstOffset(pi);
if (drawns[piOffset] >= 0) {
return;
}
PortProto pp = pi.getPortProto();
if (pp instanceof PrimitivePort && ((PrimitivePort) pp).isIsolated()) {
return;
}
drawns[piOffset] = numDrawns;
if (NetworkTool.debug) {
System.out.println(numDrawns + ": " + pi);
}
for (int k = piOffset; headConn[k] != piOffset;) {
k = headConn[k];
if (drawns[k] >= 0) {
continue;
}
if (k < arcsOffset) {
// This is port
drawns[k] = numDrawns;
if (NetworkTool.debug) {
System.out.println(numDrawns + ": " + cell.getPort(k));
}
continue;
}
ArcInst ai = cell.getArc(k - arcsOffset);
ArcProto ap = ai.getProto();
if (ap.getFunction() == ArcProto.Function.NONELEC) {
continue;
}
if (pp == busPinPort && ap != busArc) {
continue;
}
drawns[k] = numDrawns;
if (NetworkTool.debug) {
System.out.println(numDrawns + ": " + ai);
}
PortInst tpi = ai.getTailPortInst();
if (tpi.getPortProto() == busPinPort && ap != busArc) {
continue;
}
stack.add(tpi);
}
for (int k = piOffset; tailConn[k] != piOffset;) {
k = tailConn[k];
if (drawns[k] >= 0) {
continue;
}
ArcInst ai = cell.getArc(k - arcsOffset);
ArcProto ap = ai.getProto();
if (ap.getFunction() == ArcProto.Function.NONELEC) {
continue;
}
if (pp == busPinPort && ap != busArc) {
continue;
}
drawns[k] = numDrawns;
if (NetworkTool.debug) {
System.out.println(numDrawns + ": " + ai);
}
PortInst hpi = ai.getHeadPortInst();
if (hpi.getPortProto() == busPinPort && ap != busArc) {
continue;
}
stack.add(hpi);
}
}
private void addToDrawn(PortInst pi) {
assert stack.isEmpty();
stack.add(pi);
while (!stack.isEmpty()) {
pi = stack.remove(stack.size() - 1);
PortProto pp = pi.getPortProto();
NodeProto np = pp.getParent();
int numPorts = np.getNumPorts();
if (numPorts == 1 || np instanceof Cell) {
addToDrawn1(pi);
continue;
}
NodeInst ni = pi.getNodeInst();
int topology = ((PrimitivePort) pp).getTopology();
for (int i = 0; i < numPorts; i++) {
if (((PrimitivePort) np.getPort(i)).getTopology() != topology) {
continue;
}
addToDrawn1(ni.getPortInst(i));
}
}
}
void makeDrawns() {
initConnections();
Arrays.fill(drawns, -1);
stack = new ArrayList<PortInst>();
numDrawns = 0;
for (int i = 0, numPorts = cell.getNumPorts(); i < numPorts; i++) {
if (drawns[i] >= 0) {
continue;
}
drawns[i] = numDrawns;
Export export = cell.getPort(i);
addToDrawn(export.getOriginalPort());
numDrawns++;
}
numExportedDrawns = numDrawns;
for (int i = 0, numArcs = cell.getNumArcs(); i < numArcs; i++) {
if (drawns[arcsOffset + i] >= 0) {
continue;
}
ArcInst ai = cell.getArc(i);
ArcProto ap = ai.getProto();
if (ap.getFunction() == ArcProto.Function.NONELEC) {
continue;
}
drawns[arcsOffset + i] = numDrawns;
if (NetworkTool.debug) {
System.out.println(numDrawns + ": " + ai);
}
PortInst hpi = ai.getHeadPortInst();
if (hpi.getPortProto() != busPinPort || ap == busArc) {
addToDrawn(hpi);
}
PortInst tpi = ai.getTailPortInst();
if (tpi.getPortProto() != busPinPort || ap == busArc) {
addToDrawn(tpi);
}
numDrawns++;
}
numConnectedDrawns = numDrawns;
for (int i = 0, numNodes = cell.getNumNodes(); i < numNodes; i++) {
NodeInst ni = cell.getNode(i);
NodeProto np = ni.getProto();
if (ni.isIconOfParent()
|| np.getFunction() == PrimitiveNode.Function.ART && np != Generic.tech().simProbeNode
|| np == Artwork.tech().pinNode
|| np == Generic.tech().invisiblePinNode) {
continue;
}
int numPortInsts = np.getNumPorts();
for (int j = 0; j < numPortInsts; j++) {
PortInst pi = ni.getPortInst(j);
int piOffset = getPortInstOffset(pi);
if (drawns[piOffset] >= 0) {
continue;
}
if (pi.getPortProto() instanceof PrimitivePort && ((PrimitivePort) pi.getPortProto()).isIsolated()) {
continue;
}
addToDrawn(pi);
numDrawns++;
}
}
stack = null;
headConn = tailConn = null;
// showDrawns();
// System.out.println(cell + " has " + cell.getNumPorts() + " ports, " + cell.getNumNodes() + " nodes, " +
// cell.getNumArcs() + " arcs, " + (arcsOffset - cell.getNumPorts()) + " portinsts, " + netMap.length + "(" + piDrawns + ") drawns");
}
void showDrawns() {
java.io.PrintWriter out;
String filePath = "tttt";
try {
out = new java.io.PrintWriter(new java.io.BufferedWriter(new java.io.FileWriter(filePath, true)));
} catch (java.io.IOException e) {
System.out.println("Error opening " + filePath);
return;
}
out.println("Drawns " + cell);
int numPorts = cell.getNumPorts();
for (int drawn = 0; drawn < numDrawns; drawn++) {
for (int i = 0; i < drawns.length; i++) {
if (drawns[i] != drawn) {
continue;
}
if (i < numPorts) {
out.println(drawn + ": " + cell.getPort(i));
} else if (i >= arcsOffset) {
out.println(drawn + ": " + cell.getArc(i - arcsOffset));
} else {
int k = 1;
for (; k < cell.getNumNodes() && ni_pi[k] <= i; k++);
k--;
NodeInst ni = cell.getNode(k);
PortInst pi = ni.getPortInst(i - ni_pi[k]);
out.println(drawn + ": " + pi);
}
}
}
out.close();
}
void initNetnames() {
for (GenMath.MutableInteger nn : netNames.values()) {
nn.setValue(-1);
}
netNameCount = 0;
for (Iterator<Export> it = cell.getExports(); it.hasNext();) {
Export e = it.next();
addNetNames(e.getNameKey(), e, null);
}
exportedNetNameCount = netNameCount;
for (Iterator<ArcInst> it = cell.getArcs(); it.hasNext();) {
ArcInst ai = it.next();
if (ai.getProto().getFunction() == ArcProto.Function.NONELEC) {
continue;
}
if (ai.getNameKey().isBus() && ai.getProto() != busArc) {
String msg = "Network: " + cell + " has bus name <" + ai.getNameKey() + "> on arc that is not a bus";
System.out.println(msg);
networkManager.pushHighlight(ai);
networkManager.logError(msg, NetworkTool.errorSortNetworks);
}
if (ai.isUsernamed()) {
addNetNames(ai.getNameKey(), null, ai);
}
}
for (Iterator<Map.Entry<Name, GenMath.MutableInteger>> it = netNames.entrySet().iterator(); it.hasNext();) {
Map.Entry<Name, GenMath.MutableInteger> e = it.next();
Name name = e.getKey();
int index = e.getValue().intValue();
if (index < 0) {
it.remove();
} else if (NetworkTool.debug) {
System.out.println("NetName " + name + " " + index);
}
}
assert netNameCount == netNames.size();
}
void addNetNames(Name name, Export e, ArcInst ai) {
if (name.isBus()) {
System.out.println("Network: Layout " + cell + " has bus port/arc " + name);
}
addNetName(name, e, ai);
}
void addNetName(Name name, Export e, ArcInst ai) {
GenMath.MutableInteger nn = netNames.get(name);
if (nn == null) {
nn = new GenMath.MutableInteger(-1);
netNames.put(name, nn);
}
if (nn.intValue() < 0) {
nn.setValue(netNameCount++);
}
}
private void internalConnections(int[] netMapF, int[] netMapP, int[] netMapA) {
for (Iterator<NodeInst> it = cell.getNodes(); it.hasNext();) {
NodeInst ni = it.next();
int nodeOffset = ni_pi[ni.getNodeIndex()];
if (!ni.isCellInstance()) {
PrimitiveNode.Function fun = ni.getFunction();
if (fun == PrimitiveNode.Function.RESIST) {
Netlist.connectMap(netMapP, drawns[nodeOffset], drawns[nodeOffset + 1]);
Netlist.connectMap(netMapA, drawns[nodeOffset], drawns[nodeOffset + 1]);
} else if (fun.isComplexResistor()) {
Netlist.connectMap(netMapA, drawns[nodeOffset], drawns[nodeOffset + 1]);
}
continue;
}
Cell subCell = (Cell) ni.getProto();
if (subCell.isIcon() || subCell.isSchematic()) {
continue;
}
EquivPorts eq = subCell.treeUnsafe().getEquivPorts();
int[] eqN = eq.getEquivPortsN();
int[] eqP = eq.getEquivPortsP();
int[] eqA = eq.getEquivPortsA();
for (int i = 0; i < eqN.length; i++) {
if (eqN[i] != i) {
Netlist.connectMap(netMapF, drawns[nodeOffset + i], drawns[nodeOffset + eqN[i]]);
}
if (eqP[i] != i) {
Netlist.connectMap(netMapP, drawns[nodeOffset + i], drawns[nodeOffset + eqP[i]]);
}
if (eqA[i] != i) {
Netlist.connectMap(netMapA, drawns[nodeOffset + i], drawns[nodeOffset + eqA[i]]);
}
}
}
}
final int getPortInstOffset(PortInst pi) {
return ni_pi[pi.getNodeInst().getNodeIndex()] + pi.getPortProto().getPortIndex();
}
// int getPortOffset(int portIndex, int busIndex) {
// return busIndex == 0 ? portIndex : -1;
// }
NetSchem getSchem() {
return null;
}
private void buildNetworkList(int[] netMapN) {
netlistN = new NetlistImpl(this, numExportedDrawns, netMapN);
int[] netNameToNetIndex = new int[netNames.size()];
Arrays.fill(netNameToNetIndex, -1);
int numPorts = cell.getNumPorts();
for (int i = 0; i < numPorts; i++) {
Export e = cell.getPort(i);
int drawn = drawns[i];
setNetName(netNameToNetIndex, drawn, e.getNameKey(), true);
netlistN.setEquivPortIndexByNetIndex(i, netlistN.getNetIndex(e, 0));
}
int numArcs = cell.getNumArcs(), arcIndex = 0;
for (Iterator<ArcInst> it = cell.getArcs(); arcIndex < numArcs; arcIndex++) {
ArcInst ai = it.next();
if (!ai.isUsernamed()) {
continue;
}
int drawn = drawns[arcsOffset + arcIndex];
if (drawn < 0) {
continue;
}
setNetName(netNameToNetIndex, drawn, ai.getNameKey(), false);
}
arcIndex = 0;
for (Iterator<ArcInst> it = cell.getArcs(); arcIndex < numArcs; arcIndex++) {
ArcInst ai = it.next();
int drawn = drawns[arcsOffset + arcIndex];
if (drawn < 0) {
continue;
}
int netIndexN = netlistN.getNetIndexByMap(drawn);
if (netlistN.hasNames(netIndexN)) {
continue;
}
netlistN.addTempName(netIndexN, ai.getName());
}
for (int i = 0; i < cell.getNumNodes(); i++) {
NodeInst ni = cell.getNode(i);
for (int j = 0; j < ni.getProto().getNumPorts(); j++) {
int drawn = drawns[ni_pi[i] + j];
if (drawn < 0) {
continue;
}
int netIndexN = netlistN.getNetIndexByMap(drawn);
if (netlistN.hasNames(netIndexN)) {
continue;
}
netlistN.addTempName(netIndexN, ni.getName() + PORT_SEPARATOR + ni.getProto().getPort(j).getName());
}
}
// check names and equivPortIndexByNetIndex map
for (int i = 0, numNetworks = netlistN.getNumNetworks(); i < numNetworks; i++) {
assert netlistN.hasNames(i);
assert netlistN.isExported(i) == (i < netlistN.getNumExternalNetworks());
if (netlistN.isExported(i)) {
int equivPortIndex = netlistN.getEquivPortIndexByNetIndex(i);
assert equivPortIndex >= 0 && equivPortIndex < numPorts;
}
}
/*
// debug info
System.out.println("BuildNetworkList "+this);
int i = 0;
for (Iterator<Network> nit = getNetworks(); nit.hasNext(); )
{
Network network = nit.next();
String s = "";
for (Iterator<String> sit = network.getNames(); sit.hasNext(); )
{
String n = sit.next();
s += "/"+ n;
}
for (Iterator<PortInst> pit = network.getPorts(); pit.hasNext(); )
{
PortInst pi = pit.next();
s += "|"+pi.getNodeInst().getProto()+"&"+pi.getPortProto().getName();
}
System.out.println(" "+i+" "+s);
i++;
}
*/
}
private void setNetName(int[] netNamesToNetIndex, int drawn, Name name, boolean exported) {
int netIndexN = netlistN.getNetIndexByMap(drawn);
assert netIndexN >= 0;
GenMath.MutableInteger nn = netNames.get(name);
if (netNamesToNetIndex[nn.intValue()] >= 0) {
if (netNamesToNetIndex[nn.intValue()] == netIndexN) {
return;
}
String msg = "Network: Layout " + cell + " has nets with same name " + name;
System.out.println(msg);
// because this should be an infrequent event that the user will fix, let's
// put all the work here
for (int i = 0, numPorts = cell.getNumPorts(); i < numPorts; i++) {
Export e = cell.getPort(i);
if (e.getName().equals(name.toString())) {
networkManager.pushHighlight(cell.getPort(i));
}
}
for (Iterator<ArcInst> it = cell.getArcs(); it.hasNext();) {
ArcInst ai = it.next();
if (!ai.isUsernamed()) {
continue;
}
if (ai.getName().equals(name.toString())) {
networkManager.pushHighlight(ai);
}
}
networkManager.logError(msg, NetworkTool.errorSortNetworks);
} else {
netNamesToNetIndex[nn.intValue()] = netIndexN;
}
netlistN.addUserName(netIndexN, name, exported);
}
/**
* Update map of equivalent ports newEquivPort.
*/
private boolean updateInterface() {
boolean changed = false;
int numPorts = cell.getNumPorts();
if (equivPortsN == null || equivPortsN.length != numPorts) {
changed = true;
equivPortsN = new int[numPorts];
equivPortsP = new int[numPorts];
equivPortsA = new int[numPorts];
}
int[] netToPortN = new int[numPorts];
int[] netToPortP = new int[numPorts];
int[] netToPortA = new int[numPorts];
Arrays.fill(netToPortN, -1);
Arrays.fill(netToPortP, -1);
Arrays.fill(netToPortA, -1);
for (int i = 0; i < numPorts; i++) {
int netN = netlistN.netMap[drawns[i]];
if (netToPortN[netN] < 0) {
netToPortN[netN] = i;
}
if (equivPortsN[i] != netToPortN[netN]) {
changed = true;
equivPortsN[i] = netToPortN[netN];
}
int netP = netlistP.netMap[drawns[i]];
if (netToPortP[netP] < 0) {
netToPortP[netP] = i;
}
if (equivPortsP[i] != netToPortP[netP]) {
changed = true;
equivPortsP[i] = netToPortP[netP];
}
int netA = netlistA.netMap[drawns[i]];
if (netToPortA[netA] < 0) {
netToPortA[netA] = i;
}
if (equivPortsA[i] != netToPortA[netA]) {
changed = true;
equivPortsA[i] = netToPortA[netA];
}
}
if (CHECK_EQUIV_PORTS) {
EquivPorts equivPorts = cell.tree().getEquivPorts();
assert Arrays.equals(equivPortsN, equivPorts.getEquivPortsN());
assert Arrays.equals(equivPortsP, equivPorts.getEquivPortsP());
assert Arrays.equals(equivPortsA, equivPorts.getEquivPortsA());
}
return changed;
}
// /**
// * Show map of equivalent ports newEquivPort.
// */
// private void showEquivPorts()
// {
// System.out.println("Equivalent ports of "+cell);
// String s = "\t";
// Export[] ports = new Export[cell.getNumPorts()];
// int i = 0;
// for (Iterator<Export> it = cell.getExports(); it.hasNext(); i++)
// ports[i] = it.next();
// for (i = 0; i < equivPorts.length; i++)
// {
// Export pi = ports[i];
// if (equivPorts[i] != i) continue;
// boolean found = false;
// for (int j = i+1; j < equivPorts.length; j++)
// {
// if (equivPorts[i] != equivPorts[j]) continue;
// Export pj = ports[j];
// if (!found) s = s+" ( "+pi.getName();
// found = true;
// s = s+" "+pj.getName();
// }
// if (found)
// s = s+")";
// else
// s = s+" "+pi.getName();
// }
// System.out.println(s);
// }
private void updateLayout() {
synchronized (networkManager) {
CellTree oldCellTree = expectedCellTree.get();
CellTree newCellTree = cell.tree();
if (oldCellTree == newCellTree) {
return;
}
if (oldCellTree == null || !newCellTree.sameNetlist(oldCellTree)) {
// clear errors for cell
networkManager.startErrorLogging(cell);
try {
makeDrawns();
// Gather port and arc names
initNetnames();
redoNetworks1();
} finally {
networkManager.finishErrorLogging();
}
}
expectedCellTree = new WeakReference<CellTree>(newCellTree);
}
}
boolean redoNetworks1() {
/* Set index of NodeInsts */
// HashMap/*<Cell,Netlist>*/ subNetlists = new HashMap/*<Cell,Netlist>*/();
// for (Iterator<Nodable> it = getNodables(); it.hasNext(); ) {
// Nodable no = it.next();
// if (!no.isCellInstance()) continue;
// Cell subCell = (Cell)no.getProto();
// subNetlists.put(subCell, networkManager.getNetlist(subCell, false));
// }
int[] netMapN = Netlist.initMap(numDrawns);
int[] netMapP = netMapN.clone();
int[] netMapA = netMapN.clone();
internalConnections(netMapN, netMapP, netMapA);
buildNetworkList(netMapN);
netlistP = new NetlistShorted(netlistN, Netlist.ShortResistors.PARASITIC, netMapP);
netlistA = new NetlistShorted(netlistN, Netlist.ShortResistors.ALL, netMapA);
return updateInterface();
}
/**
* Update netlists to current CellTree
* Check if specified Netlist is no more fresh
* @param netlist
* @return true specified Netlist is no more fresh
*/
boolean obsolete(Netlist netlist) {
Netlist newNetlist = getNetlist(netlist.shortResistors);
netlistN.expectedCellTree = netlistP.expectedCellTree = netlistA.expectedCellTree = expectedCellTree;
return newNetlist != netlist;
}
}