/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: SubcircuitInfo.java
*
* 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.tool.ncc.processing;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.sun.electric.tool.ncc.basic.Primes;
import com.sun.electric.tool.ncc.netlist.PinType;
import com.sun.electric.tool.ncc.netlist.Port;
import com.sun.electric.tool.ncc.netlist.Subcircuit;
import com.sun.electric.tool.Job;
/** Holds information necessary to treat this Cell as a primitive subcircuit
* when performing hierarchical netlist comparison at a higher level */
public class SubcircuitInfo {
/** Characteristics shared by all equivalent subcircuits. A single
* instance of SubcircuitInfo is generated for the first Cell in the
* CellGroup (the "reference" Cell) and copied by all the other
* Cells in the CellGroup. */
private static class ReferenceInfo {
final String name;
final int ID;
final String[] portNames;
final int[] portCoeffs;
final PinType[] pinTypes;
private int[] initPortCoeffs() {
int[] coeffs = new int[portNames.length];
int nameHash = 0;
for (int i=0; i<name.length(); i++) {
nameHash = (nameHash<<1) + (int) name.charAt(i);
}
nameHash = nameHash % 257;
nameHash = Math.abs(nameHash);
for (int i=0; i<coeffs.length; i++) {
coeffs[i] = Primes.get(nameHash + i);
}
return coeffs;
}
ReferenceInfo(String name, int ID, String[] portNames) {
Job.error(name==null, "No name?");
this.name = name;
this.ID = ID;
this.portNames = portNames;
this.portCoeffs = initPortCoeffs();
pinTypes= new PinType[portNames.length];
for (int i=0; i<pinTypes.length; i++) {
String pinDesc = name+" "+portNames[i];
// The first argment isn't used by new partition algorithm
pinTypes[i] = new Subcircuit.SubcircuitPinType(0, i,pinDesc);
}
}
}
/** Arbitrarily choose one Export name from each Port. These names
* will be used to report errors when comparing hierarchically at the
* next level up.
* <p> Build a map from export names to port index */
private void processReferencePorts(String[] portNames,
Map<String,Integer> exportNameToPortIndex,
Port[] refPorts) {
for (int i=0; i<refPorts.length; i++) {
Integer portIndex = new Integer(i);
Port port = refPorts[i];
for (Iterator<String> it=port.getExportNames(); it.hasNext();) {
String exportName = it.next();
if (portNames[i]==null) portNames[i] = exportName;
exportNameToPortIndex.put(exportName, portIndex);
}
Job.error(portNames[i]==null, "Port with no name?");
}
}
// -------------------------- private data -------------------------
private final ReferenceInfo shared;
private final Map<String,Integer> exportNameToPortIndex;
// -------------------------- public methods -----------------------
/** Create the first SubcircuitInfo for the reference Cell */
public SubcircuitInfo(String name, int ID, Port[] refPorts) {
String[] portNames = new String[refPorts.length];
exportNameToPortIndex = new HashMap<String,Integer>();
processReferencePorts(portNames, exportNameToPortIndex, refPorts);
this.shared = new ReferenceInfo(name, ID, portNames);
}
/** Create SubcircuitInfos for all the rest of the Cells in the
* CellGroup */
public SubcircuitInfo(SubcircuitInfo referenceInfo,
Map<String,Integer> exportNameToPortIndex) {
this.shared = referenceInfo.shared;;
this.exportNameToPortIndex = exportNameToPortIndex;
}
/** @return the unique ID assigned to this subcircuit */
public int getID() {return shared.ID;}
/** @return the name of this subcircuit */
public String getName() {return shared.name;}
/** @return the number of subcircuit ports */
public int numPorts() {return shared.portNames.length;}
/** @return the name of the ith port */
public String getPortName(int i) {return shared.portNames[i];}
/** @return the index of the port named exportName */
public int getPortIndex(String exportName) {
Integer I = exportNameToPortIndex.get(exportName);
//LayoutLib.error(I==null, "Export name not found: "+exportName);
// If oneNamePerPort then SubcircuitInfo saves only one Export
// name with Port. If you ask for others then you get -1
return I==null ? -1 : I.intValue();
}
/** @return an array of coefficients, one entry per port */
public int[] getPortCoeffs() {return shared.portCoeffs;}
/** @return array of PinTypes, one per Port */
public PinType[] getPinTypes() {return shared.pinTypes;}
}