/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Global.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.prototype.PortCharacteristic;
import com.sun.electric.database.text.Name;
import com.sun.electric.util.TextUtils;
import java.util.Arrays;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* A Global define global signal in a network tool.
*/
public class Global {
/** the name key */
private Name name;
/** the 0-based index of this Global. */
private int index;
/** All Globals. */
private static Global[] allGlobals = new Global[0];
/** Map String -> Global. */
private static Map<String, Global> globalsByName = new HashMap<String, Global>();
/** Map canonic String -> Global. */
private static Map<String, Global> globalsByCanonicName = new HashMap<String, Global>();
/** global signal ground. */
public static final Global ground = newGlobal("gnd");
/** global signal power. */
public static final Global power = newGlobal("vdd");
/**
* Constructs Global signal with given name key.
* @param name name key
*/
private Global(Name name) {
this.name = name;
index = allGlobals.length;
Global[] newGlobals = new Global[index + 1];
for (int i = 0; i < index; i++) {
newGlobals[i] = allGlobals[i];
}
newGlobals[index] = this;
allGlobals = newGlobals;
globalsByName.put(name.toString(), this);
String canonicString = TextUtils.canonicString(name.toString());
if (globalsByCanonicName.containsKey(canonicString)) {
System.out.println("!!! " + globalsByCanonicName.get(canonicString) + " and " + this + " are not connected now !!!");
}
globalsByCanonicName.put(canonicString, this);
}
/**
* Returns name of this Global signal.
* @return name of this Global signal.
*/
public String getName() {
return name.toString();
}
/**
* Returns name key of this Global signal.
* @return name key of this Global signal.
*/
public Name getNameKey() {
return name;
}
/**
* Returns a printable version of this Global.
* @return a printable version of this Global.
*/
public String toString() {
return "Global " + name;
}
/**
* Finds or creates global signal with given name.
* @param name name
* @return Global signal with given name.
*/
public static Global newGlobal(String name) {
Name nameKey = Name.findName(name);
Global g = globalsByName.get(nameKey.toString());
// Global g = globalsByName.get(nameKey.canonicString());
if (g == null) {
g = new Global(nameKey);
}
return g;
}
/**
* A Global.Set defines a set of Global signals.
*/
public static class Set implements Comparable<Set> {
/** bitmap which defines set. */
private PortCharacteristic[] elemMap;
/** map localInd->globalInd. */
private Global[] elems;
/** map globalInd->localInd. */
private int[] indexOf;
/** Map Set->Set of all Global.Sets. */
private static Map<Set, Set> allSets = new TreeMap<Set, Set>();
/** A private set for search in allSets. */
private static Global.Set fakeSet = new Global.Set(new PortCharacteristic[0]);
/** A private set for search in allSets. */
public static final Global.Set empty = newSet(new PortCharacteristic[0]);
/**
* Constructs Global.Set with specified bitmap of Globals.
* @param elemMap bitmap which specifies which elemenst are in set.
*/
private Set(PortCharacteristic[] elemMap) {
int maxElem = -1;
int numElem = 0;
for (int i = 0; i < elemMap.length; i++) {
if (elemMap[i] == null) {
continue;
}
maxElem = i;
numElem++;
}
this.elemMap = new PortCharacteristic[maxElem + 1];
elems = new Global[numElem];
indexOf = new int[maxElem + 1];
Arrays.fill(indexOf, -1);
// List elemList = new ArrayList(numElem);
int local = 0;
for (int i = 0; i < elemMap.length; i++) {
if (elemMap[i] == null) {
continue;
}
this.elemMap[i] = elemMap[i];
elems[local] = allGlobals[i];
indexOf[i] = local;
local++;
}
}
/**
* Returns <tt>true</tt> if this Global.Set contains a specified Global.
* @param global The Global whose presence in this set is to be tested
* @return <tt>true</tt> if this Global Set contains a specified Global.
*/
public final boolean contains(Global global) {
return global.index < elemMap.length && elemMap[global.index] != null;
}
/**
* Returns characteristic of a specified Global in a set.
* Returns null if a specified Global not in a set..
* @param global The Global whose presence in this set is to be tested
* @return Characteristic of specified Global or null.
*/
public PortCharacteristic getCharacteristic(Global global) {
return global.index < elemMap.length ? elemMap[global.index] : null;
}
/**
* Returns the number of Globals in this Global.Set.
* @return the number of Globals in this Global.Set.
*/
public final int size() {
return elems.length;
}
/**
* Returns a Global from this set by specified index.
* @param i specified index of global.
* @return a Global from this set by specified index.
*/
public final Global get(int i) {
return elems[i];
}
/**
* Returns an index of specified Global in this set.
* Returns -1 if Global is not in set.
* @param g specified global.
* @return a Global from this set by specified index.
*/
public final int indexOf(Global g) {
return g.index < indexOf.length ? indexOf[g.index] : -1;
}
/**
* Returns the maximal index of Globals in this Set.
* @return the maximal index of Globals in this Set or (-1) for empty Set.
*/
public final int maxElement() {
return elemMap.length - 1;
}
/**
* Compares this Global.Set with the specified Global.Set for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.<p>
* @param set the Global.Set to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*/
public int compareTo(Global.Set set) {
int minLen = Math.min(this.elemMap.length, set.elemMap.length);
int i;
for (i = 0; i < minLen; i++) {
if (this.elemMap[i] != set.elemMap[i]) {
break;
}
}
if (i < minLen) {
if (this.elemMap[i] == null) {
return -1;
}
if (set.elemMap[i] == null) {
return 1;
}
return this.elemMap[i].getOrder() - set.elemMap[i].getOrder();
}
for (; i < this.elemMap.length; i++) {
if (this.elemMap[i] != null) {
return 1;
}
}
for (; i < set.elemMap.length; i++) {
if (set.elemMap[i] != null) {
return -1;
}
}
return 0;
}
/**
* Compares this Global.set with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.<p>
* @param o the Object to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*
* @throws ClassCastException if the specified object's type prevents it
* from being compared to this Object.
*/
//4*/ public int compareTo(Object o)
//4*/ {
//4*/ return compareTo((Global.Set)o);
//4*/ }
/**
* Returns a printable version of this GlobalSet.
* @return a printable version of this GlobalSet.
*/
public String toString() {
String s = "Global.Set {";
// for (int i = 0; i < size(); i++) {
// Global g = elems[i];
// s += " " + g + ":" + elemMap[g.index].getName();
// }
for (int i = 0; i < elemMap.length; i++) {
if (elemMap[i] == null) {
continue;
}
s += " " + allGlobals[i] + ":" + elemMap[i].getName();
}
s += "}";
return s;
}
/**
* Returns this Set with removed all globals given by the iterator.
* @param gs iterator with globals
* @return Set with removed globals.
*/
public Global.Set remove(Iterator<Global> gs) {
Buf buf = new Buf(this);
for (; gs.hasNext();) {
Global g = gs.next();
if (g.index < buf.buf.length) {
buf.buf[g.index] = null;
}
}
return buf.getBuf();
}
/**
* Finds or creates Global.Set with specified bitmap of Globals.
* @param elemMap bitmap which specifies which elemenst are in set.
* @return set of specified Globals.
*/
private static Global.Set newSet(PortCharacteristic[] elemMap) {
fakeSet.elemMap = elemMap;
Global.Set set = allSets.get(fakeSet);
fakeSet.elemMap = null;
if (set == null) {
set = new Global.Set(elemMap);
allSets.put(set, set);
}
return set;
}
}
/**
* Class for constructing sets of Global.
*/
public static class Buf {
/** Buffer for construction Global.Set. */
private PortCharacteristic[] buf = new PortCharacteristic[allGlobals.length];
/**
* Constructs buffer.
*/
public Buf() {
}
/**
* Constructs buffer from Set.
* @param set set of globals.
*/
Buf(Global.Set set) {
buf = set.elemMap.clone();
}
/**
* Add specified Global to the buffer.
* @param g specified Global.
*/
public String addToBuf(Global g, PortCharacteristic characteristic) {
String errorMsg = null;
if (buf.length <= g.index) {
PortCharacteristic[] newBuf = new PortCharacteristic[g.index + 1];
System.arraycopy(buf, 0, newBuf, 0, buf.length);
buf = newBuf;
}
PortCharacteristic oldCharacteristic = buf[g.index];
if (oldCharacteristic == null) {
buf[g.index] = characteristic;
} else if (oldCharacteristic != characteristic) {
errorMsg = g.getName() + "(" + oldCharacteristic.getName() + "->" + characteristic.getName() + ")";
}
return errorMsg;
}
/**
* Add specified Global.Set to the buffer.
* @param set specified Global.Set.
*/
public String addToBuf(Global.Set set) {
String errorMsg = null;
for (int i = 0; i < set.elems.length; i++) {
int index = set.elems[i].index;
String msg = addToBuf(allGlobals[index], set.elemMap[index]);
if (msg != null) {
if (errorMsg != null) {
errorMsg += " ";
}
errorMsg += msg;
}
}
return errorMsg;
}
/**
* Returns Global.Set of element in the buffer.
* @return set of Globals in the buffer.
*/
public Global.Set getBuf() {
return Global.Set.newSet(buf);
}
}
}