Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.sun.electric.tool.extract.ParasiticTool Maven / Gradle / Ivy
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: ParasiticTool.java
* Written by: Gilda Garreton, Sun Microsystems.
*
* Copyright (c) 2004, 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.extract;
import com.sun.electric.database.geometry.Poly;
import com.sun.electric.database.geometry.PolyBase;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.HierarchyEnumerator;
import com.sun.electric.database.hierarchy.Nodable;
import com.sun.electric.database.network.Network;
import com.sun.electric.database.prototype.NodeProto;
import com.sun.electric.database.prototype.PortProto;
import com.sun.electric.database.text.Pref;
import com.sun.electric.database.topology.ArcInst;
import com.sun.electric.database.topology.Geometric;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.database.variable.Variable;
import com.sun.electric.technology.ArcProto;
import com.sun.electric.technology.Layer;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.Technology;
import com.sun.electric.technology.technologies.Generic;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.JobException;
import com.sun.electric.tool.Tool;
import com.sun.electric.tool.simulation.SimulationTool;
import com.sun.electric.tool.user.ErrorLogger;
import com.sun.electric.util.ElapseTimer;
import com.sun.electric.util.math.FixpTransform;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Class to implement parasitic extraction.
*/
public class ParasiticTool extends Tool {
/** The Parasitic Extraction tool */ private static ParasiticTool tool = new ParasiticTool();
private static ErrorLogger errorLogger = ErrorLogger.newInstance("Parasitics Extraction");;
private ParasiticTool() { super("parasitic");}
/**
* Method to initialize the Parasitics tool.
*/
public void init()
{
}
/**
* Method to retrieve singlenton associated to parasitic tool
*/
public static ParasiticTool getParasiticTool() { return tool; }
public static ErrorLogger getParasiticErrorLogger() { return errorLogger; }
public static double getAreaScale(double scale) { return scale*scale/1000000; } // area in square microns
public static double getPerimScale(double scale) { return scale/1000; } // perim in microns
public void netwokParasitic(Network network, Cell cell)
{
new AnalyzeParasitic(network, cell);
}
public static List calculateParasistic(ParasiticGenerator tool, Cell cell, VarContext context)
{
errorLogger.clearLogs(cell);
// Netlist netList = cell.getNetlist(false);
if (context == null) context = VarContext.globalContext;
ParasiticVisitor visitor = new ParasiticVisitor(tool, context);
HierarchyEnumerator.enumerateCell(cell, context, visitor);
// HierarchyEnumerator.enumerateCell(cell, context, netList, visitor);
List list = visitor.getParasitics();
return list;
}
private static class ParasiticVisitor extends HierarchyEnumerator.Visitor
{
private Map netMap;
//private Netlist netList;
private List transAndRCList = new ArrayList();
private ParasiticGenerator tool;
private VarContext context;
public List getParasitics()
{
List list = new ArrayList(transAndRCList);
for (Network net : netMap.keySet())
{
Object value = netMap.get(net);
if (value != null) list.add(value);
}
return list;
}
public HierarchyEnumerator.CellInfo newCellInfo() { return new ParasiticCellInfo(); }
public ParasiticVisitor(ParasiticGenerator tool, VarContext context)
{
//this.netList = netList;
this.tool = tool;
netMap = new HashMap();
// netMap = new HashMap(netList.getNumNetworks());
this.context = context;
}
/**
* @param info
*/
public void exitCell(HierarchyEnumerator.CellInfo info)
{
// Done with root cell
if (info.getParentInfo() == null)
{
for (Network net : netMap.keySet())
{
NetPBucket bucket = netMap.get(net);
bucket.postProcess(false);
}
}
}
private NetPBucket getNetParasiticsBucket(Network net, HierarchyEnumerator.CellInfo info)
{
NetPBucket parasiticNet = netMap.get(net);
int numRemoveParents = context.getNumLevels();
if (parasiticNet == null)
{
String name = info.getUniqueNetNameProxy(net, "/").toString(numRemoveParents);
parasiticNet = new NetPBucket(name);
netMap.put(net, parasiticNet);
}
return parasiticNet;
}
public boolean enterCell(HierarchyEnumerator.CellInfo info)
{
ParasiticCellInfo iinfo = (ParasiticCellInfo)info;
iinfo.extInit();
int numRemoveParents = context.getNumLevels();
for(Iterator aIt = info.getCell().getArcs(); aIt.hasNext(); )
{
ArcInst ai = aIt.next();
// don't count non-electrical arcs
if (ai.getProto().getFunction() == ArcProto.Function.NONELEC) continue;
Network net = info.getNetlist().getNetwork(ai, 0); // netList.getNetwork(ai, 0);
if (net == null)
continue;
PortInst tailP = ai.getTailPortInst();
PortInst headP = ai.getHeadPortInst();
// Network net1 = netList.getNetwork(tailP);
// Network net2 = netList.getNetwork(headP);
// if (net1 != net) net2 = net1;
NetPBucket parasiticNet = getNetParasiticsBucket(net, info);
if (parasiticNet == null)
continue;
String netName = info.getUniqueNetNameProxy(net, "/").toString(numRemoveParents);
String net1Name = netName+"_"+tailP.getNodeInst().getName();
String net2Name = netName+"_"+headP.getNodeInst().getName();
boolean isDiffArc = ai.isDiffusionArc(); // check arc function
Technology tech = ai.getProto().getTechnology();
Poly [] arcInstPolyList = tech.getShapeOfArc(ai);
int tot = arcInstPolyList.length;
for(int j=0; j 0.0)
//if (layer.isDiffusionLayer() || (!isDiffArc && layer.getCapacitance() > 0.0))
parasiticNet.addCapacitance(layer, poly);
if (layer.getResistance() > 0.0)
parasiticNet.modifyResistance(layer, poly, new String[] {net1Name, net2Name}, true);
}
}
return (true);
}
/**
*
* @param no
* @param info
* @return
*/
public boolean visitNodeInst(Nodable no, HierarchyEnumerator.CellInfo info)
{
NodeInst ni = no.getNodeInst();
if (ni.isCellInstance()) return true; // hierarchical
// Its like pins, facet-center
if (NodeInst.isSpecialNode(ni)) return (false);
// initialize to examine the polygons on this node
Technology tech = ni.getProto().getTechnology();
FixpTransform trans = ni.rotateOut();
ExtractedPBucket parasitic = tool.createBucket(ni, (ParasiticCellInfo)info);
if (parasitic != null) transAndRCList.add(parasitic);
int numRemoveParents = context.getNumLevels();
PrimitiveNode.Function function = ni.getFunction();
// In case of contacts, the area is substracted.
boolean add = !function.isContact();
Poly [] polyList = tech.getShapeOfNode(ni, true, true, null);
int tot = polyList.length;
for(int i=0; i 0.0) // diffusion might have zero capacitances )
parasiticNet.addCapacitance(layer, poly);
// Doesn't include gates if user set that
if (gateLayer && !tech.isGateIncluded()) continue;
String netName = info.getUniqueNetNameProxy(net, "/").toString(numRemoveParents) + "_" + ni.getName();
if (layer.getResistance() > 0.0)
parasiticNet.modifyResistance(layer, poly, new String[] {netName, netName}, add);
}
return (true);
}
}
/****** inner class to store information ****/
private static class ParasiticBucket
{
public Poly poly;
/** Face area perpendicular to euclidean distance */ public double area;
/** Width of cross section */ public double length;
protected ParasiticBucket(Poly p, double a, double l)
{
poly = p;
area = a;
length = l;
}
}
private static class ParasiticValue
{
private ParasiticBucket[] elements = new ParasiticBucket[2];
// /** True if faces are perpendicular */ private boolean angle;
// private double distance = -1;
/**
* Overwrite Object.toString()
*/
public String toString()
{
StringBuffer buf = new StringBuffer();
for (int i = 0; i < 2; i++)
buf.append("Poly " + i + ":" + elements[i].poly.getBounds2D() +
"(area=" + elements[i].area + ", length=" + elements[i].length + ") ");
return (buf.toString());
}
/**
* similar to PolyBase.separationBox
*/
public static List initParasiticValues(Poly p1, Poly p2)
{
Rectangle2D thisBounds = p1.getBox();
Rectangle2D otherBounds = p2.getBox();
List values = new ArrayList();
// Both polygons must be manhattan-shaped type
if (thisBounds == null || otherBounds == null) return (null);
int dir = -1;
double [][] points1 = {{thisBounds.getMinX(), thisBounds.getMinY()},
{thisBounds.getMaxX(), thisBounds.getMaxY()}};
double [][] points2 = {{otherBounds.getMinX(), otherBounds.getMinY()},
{otherBounds.getMaxX(), otherBounds.getMaxY()}};
double pdx = Math.max(points2[0][PolyBase.X]-points1[1][PolyBase.X], points1[0][PolyBase.X]-points2[1][PolyBase.X]);
double pdy = Math.max(points2[0][PolyBase.Y]-points1[1][PolyBase.Y], points1[0][PolyBase.Y]-points2[1][PolyBase.Y]);
double area1 = 0, area2 = 0;
double over1 = 0, over2 = 0;
double length1 = 0, length2 = 0;
double thickP1 = p1.getLayer().getThickness();
double thickP2 = p1.getLayer().getThickness();
// 1 for now
thickP1 = thickP2 = 1;
if (pdx > 0 && pdy > 0) // Diagonal
{
// Two elements
ParasiticValue newValue1 = new ParasiticValue();
ParasiticValue newValue2 = new ParasiticValue();
// newValue1.distance = newValue2.distance = Math.hypot(pdx, pdy);
// newValue1.angle = newValue2.angle = true;
// Poly1:X v/s Poly2:Y
length1 = p1.getBox().getWidth();
length2 = p2.getBox().getHeight();
area1 = thickP1 * p1.getBox().getHeight();
area2 = thickP2 * p2.getBox().getWidth();
newValue1.elements[0] = new ParasiticBucket(p1, area1, length1);
newValue1.elements[1] = new ParasiticBucket(p2, area2, length2);
// Poly1:X v/s Poly2:Y
length1 = p1.getBox().getHeight();
length2 = p2.getBox().getWidth();
area1 = thickP1 * p1.getBox().getWidth();
area2 = thickP2 * p2.getBox().getHeight();
newValue2.elements[0] = new ParasiticBucket(p1, area1, length1);
newValue2.elements[1] = new ParasiticBucket(p2, area2, length2);
values.add(newValue1);
values.add(newValue2);
}
else
{
if (pdx == 0 || pdy == 0)
System.out.println("How do I treat this?");
ParasiticValue newValue = new ParasiticValue();
// newValue.angle = false;
if (pdx > pdy)
{
dir = PolyBase.X;
// newValue.distance = pdx;
length1 = p1.getBox().getWidth();
length2 = p2.getBox().getWidth();
}
else
{
dir = PolyBase.Y;
// newValue.distance = pdy;
length1 = p1.getBox().getHeight();
length2 = p2.getBox().getHeight();
}
int oppDir = (dir+1)%2;
over1 = over2 = Math.min(points1[1][oppDir], points2[1][oppDir]) -
Math.max(points1[0][oppDir], points2[0][oppDir]);
area1 = thickP1 * over1;
area2 = thickP2 * over2;
newValue.elements[0] = new ParasiticBucket(p1, area1, length1);
newValue.elements[1] = new ParasiticBucket(p2, area2, length2);
values.add(newValue);
}
return values;
}
}
/****************************** OPTIONS ******************************/
/****************************** Job ******************************/
private static class AnalyzeParasitic extends Job
{
Cell cell;
Network net;
protected AnalyzeParasitic(Network network, Cell cell)
{
super ("Analyze "+ network, tool, Job.Type.SERVER_EXAMINE, null, cell, Job.Priority.USER);
this.net = network;
this.cell = cell;
this.startJob();
}
private List getClosestPolys(Cell cell, Geometric geom, Technology tech, Poly poly, Rectangle2D bounds)
{
List polyList = new ArrayList();
for(Iterator it = cell.searchIterator(bounds); it.hasNext(); )
{
Geometric nGeom = it.next();
if (nGeom == geom) continue;
// Touching elements out
if (nGeom.isConnected(geom)) continue;
if (nGeom instanceof NodeInst)
{
NodeInst ni = (NodeInst)nGeom;
NodeProto np = ni.getProto();
if (np == Generic.tech().cellCenterNode) continue;
if (np.getFunction().isPin()) continue;
// don't check between technologies
if (np.getTechnology() != tech) continue;
// ignore nodes that are not primitive
if (ni.isCellInstance())
System.out.println("Skipping case for now");
else
{
//if (layer.isNonElectrical()) continue; // Valid for Pins
System.out.println("Found node " + nGeom + " for " + geom);
FixpTransform trans = ni.rotateOut();
Poly [] nodeInstPolyList = tech.getShapeOfNode(ni);
for(int i = 0; i < nodeInstPolyList.length; i++)
{
Poly nPoly = nodeInstPolyList[i];
Layer layer = nPoly.getLayer();
if (!layer.getFunction().isMetal()) continue;
nPoly.transform(trans);
polyList.addAll(ParasiticValue.initParasiticValues(poly, nPoly));
}
}
} else
{ // Arc then
ArcInst ai = (ArcInst)nGeom;
ArcProto ap = ai.getProto();
// don't check between technologies
if (ap.getTechnology() != tech) continue;
System.out.println("Found arc " + nGeom + " for " + geom);
Poly [] arcInstPolyList = tech.getShapeOfArc(ai);
for(int i = 0; i < arcInstPolyList.length; i++)
{
Poly nPoly = arcInstPolyList[i];
Layer layer = nPoly.getLayer();
if (!layer.getFunction().isMetal()) continue;
nPoly = ai.cropPerLayer(nPoly);
if (nPoly != null) // @TODO check this null condition
polyList.addAll(ParasiticValue.initParasiticValues(poly, nPoly));
}
}
}
return polyList;
}
/**
* Implementation of Job.doIt() abstract function
*/
public boolean doIt() throws JobException
{
ElapseTimer timer = ElapseTimer.createInstance().start();
System.out.println("Extracting Parasitic for " + cell + " " + net);
Rectangle2D bounds = new Rectangle2D.Double();
double maxDistance = getMaxDistance();
List polyToCheckList = new ArrayList();
// Selecting arcs attached to this network
for (Iterator it = net.getArcs(); it.hasNext(); )
{
ArcInst ai = it.next();
Technology tech = ai.getProto().getTechnology();
Poly [] arcInstPolyList = tech.getShapeOfArc(ai);
for(int i = 0; i < arcInstPolyList.length; i++)
{
Poly poly = arcInstPolyList[i];
Layer layer = poly.getLayer();
if (!layer.getFunction().isMetal()) continue;
//polyToCheckList.add(poly);
poly = ai.cropPerLayer(poly);
Rectangle2D bnd = poly.getBounds2D();
bounds.setRect(bnd.getMinX()-maxDistance, bnd.getMinY()-maxDistance,
bnd.getWidth()+maxDistance*2, bnd.getHeight()+maxDistance*2);
polyToCheckList.addAll(getClosestPolys(cell, ai, tech, poly, bounds));
//merge.add(layer, new PolyQTree.PolyNode(poly), false);
}
}
// Adding related nodes, searching per ports
Map nodeMap = new HashMap();
for (Iterator it = net.getPorts(); it.hasNext(); )
{
PortInst pi = it.next();
NodeInst ni = pi.getNodeInst();
if (nodeMap.get(ni) != null) continue; // Already analyzed
FixpTransform trans = ni.rotateOut();
NodeProto np = ni.getProto();
nodeMap.put(ni, ni);
if (!ni.isCellInstance())
{
PrimitiveNode pNp = (PrimitiveNode)np;
Technology tech = pNp.getTechnology();
Poly [] nodeInstPolyList = tech.getShapeOfNode(ni);
for(int i = 0; i < nodeInstPolyList.length; i++)
{
Poly poly = nodeInstPolyList[i];
if (poly.isPseudoLayer()) continue;
Layer layer = poly.getLayer();
if (!layer.getFunction().isMetal()) continue;
poly.transform(trans);
Rectangle2D bnd = poly.getBounds2D();
bounds.setRect(bnd.getMinX()-maxDistance, bnd.getMinY()-maxDistance,
bnd.getWidth()+maxDistance*2, bnd.getHeight()+maxDistance*2);
polyToCheckList.addAll(getClosestPolys(cell, ni, tech, poly, bounds));
//merge.add(layer, new PolyQTree.PolyNode(poly), false);
}
}
else
System.out.println("Not implemented");
}
for (ParasiticValue val : polyToCheckList)
{
System.out.println("Value " + val + " Layer " + val.elements[1].poly.getLayer());
}
timer.end();
System.out.println("Done (took " + timer + ")");
// sort the errors by layer
errorLogger.sortLogs();
return true;
}
}
//----------------------------IRSIM Cell Info for HierarchyEnumerator--------------------
/**
* Class to define cell information for Parasitic extraction
*/
public static class ParasiticCellInfo extends HierarchyEnumerator.CellInfo
{
/** M-factor to be applied to size */ private float mFactor;
/** initialize ParasiticCellInfo: called from enterCell */
protected void extInit()
{
HierarchyEnumerator.CellInfo parent = getParentInfo();
if (parent == null) mFactor = 1f;
else mFactor = ((ParasiticCellInfo)parent).getMFactor();
// get mfactor from instance we pushed into
Nodable ni = getContext().getNodable();
if (ni == null) return;
Variable mvar = ni.getVar(SimulationTool.M_FACTOR_KEY);
if (mvar == null) return;
Object mval = getContext().evalVar(mvar, null);
if (mval == null) return;
mFactor = mFactor * VarContext.objectToFloat(mval, 1f);
}
/** get mFactor */
public float getMFactor() { return mFactor; }
}
/** PREFERENCES */
private static Pref cacheMaxDistance = Pref.makeDoublePref("MaximumDistance", ParasiticTool.tool.prefs, 20);
/**
* Method to get maximum dstance for searching window
* @return double representing the preference
*/
public static double getMaxDistance() { return cacheMaxDistance.getDouble(); }
/**
* Method to set maximum distance to use during searching window
* @param value to set
*/
public static void setMaxDistance(double value) { cacheMaxDistance.setDouble(value); }
/**
* Method to get maximum dstance for searching window, by default.
* @return double representing the preference, by default.
*/
public static double getFactoryMaxDistance() { return cacheMaxDistance.getDoubleFactoryValue(); }
}