All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.electric.plugins.irsim.Config Maven / Gradle / Ivy

There is a newer version: 0.3
Show newest version
/* -*- 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");
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy