Compare commits
6 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
ddd95c4fe6 | |
|
|
c0c9993980 | |
|
|
8a20b90074 | |
|
|
3392159243 | |
|
|
24c6eb4cb9 | |
|
|
9048191486 |
|
|
@ -7544,6 +7544,11 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lob = ob;
|
lob = ob;
|
||||||
|
if (ob == NULL) {
|
||||||
|
Fprintf(stdout, "Error: Premature end of pin list on "
|
||||||
|
"instance %s.\n", firstpin->instance.name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
ob->type = i++;
|
ob->type = i++;
|
||||||
ob = ob->next;
|
ob = ob->next;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
199
base/verilog.c
199
base/verilog.c
|
|
@ -76,7 +76,8 @@ struct hashdict verilogparams;
|
||||||
// Global storage for verilog definitions
|
// Global storage for verilog definitions
|
||||||
struct hashdict verilogdefs;
|
struct hashdict verilogdefs;
|
||||||
// Record file pointer that is associated with the hash tables
|
// Record file pointer that is associated with the hash tables
|
||||||
int hashfile = -1;
|
int hashfilep = -1; /* for parameters */
|
||||||
|
int hashfiled = -1; /* for definitions */
|
||||||
|
|
||||||
// Global storage for wire buses
|
// Global storage for wire buses
|
||||||
struct hashdict buses;
|
struct hashdict buses;
|
||||||
|
|
@ -156,7 +157,8 @@ struct expr_stack {
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Evaluate an expression for an array bound. This is much like
|
// Evaluate an expression for an array bound. This is much like
|
||||||
// ReduceOneExpression() in netgen.c, but only handles basic integer
|
// ReduceOneExpression() in netgen.c, but only handles basic integer
|
||||||
// arithmetic (+,-,*,/) and grouping by parentheses.
|
// arithmetic (+,-,*,/), grouping by parentheses, bit shifts, and
|
||||||
|
// if-else operators.
|
||||||
//
|
//
|
||||||
// Returns 1 if successful, 0 on error.
|
// Returns 1 if successful, 0 on error.
|
||||||
// Evaluated result is placed in the integer pointed to by "valptr".
|
// Evaluated result is placed in the integer pointed to by "valptr".
|
||||||
|
|
@ -220,6 +222,39 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reduce (a << b) and (a >> b) */
|
||||||
|
|
||||||
|
for (texp = start; texp; texp = texp->next) {
|
||||||
|
if ((texp->last != NULL) && (texp->next != NULL) && (texp->oper != '\0')) {
|
||||||
|
if ((texp->last->oper == '\0') && (texp->next->oper == '\0')) {
|
||||||
|
if (texp->oper == '<') {
|
||||||
|
/* Left shift */
|
||||||
|
texp->last->value <<= texp->next->value;
|
||||||
|
/* Remove two items from the stack */
|
||||||
|
tmp = texp;
|
||||||
|
texp = texp->last;
|
||||||
|
texp->next = tmp->next->next;
|
||||||
|
if (tmp->next->next) tmp->next->next->last = texp;
|
||||||
|
FREE(tmp->next);
|
||||||
|
FREE(tmp);
|
||||||
|
modified = TRUE;
|
||||||
|
}
|
||||||
|
if (texp->oper == '>') {
|
||||||
|
/* Right shift */
|
||||||
|
texp->last->value >>= texp->next->value;
|
||||||
|
/* Remove two items from the stack */
|
||||||
|
tmp = texp;
|
||||||
|
texp = texp->last;
|
||||||
|
texp->next = tmp->next->next;
|
||||||
|
if (tmp->next->next) tmp->next->next->last = texp;
|
||||||
|
FREE(tmp->next);
|
||||||
|
FREE(tmp);
|
||||||
|
modified = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Reduce (a * b) and (a / b) */
|
/* Reduce (a * b) and (a / b) */
|
||||||
|
|
||||||
for (texp = start; texp; texp = texp->next) {
|
for (texp = start; texp; texp = texp->next) {
|
||||||
|
|
@ -295,6 +330,39 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reduce (a ? b : c) */
|
||||||
|
|
||||||
|
for (texp = start; texp; texp = texp->next) {
|
||||||
|
/* There must be at least five objects on the stack */
|
||||||
|
if ((texp->last != NULL) && (texp->next != NULL) && (texp->oper != '\0')
|
||||||
|
&& (texp->next->next != NULL)
|
||||||
|
&& (texp->next->next->next != NULL)) {
|
||||||
|
if ((texp->last->oper == '\0') && (texp->next->oper == '\0')
|
||||||
|
&& (texp->next->next->next->oper == '\0')) {
|
||||||
|
if ((texp->oper == '?') && (texp->next->next->oper == ':')) {
|
||||||
|
/* If-Else conditional */
|
||||||
|
if (texp->last->value)
|
||||||
|
texp->last->value = texp->next->value;
|
||||||
|
else
|
||||||
|
texp->last->value = texp->next->next->next->value;
|
||||||
|
|
||||||
|
/* Remove four items from the stack */
|
||||||
|
tmp = texp;
|
||||||
|
texp = texp->last;
|
||||||
|
texp->next = tmp->next->next->next->next;
|
||||||
|
if (tmp->next->next->next->next)
|
||||||
|
tmp->next->next->next->next->last = texp;
|
||||||
|
FREE(tmp->next->next->next);
|
||||||
|
FREE(tmp->next->next);
|
||||||
|
FREE(tmp->next);
|
||||||
|
FREE(tmp);
|
||||||
|
|
||||||
|
modified = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Reduce (a) */
|
/* Reduce (a) */
|
||||||
|
|
||||||
for (texp = start; texp; texp = texp->next) {
|
for (texp = start; texp; texp = texp->next) {
|
||||||
|
|
@ -373,8 +441,15 @@ int ParseIntegerExpression(char *expr, int *iptr)
|
||||||
|
|
||||||
if (match(sptr, "+") || match(sptr, "-")
|
if (match(sptr, "+") || match(sptr, "-")
|
||||||
|| match(sptr, "*") || match(sptr, "/")
|
|| match(sptr, "*") || match(sptr, "/")
|
||||||
|| match(sptr, "(") || match(sptr, ")")) {
|
|| match(sptr, "(") || match(sptr, ")")
|
||||||
|
|| match(sptr, "<<") || match(sptr, ">>")
|
||||||
|
|| match(sptr, "?") || match(sptr, ":")) {
|
||||||
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
|
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
|
||||||
|
/* Note that "oper" is one character and that "<<" and ">>"
|
||||||
|
* become '<' and '>', respectively. The less-than and greater-
|
||||||
|
* than operators are not (yet) handled but will need to be
|
||||||
|
* recast to some other character in "oper".
|
||||||
|
*/
|
||||||
newexp->oper = *sptr;
|
newexp->oper = *sptr;
|
||||||
newexp->value = 0;
|
newexp->value = 0;
|
||||||
newexp->next = NULL;
|
newexp->next = NULL;
|
||||||
|
|
@ -389,7 +464,7 @@ int ParseIntegerExpression(char *expr, int *iptr)
|
||||||
if ((result = sscanf(sptr, "%d", &value)) != 1) {
|
if ((result = sscanf(sptr, "%d", &value)) != 1) {
|
||||||
|
|
||||||
// Is name in the parameter list?
|
// Is name in the parameter list?
|
||||||
kl = (struct property *)HashLookup(nexttok, &verilogparams);
|
kl = (struct property *)HashLookup(sptr, &verilogparams);
|
||||||
if (kl == NULL) {
|
if (kl == NULL) {
|
||||||
Printf("Value %s in expression is not a number or a parameter.\n",
|
Printf("Value %s in expression is not a number or a parameter.\n",
|
||||||
sptr);
|
sptr);
|
||||||
|
|
@ -402,27 +477,29 @@ int ParseIntegerExpression(char *expr, int *iptr)
|
||||||
if (result != 1) {
|
if (result != 1) {
|
||||||
Printf("Parameter %s has value %s that cannot be parsed"
|
Printf("Parameter %s has value %s that cannot be parsed"
|
||||||
" as an integer.\n",
|
" as an integer.\n",
|
||||||
nexttok, kl->pdefault.string);
|
sptr, kl->pdefault.string);
|
||||||
value = 0;
|
value = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (kl->type == PROP_INTEGER) {
|
else if (kl->type == PROP_INTEGER) {
|
||||||
value = kl->pdefault.ival;
|
value = kl->pdefault.ival;
|
||||||
|
result = 1; // Assert valid result
|
||||||
}
|
}
|
||||||
else if (kl->type == PROP_DOUBLE) {
|
else if (kl->type == PROP_DOUBLE) {
|
||||||
value = (int)kl->pdefault.dval;
|
value = (int)kl->pdefault.dval;
|
||||||
if ((double)value != kl->pdefault.dval) {
|
if ((double)value != kl->pdefault.dval) {
|
||||||
Printf("Parameter %s has value %g that cannot be parsed"
|
Printf("Parameter %s has value %g that cannot be parsed"
|
||||||
" as an integer.\n",
|
" as an integer.\n",
|
||||||
nexttok, kl->pdefault.dval);
|
sptr, kl->pdefault.dval);
|
||||||
value = 0;
|
value = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
result = 1; // Assert valid result
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Printf("Parameter %s has unknown type; don't know how"
|
Printf("Parameter %s has unknown type; don't know how"
|
||||||
" to parse.\n", nexttok);
|
" to parse.\n", sptr);
|
||||||
value = 0;
|
value = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -516,7 +593,8 @@ int GetBusTok(struct bus *wb)
|
||||||
}
|
}
|
||||||
else if (match(nexttok, "+") || match(nexttok, "-")
|
else if (match(nexttok, "+") || match(nexttok, "-")
|
||||||
|| match(nexttok, "*") || match(nexttok, "/")
|
|| match(nexttok, "*") || match(nexttok, "/")
|
||||||
|| match(nexttok, "(") || match(nexttok, ")")) {
|
|| match(nexttok, "(") || match(nexttok, ")")
|
||||||
|
|| match(nexttok, "<<") || match(nexttok, ">>")) {
|
||||||
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
|
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
|
||||||
newexp->oper = *nexttok;
|
newexp->oper = *nexttok;
|
||||||
newexp->value = 0;
|
newexp->value = 0;
|
||||||
|
|
@ -1879,7 +1957,8 @@ skip_endmodule:
|
||||||
// Allowed uses of "assign" for netlists:
|
// Allowed uses of "assign" for netlists:
|
||||||
// "assign a = b" joins two nets.
|
// "assign a = b" joins two nets.
|
||||||
// "assign a = {b, c, ...}" creates a bus from components.
|
// "assign a = {b, c, ...}" creates a bus from components.
|
||||||
// "assign" using any boolean arithmetic is not structural verilog.
|
// "assign" using if-else constructs or bit shifts.
|
||||||
|
// ("assign" using any other boolean arithmetic is not structural verilog.)
|
||||||
// "assign a = {x{b}}" creates a bus by repeating a component.
|
// "assign a = {x{b}}" creates a bus by repeating a component.
|
||||||
|
|
||||||
if (nexttok && match(nexttok, "=")) {
|
if (nexttok && match(nexttok, "=")) {
|
||||||
|
|
@ -2140,6 +2219,19 @@ nextinst:
|
||||||
}
|
}
|
||||||
SkipTokComments(VLOG_DELIMITERS);
|
SkipTokComments(VLOG_DELIMITERS);
|
||||||
}
|
}
|
||||||
|
else if (loop.loopvar != NULL) {
|
||||||
|
/* Instances created within a generate block for loop have an
|
||||||
|
* implicit array
|
||||||
|
*/
|
||||||
|
int loopval;
|
||||||
|
struct property *klr;
|
||||||
|
|
||||||
|
klr = (struct property *)HashLookup(loop.loopvar, &verilogparams);
|
||||||
|
loopval = klr->pdefault.ival;
|
||||||
|
|
||||||
|
arraystart = arrayend = loopval;
|
||||||
|
sprintf(instancename + strlen(instancename), "[%d]", loopval);
|
||||||
|
}
|
||||||
|
|
||||||
if (match(nexttok, "(")) {
|
if (match(nexttok, "(")) {
|
||||||
char savetok = (char)0;
|
char savetok = (char)0;
|
||||||
|
|
@ -2202,7 +2294,8 @@ nextinst:
|
||||||
strcat(new_wire_bundle, nexttok);
|
strcat(new_wire_bundle, nexttok);
|
||||||
FREE(wire_bundle);
|
FREE(wire_bundle);
|
||||||
wire_bundle = new_wire_bundle;
|
wire_bundle = new_wire_bundle;
|
||||||
if (!strcmp(nexttok, "}")) break;
|
if (!strcmp(nexttok, "}"))
|
||||||
|
break;
|
||||||
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
|
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
|
||||||
}
|
}
|
||||||
if (!nexttok) {
|
if (!nexttok) {
|
||||||
|
|
@ -2578,6 +2671,7 @@ nextinst:
|
||||||
char *brackptr;
|
char *brackptr;
|
||||||
int j;
|
int j;
|
||||||
char locinst[MAX_STR_LEN];
|
char locinst[MAX_STR_LEN];
|
||||||
|
int arraypos = (arraystart > arrayend) ? arraymax - i : i;
|
||||||
|
|
||||||
if (i != -1)
|
if (i != -1)
|
||||||
sprintf(locinst, "%s[%d]", instancename, i);
|
sprintf(locinst, "%s[%d]", instancename, i);
|
||||||
|
|
@ -2627,7 +2721,14 @@ nextinst:
|
||||||
else if (GetBus(scan->net, &wb) == 0) {
|
else if (GetBus(scan->net, &wb) == 0) {
|
||||||
char *bptr2;
|
char *bptr2;
|
||||||
char *scanroot;
|
char *scanroot;
|
||||||
scanroot = strsave(scan->net);
|
int isbundle = FALSE;
|
||||||
|
/* Skip over a bundle delimiter */
|
||||||
|
if (*scan->net == '{') {
|
||||||
|
scanroot = strsave(scan->net + 1);
|
||||||
|
isbundle = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scanroot = strsave(scan->net);
|
||||||
brackptr = strvchr(scanroot, '[');
|
brackptr = strvchr(scanroot, '[');
|
||||||
if (brackptr) *brackptr = '\0';
|
if (brackptr) *brackptr = '\0';
|
||||||
|
|
||||||
|
|
@ -2660,6 +2761,7 @@ nextinst:
|
||||||
else {
|
else {
|
||||||
// Instance must be an array
|
// Instance must be an array
|
||||||
char netname[MAX_STR_LEN];
|
char netname[MAX_STR_LEN];
|
||||||
|
char *spos = scanroot;
|
||||||
int slice, portlen, siglen;
|
int slice, portlen, siglen;
|
||||||
|
|
||||||
/* Get the array size of the port for bit slicing */
|
/* Get the array size of the port for bit slicing */
|
||||||
|
|
@ -2671,27 +2773,49 @@ nextinst:
|
||||||
if (siglen < 0) siglen = -siglen;
|
if (siglen < 0) siglen = -siglen;
|
||||||
siglen++;
|
siglen++;
|
||||||
|
|
||||||
// If signal array is smaller than the portlength *
|
// If this is a bundle, then count out to the current
|
||||||
// length of instance array, then the signal wraps.
|
// slice and read off the index. NOTE: Need to
|
||||||
|
// handle multiple bits per bundle entry!
|
||||||
|
if (isbundle) {
|
||||||
|
int j;
|
||||||
|
if (brackptr) *brackptr = '[';
|
||||||
|
for (j = 0; j < arraypos * portlen; j++) {
|
||||||
|
spos = strvchr(spos, ',');
|
||||||
|
if (spos == NULL) break;
|
||||||
|
spos++;
|
||||||
|
}
|
||||||
|
if (spos != NULL) {
|
||||||
|
brackptr = strvchr(spos, '[');
|
||||||
|
*brackptr = '\0';
|
||||||
|
sscanf(brackptr + 1, "%d", &slice);
|
||||||
|
}
|
||||||
|
else spos = scanroot; /* should emit an error here */
|
||||||
|
}
|
||||||
|
else { /* not a bundle */
|
||||||
|
|
||||||
if (wb2.start >= wb2.end && arraystart >= arrayend) {
|
// If signal array is smaller than the portlength *
|
||||||
slice = wb.start - (arraystart - i) * portlen;
|
// length of instance array, then the signal wraps.
|
||||||
while (slice < wb2.end) slice += siglen;
|
|
||||||
}
|
if (wb2.start >= wb2.end && arraystart >= arrayend) {
|
||||||
else if (wb2.start < wb2.end && arraystart > arrayend) {
|
slice = wb.start - (arraystart - i) * portlen;
|
||||||
slice = wb.start + (arraystart - i) * portlen;
|
while (slice < wb2.end) slice += siglen;
|
||||||
while (slice > wb2.end) slice -= siglen;
|
}
|
||||||
}
|
else if (wb2.start < wb2.end && arraystart > arrayend) {
|
||||||
else if (wb2.start > wb2.end && arraystart < arrayend) {
|
slice = wb.start + (arraystart - i) * portlen;
|
||||||
slice = wb.start - (arraystart + i) * portlen;
|
while (slice > wb2.end) slice -= siglen;
|
||||||
while (slice < wb2.end) slice += siglen;
|
}
|
||||||
}
|
else if (wb2.start > wb2.end && arraystart < arrayend) {
|
||||||
else { // (wb2.start < wb2.end && arraystart < arrayend)
|
slice = wb.start - (arraystart + i) * portlen;
|
||||||
slice = wb.start + (arraystart + i) * portlen;
|
while (slice < wb2.end) slice += siglen;
|
||||||
while (slice > wb2.end) slice -= siglen;
|
}
|
||||||
|
else { // (wb2.start < wb2.end && arraystart < arrayend)
|
||||||
|
slice = wb.start + (arraystart + i) * portlen;
|
||||||
|
while (slice > wb2.end) slice -= siglen;
|
||||||
|
}
|
||||||
|
spos = scanroot;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(netname, "%s[%d]", scanroot, slice);
|
sprintf(netname, "%s[%d]", spos, slice);
|
||||||
if (LookupObject(netname, CurrentCell) == NULL) Node(netname);
|
if (LookupObject(netname, CurrentCell) == NULL) Node(netname);
|
||||||
join(netname, obptr->name);
|
join(netname, obptr->name);
|
||||||
}
|
}
|
||||||
|
|
@ -2876,18 +3000,25 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
|
||||||
hashfunc = hashcase;
|
hashfunc = hashcase;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hashfile != -1) && (hashfile != *fnum)) {
|
if ((hashfilep != -1) && (hashfilep != *fnum)) {
|
||||||
/* Started a new file, so remove all the parameters and definitions */
|
/* Started a new file, so remove all the parameters */
|
||||||
RecurseHashTable(&verilogparams, freeprop);
|
RecurseHashTable(&verilogparams, freeprop);
|
||||||
HashKill(&verilogparams);
|
HashKill(&verilogparams);
|
||||||
|
hashfilep = -1;
|
||||||
|
}
|
||||||
|
if ((hashfiled != -1) && (hashfiled != *fnum)) {
|
||||||
|
/* Started a new file, so remove all the definitions */
|
||||||
RecurseHashTable(&verilogdefs, freeprop);
|
RecurseHashTable(&verilogdefs, freeprop);
|
||||||
HashKill(&verilogdefs);
|
HashKill(&verilogdefs);
|
||||||
hashfile = -1;
|
hashfiled = -1;
|
||||||
}
|
}
|
||||||
if (hashfile == -1) {
|
if (hashfilep == -1) {
|
||||||
InitializeHashTable(&verilogparams, OBJHASHSIZE);
|
InitializeHashTable(&verilogparams, OBJHASHSIZE);
|
||||||
|
hashfilep = filenum;
|
||||||
|
}
|
||||||
|
if (hashfiled == -1) {
|
||||||
InitializeHashTable(&verilogdefs, OBJHASHSIZE);
|
InitializeHashTable(&verilogdefs, OBJHASHSIZE);
|
||||||
hashfile = *fnum;
|
hashfiled = filenum;
|
||||||
}
|
}
|
||||||
definitions = &verilogdefs;
|
definitions = &verilogdefs;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -429,7 +429,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
set file1 $name1
|
set file1 $name1
|
||||||
set cell1 $name1
|
set cell1 $name1
|
||||||
}
|
}
|
||||||
puts stdout "Reading netlist file $file1"
|
puts stdout "Reading netlist file $file1 for $name1"
|
||||||
set fnum1 [netgen::readnet $file1]
|
set fnum1 [netgen::readnet $file1]
|
||||||
} else {
|
} else {
|
||||||
set cell1 [lindex $flist1 0]
|
set cell1 [lindex $flist1 0]
|
||||||
|
|
@ -446,7 +446,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
set file2 $name2
|
set file2 $name2
|
||||||
set cell2 $name2
|
set cell2 $name2
|
||||||
}
|
}
|
||||||
puts stdout "Reading netlist file $file2"
|
puts stdout "Reading netlist file $file2 for $name2"
|
||||||
set fnum2 [netgen::readnet $file2]
|
set fnum2 [netgen::readnet $file2]
|
||||||
} else {
|
} else {
|
||||||
set cell2 [lindex $flist2 0]
|
set cell2 [lindex $flist2 0]
|
||||||
|
|
@ -461,7 +461,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
}
|
}
|
||||||
|
|
||||||
set clist1 [cells list $fnum1]
|
set clist1 [cells list $fnum1]
|
||||||
set cidx [lsearch -regexp $clist1 ^$cell1$]
|
set cidx [lsearch -exact $clist1 $cell1]
|
||||||
if {$cidx < 0} {
|
if {$cidx < 0} {
|
||||||
puts stderr "Cannot find cell $cell1 in file $file1"
|
puts stderr "Cannot find cell $cell1 in file $file1"
|
||||||
return
|
return
|
||||||
|
|
@ -469,7 +469,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
set cell1 [lindex $clist1 $cidx]
|
set cell1 [lindex $clist1 $cidx]
|
||||||
}
|
}
|
||||||
set clist2 [cells list $fnum2]
|
set clist2 [cells list $fnum2]
|
||||||
set cidx [lsearch -regexp $clist2 ^$cell2$]
|
set cidx [lsearch -exact $clist2 $cell2]
|
||||||
if {$cidx < 0} {
|
if {$cidx < 0} {
|
||||||
puts stderr "Cannot find cell $cell2 in file $file2"
|
puts stderr "Cannot find cell $cell2 in file $file2"
|
||||||
return
|
return
|
||||||
|
|
@ -516,6 +516,14 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close $fsetup
|
close $fsetup
|
||||||
|
if {$command != {}} {
|
||||||
|
# Incomplete command. Evaluate it to get a meaningful error message
|
||||||
|
if {[catch {uplevel 1 [list namespace eval netgen $command]} msg]} {
|
||||||
|
set msg [string trimright $msg "\n"]
|
||||||
|
puts stderr "Error $setupfile:$sline (ignoring), $msg"
|
||||||
|
incr perrors
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
puts stdout "Error: Cannot read the setup file $setupfile"
|
puts stdout "Error: Cannot read the setup file $setupfile"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue