/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: NetlistImpl.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.CellTree;
import com.sun.electric.database.Snapshot;
import com.sun.electric.database.text.ArrayIterator;
import com.sun.electric.database.text.Name;
import com.sun.electric.database.text.TextUtils;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
/**
*
* @author dn146861
*/
public class NetlistImpl extends Netlist {
private static final String[] NULL_STRING_ARRAY = {};
/**
* Arrays of names for each net.
* First names are exported names in STRING_NUMBER_ORDER,
* Then internal user-defined names in STRING_NUMBER_ORDER.
* If this net has no exported or user-defined names, then this
* list contains one of temporary names.
* Hence the first name in the list are most appropriate.
**/
private String[][] names;
/** Nets which have has user-defiend names */
private BitSet isUsernamed = new BitSet();
/** Number of export names for each net */
private int[] exportedNamesCount;
private int[] equivPortIndexByNetIndex;
NetlistImpl(NetCell netCell, int numExternals, int[] map) {
super(netCell, Netlist.ShortResistors.NO, numExternals, map);
if (netCell instanceof NetSchem) {
expectedSnapshot = new WeakReference<Snapshot>(netCell.database.backup());
} else {
expectedCellTree = new WeakReference<CellTree>(netCell.cell.tree());
}
exportedNamesCount = new int[numExternalNets];
equivPortIndexByNetIndex = new int[numExternalNets];
Arrays.fill(equivPortIndexByNetIndex, -1);
names = new String[getNumNetworks()][];
Arrays.fill(names, NULL_STRING_ARRAY);
}
void setEquivPortIndexByNetIndex(int equivIndex, int netIndex) {
equivPortIndexByNetIndex[netIndex] = equivIndex;
}
@Override
Iterator<String> getNames(int netIndex) {
return ArrayIterator.iterator(names[netIndex]);
}
@Override
Iterator<String> getExportedNames(int netIndex) {
int exportedNamesCount = netIndex < numExternalNets ? this.exportedNamesCount[netIndex] : 0;
return ArrayIterator.iterator(names[netIndex], 0, exportedNamesCount);
}
@Override
String getName(int netIndex) {
return names[netIndex][0];
}
@Override
boolean hasName(int netIndex, String nm) {
String[] theseNames = names[netIndex];
for (int i = 0; i < theseNames.length; i++) {
if (theseNames[i].equals(nm)) {
return true;
}
}
return false;
}
@Override
void fillNames(int netIndex, Collection<String> exportedNames, Collection<String> privateNames) {
if (!isUsernamed(netIndex)) {
return;
}
String[] names = this.names[netIndex];
int exportedNamesCount = netIndex < numExternalNets ? this.exportedNamesCount[netIndex] : 0;
for (int i = 0; i < exportedNamesCount; i++) {
exportedNames.add(names[i]);
}
if (privateNames != null) {
for (int i = exportedNamesCount; i < names.length; i++) {
privateNames.add(names[i]);
}
}
}
@Override
boolean isUsernamed(int netIndex) {
return isUsernamed.get(netIndex);
}
boolean hasNames(int netIndex) {
return names[netIndex].length > 0;
}
@Override
int getEquivPortIndexByNetIndex(int netIndex) {
return equivPortIndexByNetIndex[netIndex];
}
/**
* Add user name to list of names of this Network.
* @param netIndex index of Network
* @param nameKey name key to add.
* @param exported true if name is exported.
*/
void addUserName(int netIndex, Name nameKey, boolean exported) {
assert !nameKey.isTempname();
String name = nameKey.toString();
String[] theseNames = names[netIndex];
int exportedCount = netIndex < numExternalNets ? exportedNamesCount[netIndex] : 0;
if (exported) {
assert exportedCount == theseNames.length;
}
int i = 0;
for (; i < theseNames.length; i++) {
String n = names[netIndex][i];
int cmp = TextUtils.STRING_NUMBER_ORDER.compare(name, n);
if (cmp == 0) {
return;
}
if (cmp < 0 && (exported || i >= exportedCount)) {
break;
}
}
if (theseNames.length == 0) {
names[netIndex] = new String[]{name};
} else {
String[] newNames = new String[theseNames.length + 1];
System.arraycopy(theseNames, 0, newNames, 0, i);
newNames[i] = name;
System.arraycopy(theseNames, i, newNames, i + 1, theseNames.length - i);
names[netIndex] = newNames;
}
if (exported) {
exportedNamesCount[netIndex]++;
}
isUsernamed.set(netIndex);
}
void addTempName(int netIndex, String name) {
assert names[netIndex].length == 0;
names[netIndex] = new String[]{name};
}
}