/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: NetlistShorted.java
* Written by: Dmitry Nadezhin, 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.database.network;
import com.sun.electric.database.text.ArrayIterator;
import com.sun.electric.database.text.TextUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.TreeSet;
/**
* This class represents Netlist obtained from base Netlist by shortening some Networks.
*/
public class NetlistShorted extends Netlist {
private Netlist baseNetlist;
private int[] thisNetHead;
private int[] baseNetNext;
private BitSet isUsernamed = new BitSet();
private BitSet isExported = new BitSet();
private String[] firstNames;
NetlistShorted(Netlist baseNetlist, Netlist.ShortResistors shortResistors, int[] netMap) {
super(baseNetlist.netCell, shortResistors, baseNetlist.numExternalEntries, netMap);
this.baseNetlist = baseNetlist;
expectedSnapshot = baseNetlist.expectedSnapshot;
expectedCellTree = baseNetlist.expectedCellTree;
assert nm_net.length == baseNetlist.nm_net.length;
int[] baseNetToThisNet = new int[baseNetlist.getNumNetworks()];
Arrays.fill(baseNetToThisNet, -1);
for (int mapOffset = 0; mapOffset < nm_net.length; mapOffset++) {
int baseNetIndex = baseNetlist.nm_net[mapOffset];
int thisNetIndex = nm_net[mapOffset];
if (baseNetToThisNet[baseNetIndex] < 0) {
baseNetToThisNet[baseNetIndex] = thisNetIndex;
} else {
assert baseNetToThisNet[baseNetIndex] == thisNetIndex;
}
}
for (int thisNet : baseNetToThisNet) {
assert thisNet >= 0;
}
thisNetHead = new int[getNumNetworks()];
Arrays.fill(thisNetHead, -1);
baseNetNext = new int[baseNetlist.getNumNetworks()];
Arrays.fill(baseNetNext, -1);
for (int baseNetIndex = baseNetlist.getNumNetworks() - 1; baseNetIndex >= 0; baseNetIndex--) {
int thisNetIndex = baseNetToThisNet[baseNetIndex];
baseNetNext[baseNetIndex] = thisNetHead[thisNetIndex];
thisNetHead[thisNetIndex] = baseNetIndex;
if (baseNetlist.isUsernamed(baseNetIndex)) {
isUsernamed.set(thisNetIndex);
}
}
for (int thisHead : thisNetHead) {
assert thisHead >= 0;
}
firstNames = new String[getNumNetworks()];
for (int thisNetIndex = 0; thisNetIndex < getNumNetworks(); thisNetIndex++) {
makeName(thisNetIndex);
}
}
/**
* Returns most appropriate name of the net.
* Intitialized net has at least one name - user-defiend or temporary.
*/
@Override
String getName(int netIndex) {
String name = firstNames[netIndex];
if (name != null) {
return name;
} else {
return makeName(netIndex);
}
}
private String makeName(int thisNetIndex) {
int baseIndexLimit = isExported(thisNetIndex) ? baseNetlist.getNumExternalNetworks() : baseNetlist.getNumNetworks();
String firstName = null;
if (isUsernamed(thisNetIndex)) {
for (int baseNetIndex = thisNetHead[thisNetIndex]; baseNetIndex >= 0 && baseNetIndex < baseIndexLimit; baseNetIndex = baseNetNext[baseNetIndex]) {
if (!baseNetlist.isUsernamed(baseNetIndex)) {
continue;
}
String name = baseNetlist.getName(baseNetIndex);
if (firstName == null || TextUtils.STRING_NUMBER_ORDER.compare(name, firstName) < 0) {
firstName = name;
}
}
} else {
firstName = baseNetlist.getName(thisNetHead[thisNetIndex]);
}
firstNames[thisNetIndex] = firstName;
return firstName;
}
@Override
Iterator<String> getNames(int netIndex) {
if (isUsernamed(netIndex)) {
TreeSet<String> exportedNames = new TreeSet<String>(TextUtils.STRING_NUMBER_ORDER);
TreeSet<String> privateNames = new TreeSet<String>(TextUtils.STRING_NUMBER_ORDER);
fillNames(netIndex, exportedNames, privateNames);
ArrayList<String> allNames = new ArrayList<String>(exportedNames);
for (String name : privateNames) {
if (exportedNames.contains(name)) {
continue;
}
allNames.add(name);
}
return allNames.iterator();
} else {
return Collections.singleton(getName(netIndex)).iterator();
}
}
@Override
Iterator<String> getExportedNames(int netIndex) {
if (isExported(netIndex)) {
TreeSet<String> exportedNames = new TreeSet<String>(TextUtils.STRING_NUMBER_ORDER);
fillNames(netIndex, exportedNames, null);
return exportedNames.iterator();
} else {
return ArrayIterator.<String>emptyIterator();
}
}
/** Returns true if nm is one of Network's names */
@Override
boolean hasName(int netIndex, String nm) {
if (isUsernamed(netIndex)) {
for (int baseNetIndex = thisNetHead[netIndex]; baseNetIndex >= 0; baseNetIndex = baseNetNext[baseNetIndex]) {
if (baseNetlist.hasName(baseNetIndex, nm)) {
return true;
}
}
return false;
} else {
return nm.equals(getName(netIndex));
}
}
/**
* 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.
*/
@Override
void fillNames(int netIndex, Collection<String> exportedNames, Collection<String> privateNames) {
if (!isUsernamed(netIndex)) {
return;
}
for (int baseNetIndex = thisNetHead[netIndex]; baseNetIndex >= 0; baseNetIndex = baseNetNext[baseNetIndex]) {
baseNetlist.fillNames(baseNetIndex, exportedNames, privateNames);
}
}
/**
* Method to tell whether this network has user-defined name.
* @return true if this Network has user-defined name.
*/
@Override
boolean isUsernamed(int netIndex) {
return isUsernamed.get(netIndex);
}
@Override
int getEquivPortIndexByNetIndex(int netIndex) {
return baseNetlist.getEquivPortIndexByNetIndex(thisNetHead[netIndex]);
}
// void checkNames() {
// TreeSet<String> exportedNames = new TreeSet<String>(TextUtils.STRING_NUMBER_ORDER);
// TreeSet<String> privateNames = new TreeSet<String>(TextUtils.STRING_NUMBER_ORDER);
// for (int thisNetIndex = 0; thisNetIndex < getNumNetworks(); thisNetIndex++) {
// exportedNames.clear();
// privateNames.clear();
// for (int baseNetIndex = thisNetHead[thisNetIndex]; baseNetIndex >= 0; baseNetIndex = baseNetNext[baseNetIndex]) {
// baseNetlist.fillNames(baseNetIndex, exportedNames, privateNames);
// }
// if (exportedNames.size() > 0 || privateNames.size() > 0) {
// assert isUsernamed(thisNetIndex);
// assert getName(thisNetIndex) == (exportedNames.size() > 0 ? exportedNames : privateNames).iterator().next();
// assert isExported(thisNetIndex) == (exportedNames.size() > 0);
// Iterator<String> eIt = getExportedNames(thisNetIndex);
// Iterator<String> pIt = getNames(thisNetIndex);
// for (String name : exportedNames) {
// assert eIt.next().equals(name);
// assert pIt.next().equals(name);
// }
// assert !eIt.hasNext();
// for (String name : privateNames) {
// if (exportedNames.contains(name)) {
// continue;
// }
// String pName = pIt.next();
// if (!pName.equals(name)) {
// int x = 0;
// }
// assert pName.equals(name);
// }
// assert !pIt.hasNext();
// } else {
// assert !isUsernamed(thisNetIndex);
// assert !isExported(thisNetIndex);
// boolean hasTempName = false;
// String tempName = getName(thisNetIndex);
// for (int baseNetIndex = thisNetHead[thisNetIndex]; baseNetIndex >= 0; baseNetIndex = baseNetNext[baseNetIndex]) {
// assert !baseNetlist.isUsernamed(baseNetIndex);
// if (baseNetlist.getName(baseNetIndex).equals(tempName)) {
// hasTempName = true;
// }
// }
// assert hasTempName;
// }
// }
// }
}