Merge branch 'master' into magic-8.2

This commit is contained in:
Tim Edwards 2019-10-29 03:00:10 -04:00
commit 33e68615bd
9 changed files with 208 additions and 120 deletions

View File

@ -1771,7 +1771,8 @@ esHierVisit(hc, cdata)
if (def != topdef)
{
if ((def->def_devs == NULL) && (HashGetNumEntries(&def->def_uses) == 0))
if ((HashGetNumEntries(&def->def_devs) == 0) &&
(HashGetNumEntries(&def->def_uses) == 0))
{
if (locDoSubckt == AUTO)
{

View File

@ -591,23 +591,28 @@ efBuildDevice(def, class, type, r, argc, argv)
Rect *r; /* Coordinates of 1x1 rectangle entirely inside device */
int argc; /* Size of argv */
char *argv[]; /* Tokens for the rest of the dev line.
* The first depend on the type of device. The rest
* are taken in groups of 3, one for each terminal.
* Each group of 3 consists of the node name to which
* the terminal connects, the length of the terminal,
* and an attribute list (or the token 0).
* Starts with the last two position values, used to
* hash the device record. The next arguments depend
* on the type of device. The rest are taken in groups
* of 3, one for each terminal. Each group of 3 consists
* of the node name to which the terminal connects, the
* length of the terminal, and an attribute list (or the
* token 0).
*/
{
int n, nterminals, pn;
HashEntry *he;
DevTerm *term;
Dev *newdev, devtmp;
DevParam *newparm, *devp, *sparm;
char ptype, *pptr, **av;
char devhash[24];
int argstart = 1; /* start of terminal list in argv[] */
bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
newdev = (Dev *)NULL;
devtmp.dev_subsnode = NULL;
devtmp.dev_cap = 0.0;
devtmp.dev_res = 0.0;
@ -713,7 +718,6 @@ efBuildDevice(def, class, type, r, argc, argv)
}
/* Check for optional substrate node */
switch (class)
{
case DEV_RES:
@ -743,93 +747,149 @@ efBuildDevice(def, class, type, r, argc, argv)
nterminals = (argc - argstart) / 3;
newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals));
newdev->dev_subsnode = devtmp.dev_subsnode;
newdev->dev_cap = devtmp.dev_cap;
newdev->dev_res = devtmp.dev_res;
newdev->dev_area = devtmp.dev_area;
newdev->dev_perim = devtmp.dev_perim;
newdev->dev_length = devtmp.dev_length;
newdev->dev_width = devtmp.dev_width;
newdev->dev_params = devtmp.dev_params;
/* Determine if this device has been seen before */
newdev->dev_nterm = nterminals;
newdev->dev_rect = *r;
newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type);
newdev->dev_class = class;
sprintf(devhash, "%dx%d", r->r_xbot, r->r_ybot);
he = HashFind(&def->def_devs, devhash);
newdev = (Dev *)HashGetValue(he);
if (newdev)
{
/* Duplicate device. Duplicates will only appear in res.ext files
* where a device has nodes changed. Merge all properties of the
* original device with nodes from the new device. Keep the
* original device and discard the new one.
*
* Check that the device is actually the same device type and number
* of terminals. If not, throw an error and abandon the new device.
*/
if ((newdev->dev_class != class) ||
(strcmp(EFDevTypes[newdev->dev_type], type)))
{
TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n",
extDevTable[class], type, r->r_xbot, r->r_ybot,
extDevTable[newdev->dev_class], EFDevTypes[newdev->dev_type]);
return 0;
}
else if (newdev->dev_nterm != nterminals)
{
TxError("Device %s %s at (%d, %d) overlaps device with incompatible"
" number of terminals (%d vs. %d)!\n",
extDevTable[class], type, r->r_xbot, r->r_ybot, nterminals,
newdev->dev_nterm);
return 0;
}
}
else
{
newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals));
/* Add this dev to the hash table for def */
HashSetValue(he, (ClientData)newdev);
newdev->dev_cap = devtmp.dev_cap;
newdev->dev_res = devtmp.dev_res;
newdev->dev_area = devtmp.dev_area;
newdev->dev_perim = devtmp.dev_perim;
newdev->dev_length = devtmp.dev_length;
newdev->dev_width = devtmp.dev_width;
newdev->dev_params = devtmp.dev_params;
newdev->dev_nterm = nterminals;
newdev->dev_rect = *r;
newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type);
newdev->dev_class = class;
switch (class)
{
case DEV_FET: /* old-style "fet" record */
newdev->dev_area = atoi(argv[0]);
newdev->dev_perim = atoi(argv[1]);
break;
case DEV_MOSFET: /* new-style "device mosfet" record */
case DEV_ASYMMETRIC:
case DEV_BJT:
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
break;
case DEV_RES:
if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
{
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
}
else if (StrIsNumeric(argv[0]))
{
newdev->dev_res = (float)atof(argv[0]);
}
else
{
if (hasModel)
{
efReadError("Error: expected L and W, got %s %s\n", argv[0],
argv[1]);
newdev->dev_length = 0;
newdev->dev_width = 0;
}
else
{
efReadError("Error: expected resistance value, got %s\n",
argv[0]);
newdev->dev_res = 0.0;
}
}
break;
case DEV_CAP:
case DEV_CAPREV:
if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
{
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
}
else if (StrIsNumeric(argv[0]))
{
newdev->dev_cap = (float)atof(argv[0]);
}
else
{
if (hasModel)
{
efReadError("Error: expected L and W, got %s %s\n", argv[0],
argv[1]);
newdev->dev_length = 0;
newdev->dev_width = 0;
}
else
{
efReadError("Error: expected capacitance value, got %s\n",
argv[0]);
newdev->dev_cap = 0.0;
}
}
break;
}
}
newdev->dev_subsnode = devtmp.dev_subsnode;
switch (class)
{
case DEV_FET: /* old-style "fet" record */
newdev->dev_area = atoi(argv[0]);
newdev->dev_perim = atoi(argv[1]);
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
case DEV_MOSFET: /* new-style "device mosfet" record */
case DEV_ASYMMETRIC:
case DEV_BJT:
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
/* "None" in the place of the substrate name means substrate is ignored */
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
case DEV_RES:
if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
{
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
}
else if (StrIsNumeric(argv[0]))
{
newdev->dev_res = (float)atof(argv[0]);
}
else
{
if (hasModel)
{
efReadError("Error: expected L and W, got %s %s\n", argv[0],
argv[1]);
newdev->dev_length = 0;
newdev->dev_width = 0;
}
else
{
efReadError("Error: expected resistance value, got %s\n", argv[0]);
newdev->dev_res = 0.0;
}
}
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
case DEV_CAP:
case DEV_CAPREV:
if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
{
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
}
else if (StrIsNumeric(argv[0]))
{
newdev->dev_cap = (float)atof(argv[0]);
}
else
{
if (hasModel)
{
efReadError("Error: expected L and W, got %s %s\n", argv[0],
argv[1]);
newdev->dev_length = 0;
newdev->dev_width = 0;
}
else
{
efReadError("Error: expected capacitance value, got %s\n", argv[0]);
newdev->dev_cap = 0.0;
}
}
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
@ -859,10 +919,6 @@ efBuildDevice(def, class, type, r, argc, argv)
#undef TERM_PERIM
#undef TERM_ATTRS
/* Add this dev to the list for def */
newdev->dev_next = def->def_devs;
def->def_devs = newdev;
return 0;
}
@ -1696,6 +1752,36 @@ efFreeUseTable(table)
}
}
/*
* ----------------------------------------------------------------------------
*
* efFreeDevTable --
*
* Free the device records allocated for each entry in the device hash table,
* the memory allocated by the device, leaving the hash entry null.
*
* ----------------------------------------------------------------------------
*/
void
efFreeDevTable(table)
HashTable *table;
{
Dev *dev;
HashSearch hs;
HashEntry *he;
int n;
HashStartSearch(&hs);
while (he = HashNext(table, &hs))
{
dev = (Dev *)HashGetValue(he);
for (n = 0; n < (int)dev->dev_nterm; n++)
if (dev->dev_terms[n].dterm_attrs)
freeMagic((char *) dev->dev_terms[n].dterm_attrs);
freeMagic((char *) dev);
}
}
/*
* ----------------------------------------------------------------------------

View File

@ -103,7 +103,6 @@ EFDone()
Kill *kill;
Def *def;
Use *use;
Dev *dev;
int n;
HashStartSearch(&hs);
@ -114,22 +113,18 @@ EFDone()
efFreeNodeTable(&def->def_nodes);
efFreeNodeList(&def->def_firstn);
efFreeUseTable(&def->def_uses);
efFreeDevTable(&def->def_devs);
HashKill(&def->def_nodes);
HashKill(&def->def_dists);
HashKill(&def->def_uses);
HashKill(&def->def_devs);
for (conn = def->def_conns; conn; conn = conn->conn_next)
efFreeConn(conn);
for (conn = def->def_caps; conn; conn = conn->conn_next)
efFreeConn(conn);
for (conn = def->def_resistors; conn; conn = conn->conn_next)
efFreeConn(conn);
for (dev = def->def_devs; dev; dev = dev->dev_next)
{
for (n = 0; n < (int)dev->dev_nterm; n++)
if (dev->dev_terms[n].dterm_attrs)
freeMagic((char *) dev->dev_terms[n].dterm_attrs);
freeMagic((char *) dev);
}
for (kill = def->def_kills; kill; kill = kill->kill_next)
{
freeMagic(kill->kill_name);
@ -151,13 +146,6 @@ EFDone()
EFTech = (char *)NULL;
}
/* Free up all HierNames that were stored in efFreeHashTable */
/*
HashStartSearch(&hs);
while (he = HashNext(&efFreeHashTable, &hs))
freeMagic(he->h_key.h_ptr);
*/
/* Free up the parameter name tables for each device */
HashStartSearch(&hs);
@ -244,7 +232,6 @@ efDefNew(name)
newdef->def_conns = (Connection *) NULL;
newdef->def_caps = (Connection *) NULL;
newdef->def_resistors = (Connection *) NULL;
newdef->def_devs = (Dev *) NULL;
newdef->def_kills = (Kill *) NULL;
/* Initialize circular list of nodes */
@ -257,6 +244,9 @@ efDefNew(name)
/* Initialize hash table of node names */
HashInit(&newdef->def_nodes, INITNODESIZE, HT_STRINGKEYS);
/* Initialize hash table of devices */
HashInit(&newdef->def_devs, INITNODESIZE, HT_STRINGKEYS);
/* Initialize hash table of distances */
HashInitClient(&newdef->def_dists, INITNODESIZE, HT_CLIENTKEYS,
efHNDistCompare, efHNDistCopy, efHNDistHash, efHNDistKill);

