Some changes to ext2sim and extresist to support arbitrary device
types and substrate connections. This is an intermediate step to switching from a sim file format to an ext file format for input, but resolves the worst issues of having the sim file not recognize the devices or the substrate nodes. Implemented by using the sim subcircuit format introduced in IRSIM with the "user subcircuit" package. Implementation unfinished (work in progress).
This commit is contained in:
parent
1e08e90b2f
commit
abb3c3b98b
|
|
@ -999,11 +999,12 @@ simdevVisit(dev, hc, scale, trans)
|
|||
float scale; /* Scale transform for output */
|
||||
Transform *trans; /* Coordinate transform */
|
||||
{
|
||||
DevTerm *gate, *source, *drain;
|
||||
DevTerm *gate, *source, *drain, *term;
|
||||
EFNode *subnode, *snode, *dnode;
|
||||
int l, w;
|
||||
Rect r;
|
||||
char name[12];
|
||||
bool is_subckt = FALSE;
|
||||
HierName *hierName = hc->hc_hierName;
|
||||
|
||||
sprintf(name, "output");
|
||||
|
|
@ -1057,7 +1058,6 @@ simdevVisit(dev, hc, scale, trans)
|
|||
case DEV_FET:
|
||||
case DEV_MOSFET:
|
||||
case DEV_ASYMMETRIC:
|
||||
case DEV_MSUBCKT:
|
||||
/* The sim file format only understands "n" and "p" for FETs. */
|
||||
/* The extraction method says nothing about which is which. */
|
||||
/* The EFDevTypes[] should ideally start with "n" or "p". If */
|
||||
|
|
@ -1089,6 +1089,19 @@ simdevVisit(dev, hc, scale, trans)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case DEV_MSUBCKT:
|
||||
case DEV_CSUBCKT:
|
||||
case DEV_RSUBCKT:
|
||||
case DEV_SUBCKT:
|
||||
/* Use the 'x' type in .sim format. This is implemented in the */
|
||||
/* IRSIM "user subcircuit" package, so it has a valid syntax. */
|
||||
/* It is used by the extresist code in magic as a way to work */
|
||||
/* around the lack of substrate and lack of device names in the */
|
||||
/* .sim format. */
|
||||
is_subckt = TRUE;
|
||||
fprintf(esSimF, "x");
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(esSimF, "%c", EFDevTypes[dev->dev_type][0]);
|
||||
break;
|
||||
|
|
@ -1121,8 +1134,31 @@ simdevVisit(dev, hc, scale, trans)
|
|||
else if (dev->dev_nterm > 2)
|
||||
simdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, name, esSimF);
|
||||
|
||||
if (dev->dev_nterm > 3) /* For subcircuit support ('x' device) */
|
||||
{
|
||||
int i;
|
||||
|
||||
sprintf(name, "subckt");
|
||||
for (i = 3; i < dev->dev_nterm; i++)
|
||||
{
|
||||
term = &dev->dev_terms[i];
|
||||
simdevOutNode(hierName, term->dterm_node->efnode_name->efnn_hier,
|
||||
name, esSimF);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_subckt && subnode)
|
||||
{
|
||||
/* As a general policy on subcircuits supporting extresist, */
|
||||
/* output the subcircuit node as the last port of the */
|
||||
/* subcircuit definition. */
|
||||
putc(' ', esSimF);
|
||||
simdevSubstrate(hierName, subnode->efnode_name->efnn_hier,
|
||||
dev->dev_type, 0.0, FALSE, esSimF);
|
||||
}
|
||||
|
||||
/* Support gemini's substrate comparison */
|
||||
if (esFormat == LBL && subnode)
|
||||
else if (esFormat == LBL && subnode)
|
||||
{
|
||||
putc(' ', esSimF);
|
||||
simdevSubstrate(hierName, subnode->efnode_name->efnn_hier,
|
||||
|
|
@ -1165,6 +1201,15 @@ simdevVisit(dev, hc, scale, trans)
|
|||
else if (dev->dev_class == DEV_CAPREV) { /* generate a capacitor */
|
||||
fprintf(esSimF, " %f", (double)(dev->dev_cap));
|
||||
}
|
||||
else if (is_subckt)
|
||||
{
|
||||
/* Output length, width, and position as attributes */
|
||||
fprintf(esSimF, " l=%g w=%g x=%g y=%g",
|
||||
l * scale, w * scale, r.r_xbot * scale, r.r_ybot * scale);
|
||||
|
||||
/* Output tile type as an attribute for quick lookup by ResReadSim */
|
||||
fprintf(esSimF, " t=%d", fetInfo[dev->dev_type].devType);
|
||||
}
|
||||
else if ((dev->dev_class != DEV_DIODE) && (dev->dev_class != DEV_PDIODE)
|
||||
&& (dev->dev_class != DEV_NDIODE)) {
|
||||
|
||||
|
|
@ -1235,6 +1280,13 @@ simdevVisit(dev, hc, scale, trans)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_subckt)
|
||||
{
|
||||
/* Last token on a subcircuit 'x' line is the subcircuit name */
|
||||
fprintf(esSimF, " %s", EFDevTypes[dev->dev_type]);
|
||||
}
|
||||
|
||||
fprintf(esSimF, "\n");
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -27,12 +27,13 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "textio/textio.h"
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extractInt.h"
|
||||
#include "extflat/extflat.h"
|
||||
#include "windows/windows.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
#include "utils/utils.h"
|
||||
#include "utils/tech.h"
|
||||
#include "textio/txcommands.h"
|
||||
#include "resis/resis.h"
|
||||
#include "resis/resis.h"
|
||||
|
||||
|
||||
/* constants defining where various fields can be found in .sim files. */
|
||||
|
|
@ -119,10 +120,10 @@ extern void ResSimProcessDrivePoints();
|
|||
*/
|
||||
|
||||
int
|
||||
ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc)
|
||||
ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
||||
char *simfile;
|
||||
int (*fetproc)(),(*capproc)(),(*resproc)();
|
||||
int (*attrproc)(),(*mergeproc)();
|
||||
int (*fetproc)(), (*capproc)(), (*resproc)();
|
||||
int (*attrproc)(), (*mergeproc)(), (*subproc)();
|
||||
|
||||
{
|
||||
char line[MAXLINE][MAXTOKEN];
|
||||
|
|
@ -172,6 +173,8 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc)
|
|||
line[ATTRIBUTEVALUE],
|
||||
simfile, &extfile);
|
||||
break;
|
||||
case 'x': fettype = DBNumTypes;
|
||||
break;
|
||||
case 'D':
|
||||
case 'c':
|
||||
case 'r': break;
|
||||
|
|
@ -184,6 +187,10 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc)
|
|||
TxError("Error in Reading device line of sim file.\n");
|
||||
result = 1;
|
||||
}
|
||||
else if (fettype == DBNumTypes)
|
||||
{
|
||||
result = (*subproc)(line);
|
||||
}
|
||||
else if (fettype != MINFINITY)
|
||||
{
|
||||
float sheetr;
|
||||
|
|
@ -317,6 +324,130 @@ gettokens(line,fp)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResSimSubckt-- Processes a subcircuit line from a sim file.
|
||||
* This uses the "user subcircuit" extension defined in
|
||||
* IRSIM, although it is mostly intended as a way to work
|
||||
* around the device type limitations of the .sim format
|
||||
* when using extresist.
|
||||
*
|
||||
* Results: returns 0 if line was added correctly.
|
||||
*
|
||||
* Side Effects: Allocates devices and adds nodes to the node hash table.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
ResSimSubckt(line)
|
||||
char line[][MAXTOKEN];
|
||||
{
|
||||
RDev *device;
|
||||
int rvalue, i, j, k;
|
||||
static int nowarning = TRUE;
|
||||
float lambda;
|
||||
TileType ttype = TT_SPACE;
|
||||
char *lptr = NULL, *wptr = NULL;
|
||||
|
||||
device = (RDev *) mallocMagic((unsigned) (sizeof(RDev)));
|
||||
|
||||
device->status = FALSE;
|
||||
device->nextDev = ResRDevList;
|
||||
|
||||
lambda = (float)ExtCurStyle->exts_unitsPerLambda / resscale;
|
||||
device->location.p_x = 0;
|
||||
device->location.p_y = 0;
|
||||
|
||||
device->rs_gattr=RDEV_NOATTR;
|
||||
device->rs_sattr=RDEV_NOATTR;
|
||||
device->rs_dattr=RDEV_NOATTR;
|
||||
|
||||
ResRDevList = device;
|
||||
device->layout = NULL;
|
||||
|
||||
/* The last argument is the name of the device */
|
||||
for (i = 1; line[i][0] != '\0'; i++);
|
||||
i--;
|
||||
|
||||
for (j = 0; j < EFDevNumTypes; j++)
|
||||
if (!strcmp(EFDevTypes[j], line[i]))
|
||||
break;
|
||||
|
||||
/* Read attributes, especially to pick up values for L, W, X, and Y,
|
||||
* that are critical for use by extresist.
|
||||
*/
|
||||
for (k = 1; line[k][0] != '\0'; k++)
|
||||
{
|
||||
char *eqptr;
|
||||
eqptr = strchr(line[k], '=');
|
||||
if (eqptr != NULL)
|
||||
{
|
||||
if (k < i) i = k;
|
||||
eqptr++;
|
||||
switch (line[k][0]) {
|
||||
case 'l':
|
||||
lptr = eqptr;
|
||||
break;
|
||||
case 'w':
|
||||
wptr = eqptr;
|
||||
break;
|
||||
case 'x':
|
||||
device->location.p_x = (int)((float)atof(eqptr) / lambda);
|
||||
break;
|
||||
case 'y':
|
||||
device->location.p_y = (int)((float)atof(eqptr) / lambda);
|
||||
break;
|
||||
case 't':
|
||||
ttype = (int)(atoi(eqptr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This should not be needed, as ext2sim should encode device type */
|
||||
/* in the attributes list. */
|
||||
if (ttype == TT_SPACE)
|
||||
{
|
||||
if (j == EFDevNumTypes)
|
||||
{
|
||||
TxError("Failure to find device type %s\n", line[i]);
|
||||
return 1;
|
||||
}
|
||||
ttype = extGetDevType(EFDevTypes[j]);
|
||||
}
|
||||
|
||||
device->rs_ttype = ttype;
|
||||
|
||||
if (lptr != NULL && wptr != NULL)
|
||||
{
|
||||
float rpersquare;
|
||||
ExtDevice *devptr;
|
||||
|
||||
devptr = ExtCurStyle->exts_device[ttype];
|
||||
rpersquare =(float)devptr->exts_linearResist;
|
||||
device->resistance = MagAtof(lptr) * rpersquare/MagAtof(wptr);
|
||||
}
|
||||
else
|
||||
device->resistance = 0;
|
||||
|
||||
rvalue = 0;
|
||||
for (k = 1; k < i; k++)
|
||||
{
|
||||
if (k > SUBS)
|
||||
{
|
||||
TxError("Device %s has more than 4 ports (not handled).\n", line[i]);
|
||||
break; /* No method to handle more ports than this */
|
||||
}
|
||||
rvalue += ResSimNewNode(line[k], k, device);
|
||||
}
|
||||
|
||||
return rvalue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -330,7 +461,7 @@ gettokens(line,fp)
|
|||
*/
|
||||
|
||||
int
|
||||
ResSimDevice(line,rpersquare,ttype)
|
||||
ResSimDevice(line, rpersquare, ttype)
|
||||
char line[][MAXTOKEN];
|
||||
float rpersquare;
|
||||
TileType ttype;
|
||||
|
|
@ -428,7 +559,7 @@ ResSimDevice(line,rpersquare,ttype)
|
|||
*/
|
||||
|
||||
int
|
||||
ResSimNewNode(line,type,device)
|
||||
ResSimNewNode(line, type, device)
|
||||
char line[];
|
||||
int type;
|
||||
RDev *device;
|
||||
|
|
@ -443,7 +574,7 @@ ResSimNewNode(line,type,device)
|
|||
TxError("Missing device connection\n");
|
||||
return(1);
|
||||
}
|
||||
entry = HashFind(&ResNodeTable,line);
|
||||
entry = HashFind(&ResNodeTable, line);
|
||||
node = ResInitializeNode(entry);
|
||||
tptr = (devPtr *) mallocMagic((unsigned) (sizeof(devPtr)));
|
||||
tptr->thisDev = device;
|
||||
|
|
@ -458,6 +589,8 @@ ResSimNewNode(line,type,device)
|
|||
break;
|
||||
case DRAIN: device->drain = node;
|
||||
break;
|
||||
case SUBS: device->subs = node;
|
||||
break;
|
||||
default: TxError("Bad Terminal Specifier\n");
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,8 +105,8 @@ ExtResisForDef(celldef, resisdata)
|
|||
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||
/* read in .sim file */
|
||||
result = (ResReadSim(celldef->cd_name,
|
||||
ResSimDevice,ResSimCapacitor,ResSimResistor,
|
||||
ResSimAttribute,ResSimMerge) == 0);
|
||||
ResSimDevice, ResSimCapacitor, ResSimResistor,
|
||||
ResSimAttribute, ResSimMerge, ResSimSubckt) == 0);
|
||||
|
||||
if (result)
|
||||
/* read in .nodes file */
|
||||
|
|
|
|||
|
|
@ -293,6 +293,7 @@ typedef struct rdev
|
|||
struct ressimnode *gate; /* Terminals of transistor. */
|
||||
struct ressimnode *source;
|
||||
struct ressimnode *drain;
|
||||
struct ressimnode *subs; /* Used with subcircuit type only */
|
||||
Point location; /* Location of lower left point of */
|
||||
/* device. */
|
||||
float resistance; /* "Resistance" of device. */
|
||||
|
|
@ -519,6 +520,7 @@ typedef struct capval
|
|||
#define GATE 1
|
||||
#define SOURCE 2
|
||||
#define DRAIN 3
|
||||
#define SUBS 4
|
||||
|
||||
#define DRIVEONLY 0x00001000
|
||||
#define ORIGIN 0x00000008
|
||||
|
|
@ -610,6 +612,7 @@ extern int ResSimCapacitor();
|
|||
extern int ResSimResistor();
|
||||
extern int ResSimAttribute();
|
||||
extern int ResSimMerge();
|
||||
extern int ResSimSubckt();
|
||||
extern int dbSrConnectStartFunc();
|
||||
extern int ResEach(),ResAddPlumbing(),ResRemovePlumbing();
|
||||
extern float ResCalculateChildCapacitance();
|
||||
|
|
|
|||
Loading…
Reference in New Issue