/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Subcircuit.java
*
* 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.tool.ncc.netlist;
import java.util.HashMap;
import java.util.Map;
import com.sun.electric.technology.PrimitiveNode.Function;
import com.sun.electric.tool.ncc.NccOptions;
import com.sun.electric.tool.ncc.netlist.NccNameProxy.PartNameProxy;
import com.sun.electric.tool.ncc.processing.SubcircuitInfo;
import com.sun.electric.tool.Job;
/** A Cell instance that is being treated as a primitive circuit component
* during a hierarchical netlist comparison */
public class Subcircuit extends Part {
/** presume that no ports are interchangeable */
public static class SubcircuitPinType implements PinType {
private int typeCode;
private int portIndex;
private String description;
public SubcircuitPinType(int typeCode, int portIndex, String description) {
this.typeCode = typeCode;
this.portIndex = portIndex;
this.description = description;
}
public String description() {return description;}
}
private final int[] pinCoeffs;
// For each wire, store the sum of the coefficients of the pins attached to
// that wire
private final Map<Wire,Integer> wireToCoeffSum;
private final SubcircuitInfo subcircuitInfo;
private String getPortName(int i) {return subcircuitInfo.getPortName(i);}
private Map<Wire,Integer> computeWireToCoeffSum(Wire[] pins, int[] coeffs) {
Map<Wire,Integer> wireToCoeffs = new HashMap<Wire,Integer>();
for (int i=0; i<pins.length; i++) {
Wire w = pins[i];
int coeff = pinCoeffs[i];
Integer coeffSum = wireToCoeffs.get(w);
if (coeffSum==null) coeffSum = new Integer(0);
coeffSum += coeff;
wireToCoeffs.put(w, coeffSum);
}
return wireToCoeffs;
}
@Override
public String valueDescription() {return "";}
@Override
public int[] getPinCoeffs() {return pinCoeffs;}
@Override
public boolean parallelMerge(Part p, NccOptions nccOpt) {
Job.error(true, "we never parallel merge subcircuits so don't call this method");
return false;
}
/** I never parallel merge subcircuits so this really doesn't matter.
* This method is too slow for subcircuits with tens of thousands of
* pins. It's better to avoid calling this method at a higher level.*/
@Override
public Integer hashCodeForParallelMerge() {
Job.error(true, "we never parallel merge subcircuits so don't call this method");
// include how many Wires may be connected
int hc = pins.length;
// include what's connected
for (int i=0; i<pins.length; i++)
hc += pins[i].hashCode() * pinCoeffs[i];
// include the class
hc += getClass().hashCode();
// include subcircuit ID
hc += subcircuitInfo.getID();
return new Integer(hc);
}
@Override
public String typeString() {return subcircuitInfo.getName();}
@Override
public int typeCode() {
return type().ordinal() +
(subcircuitInfo.getID() << Part.TYPE_FIELD_WIDTH);
}
@Override
public PinType getPinTypeOfNthPin(int n) {
PinType[] pinTypes = subcircuitInfo.getPinTypes();
return pinTypes[n];
}
@Override
public String connectionDescription(Wire w) {
String msg = "";
for (int i=0; i<pins.length; i++) {
if (pins[i]==w) {
if (msg.length()!=0) msg += ',';
msg += getPortName(i);
}
}
return msg;
}
@Override
public String connectionDescription(int maxCon) {
String msg = "";
for (int i=0; i<maxCon && i<pins.length; i++) {
if (msg.length()!=0) msg += " ";
msg += getPortName(i)+"="+pins[i].getName();
}
return msg;
}
/** Subcircuits can have tens of thousands of pins. Part.getHashFor(Wire)
* is O(n) in the number of pins. Since it gets called n times we have
* O(n^2) execution time. Subcircuit.getHashFor(Wire) takes more
* storage but executes in constant time.
* @param w the Wire for which a hash code is needed
* @return an int with the code contribution. */
@Override
public int getHashFor(Wire w) {
Integer coeffSum = wireToCoeffSum.get(w);
Job.error(coeffSum==null, "Wire not found");
return coeffSum*getCode();
}
public Subcircuit(PartNameProxy instName, SubcircuitInfo subcircuitInfo,
Wire[] pins) {
super(instName, Function.UNKNOWN, pins);
this.subcircuitInfo = subcircuitInfo;
pinCoeffs = subcircuitInfo.getPortCoeffs();
wireToCoeffSum = computeWireToCoeffSum(pins, pinCoeffs);
}
}