/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: LENetlister2.java
* Written by Jonathan Gainsley, 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.
*
* Created on November 11, 2003, 3:56 PM
*/
package com.sun.electric.tool.logicaleffort;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.Export;
import com.sun.electric.database.hierarchy.HierarchyEnumerator;
import com.sun.electric.database.hierarchy.Nodable;
import com.sun.electric.database.network.Netlist;
import com.sun.electric.database.network.Network;
import com.sun.electric.database.prototype.PortCharacteristic;
import com.sun.electric.database.prototype.PortProto;
import com.sun.electric.database.text.TextUtils;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.database.variable.Variable;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.Technology;
import com.sun.electric.technology.technologies.Schematics;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.Tool;
import com.sun.electric.tool.logicaleffort.LENetlister.NetlisterConstants;
import com.sun.electric.tool.user.ErrorLogger;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Creates a logical effort netlist to be sized by LESizer.
* This is so the LESizer is independent of Electric's Database,
* and can match George Chen's C++ version being developed for
* PNP.
*
* @author gainsley
*/
public class LENetlister2 extends LENetlister {
/** Netlister constants */ protected NetlisterConstants constants;
/** Map of Cells to CachedCells */ private Map<Cell,CachedCell> cellMap;
/** Map of globalID's to LENetworks */ private Map<Integer,LENetwork> globalNetworks;
/** List of sizeable unique LENodables */ private List<LENodable> sizableLENodables;
/** List of all unique LENodables */ private List<LENodable> allLENodables;
/** Map of Nodables to LENodable definitions */ private Map<Nodable,LENodable> nodablesDefinitions;
/** Sizer */ private LESizer2 sizer;
/** Job we are part of */ private Job job;
/** Where to direct output */ private PrintStream out;
/** True if we got aborted */ private boolean aborted;
/** for logging errors */ private ErrorLogger errorLogger;
/** record definition errors so no multiple warnings */ private HashMap<Export,Export> lePortError;
/** The top level cell netlisted */ private Cell topLevelCell;
/** whether or not to disable caching */ private boolean disableCaching = true;
private static final boolean DEBUG = false;
private static final boolean DEBUG_FIRSTPASS = false;
private static final boolean DEBUG_PRINTCACHEDCELLS = false;
/** Creates a new instance of LENetlister */
public LENetlister2(Job job, Technology layoutTech) {
super(layoutTech);
// get preferences for this package
Tool leTool = Tool.findTool("logical effort");
constants = null;
topLevelCell = null;
this.job = job;
this.cellMap = new HashMap<Cell,CachedCell>();
this.globalNetworks = new HashMap<Integer,LENetwork>();
this.sizableLENodables = new ArrayList<LENodable>();
this.allLENodables = new ArrayList<LENodable>();
this.nodablesDefinitions = new HashMap<Nodable,LENodable>();
this.lePortError = new HashMap<Export,Export>();
this.out = new PrintStream((OutputStream)System.out);
errorLogger = null;
aborted = false;
}
// Entry point: This netlists the cell
@Override
public boolean netlist(Cell cell, VarContext context, boolean useCaching) {
disableCaching = !useCaching;
//ArrayList connectedPorts = new ArrayList();
//connectedPorts.add(Schematics.tech.resistorNode.getPortsList());
assert errorLogger == null;
// if (errorLogger != null) errorLogger.delete();
errorLogger = ErrorLogger.newInstance("LE Netlister");
// Netlist netlist = cell.getNetlist(true);
// read schematic-specific sizing options
constants = getSettings(cell);
if (constants == null) {
constants = new NetlisterConstants(layoutTech);
if (!saveSettings(constants, cell)) {
// couldn't save settings to cell, abort
return false;
}
}
topLevelCell = cell;
FirstPassEnum firstPass = new FirstPassEnum(this);
HierarchyEnumerator.enumerateCell(cell, context, firstPass, SHORT_RESISTORS);
// HierarchyEnumerator.enumerateCell(cell, context, netlist, firstPass);
firstPass.cleanup(disableCaching);
System.out.println("Cached "+cellMap.size()+" cells");
if (DEBUG_FIRSTPASS) {
for (Map.Entry<Cell,CachedCell> entry : cellMap.entrySet()) {
Cell acell = (Cell)entry.getKey();
CachedCell cc = (CachedCell)entry.getValue();
System.out.println("Cached "+acell);
}
}
if (DEBUG_PRINTCACHEDCELLS) {
String outputFile = System.getProperty("user.dir") + File.separator + "PrintCachedCells.txt";
try {
FileOutputStream fos = new FileOutputStream(outputFile, false);
BufferedOutputStream bout = new BufferedOutputStream(fos);
PrintStream out2 = new PrintStream(bout);
// redirect stderr to the log file
//System.setErr(new PrintStream(bout, true));
for (Map.Entry<Cell,CachedCell> entry : cellMap.entrySet()) {
Cell acell = (Cell)entry.getKey();
CachedCell cc = (CachedCell)entry.getValue();
cc.printContents(" ", out2);
}
out2.close();
System.out.println("Wrote debug to "+outputFile);
} catch (IOException e) {
System.out.println("Cannot write CachedCells debug: "+e.getMessage());
}
}
HierarchyEnumerator.enumerateCell(cell, context, this, SHORT_RESISTORS);
// HierarchyEnumerator.enumerateCell(cell, context, netlist, this);
if (aborted) return false;
return true;
}
/**
* Size the netlist.
* @return true on success, false otherwise.
*/
public boolean size(LESizer.Alg algorithm) {
//lesizer.printDesign();
boolean verbose = false;
// create a new sizer
sizer = new LESizer2(algorithm, this, job, errorLogger);
boolean success = sizer.optimizeLoops(constants.epsilon, constants.maxIterations, verbose, constants.alpha, constants.keeperRatio);
//out.println("---------After optimization:------------");
//lesizer.printDesign();
// get rid of the sizer
sizer = null;
return success;
}
/**
* Updates the size of all Logical Effort gates
*/
public void getSizes(List<Float> sizes, List<String> varNames,
List<NodeInst> nodes, List<VarContext> contexts) {
// iterator over all LEGATEs
for (Iterator<LENodable> cit = getSizeableNodables(); cit.hasNext(); ) {
LENodable leno = cit.next();
Nodable no = leno.getNodable();
NodeInst ni = no.getNodeInst();
if (ni != null) no = ni;
// ignore it if not a sizeable gate
if (!leno.isLeGate()) continue;
String varName = "LEDRIVE_" + leno.getName();
//no.newVar(varName, new Float(leno.leX));
//topLevelCell.newVar(varName, new Float(leno.leX));
sizes.add(new Float(leno.leX));
varNames.add(varName);
nodes.add(ni);
contexts.add(leno.context);
}
}
/**
* Updates the size of all Logical Effort gates
*/
public void updateSizes() {
// iterator over all LEGATEs
for (Iterator<LENodable> cit = getSizeableNodables(); cit.hasNext(); ) {
LENodable leno = cit.next();
Nodable no = leno.getNodable();
NodeInst ni = no.getNodeInst();
if (ni != null) no = ni;
// ignore it if not a sizeable gate
if (!leno.isLeGate()) continue;
String varName = "LEDRIVE_" + leno.getName();
//no.newVar(varName, new Float(leno.leX));
topLevelCell.newVar(varName, new Float(leno.leX));
if (leno.leX < 1.0f) {
String msg = "WARNING: Instance "+ni+" has size "+TextUtils.formatDistance(leno.leX)+" less than 1 ("+leno.getName()+")";
System.out.println(msg);
if (ni != null) {
errorLogger.logWarning(msg, ni, ni.getParent(), leno.context, 2);
}
}
}
}
public void done() {
errorLogger.termLogging(true);
//errorLogger = null;
}
public ErrorLogger getErrorLogger() { return errorLogger; }
public void nullErrorLogger() { errorLogger = null; }
public NetlisterConstants getConstants() { return constants; }
protected Iterator<LENodable> getSizeableNodables() { return sizableLENodables.iterator(); }
protected float getGlobalSU() { return constants.su; }
protected LESizer2 getSizer() { return sizer; }
protected float getKeeperRatio() { return constants.keeperRatio; }
private LENetwork getNetwork(int globalID, HierarchyEnumerator.CellInfo info) {
LENetwork net = globalNetworks.get(new Integer(globalID));
if (net == null) {
String name = (info == null) ? null : info.getUniqueNetName(globalID, ".");
net = new LENetwork(name);
globalNetworks.put(new Integer(globalID), net);
}
return net;
}
// ======================= Hierarchy Enumerator ==============================
/**
* Class to implement the first pass of definitions for all LENodables.
* The first pass creates the definitions for all LENodables, and sees which
* Cells can be cached (i.e. do not have parameters that need parent context
* to evaluate, and do not have sizeable gates in them)
*/
private static class FirstPassEnum extends HierarchyEnumerator.Visitor {
/** LENetlister2 */ private LENetlister2 netlister;
private FirstPassEnum(LENetlister2 netlister) {
this.netlister = netlister;
}
/**
* Override the default Cell info to pass along logical effort specific information
* @return a LECellInfo
*/
public HierarchyEnumerator.CellInfo newCellInfo() { return new LECellInfo(); }
public boolean enterCell(HierarchyEnumerator.CellInfo info) {
if (netlister.aborted) return false;
if (((LETool.AnalyzeCell)netlister.job).checkAbort(null)) {
netlister.aborted = true;
return false;
}
CachedCell cachedCell = netlister.cellMap.get(info.getCell());
if (cachedCell == null) {
cachedCell = new CachedCell(info.getCell(), info.getNetlist());
if (netlister.cellMap.containsKey(info.getCell()))
System.out.println("Possible hash map conflict in netlister.cellMap!");
netlister.cellMap.put(info.getCell(), cachedCell);
if (DEBUG_FIRSTPASS) System.out.println(" === entering "+info.getCell());
return true;
} else {
// because this cell is already cached, we will not be visiting nodeinsts,
// and we will not be calling exit cell. So link into parent here, because
// we won't be linking into parent from exit cell.
// add this to parent cached cell if any
if (DEBUG_FIRSTPASS) System.out.println(" === not entering, using cached version for "+info.getCell());
HierarchyEnumerator.CellInfo parentInfo = info.getParentInfo();
if (parentInfo != null) {
Cell parent = info.getParentInfo().getCell();
CachedCell parentCached = netlister.cellMap.get(parent);
Nodable no = info.getParentInst();
parentCached.add(no, (LECellInfo)info.getParentInfo(), cachedCell, (LECellInfo)info, netlister.constants);
}
}
return false;
}
public boolean visitNodeInst(Nodable ni, HierarchyEnumerator.CellInfo info) {
CachedCell cachedCell = netlister.cellMap.get(info.getCell());
if (ni.getNodeInst().isCellInstance())
if (DEBUG_FIRSTPASS) System.out.println(" === visiting "+ni.getName());
// see if we can make an LENodable from the nodable
LENodable.Type type = netlister.getType(ni, info);
if (type == null) return true; // recurse
if (type == LENodable.Type.IGNORE) return false; // ignore
LENodable leno = netlister.createLENodable(type, ni, info);
// if no lenodable, recurse
if (leno == null) return true;
cachedCell.add(ni, leno);
if (netlister.nodablesDefinitions.containsKey(ni))
System.out.println("Possible hash map conflict in netlister.nodablesDefinitions!");
netlister.nodablesDefinitions.put(ni, leno);
return false;
}
public void exitCell(HierarchyEnumerator.CellInfo info) {
CachedCell cachedCell = netlister.cellMap.get(info.getCell());
if (DEBUG_FIRSTPASS) System.out.println(" === exiting "+info.getCell());
// add this to parent cached cell if any
HierarchyEnumerator.CellInfo parentInfo = info.getParentInfo();
if (parentInfo != null) {
Cell parent = info.getParentInfo().getCell();
CachedCell parentCached = netlister.cellMap.get(parent);
Nodable no = info.getParentInst();
parentCached.add(no, (LECellInfo)info.getParentInfo(), cachedCell, (LECellInfo)info, netlister.constants);
}
}
protected void cleanup(boolean disableCaching) {
// remove all cachedCells that contain sizeable gates or are not context free
HashMap<Cell,CachedCell> cachedMap = new HashMap<Cell,CachedCell>();
for (Map.Entry<Cell,CachedCell> entry : netlister.cellMap.entrySet()) {
Cell cell = (Cell)entry.getKey();
CachedCell cachedCell = (CachedCell)entry.getValue();
if (cachedCell.isContextFree(netlister.constants)) {
cachedMap.put(cell, cachedCell);
}
}
netlister.cellMap = cachedMap;
if (disableCaching) netlister.cellMap = new HashMap<Cell,CachedCell>();
}
}
/**
* Override the default Cell info to pass along logical effort specific information
* @return a LECellInfo
*/
public HierarchyEnumerator.CellInfo newCellInfo() { return new LECellInfo(); }
/**
* Enter cell initializes the LECellInfo.
* @param info the LECellInfo
* @return true to process the cell, false to ignore.
*/
public boolean enterCell(HierarchyEnumerator.CellInfo info) {
if (aborted) return false;
if (((LETool.AnalyzeCell)job).checkAbort(null)) {
aborted = true;
return false;
}
LECellInfo leinfo = (LECellInfo)info;
leinfo.leInit(constants);
// check if conflicting settings
if (topLevelCell != info.getCell()) {
if (isSettingsConflict(leinfo.getSettings(), topLevelCell, info.getContext(), info.getCell())) {
aborted = true;
return false;
}
}
boolean enter = true;
// if there is a cachedCell, do not enter
CachedCell cachedCell = cellMap.get(info.getCell());
// if this was a cached cell, link cached networks into global network
// note that a cached cell cannot by definition contain sizeable LE gates
if ((cachedCell != null) && (leinfo.getMFactor() == 1f)) {
for (Map.Entry<Network,LENetwork> entry : cachedCell.getLocalNetworks().entrySet()) {
Network jnet = (Network)entry.getKey();
LENetwork subnet = (LENetwork)entry.getValue();
int globalID = info.getNetID(jnet);
LENetwork net = (LENetwork)getNetwork(globalID, info);
if (net == null) continue;
net.add(subnet);
if (DEBUG) {
if (net.getName().equals("vdd")) continue;
if (net.getName().equals("gnd")) continue;
System.out.println(" Added to global net "+net.getName() +" "+subnet.getName()+" from "+info.getCell().describe(false));
System.out.println(" subcell="+info.getCell().describe(false)+" subnet="+subnet.getName()+": ");
subnet.print();
System.out.println(" result: global net="+net.getName()+": ");
net.print();
}
}
//for (Iterator it = cachedCell.getAllCachedNodables().iterator(); it.hasNext(); ) {
// allLENodables.add(it.next());
//}
enter = false;
}
return enter;
}
/**
* Visit NodeInst creates a new Logical Effort instance from the
* parameters found on the Nodable, if that Nodable is an LEGATE.
* It also creates instances for wire models (LEWIREs).
* @param ni the Nodable being visited
* @param info the cell info
* @return true to push down into the Nodable, false to continue.
*/
public boolean visitNodeInst(Nodable ni, HierarchyEnumerator.CellInfo info) {
LECellInfo leinfo = (LECellInfo)info;
LENodable def = nodablesDefinitions.get(ni);
if (def == null) return true;
else {
// create hierarchical unique instance from definition
LENetwork outputNet = null;
if (def.isLeGate()) {
// get global output network
Network outNet = def.getOutputNet();
int globalID = info.getNetID(outNet);
outputNet = getNetwork(globalID, info);
}
float localsu = constants.su;
if (leinfo.getSU() != -1f) localsu = leinfo.getSU();
LENodable uniqueLeno = def.createUniqueInstance(info.getContext(), outputNet,
leinfo.getMFactor(), localsu, constants);
if (uniqueLeno.isLeGate())
sizableLENodables.add(uniqueLeno);
allLENodables.add(uniqueLeno);
// add pins to global networks
for (LEPin pin : uniqueLeno.getPins()) {
int globalID = info.getNetID(pin.getNetwork());
LENetwork net = getNetwork(globalID, info);
net.add(pin);
}
//uniqueLeno.print();
//uniqueLeno.printPins();
}
return false;
}
public void doneVisitNodeInst(Nodable ni, HierarchyEnumerator.CellInfo info) {}
/**
* Nothing to do for exitCell
*/
public void exitCell(HierarchyEnumerator.CellInfo info) {
}
/**
* Logical Effort Cell Info class. Keeps track of:
* <p>- M factors
*/
public static class LECellInfo extends LENetlister.LECellInfo {
/** the cached cell */ private CachedCell cachedCell;
protected void setCachedCell(CachedCell c) { cachedCell = c; }
protected CachedCell getCachedCell() { return cachedCell; }
}
/**
* Get the LENodable type of this Nodable. If it is not a valid type, return null.
* @param ni the Nodable to examine
* @param info the current info
* @return the LENodable type, or null if not an LENodable
*/
private LENodable.Type getType(Nodable ni, HierarchyEnumerator.CellInfo info) {
Variable var = null;
if ((var = ni.getParameter(ATTR_LEGATE)) != null) {
// assume it is LEGATE if can't resolve value
int gate = VarContext.objectToInt(info.getContext().evalVar(var), 1);
if (gate == 1)
return LENodable.Type.LEGATE;
}
else if ((var = ni.getParameter(ATTR_LEKEEPER)) != null) {
// assume it is LEKEEPER if can't resolve value
int gate = VarContext.objectToInt(info.getContext().evalVar(var), 1);
if (gate == 1)
return LENodable.Type.LEKEEPER;
}
else if (ni.getParameter(ATTR_LEWIRE) != null) {
return LENodable.Type.WIRE;
}
else if ((ni.getProto() != null) && (ni.getProto().getFunction().isTransistor())) {
return LENodable.Type.TRANSISTOR;
}
else if ((ni.getProto() != null) && (ni.getProto().getFunction().isCapacitor())) {
return LENodable.Type.CAPACITOR;
}
else if ((var = ni.getParameterOrVariable(ATTR_LEIGNORE)) != null) {
int ignore = VarContext.objectToInt(info.getContext().evalVar(var), 1);
if (ignore == 1)
return LENodable.Type.IGNORE;
}
else if ((var = ni.getParameter(ATTR_LEIGNORE)) != null) {
int ignore = VarContext.objectToInt(info.getContext().evalVar(var), 1);
if (ignore == 1)
return LENodable.Type.IGNORE;
}
return null;
}
/**
* Create an LENodable of the given type for the Nodable
* @param type the type to create
* @param ni the source nodable
* @param info the current info
* @return an LENodable, or null if error
*/
private LENodable createLENodable(LENodable.Type type, Nodable ni, HierarchyEnumerator.CellInfo info) {
if (type == null) return null;
Variable var = null;
if (DEBUG) System.out.println("------------------------------------");
// Build an LENodable. M can be variable or parameter
LENodable lenodable = new LENodable(ni, type, LETool.getMFactor(ni), ni.getParameter(ATTR_su), ni.getParameter(ATTR_LEPARALLGRP));
Network outputNet = null;
Netlist netlist = info.getNetlist();
for (Iterator<PortProto> ppIt = ni.getProto().getPorts(); ppIt.hasNext();) {
PortProto pp = ppIt.next();
// Note: default 'le' value should be one
float le = getLE(ni, type, pp, info);
Network jnet = netlist.getNetwork(ni, pp, 0);
LEPin.Dir dir = LEPin.Dir.INPUT;
// if it's not an output, it doesn't really matter what it is.
if (pp.getCharacteristic() == PortCharacteristic.OUT) {
dir = LEPin.Dir.OUTPUT;
// set output net
if ((type == LENodable.Type.LEGATE || type == LENodable.Type.LEKEEPER) && outputNet != null) {
System.out.println("Error: Sizable gate "+ni.getNodeInst()+" has more than one output port!! Ignoring Gate");
return null;
}
outputNet = jnet;
lenodable.setOutputNet(jnet);
}
if (type == LENodable.Type.TRANSISTOR) {
// primitive Electric Transistors have their source and drain set to BIDIR, we
// want them set to OUTPUT so that they count as diffusion capacitance
if (pp.getCharacteristic() == PortCharacteristic.BIDIR) dir = LEPin.Dir.OUTPUT;
if (dir == LEPin.Dir.INPUT) {
// gate load: check if length > 2, if so, increase LE to account for added capacitance
var = ni.getParameterOrVariable(Schematics.ATTR_LENGTH);
if (var == null) {
System.out.println("Error: transistor "+ni.getName()+" has no length in Cell "+ni.getParent());
//ErrorLogger.ErrorLog log = errorLogger.logError("Error: transistor "+ni+" has no length in Cell "+info.getCell(), info.getCell(), 0);
//log.addGeom(ni.getNodeInst(), true, info.getCell(), info.getContext());
}
float length = VarContext.objectToFloat(info.getContext().evalVar(var), (float)2.0);
// not exactly correct because assumes all cap is area cap, which it isn't
if (length != constants.x1inverter_length)
le = le * length / constants.x1inverter_length;
}
}
lenodable.addPort(pp.getName(), dir, le, jnet);
if (DEBUG) System.out.println(" Added "+dir+" pin "+pp.getName()+", le: "+le+", Network: "+jnet);
if (type == LENodable.Type.WIRE) break; // this is LEWIRE, only add one pin of it
}
return lenodable;
}
private float getLE(Nodable ni, LENodable.Type type, PortProto pp, HierarchyEnumerator.CellInfo info) {
boolean leFound = false;
// Note default 'le' value should be one
float le = 1.0f;
if (!(pp instanceof Export))
return le;
Variable var = ((Export)pp).getParameterOrVariable(ATTR_le);
if (var != null) {
leFound = true;
le = VarContext.objectToFloat(info.getContext().evalVar(var), 1.0f);
} else if ((pp.getCharacteristic() == PortCharacteristic.OUT) &&
(type == LENodable.Type.LEGATE || type == LENodable.Type.LEKEEPER)) {
// if this is an Sizeable gate's output, look for diffn and diffp
float diff = 0;
var = ((Export)pp).getParameterOrVariable(ATTR_diffn);
if (var != null) {
diff += VarContext.objectToFloat(info.getContext().evalVar(var), 0);
leFound = true;
}
var = ((Export)pp).getParameterOrVariable(ATTR_diffp);
if (var != null) {
diff += VarContext.objectToFloat(info.getContext().evalVar(var), 0);
leFound = true;
}
le = diff/3.0f;
}
if (!leFound && (type == LENodable.Type.LEGATE || type == LENodable.Type.LEKEEPER)) {
Cell cell = (Cell)ni.getProto();
Export exp = cell.findExport(pp.getName());
if (exp != null && lePortError.get(exp) == null) {
String msg = "Warning: Sizeable gate has no logical effort specified for port "+pp.getName()+" in "+cell;
System.out.println(msg);
errorLogger.logWarning(msg, exp, cell, info.getContext().push(ni), 0);
lePortError.put(exp, exp);
}
}
return le;
}
// =============================== Statistics ==================================
public void printStatistics() {
float totalsize = 0f;
float instsize = 0f;
int numLEGates = 0;
int numLEWires = 0;
// iterator over all LEGATEs
for (LENodable leno : allLENodables) {
// ignore it if not a sizeable gate
if (leno.isLeGate()) {
numLEGates++;
instsize += leno.leX;
}
if (leno.getType() == LENodable.Type.WIRE)
numLEWires++;
totalsize += leno.leX;
}
System.out.println("Number of LEGATEs: "+numLEGates);
//System.out.println("Number of Wires: "+numLEWires);
System.out.println("Total size of all LEGATEs: "+instsize);
//System.out.println("Total size of all instances (sized and loads): "+totalsize);
}
public float getTotalLESize() {
float instsize = 0f;
// iterator over all LEGATEs
for (LENodable leno : allLENodables) {
// ignore it if not a sizeable gate
if (leno.isLeGate()) {
instsize += leno.leX;
}
}
return instsize;
}
public boolean printResults(Nodable no, VarContext context) {
// if this is a NodeInst, convert to Nodable
if (no instanceof NodeInst) {
no = Netlist.getNodableFor((NodeInst)no, 0);
}
LENodable leno = null;
for (LENodable aleno : allLENodables) {
if (aleno.getNodable().getNodeInst() == no.getNodeInst()) {
if (aleno.context.getInstPath(".").equals(context.getInstPath("."))) {
leno = aleno;
break;
}
}
}
if (leno == null) return false;
// print netlister info
System.out.println("Netlister: Gate Cap="+constants.gateCap+", Alpha="+constants.alpha);
// print instance info
leno.print();
// collect info about what is driven
LENetwork outputNet = leno.outputNetwork;
ArrayList<LEPin> gatesDrivenPins = new ArrayList<LEPin>();
ArrayList<LEPin> loadsDrivenPins = new ArrayList<LEPin>();
ArrayList<LEPin> wiresDrivenPins = new ArrayList<LEPin>();
ArrayList<LEPin> gatesFightingPins = new ArrayList<LEPin>();
if (outputNet == null) return false;
for (LEPin pin : outputNet.getAllPins()) {
LENodable loopLeno = pin.getInstance();
if (pin.getDir() == LEPin.Dir.INPUT) {
if (loopLeno.isGate()) gatesDrivenPins.add(pin);
if (loopLeno.getType() == LENodable.Type.LOAD) loadsDrivenPins.add(pin);
if (loopLeno.getType() == LENodable.Type.TRANSISTOR) loadsDrivenPins.add(pin);
if (loopLeno.getType() == LENodable.Type.CAPACITOR) loadsDrivenPins.add(pin);
if (loopLeno.getType() == LENodable.Type.WIRE) wiresDrivenPins.add(pin);
}
if (pin.getDir() == LEPin.Dir.OUTPUT) {
if (loopLeno.isGate()) gatesFightingPins.add(pin);
if (loopLeno.getType() == LENodable.Type.TRANSISTOR) loadsDrivenPins.add(pin);
}
}
System.out.println("Note: Load = Size * LE * M");
System.out.println("Note: Load = Size * LE * M * Alpha, for Gates Fighting");
float totalLoad = 0f;
System.out.println(" -------------------- Gates Driven ("+gatesDrivenPins.size()+") --------------------");
for (LEPin pin : gatesDrivenPins) {
totalLoad += pin.getInstance().printLoadInfo(pin, constants.alpha);
}
System.out.println(" -------------------- Loads Driven ("+loadsDrivenPins.size()+") --------------------");
for (LEPin pin : loadsDrivenPins) {
totalLoad += pin.getInstance().printLoadInfo(pin, constants.alpha);
}
System.out.println(" -------------------- Wires Driven ("+wiresDrivenPins.size()+") --------------------");
for (LEPin pin : wiresDrivenPins) {
totalLoad += pin.getInstance().printLoadInfo(pin, constants.alpha);
}
System.out.println(" -------------------- Gates Fighting ("+gatesFightingPins.size()+") --------------------");
for (LEPin pin : gatesFightingPins) {
totalLoad += pin.getInstance().printLoadInfo(pin, constants.alpha);
}
System.out.println("*** Total Load: "+TextUtils.formatDouble(totalLoad, 2));
//msgs.setFont(oldFont);
return true;
}
// ---- TEST STUFF ----- REMOVE LATER ----
public static void test1() {
LESizer.test1();
}
}