com.sun.electric.plugins.irsim.Config Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of electric-irsim Show documentation
Show all versions of electric-irsim Show documentation
IRSIM simulator rewritten to Java.
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Config.java
* IRSIM simulator
* Translated by Steven M. Rubin, Sun Microsystems.
*
* Copyright (C) 1988, 1990 Stanford University.
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. Stanford University
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
package com.sun.electric.plugins.irsim;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
public class Config
{
/**
* info on resistance vs. width and length are stored first sorted by
* width, then by length.
*/
private static class Length
{
/** next element with same width */ Length next;
/** length of this channel in centimicrons */ long l;
/** equivalent resistance/square */ double r;
};
private static class Width
{
/** next width */ Width next;
/** width of this channel in centimicrons */ long w;
/** list of length structures */ Length list;
}
/** centimicrons per micron */ private static final double CM_M = 100.0;
/* values of configFlags */
/** set if capacitance from gate of pullup should be included. */ private static final int CNTPULLUP = 0x2;
/** set if diffusion perimeter does not include sources/drains of transistors. */ private static final int DIFFPERIM = 0x4;
/** set if poly over xistor doesn't make a capacitor */ private static final int SUBPAREA = 0x8;
/** set if we should add capacitance due to diffusion-extension of source/drain. */ private static final int DIFFEXTF = 0x10;
/** set if DIFFPERIM or DIFFEXTF are true */ private static final int TDIFFCAP = 0x1;
private static final int RES_TAB_SIZE = 67;
/*
* electrical parameters used for deriving capacitance info for charge
* sharing. Default values aren't for any particular process, but are
* self-consistent.
* Area capacitances are all in pfarads/sq-micron units.
* Perimeter capacitances are all in pfarads/micron units.
*/
/** 2nd metal capacitance -- area */ public double CM2A = .00000;
/** 2nd metal capacitance -- perimeter */ public double CM2P = .00000;
/** 1st metal capacitance -- area */ public double CMA = .00003;
/** 1st metal capacitance -- perimeter */ public double CMP = .00000;
/** poly capacitance -- area */ public double CPA = .00004;
/** poly capacitance -- perimeter */ public double CPP = .00000;
/** n-diffusion capacitance -- area */ public double CDA = .00010;
/** n-diffusion capacitance -- perimeter */ public double CDP = .00060;
/** p-diffusion capacitance -- area */ public double CPDA = .00010;
/** p-diffusion capacitance -- perimeter */ public double CPDP = .00060;
/** gate capacitance -- area */ private double CGA = .00040;
/** microns/lambda */ public double lambda = 2.5;
/** LAMBDA**2 */ public double lambdaSquared = 6.25;
/** centi-microns/lambda */ public long lambdaCM = 250;
/** low voltage threshold, normalized units */ public double lowThresh = 0.3;
/** high voltage threshold,normalized units */ public double highThresh = 0.8;
// /** width of source/drain diffusion */ private double DIFFEXT = 0;
/* the following are computed from above */
/** xtor gate capacitance -- area */ public double CTGA;
private List [][] resHTab;
private int configFlags;
private String [] tTypeDrop;
private Width [][] resistances;
/**
* Class for storing and reading configuration information.
*/
public Config()
{
resHTab = new List[Sim.NTTYPES][];
for(int i=0; i= 6)
insert(fileName, lineReader.getLineNumber(), targ[1], targ[2], targ[3], targ[4], targ[5], analyzer); else
{
Sim.reportError(fileName, lineReader.getLineNumber(), "syntax error in resistance spec");
}
} else
{
if (targ[0].equals("capm2a")) CM2A = analyzer.atof(targ[1]); else
if (targ[0].equals("capm2p")) CM2P = analyzer.atof(targ[1]); else
if (targ[0].equals("capma")) CMA = analyzer.atof(targ[1]); else
if (targ[0].equals("capmp")) CMP = analyzer.atof(targ[1]); else
if (targ[0].equals("cappa")) CPA = analyzer.atof(targ[1]); else
if (targ[0].equals("cappp")) CPP = analyzer.atof(targ[1]); else
if (targ[0].equals("capda")) CDA = analyzer.atof(targ[1]); else
if (targ[0].equals("capdp")) CDP = analyzer.atof(targ[1]); else
if (targ[0].equals("cappda")) CPDA = analyzer.atof(targ[1]); else
if (targ[0].equals("cappdp")) CPDP = analyzer.atof(targ[1]); else
if (targ[0].equals("capga")) CGA = analyzer.atof(targ[1]); else
if (targ[0].equals("lambda")) lambda = analyzer.atof(targ[1]); else
if (targ[0].equals("lowthresh")) lowThresh = analyzer.atof(targ[1]); else
if (targ[0].equals("highthresh")) highThresh = analyzer.atof(targ[1]); else
if (targ[0].equals("diffperim"))
{
if (analyzer.atof(targ[1]) != 0.0) configFlags |= DIFFPERIM;
} else if (targ[0].equals("cntpullup"))
{
if (analyzer.atof(targ[1]) != 0.0) configFlags |= CNTPULLUP;
} else if (targ[0].equals("subparea"))
{
if (analyzer.atof(targ[1]) != 0.0) configFlags |= SUBPAREA;
} else if (targ[0].equals("diffext"))
{
if (analyzer.atof(targ[1]) != 0.0)
{
// DIFFEXT = analyzer.atof(targ[1]);
configFlags |= DIFFEXTF;
}
} else
{
Sim.reportError(fileName, lineReader.getLineNumber(), "unknown electrical parameter: (" + targ[0] + ")");
}
}
}
inputStream.close();
} catch (IOException e)
{
System.out.println("Error reading electrical parameters file");
}
lambdaSquared = lambda * lambda;
lambdaCM = (long)(lambda * CM_M);
CTGA = ((configFlags & SUBPAREA) != 0 ? (CGA - CPA) : CGA) / (CM_M * CM_M);
// double CTDW = 0; // xtor diff-width capacitance -- perimeter
// double CPTDW = 0;
// double CTDE = 0; // xtor diff-extension cap. -- perimeter
// double CPTDE = 0;
switch(configFlags & (DIFFEXTF | DIFFPERIM))
{
case DIFFPERIM:
configFlags |= TDIFFCAP;
// CTDE = CPTDE = 0.0;
// CTDW = -(CDP / CM_M);
// CPTDW = -(CPDP / CM_M);
break;
case DIFFEXTF:
configFlags |= TDIFFCAP;
// CTDE = (2 * DIFFEXT * lambda * CDP);
// CPTDE = (2 * DIFFEXT * lambda * CPDP);
// CTDW = (CDP + DIFFEXT * lambda * CDA) / CM_M;
// CPTDW = (CPDP + DIFFEXT * lambda * CPDA) / CM_M;
break;
case (DIFFEXTF | DIFFPERIM):
configFlags |= TDIFFCAP;
// CTDE = (2 * DIFFEXT * lambda * CDP);
// CPTDE = (2 * DIFFEXT * lambda * CPDP);
// CTDW = (DIFFEXT * lambda * CDA) / CM_M;
// CPTDW = (DIFFEXT * lambda * CPDA) / CM_M;
break;
}
if ((configFlags & CNTPULLUP) != 0)
System.out.println("warning: cntpullup is not supported");
return false;
}
/**
* Compute equivalent resistance given width, length and type of transistor.
* for all contexts (STATIC, DYNHIGH, DYNLOW). Place the result on the
* transistor
*/
public Sim.Resists rEquiv(int type, long width, long length)
{
type = Sim.baseType(type);
List [] rTab = resHTab[type];
if (rTab == null)
{
rTab = new List[RES_TAB_SIZE];
for(int n = 0; n < RES_TAB_SIZE; n++) rTab[n] = null;
resHTab[type] = rTab;
}
int n = (int)(Math.abs(length * 110133 + width) % RES_TAB_SIZE);
if (rTab[n] != null)
{
for(Sim.Resists rr : rTab[n])
{
if (rr.length == length && rr.width == width) return rr;
}
}
Sim.Resists rr = new Sim.Resists();
if (rTab[n] == null) rTab[n] = new ArrayList();
rTab[n].add(rr);
rr.length = length;
rr.width = width;
if (type == Sim.RESIST)
{
rr.dynRes[Sim.R_LOW] = rr.dynRes[Sim.R_HIGH] = rr.rStatic = (float) length / lambdaCM;
} else
{
rr.rStatic = (float)wResist(resistances[Sim.STATIC][type], width, length);
rr.dynRes[Sim.R_LOW] = (float)wResist(resistances[Sim.DYNLOW][type], width, length);
rr.dynRes[Sim.R_HIGH] = (float)wResist(resistances[Sim.DYNHIGH][type], width, length);
}
return rr;
}
/**
* linear interpolation, assume that x1 < x <= x2
*/
private double interp(double x, double x1, double y1, double x2, double y2)
{
return ((x - x1) / (x2 - x1)) * (y2 - y1) + y1;
}
/**
* given a list of length structures, sorted by increasing length return
* resistance of given channel. If no exact match, return result of
* linear interpolation using two closest channels.
*/
private double lResist(Length list, long l, double size)
{
Length q = null;
for(Length p = list; p != null; q = p, p = p.next)
{
if (p.l == l ||(p.l > l && q == null))
return p.r * size;
if (p.l > l)
return size * interp(l, q.l, q.r, p.l, p.r);
}
if (q != null)
return q.r *size;
return 1E4 * size;
}
/**
* given a pointer to the width structures for a particular type of
* channel compute the resistance for the specified channel.
*/
private double wResist(Width list, long w, long l)
{
double size = ((double) l) / ((double) w);
Width q = null;
for(Width p = list; p != null; q = p, p = p.next)
{
if (p.w == w || (p.w > w && q == null))
return lResist(p.list, l, size);
if (p.w > w)
{
double temp = lResist(q.list, l, size);
return interp(w, q.w, temp, p.w, lResist(p.list, l, size));
}
}
if (q != null)
return lResist(q.list, l, size);
return 1E4 * size;
}
private Length lInsert(Length list, long l, double resist)
{
Length ret = list;
Length p = list, q = null;
for( ; p != null; q = p, p = p.next)
{
if (p.l == l)
{
p.r = resist;
return ret;
}
if (p.l > l) break;
}
Length lNew = new Length();
lNew.next = p;
lNew.l = l;
lNew.r = resist;
if (q == null)
ret = lNew;
else
q.next = lNew;
return ret;
}
/**
* add a new data point to the interpolation array
*/
private void wInsert(int c, int t, long w, long l, double resist)
{
Width list = resistances[c][t];
Width p = list, q = null;
for( ; p != null; q = p, p = p.next)
{
if (p.w == w)
{
p.list = lInsert(p.list, l, resist);
return;
}
if (p.w > w) break;
}
Width wNew = new Width();
Length lNew = new Length();
wNew.next = p;
wNew.list = lNew;
wNew.w = w;
if (q == null)
resistances[c][t] = wNew;
else
q.next = wNew;
lNew.next = null;
lNew.l = l;
lNew.r = resist;
}
/**
* interpret resistance specification command
*/
private void insert(String fileName, int lineNo, String type, String context, String w, String l, String r, SimAPI.Analyzer analyzer)
{
long width = (long)(analyzer.atof(w) * CM_M);
long length = (long)(analyzer.atof(l) * CM_M);
double resist = analyzer.atof(r);
if (width <= 0 || length <= 0 || resist <= 0)
{
Sim.reportError(fileName, lineNo, "bad w, l, or r in config file");
return;
}
int c = 0;
if (context.equalsIgnoreCase("static")) c = Sim.STATIC; else
if (context.equalsIgnoreCase("dynamic-high")) c = Sim.DYNHIGH; else
if (context.equalsIgnoreCase("dynamic-low")) c = Sim.DYNLOW; else
if (context.equalsIgnoreCase("power")) c = Sim.POWER; else
{
Sim.reportError(fileName, lineNo, "bad resistance context in config file");
return;
}
for(int t = 0; t < Sim.NTTYPES; t++)
{
if (Sim.transistorType[t].equalsIgnoreCase(type))
{
if (c != Sim.POWER)
wInsert(c, t, width, length, resist*width/length);
return;
}
if (tTypeDrop[t].equalsIgnoreCase(type)) return;
}
Sim.reportError(fileName, lineNo, "bad resistance transistor type");
}
}