mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-23 06:27:07 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b4a8fe9d6 | ||
|
|
3eadc8b0dc | ||
|
|
b3af7b98b4 | ||
|
|
9630670071 | ||
|
|
f29452e550 | ||
|
|
da3b96ae9e | ||
|
|
8a2bbe0723 | ||
|
|
a0c49a026a | ||
|
|
1520e276bc | ||
|
|
665203bba1 | ||
|
|
f02802dd21 | ||
|
|
0192558d4b | ||
|
|
21d329b22d | ||
|
|
b76c9a1712 | ||
|
|
37b1a2a07d | ||
|
|
4d44abcca4 | ||
|
|
777f7ef095 | ||
|
|
29ee16644d | ||
|
|
9b4185fe62 | ||
|
|
f5147e5af6 | ||
|
|
ddd95c4fe6 | ||
|
|
23b4e19204 | ||
|
|
c0c9993980 | ||
|
|
8a20b90074 | ||
|
|
5bb279a9e4 | ||
|
|
3392159243 |
+2
-2
@@ -91,7 +91,7 @@ char *ActelName(char *Name)
|
||||
/* strip physical-pin information, if it exists */
|
||||
if ((nm = strrchr(name,PHYSICALPIN[0])) != NULL) *nm = '\0';
|
||||
if (strlen(name) > 13) {
|
||||
ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
|
||||
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE;
|
||||
/* format the value of the hashed value of the string */
|
||||
sprintf(ActelNames[ActelIndex], "$%lX", ActelNameHash(name));
|
||||
if (Debug)
|
||||
@@ -102,7 +102,7 @@ Printf("ActelNameHash returns %s on name %s\n",ActelNames[ActelIndex], name);
|
||||
NeedsQuoting = 0;
|
||||
if (NULL != strpbrk(name, ".,:; \t\"'\n\r")) NeedsQuoting = 1;
|
||||
|
||||
ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
|
||||
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE;
|
||||
if (!NeedsQuoting) {
|
||||
strcpy(ActelNames[ActelIndex], name);
|
||||
return(ActelNames[ActelIndex]);
|
||||
|
||||
+15
-4
@@ -2018,8 +2018,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
/* Do NOT remove shorting devices that */
|
||||
if (found) {
|
||||
/* Beware remove shorting devices that */
|
||||
/* connect two ports. Otherwise the */
|
||||
/* port lists get screwed up. It is */
|
||||
/* better in that case to force the */
|
||||
@@ -2027,6 +2030,10 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
/* This is ignored for a top-level cell */
|
||||
/* because it will just show up as a */
|
||||
/* port mismatch error as it should. */
|
||||
/* (12/12/2025---disabling this worked; */
|
||||
/* may need to go back to a failing */
|
||||
/* example and determine how pin */
|
||||
/* matching gets scrambled.) */
|
||||
|
||||
if ((not_top == TRUE) &&
|
||||
(ecomp->cell1->class != CLASS_ISOURCE)) {
|
||||
@@ -2039,14 +2046,18 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
else if (ob2->node == node2)
|
||||
found2 = TRUE;
|
||||
if (found1 && found2) {
|
||||
found = FALSE;
|
||||
Fprintf(stdout, "Warning: "
|
||||
"zero-valued device connects "
|
||||
"port %s to another port; pin "
|
||||
"matching may be affected.\n",
|
||||
ob2->name);
|
||||
// found = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
Fprintf(stdout, "Removing zero-valued device "
|
||||
"%s from cell %s (%d) makes a better "
|
||||
|
||||
+20
-13
@@ -137,32 +137,39 @@ static unsigned char uppercase[] = {
|
||||
// horrible things can happen, as, for example, names AOI12 and OAI12
|
||||
// have exactly the same hash result. Lousy for binning and even
|
||||
// lousier for generating class magic numbers.
|
||||
//
|
||||
// Updated again 4/2/2026 to the FNV-1a hash, which is better than
|
||||
// SDBM for this application, according to ChatGPT.
|
||||
|
||||
unsigned long hashnocase(char *s, int hashsize)
|
||||
{
|
||||
unsigned long hashval;
|
||||
|
||||
for (hashval = 0; *s != '\0'; )
|
||||
hashval = uppercase[*s++]
|
||||
+ (hashval << 6) + (hashval << 16) - hashval;
|
||||
unsigned long hashval = 2166136261ul;
|
||||
for (; *s != '\0'; s++) {
|
||||
hashval ^= uppercase[*s];
|
||||
hashval *= 16777619ul;
|
||||
}
|
||||
return (hashsize == 0) ? hashval : (hashval % hashsize);
|
||||
}
|
||||
|
||||
unsigned long hashcase(char *s, int hashsize)
|
||||
{
|
||||
unsigned long hashval;
|
||||
|
||||
for (hashval = 0; *s != '\0'; )
|
||||
hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
|
||||
unsigned long hashval = 2166136261ul;
|
||||
for (; *s != '\0'; s++) {
|
||||
hashval ^= (unsigned char)(*s);
|
||||
hashval *= 16777619ul;
|
||||
}
|
||||
return (hashsize == 0) ? hashval : (hashval % hashsize);
|
||||
}
|
||||
|
||||
unsigned long genhash(char *s, int c, int hashsize)
|
||||
{
|
||||
unsigned long hashval;
|
||||
|
||||
for (hashval = (unsigned long)c; *s != '\0'; )
|
||||
hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
|
||||
unsigned long hashval = 2166136261ul;
|
||||
hashval ^= (unsigned long)c;
|
||||
hashval *= 16777619ul;
|
||||
for (; *s != '\0'; s++) {
|
||||
hashval ^= (unsigned char)(*s);
|
||||
hashval *= 16777619ul;
|
||||
}
|
||||
return (hashsize == 0) ? hashval : (hashval % hashsize);
|
||||
}
|
||||
|
||||
|
||||
+62
-4
@@ -52,7 +52,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
int InterruptPending = 0;
|
||||
void (*oldinthandler)() = SIG_DFL;
|
||||
void (*oldinthandler)(int) = SIG_DFL;
|
||||
extern Tcl_Interp *netgeninterp;
|
||||
extern int check_interrupt();
|
||||
#endif
|
||||
@@ -1622,8 +1622,8 @@ void FormatIllegalElementClasses()
|
||||
char *permcount;
|
||||
int bytesleft;
|
||||
|
||||
permname = CALLOC(right_col_end + 2, sizeof(char));
|
||||
permcount = CALLOC(right_col_end + 2, sizeof(char));
|
||||
permname = CALLOC(right_col_end + 100, sizeof(char));
|
||||
permcount = CALLOC(right_col_end + 100, sizeof(char));
|
||||
ostr = output_string_init();
|
||||
|
||||
found = 0;
|
||||
@@ -7544,6 +7544,11 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
|
||||
}
|
||||
else {
|
||||
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 = ob->next;
|
||||
}
|
||||
@@ -7891,7 +7896,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (*(cover + i) == (char)0) {
|
||||
j = 0;
|
||||
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
|
||||
char *name1, *name2;
|
||||
char *name1, *name2, *aptr1 = NULL, *aptr2 = NULL;
|
||||
|
||||
if (!IsPort(ob2)) break;
|
||||
|
||||
@@ -7909,8 +7914,59 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (!strncmp(name1, "proxy", 5) && (ob2->node == -1)) name1 +=5;
|
||||
if (!strncmp(name2, "proxy", 5) && (ob1->node == -1)) name2 +=5;
|
||||
|
||||
/* Recognize an array as matching a non-array of the same */
|
||||
/* name if the array is size 1. There must be a better way */
|
||||
/* to do this; this method makes excessive calls to */
|
||||
/* matchfunc(). */
|
||||
|
||||
if ((tc1->flags & CELL_PLACEHOLDER) || (tc2->flags && CELL_PLACEHOLDER)) {
|
||||
aptr1 = strchr(name1, '[');
|
||||
aptr2 = strchr(name2, '[');
|
||||
|
||||
if ((aptr1 != NULL) && (aptr2 == NULL)) {
|
||||
*aptr1 = '\0';
|
||||
if ((*matchfunc)(name1, name2)) {
|
||||
/* Check that name1 does not have another array
|
||||
* component in ob1
|
||||
*/
|
||||
struct objlist *ob3;
|
||||
for (ob3 = tc1->cell; ob3; ob3 = ob3->next) {
|
||||
if (!IsPort(ob3)) break;
|
||||
if (ob3 == ob1) continue;
|
||||
if (!strncmp(ob3->name, name1, strlen(name1)) &&
|
||||
*(ob3->name + strlen(name1)) == '[') {
|
||||
*aptr1 = '[';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((aptr1 == NULL) && (aptr2 != NULL)) {
|
||||
*aptr2 = '\0';
|
||||
if ((*matchfunc)(name1, name2)) {
|
||||
/* Check that name2 does not have another array
|
||||
* component in ob1
|
||||
*/
|
||||
struct objlist *ob3;
|
||||
for (ob3 = tc2->cell; ob3; ob3 = ob3->next) {
|
||||
if (!IsPort(ob3)) break;
|
||||
if (ob3 == ob2) continue;
|
||||
if (!strncmp(ob3->name, name2, strlen(name2)) &&
|
||||
*(ob3->name + strlen(name2)) == '[') {
|
||||
*aptr2 = '[';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((*matchfunc)(name1, name2)) {
|
||||
|
||||
if (aptr1) *aptr1 = '[';
|
||||
if (aptr2) *aptr2 = '[';
|
||||
|
||||
/* If both sides have unconnected nodes, then pins with */
|
||||
/* matching names are an automatic match. Otherwise, if */
|
||||
/* matching black-box entries, then pins are always */
|
||||
@@ -8064,6 +8120,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
}
|
||||
}
|
||||
if (bangptr2) *bangptr2 = '!';
|
||||
if (aptr1) *aptr1 = '[';
|
||||
if (aptr2) *aptr2 = '[';
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,6 +685,7 @@ void SpiceSkipNewLine(void)
|
||||
ungetc(contline, infile);
|
||||
}
|
||||
|
||||
#if 0 /* Commented with "#if 0" due to comment characters in the comment */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Function similar to strtok() for token parsing. The difference is */
|
||||
/* that it takes two sets of delimiters. The first is whitespace */
|
||||
@@ -705,6 +706,7 @@ void SpiceSkipNewLine(void)
|
||||
/* the first character of the delimiter string in addition to marking */
|
||||
/* the boundary between two-character and one-character delimiters. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog)
|
||||
{
|
||||
|
||||
+5
-1
@@ -449,6 +449,7 @@ int removeshorted(struct hashlist *p, int file)
|
||||
ob = nob;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Remove shorted instances of class "class" from the database */
|
||||
@@ -539,6 +540,7 @@ int deleteclass(struct hashlist *p, int file)
|
||||
}
|
||||
}
|
||||
FREE(checknodes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Remove all instances of class "class" from the database */
|
||||
@@ -576,6 +578,7 @@ int renameinstances(struct hashlist *p, int file)
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InstanceRename(char *from, char *to, int file)
|
||||
@@ -598,9 +601,10 @@ int freeprop(struct hashlist *p)
|
||||
struct property *prop;
|
||||
|
||||
prop = (struct property *)(p->ptr);
|
||||
if (prop->type == PROP_STRING)
|
||||
if (prop->type == PROP_STRING) {
|
||||
if (prop->pdefault.string != NULL)
|
||||
FREE(prop->pdefault.string);
|
||||
}
|
||||
else if (prop->type == PROP_EXPRESSION) {
|
||||
struct tokstack *stackptr, *nptr;
|
||||
stackptr = prop->pdefault.stack;
|
||||
|
||||
+3
-2
@@ -319,7 +319,7 @@ void Fanout(char *cell, char *node, int filter)
|
||||
while (ob != NULL) {
|
||||
char *obname = ob->name;
|
||||
if (*obname == '/') obname++;
|
||||
if (ob->node == nodenum)
|
||||
if (ob->node == nodenum) {
|
||||
if (filter == ALLOBJECTS) {
|
||||
Printf(" %s (", obname);
|
||||
PrintObjectType(ob->type);
|
||||
@@ -331,6 +331,7 @@ void Fanout(char *cell, char *node, int filter)
|
||||
else if (ob->type == filter) {
|
||||
Printf(" %s\n", obname);
|
||||
}
|
||||
}
|
||||
ob = ob->next;
|
||||
}
|
||||
}
|
||||
@@ -933,7 +934,7 @@ static int PrintLeavesInCellHash(struct hashlist *p)
|
||||
struct nlist *ptr;
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
if ((ptr->class == CLASS_SUBCKT)) PrintLeavesInCell(ptr->name, ptr->file);
|
||||
if (ptr->class == CLASS_SUBCKT) PrintLeavesInCell(ptr->name, ptr->file);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
+17
-7
@@ -196,7 +196,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
if (ob->type == PROPERTY) {
|
||||
struct valuelist *vl;
|
||||
int i;
|
||||
for (i == 0;; i++) {
|
||||
for (i = 0;; i++) {
|
||||
vl = &(ob->instance.props[i]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
else if (vl->type == PROP_VALUE) {
|
||||
@@ -216,7 +216,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
if (ob->type == PROPERTY) {
|
||||
struct valuelist *vl;
|
||||
int i;
|
||||
for (i == 0;; i++) {
|
||||
for (i = 0;; i++) {
|
||||
vl = &(ob->instance.props[i]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
else if (vl->type == PROP_VALUE) {
|
||||
@@ -236,7 +236,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
if (ob->type == PROPERTY) {
|
||||
struct valuelist *vl;
|
||||
int i;
|
||||
for (i == 0;; i++) {
|
||||
for (i = 0;; i++) {
|
||||
vl = &(ob->instance.props[i]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
else if (vl->type == PROP_VALUE) {
|
||||
@@ -399,7 +399,7 @@ int renamepins(struct hashlist *p, int file)
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
|
||||
if (ptr->file != file)
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
|
||||
if (ob->type == FIRSTPIN) {
|
||||
@@ -426,6 +426,7 @@ int renamepins(struct hashlist *p, int file)
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If any pins are marked unconnected, see if there are */
|
||||
@@ -1782,10 +1783,19 @@ skip_ends:
|
||||
if (scan->next != NULL) scan = scan->next;
|
||||
tail->next = NULL;
|
||||
|
||||
/* Check for class defined inside itself (self-referential loop) */
|
||||
|
||||
if (!strcasecmp(model, scan->name)) {
|
||||
Fprintf(stderr, "Fatal: Class \"%s\" is instanced inside of itself!\n",
|
||||
scan->name);
|
||||
InputParseError(stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for ignored class */
|
||||
|
||||
if ((itype = IsIgnored(subcktname, filenum)) == IGNORE_CLASS) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
if ((itype = IsIgnored(scan->name, filenum)) == IGNORE_CLASS) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", scan->name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1800,7 +1810,7 @@ skip_ends:
|
||||
break;
|
||||
}
|
||||
if (shorted == (unsigned char)1) {
|
||||
Printf("Instance of '%s' is shorted, ignoring.\n", subcktname);
|
||||
Printf("Instance of '%s' is shorted, ignoring.\n", scan->name);
|
||||
while (head) {
|
||||
p = head->next;
|
||||
FREE(head);
|
||||
|
||||
+176
-34
@@ -76,7 +76,8 @@ struct hashdict verilogparams;
|
||||
// Global storage for verilog definitions
|
||||
struct hashdict verilogdefs;
|
||||
// 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
|
||||
struct hashdict buses;
|
||||
@@ -156,7 +157,8 @@ struct expr_stack {
|
||||
//-------------------------------------------------------------------------
|
||||
// Evaluate an expression for an array bound. This is much like
|
||||
// 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.
|
||||
// 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) */
|
||||
|
||||
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) */
|
||||
|
||||
for (texp = start; texp; texp = texp->next) {
|
||||
@@ -373,8 +441,15 @@ int ParseIntegerExpression(char *expr, int *iptr)
|
||||
|
||||
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, ":")) {
|
||||
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->value = 0;
|
||||
newexp->next = NULL;
|
||||
@@ -389,7 +464,7 @@ int ParseIntegerExpression(char *expr, int *iptr)
|
||||
if ((result = sscanf(sptr, "%d", &value)) != 1) {
|
||||
|
||||
// Is name in the parameter list?
|
||||
kl = (struct property *)HashLookup(nexttok, &verilogparams);
|
||||
kl = (struct property *)HashLookup(sptr, &verilogparams);
|
||||
if (kl == NULL) {
|
||||
Printf("Value %s in expression is not a number or a parameter.\n",
|
||||
sptr);
|
||||
@@ -402,27 +477,29 @@ int ParseIntegerExpression(char *expr, int *iptr)
|
||||
if (result != 1) {
|
||||
Printf("Parameter %s has value %s that cannot be parsed"
|
||||
" as an integer.\n",
|
||||
nexttok, kl->pdefault.string);
|
||||
sptr, kl->pdefault.string);
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (kl->type == PROP_INTEGER) {
|
||||
value = kl->pdefault.ival;
|
||||
result = 1; // Assert valid result
|
||||
}
|
||||
else if (kl->type == PROP_DOUBLE) {
|
||||
value = (int)kl->pdefault.dval;
|
||||
if ((double)value != kl->pdefault.dval) {
|
||||
Printf("Parameter %s has value %g that cannot be parsed"
|
||||
" as an integer.\n",
|
||||
nexttok, kl->pdefault.dval);
|
||||
sptr, kl->pdefault.dval);
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
result = 1; // Assert valid result
|
||||
}
|
||||
else {
|
||||
Printf("Parameter %s has unknown type; don't know how"
|
||||
" to parse.\n", nexttok);
|
||||
" to parse.\n", sptr);
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
@@ -516,7 +593,8 @@ int GetBusTok(struct bus *wb)
|
||||
}
|
||||
else if (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->oper = *nexttok;
|
||||
newexp->value = 0;
|
||||
@@ -1879,7 +1957,8 @@ skip_endmodule:
|
||||
// Allowed uses of "assign" for netlists:
|
||||
// "assign a = b" joins two nets.
|
||||
// "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.
|
||||
|
||||
if (nexttok && match(nexttok, "=")) {
|
||||
@@ -2140,6 +2219,19 @@ nextinst:
|
||||
}
|
||||
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, "(")) {
|
||||
char savetok = (char)0;
|
||||
@@ -2202,7 +2294,19 @@ nextinst:
|
||||
strcat(new_wire_bundle, nexttok);
|
||||
FREE(wire_bundle);
|
||||
wire_bundle = new_wire_bundle;
|
||||
if (!strcmp(nexttok, "}")) break;
|
||||
if (!strcmp(nexttok, "}"))
|
||||
{
|
||||
/* If a "bundle" has only one component, then it is
|
||||
* not really a bundle and should be treated as a
|
||||
* single wire.
|
||||
*/
|
||||
if (strchr(wire_bundle, ',') == NULL) {
|
||||
int blen = strlen(wire_bundle + 1) - 1;
|
||||
memmove(wire_bundle, wire_bundle + 1, blen);
|
||||
*(wire_bundle + blen) = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
|
||||
}
|
||||
if (!nexttok) {
|
||||
@@ -2578,6 +2682,7 @@ nextinst:
|
||||
char *brackptr;
|
||||
int j;
|
||||
char locinst[MAX_STR_LEN];
|
||||
int arraypos = (arraystart > arrayend) ? arraymax - i : i;
|
||||
|
||||
if (i != -1)
|
||||
sprintf(locinst, "%s[%d]", instancename, i);
|
||||
@@ -2627,7 +2732,14 @@ nextinst:
|
||||
else if (GetBus(scan->net, &wb) == 0) {
|
||||
char *bptr2;
|
||||
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, '[');
|
||||
if (brackptr) *brackptr = '\0';
|
||||
|
||||
@@ -2660,6 +2772,7 @@ nextinst:
|
||||
else {
|
||||
// Instance must be an array
|
||||
char netname[MAX_STR_LEN];
|
||||
char *spos = scanroot;
|
||||
int slice, portlen, siglen;
|
||||
|
||||
/* Get the array size of the port for bit slicing */
|
||||
@@ -2671,27 +2784,49 @@ nextinst:
|
||||
if (siglen < 0) siglen = -siglen;
|
||||
siglen++;
|
||||
|
||||
// If signal array is smaller than the portlength *
|
||||
// length of instance array, then the signal wraps.
|
||||
// If this is a bundle, then count out to the current
|
||||
// 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) {
|
||||
slice = wb.start - (arraystart - i) * portlen;
|
||||
while (slice < wb2.end) slice += siglen;
|
||||
}
|
||||
else if (wb2.start < wb2.end && arraystart > arrayend) {
|
||||
slice = wb.start + (arraystart - i) * portlen;
|
||||
while (slice > wb2.end) slice -= siglen;
|
||||
}
|
||||
else if (wb2.start > wb2.end && arraystart < arrayend) {
|
||||
slice = wb.start - (arraystart + i) * portlen;
|
||||
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;
|
||||
// If signal array is smaller than the portlength *
|
||||
// length of instance array, then the signal wraps.
|
||||
|
||||
if (wb2.start >= wb2.end && arraystart >= arrayend) {
|
||||
slice = wb.start - (arraystart - i) * portlen;
|
||||
while (slice < wb2.end) slice += siglen;
|
||||
}
|
||||
else if (wb2.start < wb2.end && arraystart > arrayend) {
|
||||
slice = wb.start + (arraystart - i) * portlen;
|
||||
while (slice > wb2.end) slice -= siglen;
|
||||
}
|
||||
else if (wb2.start > wb2.end && arraystart < arrayend) {
|
||||
slice = wb.start - (arraystart + i) * portlen;
|
||||
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);
|
||||
join(netname, obptr->name);
|
||||
}
|
||||
@@ -2876,18 +3011,25 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
|
||||
hashfunc = hashcase;
|
||||
}
|
||||
|
||||
if ((hashfile != -1) && (hashfile != *fnum)) {
|
||||
/* Started a new file, so remove all the parameters and definitions */
|
||||
if ((hashfilep != -1) && (hashfilep != *fnum)) {
|
||||
/* Started a new file, so remove all the parameters */
|
||||
RecurseHashTable(&verilogparams, freeprop);
|
||||
HashKill(&verilogparams);
|
||||
hashfilep = -1;
|
||||
}
|
||||
if ((hashfiled != -1) && (hashfiled != *fnum)) {
|
||||
/* Started a new file, so remove all the definitions */
|
||||
RecurseHashTable(&verilogdefs, freeprop);
|
||||
HashKill(&verilogdefs);
|
||||
hashfile = -1;
|
||||
hashfiled = -1;
|
||||
}
|
||||
if (hashfile == -1) {
|
||||
if (hashfilep == -1) {
|
||||
InitializeHashTable(&verilogparams, OBJHASHSIZE);
|
||||
hashfilep = filenum;
|
||||
}
|
||||
if (hashfiled == -1) {
|
||||
InitializeHashTable(&verilogdefs, OBJHASHSIZE);
|
||||
hashfile = *fnum;
|
||||
hashfiled = filenum;
|
||||
}
|
||||
definitions = &verilogdefs;
|
||||
|
||||
|
||||
@@ -516,6 +516,14 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
}
|
||||
}
|
||||
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 {
|
||||
puts stdout "Error: Cannot read the setup file $setupfile"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user