diff --git a/ext2sim/ext2sim.c b/ext2sim/ext2sim.c index 35b28c05..e40148b7 100644 --- a/ext2sim/ext2sim.c +++ b/ext2sim/ext2sim.c @@ -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; diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index 8c040e48..e2bfc2b5 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -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; } diff --git a/resis/ResRex.c b/resis/ResRex.c index 1fb8f4a8..bde291e2 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -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 */ diff --git a/resis/resis.h b/resis/resis.h index cadf28cc..9507df0f 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -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();