View File

@ -205,7 +205,7 @@ EFFlatBuildOneLevel(def, flags)
if (usecount > 0)
efHierSrUses(&efFlatContext, efFlatNodesDeviceless, (ClientData)&usecount);
if ((usecount == 0) && (efFlatRootUse.use_def->def_devs == NULL))
if ((usecount == 0) && (HashGetNumEntries(&efFlatRootUse.use_def->def_devs) == 0))
efFlatRootUse.use_def->def_flags |= DEF_NODEVICES;
/* Record all local nodes */
@ -372,7 +372,7 @@ efFlatNodesDeviceless(hc, cdata)
if (newcount > 0)
efHierSrUses(hc, efFlatNodesDeviceless, (ClientData)&newcount);
if ((hc->hc_use->use_def->def_devs == NULL) && (newcount == 0))
if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0))
{
/* Add all our own nodes to the table */
efAddNodes(hc, TRUE);

View File

@ -471,6 +471,8 @@ efHierVisitDevs(hc, ca)
{
Def *def = hc->hc_use->use_def;
Dev *dev;
HashSearch hs;
HashEntry *he;
float scale;
/*
@ -482,8 +484,10 @@ efHierVisitDevs(hc, ca)
scale = (efScaleChanged && def->def_scale != 1.0) ? def->def_scale : 1.0;
/* Visit all devices */
for (dev = def->def_devs; dev; dev = dev->dev_next)
HashStartSearch(&hs);
while (he = HashNext(&def->def_devs, &hs))
{
dev = (Dev *)HashGetValue(he);
if (efHierDevKilled(hc, dev, hc->hc_hierName))
continue;

View File

@ -156,6 +156,7 @@ typedef struct def
HashTable def_nodes; /* Map names into EFNodeNames */
HashTable def_dists; /* Map pairs of names into Distances */
HashTable def_uses; /* Hash children of this def by name */
HashTable def_devs; /* Devices (hash by position) */
EFNode def_firstn; /* Head of circular list of nodes */
/* The following are all NULL-terminated lists */
@ -163,7 +164,6 @@ typedef struct def
Connection *def_conns; /* Hierarchical connections/adjustments */
Connection *def_caps; /* Two-terminal capacitors */
Connection *def_resistors; /* Two-terminal resistors */
Dev *def_devs; /* Devices */
Kill *def_kills; /* Used to modify hierarchical structure
* using information present only in the
* parent, e.g, to kill an old node and

View File

@ -356,8 +356,7 @@ readfile:
r.r_xtop = atoi(argv[5]);
r.r_ytop = atoi(argv[6]);
if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7,
&argv[7]) != 0)
if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0)
{
efReadError("Incomplete terminal description for device\n");
continue;

View File

@ -300,6 +300,8 @@ efVisitDevs(hc, ca)
Dev *dev;
float scale;
Transform t;
HashSearch hs;
HashEntry *he;
if (def->def_flags & DEF_SUBCIRCUIT) return 0;
@ -311,15 +313,17 @@ efVisitDevs(hc, ca)
t = hc->hc_trans;
/* Visit our own devices */
for (dev = def->def_devs; dev; dev = dev->dev_next)
HashStartSearch(&hs);
while (he = HashNext(&def->def_devs, &hs))
{
dev = (Dev *)HashGetValue(he);
if (efDevKilled(dev, hc->hc_hierName))
continue;
if ((*ca->ca_proc)(dev, hc->hc_hierName, scale, &t, ca->ca_cdata))
return 1;
}
return 0;
}

View File

@ -79,7 +79,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
ResSimNode *ResInitializeNode();
ResSimNode *ResOriginalNodes; /*Linked List of Nodes */
static float lambda=1.0; /* Scale factor */
static float resscale=1.0; /* Scale factor */
char RDEV_NOATTR[1]={'0'};
ResFixPoint *ResFixList;
@ -146,12 +146,8 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc)
case '|':
if (strcmp(line[NODEUNITS],"units:") == 0)
{
lambda = (float)atof(line[NODELAMBDA]);
if (lambda == 0.0) lambda = 1.0;
/* NOTE: units is derived from EFScale */
/* which needs a factor of 100 conversion */
/* to database units. */
lambda *= 100.0;
resscale = (float)atof(line[NODELAMBDA]);
if (resscale == 0.0) resscale = 1.0;
}
result=0;
break;
@ -231,6 +227,14 @@ ResReadNode(nodefile)
HashEntry *entry;
ResSimNode *node;
char *cp;
float lambda;
/* NOTE: Units from the .sim file or the .nodes file are in centimicrons
* when multiplied by resscale (units from the .sim file 1st line).
* multiply resscale by the extract scale (exts_unitsPerLambda) used to
* generate .ext dimensions originally, to get back to database units.
*/
lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda;
fp = PaOpen(nodefile,"r",".nodes",".", (char *) NULL, (char **) NULL);
if (fp == NULL)
@ -243,17 +247,13 @@ ResReadNode(nodefile)
entry = HashFind(&ResNodeTable,line[NODENODENAME]);
node = ResInitializeNode(entry);
/* NOTE: Fixed 10/15/2019. No scalefactor is passed to EFNodeVisit()
* so there is no scaling by lambda. Values are in centimicrons always,
* and factor of 100 is required to get database units.
*/
node->location.p_x = (int)((float)atof(line[NODENODEX]) / 100.0);
node->location.p_y = (int)((float)atof(line[NODENODEY]) / 100.0);
node->location.p_x = (int)((float)atof(line[NODENODEX]) / lambda);
node->location.p_y = (int)((float)atof(line[NODENODEY]) / lambda);
#ifdef ARIEL
node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X]) / 100.0);
node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y]) / 100.0);
node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X]) / 100.0);
node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y]) / 100.0);
node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X]) / lambda);
node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y]) / lambda);
node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X]) / lambda);
node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y]) / lambda);
#endif
if (cp = strchr(line[NODETYPE], ';')) *cp = '\0';
node->type = DBTechNameType(line[NODETYPE]);
@ -340,6 +340,7 @@ ResSimDevice(line,rpersquare,ttype)
int rvalue,i,j,k;
char *newattr,tmpattr[MAXTOKEN];
static int nowarning = TRUE;
float lambda;
device = (RDev *) mallocMagic((unsigned) (sizeof(RDev)));
if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0'))
@ -360,8 +361,11 @@ ResSimDevice(line,rpersquare,ttype)
device->tnumber = ++Maxtnumber;
device->status = FALSE;
device->nextDev = ResRDevList;
device->location.p_x = atoi(line[RDEV_DEVX]);
device->location.p_y = atoi(line[RDEV_DEVY]);
lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda;
device->location.p_x = (int)((float)atof(line[RDEV_DEVX]) / lambda);
device->location.p_y = (int)((float)atof(line[RDEV_DEVY]) / lambda);
device->rs_gattr=RDEV_NOATTR;
device->rs_sattr=RDEV_NOATTR;
device->rs_dattr=RDEV_NOATTR;