mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 14:07:07 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1ed4ce49e | ||
|
|
6d23844483 | ||
|
|
cc84364263 | ||
|
|
00b906c109 | ||
|
|
ab327c5f82 | ||
|
|
25a0e12428 | ||
|
|
eabb898578 | ||
|
|
2cb3937ee3 | ||
|
|
ec0e097fcf | ||
|
|
9b0afa893d | ||
|
|
f59c9ebcb7 | ||
|
|
c0f7ebd625 | ||
|
|
ce097d5d76 | ||
|
|
619409556c | ||
|
|
b1374e2bc8 |
+298
-7
@@ -31,6 +31,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "print.h"
|
||||
#include "hash.h"
|
||||
|
||||
static int invlambda = 100; /* Used in sim and prm files */
|
||||
|
||||
void extCell(char *name, int filenum)
|
||||
{
|
||||
struct nlist *tp, *tp2;
|
||||
@@ -450,7 +452,8 @@ void simCell(char *name, int filenum)
|
||||
struct nlist *tp, *tp2;
|
||||
struct objlist *ob, *ob2;
|
||||
char FileName[500], simclass;
|
||||
short i;
|
||||
char writeLine[1024], paramString[128];
|
||||
short i, p, mult;
|
||||
double l, w, v;
|
||||
|
||||
tp = LookupCellFile(name, filenum);
|
||||
@@ -478,9 +481,9 @@ void simCell(char *name, int filenum)
|
||||
}
|
||||
|
||||
/* print out header list */
|
||||
/* distance units are multiplied by 100 (distances are in um) */
|
||||
/* distance units are multiplied by invlambda */
|
||||
|
||||
FlushString("| units: 100 tech: scmos\n");
|
||||
FlushString("| units: %d tech: scmos\n", 100 * invlambda);
|
||||
|
||||
/* now run through cell's contents, print instances */
|
||||
for (ob = tp->cell; ob != NULL; ob = ob->next) {
|
||||
@@ -516,13 +519,17 @@ void simCell(char *name, int filenum)
|
||||
case CLASS_NPN:
|
||||
simclass = 'b';
|
||||
break;
|
||||
default:
|
||||
case CLASS_SUBCKT:
|
||||
case CLASS_MODULE:
|
||||
simclass = 'x';
|
||||
break;
|
||||
default:
|
||||
simclass = '|';
|
||||
break;
|
||||
}
|
||||
|
||||
if (simclass != 'x')
|
||||
FlushString("%c", simclass);
|
||||
FlushString("%c", simclass);
|
||||
|
||||
switch (tp2->class) {
|
||||
case CLASS_NMOS: case CLASS_NMOS4:
|
||||
@@ -590,6 +597,115 @@ void simCell(char *name, int filenum)
|
||||
FlushString(" %g\n", v);
|
||||
break;
|
||||
|
||||
case CLASS_MODULE:
|
||||
*writeLine = 'x';
|
||||
*(writeLine + 1) = '\0';
|
||||
mult = 1;
|
||||
|
||||
/* Important---Need to look up the cell definition; if
|
||||
* the first pin is "drain" then it is a FET, and pins
|
||||
* get swapped from D-G-S-B to G-S-D-B. Source and drain
|
||||
* are treated here as equivalent because the .sim format
|
||||
* has no concept of an asymmetric source and drain.
|
||||
*/
|
||||
ob2 = tp2->cell;
|
||||
if ((*matchfunc)(ob2->next->name, "gate"))
|
||||
{
|
||||
strcat(writeLine, " ");
|
||||
strcat(writeLine, NodeAlias(tp, ob->next));
|
||||
strcat(writeLine, " ");
|
||||
strcat(writeLine, NodeAlias(tp, ob));
|
||||
ob2 = ob->next->next;
|
||||
}
|
||||
else
|
||||
ob2 = ob;
|
||||
|
||||
while (ob2 != NULL) {
|
||||
strcat(writeLine, " ");
|
||||
strcat(writeLine, NodeAlias(tp, ob2));
|
||||
ob2 = ob2->next;
|
||||
if ((ob2 == NULL) || (ob2->type <= FIRSTPIN)) break;
|
||||
}
|
||||
|
||||
if (ob2 && ob2->type == PROPERTY) {
|
||||
struct valuelist *vl;
|
||||
/* Only known parameters are L, W, X, and Y */
|
||||
for (p = 0;; p++) {
|
||||
vl = (struct valuelist *)(&(ob2->instance.props[p]));
|
||||
if (vl->type == PROP_ENDLIST) {
|
||||
strcat(writeLine, " l=1");
|
||||
break;
|
||||
}
|
||||
else if ((*matchfunc)(vl->key, "L")) {
|
||||
v = vl->value.dval;
|
||||
sprintf(paramString, " l=%d", (int)(0.5 + (v * invlambda)));
|
||||
strcat(writeLine, paramString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (p = 0;; p++) {
|
||||
vl = (struct valuelist *)(&(ob2->instance.props[p]));
|
||||
if (vl->type == PROP_ENDLIST) {
|
||||
strcat(writeLine, " w=1");
|
||||
break;
|
||||
}
|
||||
else if ((*matchfunc)(vl->key, "W")) {
|
||||
v = vl->value.dval;
|
||||
sprintf(paramString, " w=%d", (int)(0.5 + (v * invlambda)));
|
||||
strcat(writeLine, paramString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (p = 0;; p++) {
|
||||
vl = (struct valuelist *)(&(ob2->instance.props[p]));
|
||||
if (vl->type == PROP_ENDLIST) {
|
||||
strcat(writeLine, " x=0");
|
||||
break;
|
||||
}
|
||||
else if ((*matchfunc)(vl->key, "X")) {
|
||||
i = vl->value.ival;
|
||||
sprintf(paramString, " x=%d", i);
|
||||
strcat(writeLine, paramString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (p = 0;; p++) {
|
||||
vl = (struct valuelist *)(&(ob2->instance.props[p]));
|
||||
if (vl->type == PROP_ENDLIST) {
|
||||
strcat(writeLine, " y=0");
|
||||
break;
|
||||
}
|
||||
else if ((*matchfunc)(vl->key, "Y")) {
|
||||
i = vl->value.ival;
|
||||
sprintf(paramString, " y=%d", i);
|
||||
strcat(writeLine, paramString);
|
||||
}
|
||||
}
|
||||
for (p = 0;; p++) {
|
||||
vl = (struct valuelist *)(&(ob2->instance.props[p]));
|
||||
if (vl->type == PROP_ENDLIST) {
|
||||
break;
|
||||
}
|
||||
else if ((*matchfunc)(vl->key, "M")) {
|
||||
if (vl->type == PROP_INTEGER)
|
||||
mult = vl->value.ival;
|
||||
else
|
||||
mult = vl->value.dval;
|
||||
}
|
||||
}
|
||||
}
|
||||
strcat(writeLine, " ");
|
||||
strcat(writeLine, tp2->name);
|
||||
strcat(writeLine, "\n");
|
||||
|
||||
/* Multiple instances (M != 1) are written multiple times.
|
||||
* NF is ignored in favor of having a single device with
|
||||
* the total width.
|
||||
*/
|
||||
for (i = 0; i < mult; i++)
|
||||
FlushString(writeLine);
|
||||
break;
|
||||
|
||||
default:
|
||||
FlushString("| unhandled component %s\n", tp2->name);
|
||||
break;
|
||||
@@ -626,6 +742,181 @@ int StrIsInt(char *s)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Read a .prm format file. This is specifically to */
|
||||
/* get the "device" lines that indicate how a SPICE */
|
||||
/* subcircuit model or a .sim "x" record needs to be */
|
||||
/* translated into a specific component type like a */
|
||||
/* FET, diode, resistor, etc. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
char *ReadPrm(char *fname, int *fnum)
|
||||
{
|
||||
int filenum;
|
||||
struct keyvalue *kvlist = NULL;
|
||||
struct nlist *tp;
|
||||
|
||||
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
|
||||
char name[MAX_STR_LEN];
|
||||
|
||||
SetExtension(name, fname, PRM_EXTENSION);
|
||||
if (OpenParseFile(name, *fnum) < 0) {
|
||||
Printf("Error in prm file read: No file %s\n",name);
|
||||
*fnum = filenum;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure all .prm file reading is case INsensitive */
|
||||
/* This is because the only reason to read a PRM file */
|
||||
/* is to find all the subcircuit device types so that */
|
||||
/* a SPICE file can be read and a SIM file written. */
|
||||
|
||||
matchfunc = matchnocase;
|
||||
matchintfunc = matchfile;
|
||||
hashfunc = hashnocase;
|
||||
|
||||
CellDef(fname, filenum);
|
||||
|
||||
while (!EndParseFile()) {
|
||||
char devicename[MAX_STR_LEN];
|
||||
SkipTok(NULL);
|
||||
|
||||
if (EndParseFile()) break;
|
||||
if (nexttok[0] == ';') continue; /* Comment line */
|
||||
else if (nexttok[0] == '\0') continue; /* Blank line */
|
||||
else if (match(nexttok, "lambda")) {
|
||||
SkipTok(NULL);
|
||||
invlambda = (int)(0.5 + (1.0 / atof(nexttok)));
|
||||
SkipNewLine(NULL); /* skip any attributes */
|
||||
}
|
||||
else if (match(nexttok, "device")) {
|
||||
SkipTok(NULL);
|
||||
if (match(nexttok, "nfet")) {
|
||||
SkipTok(NULL);
|
||||
strcpy(devicename, nexttok);
|
||||
/* Create 4-terminal nfet subcircuit device record */
|
||||
if (LookupCellFile(devicename, filenum) == NULL) {
|
||||
CellDef(devicename, filenum);
|
||||
Port("drain");
|
||||
Port("gate");
|
||||
Port("source");
|
||||
Port("bulk");
|
||||
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
|
||||
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
|
||||
PropertyInteger(devicename, filenum, "nf", 0, 1);
|
||||
PropertyInteger(devicename, filenum, "m", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef(fname, filenum);
|
||||
}
|
||||
LinkProperties(devicename, kvlist);
|
||||
SkipNewLine(NULL); /* skip any attributes */
|
||||
}
|
||||
else if (match(nexttok, "pfet")) {
|
||||
SkipTok(NULL);
|
||||
strcpy(devicename, nexttok);
|
||||
/* Create 4-terminal pfet subcircuit device record */
|
||||
if (LookupCellFile(devicename, filenum) == NULL) {
|
||||
CellDef(devicename, filenum);
|
||||
Port("drain");
|
||||
Port("gate");
|
||||
Port("source");
|
||||
Port("well");
|
||||
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
|
||||
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
|
||||
PropertyInteger(devicename, filenum, "nf", 0, 1);
|
||||
PropertyInteger(devicename, filenum, "m", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef(fname, filenum);
|
||||
}
|
||||
LinkProperties(devicename, kvlist);
|
||||
SkipNewLine(NULL); /* skip various attributes */
|
||||
}
|
||||
else if (match(nexttok, "resistor")) {
|
||||
SkipTok(NULL);
|
||||
strcpy(devicename, nexttok);
|
||||
/* Resistor device has additional record for the value */
|
||||
/* (Need to do something with this. . . ?) */
|
||||
SkipTok(NULL);
|
||||
/* Create resistor subcircuit device record */
|
||||
if (LookupCellFile(devicename, filenum) == NULL) {
|
||||
CellDef(devicename, filenum);
|
||||
Port("end_a");
|
||||
Port("end_b");
|
||||
PropertyDouble(devicename, filenum, "value", 0.01, 0.0);
|
||||
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
|
||||
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
|
||||
PropertyInteger(devicename, filenum, "m", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef(fname, filenum);
|
||||
}
|
||||
LinkProperties(devicename, kvlist);
|
||||
SkipNewLine(NULL); /* skip various attributes */
|
||||
}
|
||||
else if (match(nexttok, "capacitor")) {
|
||||
SkipTok(NULL);
|
||||
strcpy(devicename, nexttok);
|
||||
/* Capacitor device has additional record for the value */
|
||||
/* (Need to do something with this. . . ?) */
|
||||
SkipTok(NULL);
|
||||
/* Create capacitor subcircuit device record */
|
||||
if (LookupCellFile(devicename, filenum) == NULL) {
|
||||
CellDef(devicename, filenum);
|
||||
Port("top");
|
||||
Port("bottom");
|
||||
PropertyDouble(devicename, filenum, "value", 0.01, 0.0);
|
||||
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
|
||||
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
|
||||
PropertyInteger(devicename, filenum, "m", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef(fname, filenum); /* Reopen */
|
||||
}
|
||||
LinkProperties(devicename, kvlist);
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else if (match(nexttok, "diode")) {
|
||||
SkipTok(NULL);
|
||||
strcpy(devicename, nexttok);
|
||||
/* Create diode subcircuit device record */
|
||||
if (LookupCellFile(devicename, filenum) == NULL) {
|
||||
CellDef(devicename, filenum);
|
||||
Port("anode");
|
||||
Port("cathode");
|
||||
PropertyInteger(devicename, filenum, "m", 0, 1);
|
||||
SetClass(CLASS_MODULE);
|
||||
EndCell();
|
||||
ReopenCellDef(fname, filenum); /* Reopen */
|
||||
}
|
||||
LinkProperties(devicename, kvlist);
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
Printf("Unknown device type in .prm: '%s'\n", nexttok);
|
||||
InputParseError(stderr);
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Could spell out all the keywords used in .prm files */
|
||||
/* but probably not worth the effort. */
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
DeleteProperties(&kvlist);
|
||||
}
|
||||
EndCell();
|
||||
CloseParseFile();
|
||||
|
||||
tp = LookupCellFile(fname, filenum);
|
||||
if (tp) tp->flags |= CELL_TOP;
|
||||
|
||||
*fnum = filenum;
|
||||
return fname;
|
||||
}
|
||||
|
||||
/*-------------------------*/
|
||||
/* Read a .sim format file */
|
||||
/*-------------------------*/
|
||||
@@ -644,7 +935,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
|
||||
SetExtension(name, fname, SIM_EXTENSION);
|
||||
if (OpenParseFile(name, *fnum) < 0) {
|
||||
Printf("Error in ext file read: No file %s\n",name);
|
||||
Printf("Error in sim file read: No file %s\n",name);
|
||||
*fnum = filenum;
|
||||
return NULL;
|
||||
}
|
||||
@@ -847,7 +1138,7 @@ char *ReadSim(char *fname, int *fnum)
|
||||
}
|
||||
else if (match(nexttok, "r")) { /* 2-port resistors */
|
||||
if (IgnoreRC) {
|
||||
/* ignore all capacitances */
|
||||
/* ignore all resistances */
|
||||
SkipNewLine(NULL);
|
||||
}
|
||||
else {
|
||||
|
||||
+53
-3
@@ -136,17 +136,16 @@ void flattenCell(char *name, int file)
|
||||
ob2 = ob2->next;
|
||||
}
|
||||
|
||||
|
||||
/* delete all port elements from child */
|
||||
while (IsPort(ChildObjList)) {
|
||||
/* delete all ports at beginning of list */
|
||||
if (Debug) Printf("deleting leading port from child\n");
|
||||
tmp = ChildObjList->next;
|
||||
FreeObjectAndHash(ChildObjList, ChildCell);
|
||||
ChildObjList = tmp;
|
||||
if ((ChildObjList = tmp) == NULL) break;
|
||||
}
|
||||
tmp = ChildObjList;
|
||||
while (tmp->next != NULL) {
|
||||
while (tmp && (tmp->next != NULL)) {
|
||||
if (IsPort(tmp->next)) {
|
||||
ob2 = (tmp->next)->next;
|
||||
if (Debug) Printf("deleting a port from child\n");
|
||||
@@ -1632,6 +1631,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
ECompList *list0X, *listX0;
|
||||
int hascontents1, hascontents2;
|
||||
int match, modified = 0;
|
||||
int not_top;
|
||||
|
||||
if (file1 == -1)
|
||||
tc1 = LookupCell(name1);
|
||||
@@ -1902,6 +1902,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
// Remove non-matching zero-value devices. This can
|
||||
// be done on a per-instance basis.
|
||||
|
||||
not_top = (PeekCompareQueueTop(NULL, NULL, NULL, NULL) == -1) ? FALSE : TRUE;
|
||||
|
||||
ecomp = (ECompare *)HashFirst(&compdict);
|
||||
while (ecomp != NULL) {
|
||||
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
|
||||
@@ -1948,6 +1950,33 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do NOT remove shorting devices that */
|
||||
/* connect two ports. Otherwise the */
|
||||
/* port lists get screwed up. It is */
|
||||
/* better in that case to force the */
|
||||
/* cells to be declared mismatched. */
|
||||
/* This is ignored for a top-level cell */
|
||||
/* because it will just show up as a */
|
||||
/* port mismatch error as it should. */
|
||||
|
||||
if ((not_top == TRUE) &&
|
||||
(ecomp->cell1->class != CLASS_ISOURCE)) {
|
||||
int found1 = FALSE;
|
||||
int found2 = FALSE;
|
||||
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
|
||||
if (!IsPort(ob2)) break;
|
||||
else if (ob2->node == node1)
|
||||
found1 = TRUE;
|
||||
else if (ob2->node == node2)
|
||||
found2 = TRUE;
|
||||
if (found1 && found2) {
|
||||
found = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) break;
|
||||
}
|
||||
if (found) {
|
||||
@@ -2069,6 +2098,27 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* (See comments above about removing shorts */
|
||||
/* between two ports.) */
|
||||
|
||||
if ((not_top == TRUE) &&
|
||||
(ecomp->cell2->class != CLASS_ISOURCE)) {
|
||||
int found1 = FALSE;
|
||||
int found2 = FALSE;
|
||||
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
|
||||
if (!IsPort(ob1)) break;
|
||||
else if (ob1->node == node1)
|
||||
found1 = TRUE;
|
||||
else if (ob1->node == node2)
|
||||
found2 = TRUE;
|
||||
if (found1 && found2) {
|
||||
found = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) break;
|
||||
}
|
||||
if (found) {
|
||||
|
||||
+26
-14
@@ -3773,20 +3773,23 @@ int CreateCompareQueue(char *name1, int file1, char *name2, int file2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------*/
|
||||
/* Read the top of the compare queue, but do */
|
||||
/* not alter the stack. */
|
||||
/*----------------------------------------------*/
|
||||
/*----------------------------------------------------------------*/
|
||||
/* Read the top of the compare queue, but do not alter the stack. */
|
||||
/* Return -1 if there is no compare queue. This is a way to */
|
||||
/* check if the current cells being checked are the topmost in */
|
||||
/* the queue. Call with all NULL values for a quick check for a */
|
||||
/* top-level compare. */
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
int PeekCompareQueueTop(char **name1, int *file1, char **name2, int *file2)
|
||||
{
|
||||
if (CompareQueue == NULL)
|
||||
return -1;
|
||||
|
||||
*name1 = CompareQueue->class1;
|
||||
*file1 = CompareQueue->file1;
|
||||
*name2 = CompareQueue->class2;
|
||||
*file2 = CompareQueue->file2;
|
||||
if (name1) *name1 = CompareQueue->class1;
|
||||
if (file1) *file1 = CompareQueue->file1;
|
||||
if (name2) *name2 = CompareQueue->class2;
|
||||
if (file2) *file2 = CompareQueue->file2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5026,21 +5029,30 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
switch(vl->type) {
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
dval = 2 * fabs(vl->value.dval - vl2->value.dval)
|
||||
if ((vl2->type == PROP_DOUBLE) || (vl2->type == PROP_VALUE)) {
|
||||
dval = 2 * fabs(vl->value.dval - vl2->value.dval)
|
||||
/ (vl->value.dval + vl2->value.dval);
|
||||
if (dval <= kl->slop.dval) pmatch++;
|
||||
if (dval <= kl->slop.dval) pmatch++;
|
||||
}
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
ival = abs(vl->value.ival - vl2->value.ival);
|
||||
if (ival <= kl->slop.ival) pmatch++;
|
||||
if (vl2->type == PROP_INTEGER) {
|
||||
ival = abs(vl->value.ival - vl2->value.ival);
|
||||
if (ival <= kl->slop.ival) pmatch++;
|
||||
}
|
||||
break;
|
||||
case PROP_STRING:
|
||||
if ((*matchfunc)(vl->value.string, vl2->value.string)) pmatch++;
|
||||
if (vl2->type == PROP_STRING) {
|
||||
if ((*matchfunc)(vl->value.string, vl2->value.string)) pmatch++;
|
||||
}
|
||||
break;
|
||||
|
||||
/* will not attempt to match expressions, but it could
|
||||
/* Will not attempt to match expressions, but it could
|
||||
* be done with some minor effort by matching each
|
||||
* stack token and comparing those that are strings.
|
||||
* Likewise, will not attempt to match properties
|
||||
* whose types are mismatched, but they could be
|
||||
* promoted here.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
+20
-11
@@ -611,7 +611,8 @@ void SpiceTokNoNewline(void)
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Skip to the next token, ignoring any C-style comments. */
|
||||
/* Skip to the next token, ignoring any C-style comments and verilog */
|
||||
/* "(* ... *)"-style comments. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void SkipTokComments(char *delimiter)
|
||||
@@ -627,6 +628,11 @@ void SkipTokComments(char *delimiter)
|
||||
SkipTok(delimiter);
|
||||
if (nexttok) SkipTok(delimiter);
|
||||
}
|
||||
else if (match(nexttok, "(*")) {
|
||||
while (nexttok && !match(nexttok, "*)"))
|
||||
SkipTok(delimiter);
|
||||
if (nexttok) SkipTok(delimiter);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
@@ -731,7 +737,7 @@ char *strdtok(char *pstring, char *delim1, char *delim2)
|
||||
if (*s == '\\') {
|
||||
s++;
|
||||
while (*s != '\0') {
|
||||
if ((*s == ' ') || (*s == '\\')) {
|
||||
if ((*s == ' ') || ((*s == '\\') && (*(s + 1) == '\0'))) {
|
||||
s++;
|
||||
break;
|
||||
}
|
||||
@@ -880,7 +886,7 @@ char *ReadNetlist(char *fname, int *fnum)
|
||||
};
|
||||
|
||||
#ifdef mips
|
||||
struct filetype formats[7];
|
||||
struct filetype formats[8];
|
||||
|
||||
formats[0].extension = NTK_EXTENSION;
|
||||
formats[0].proc = ReadNtk;
|
||||
@@ -888,14 +894,16 @@ char *ReadNetlist(char *fname, int *fnum)
|
||||
formats[1].proc = ReadExtHier;
|
||||
formats[2].extension = SIM_EXTENSION;
|
||||
formats[2].proc = ReadSim;
|
||||
formats[3].extension = SPICE_EXTENSION;
|
||||
formats[3].proc = ReadSpice;
|
||||
formats[4].extension = NETGEN_EXTENSION;
|
||||
formats[4].proc = ReadNetgenFile;
|
||||
formats[5].extension = VERILOG_EXTENSION;
|
||||
formats[5].proc = ReadVerilogFile;
|
||||
formats[6].extension = NULL;
|
||||
formats[6].proc = NULL;
|
||||
formats[3].extension = PRM_EXTENSION;
|
||||
formats[3].proc = ReadPrm;
|
||||
formats[4].extension = SPICE_EXTENSION;
|
||||
formats[4].proc = ReadSpice;
|
||||
formats[5].extension = NETGEN_EXTENSION;
|
||||
formats[5].proc = ReadNetgenFile;
|
||||
formats[6].extension = VERILOG_EXTENSION;
|
||||
formats[6].proc = ReadVerilogFile;
|
||||
formats[7].extension = NULL;
|
||||
formats[7].proc = NULL;
|
||||
|
||||
#else /* not mips (i.e. compiler with reasonable initializers) */
|
||||
|
||||
@@ -904,6 +912,7 @@ char *ReadNetlist(char *fname, int *fnum)
|
||||
{NTK_EXTENSION, ReadNtk},
|
||||
{EXT_EXTENSION, ReadExtHier},
|
||||
{SIM_EXTENSION, ReadSim},
|
||||
{PRM_EXTENSION, ReadPrm},
|
||||
{SPICE_EXTENSION, ReadSpice},
|
||||
{SPICE_EXT2, ReadSpice},
|
||||
{SPICE_EXT3, ReadSpice},
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define WOMBAT_EXTENSION ".wom"
|
||||
#define EXT_EXTENSION ".ext"
|
||||
#define SIM_EXTENSION ".sim"
|
||||
#define PRM_EXTENSION ".prm"
|
||||
#define SPICE_EXTENSION ".spice"
|
||||
#define SPICE_EXT2 ".spc"
|
||||
#define SPICE_EXT3 ".sp"
|
||||
|
||||
@@ -191,6 +191,7 @@ extern char *ReadNtk (char *fname, int *fnum);
|
||||
extern char *ReadExtHier(char *fname, int *fnum);
|
||||
extern char *ReadExtFlat(char *fname, int *fnum);
|
||||
extern char *ReadSim(char *fname, int *fnum);
|
||||
extern char *ReadPrm(char *fname, int *fnum);
|
||||
extern char *ReadSpice(char *fname, int *fnum);
|
||||
extern char *ReadSpiceLib(char *fname, int *fnum);
|
||||
extern char *ReadNetgenFile (char *fname, int *fnum);
|
||||
|
||||
@@ -741,6 +741,19 @@ set auto_noexec 1 ;# don't EVER call UNIX commands w/o "shell" in front
|
||||
# Cross-Application section
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# For use with open_pdks, set PDK_ROOT from the environment. If no
|
||||
# such environment variable exists, check some common locations.
|
||||
|
||||
if {[catch {set PDK_ROOT $::env(PDK_ROOT)}]} {
|
||||
if {[file isdir /usr/local/share/pdk] == 1} {
|
||||
set PDK_ROOT /usr/local/share/pdk
|
||||
} elseif {[file isdir /usr/share/pdk] == 1} {
|
||||
set PDK_ROOT /usr/share/pdk
|
||||
} elseif {[file isdir /foss/pdk] == 1} {
|
||||
set PDK_ROOT /foss/pdk
|
||||
}
|
||||
}
|
||||
|
||||
# Setup IRSIM assuming that the Tcl version is installed.
|
||||
# We do not need to rename procedure irsim to NULL because it is
|
||||
# redefined in a script, which simply overwrites the original.
|
||||
|
||||
+5
-2
@@ -707,11 +707,11 @@ _netgen_readnet(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
char *formats[] = {
|
||||
"automatic", "ext", "extflat", "sim", "ntk", "spice",
|
||||
"automatic", "ext", "extflat", "sim", "prm", "ntk", "spice",
|
||||
"verilog", "netgen", "actel", "xilinx", NULL
|
||||
};
|
||||
enum FormatIdx {
|
||||
AUTO_IDX, EXT_IDX, EXTFLAT_IDX, SIM_IDX, NTK_IDX,
|
||||
AUTO_IDX, EXT_IDX, EXTFLAT_IDX, SIM_IDX, PRM_IDX, NTK_IDX,
|
||||
SPICE_IDX, VERILOG_IDX, NETGEN_IDX, ACTEL_IDX, XILINX_IDX
|
||||
};
|
||||
struct nlist *tc;
|
||||
@@ -807,6 +807,9 @@ _netgen_readnet(ClientData clientData,
|
||||
case SIM_IDX:
|
||||
retstr = ReadSim(savstr, &filenum);
|
||||
break;
|
||||
case PRM_IDX:
|
||||
retstr = ReadPrm(savstr, &filenum);
|
||||
break;
|
||||
case NTK_IDX:
|
||||
retstr = ReadNtk(savstr, &filenum);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user