mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 14:07:07 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e9288f746 | ||
|
|
cff954f36a | ||
|
|
c27d933adc | ||
|
|
bcbc736b51 | ||
|
|
615c55cbe2 | ||
|
|
f5f1240073 | ||
|
|
87d8759a69 | ||
|
|
02d7a1bd01 | ||
|
|
1efa054ac1 | ||
|
|
7878b3cfbc | ||
|
|
609d1de250 | ||
|
|
7f727e6674 | ||
|
|
47c3b34612 |
+69
-17
@@ -536,11 +536,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
|
||||
/* Do property inheritance */
|
||||
|
||||
/* NOTE: Need to do: Check properties for M > 1 and decrement
|
||||
* and repeat without moving CurrentProp
|
||||
*/
|
||||
|
||||
if (CurrentProp) {
|
||||
int i, mval;
|
||||
struct valuelist *kv;
|
||||
|
||||
for (ob2 = ChildStart; ob2 != NULL; ob2=ob2->next) {
|
||||
|
||||
/* If the parent cell has properties to declare, then */
|
||||
@@ -548,10 +547,49 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
/* spiceparams dictionary is active (during file */
|
||||
/* reading only). */
|
||||
|
||||
if (ob2->type == PROPERTY)
|
||||
if (ob2->type == PROPERTY) {
|
||||
ReduceExpressions(ob2, CurrentProp, ChildCell,
|
||||
(spiceparams.hashtab == NULL) ? 0 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for property M. If it exists and is greater than */
|
||||
/* one, reduce it and repeat; i.e., generate multiple */
|
||||
/* child instances to match the M value. Probably this */
|
||||
/* could be done quicker by just creating a new property */
|
||||
/* M for a single child. */
|
||||
|
||||
mval = 0;
|
||||
for (i = 0; ; i++) {
|
||||
kv = &(CurrentProp->instance.props[i]);
|
||||
if (kv->type == PROP_ENDLIST) break;
|
||||
if ((*matchfunc)(kv->key, "M")) {
|
||||
if (kv->type == PROP_INTEGER) {
|
||||
mval = kv->value.ival;
|
||||
kv->value.ival = mval - 1;
|
||||
break;
|
||||
}
|
||||
else if (kv->type == PROP_DOUBLE) {
|
||||
mval = (int)kv->value.dval;
|
||||
kv->value.dval = (double)mval - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mval > 1) {
|
||||
/* Put the child cell at the start of ChildObjList */
|
||||
if (ChildEnd) {
|
||||
ChildEnd->next = ChildObjList;
|
||||
ChildObjList = ChildStart;
|
||||
|
||||
/* Continue without moving CurrentProp */
|
||||
/* Note that if ChildEnd is NULL then the child cell
|
||||
* is optimized out and there is no need to do it
|
||||
* M times.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Repeat for each property record, as each property represents a
|
||||
* unique instance that must be flattened individually.
|
||||
@@ -1177,7 +1215,6 @@ int UniquePins(char *name, int filenum)
|
||||
firstport = (struct objlist **)CALLOC(maxnode + 1, sizeof(struct objlist *));
|
||||
|
||||
portcount = FIRSTPIN;
|
||||
lob = NULL;
|
||||
for (ob = ThisCell->cell; ob != NULL; ob = ob->next) {
|
||||
if (ob->type != PORT) break;
|
||||
if (ob->node > 0) {
|
||||
@@ -1188,16 +1225,12 @@ int UniquePins(char *name, int filenum)
|
||||
firstport[ob->node]->name, ThisCell->name, ThisCell->file);
|
||||
/* Do not count this as a duplicate pin. */
|
||||
nodecount[ob->node]--;
|
||||
/* Move the pin adjacent to the one it is shorted to (if it
|
||||
* isn't already); this will make the work of MatchPins() easier.
|
||||
/* Note: Previously there was code here to move the shorted port
|
||||
* next to the pin it is shorted to. This causes the cell def pins
|
||||
* to become scrambled with respect to the pin order of its instances.
|
||||
* Removed the code 9/1/2023. But---Not sure if any code depends
|
||||
* on shorted pins being adjacent.
|
||||
*/
|
||||
if (firstport[ob->node]->next != ob) {
|
||||
lob->next = ob->next;
|
||||
ob->next = firstport[ob->node]->next;
|
||||
firstport[ob->node]->next = ob;
|
||||
ob = lob;
|
||||
}
|
||||
lob = ob;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
@@ -1218,7 +1251,6 @@ int UniquePins(char *name, int filenum)
|
||||
}
|
||||
}
|
||||
portcount++;
|
||||
lob = ob;
|
||||
}
|
||||
|
||||
if (needscleanup)
|
||||
@@ -1929,6 +1961,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
|
||||
if (ecomp->cell1->class != CLASS_ISOURCE) {
|
||||
/* merge node of endpoints */
|
||||
/* Prefer a port node over a non-port node */
|
||||
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
|
||||
if (!IsPort(ob2)) break;
|
||||
else if (ob2->node == node1) break;
|
||||
else if (ob2->node == node2) {
|
||||
int ntemp = node1;
|
||||
node1 = node2;
|
||||
node2 = ntemp;
|
||||
}
|
||||
}
|
||||
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->node == node2)
|
||||
ob2->node = node1;
|
||||
@@ -2037,6 +2079,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
|
||||
/* merge node of endpoints */
|
||||
if (ecomp->cell2->class != CLASS_ISOURCE) {
|
||||
/* Prefer a port node over a non-port node */
|
||||
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
|
||||
if (!IsPort(ob1)) break;
|
||||
else if (ob1->node == node1) break;
|
||||
else if (ob1->node == node2) {
|
||||
int ntemp = node1;
|
||||
node1 = node2;
|
||||
node2 = ntemp;
|
||||
}
|
||||
}
|
||||
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
|
||||
if (ob1->node == node2)
|
||||
ob1->node = node1;
|
||||
|
||||
+109
-28
@@ -7428,6 +7428,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
int result = 1, haspins = 0, notempty = 0;
|
||||
int hasproxy1 = 0, hasproxy2 = 0;
|
||||
int needclean1 = 0, needclean2 = 0;
|
||||
int nomatch = 0;
|
||||
int *correspond;
|
||||
char *ostr;
|
||||
#ifdef TCL_NETGEN
|
||||
Tcl_Obj *mlist, *plist1, *plist2;
|
||||
@@ -7519,58 +7521,77 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
obp = N2->object;
|
||||
j = 0;
|
||||
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next, j++) {
|
||||
nomatch = FALSE;
|
||||
if ((IsPort(ob2)) && (ob2->node == obp->node)) {
|
||||
if (Debug == 0) {
|
||||
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
||||
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
||||
snprintf(ostr, left_col_end, "%s", ob1->name);
|
||||
if ((*matchfunc)(ob1->name, ob2->name))
|
||||
}
|
||||
if ((*matchfunc)(ob1->name, ob2->name)) {
|
||||
if (Debug == 0)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
||||
else {
|
||||
/* Check remainder of ports to see if there is a name match on the
|
||||
* same net number (multiple ports tied to the same net)
|
||||
*/
|
||||
struct objlist *ob3;
|
||||
for (ob3 = ob2->next, ++j; ob3 != NULL; ob3 = ob3->next, j++) {
|
||||
if ((IsPort(ob3)) && (ob3->node == ob2->node)) {
|
||||
if ((*matchfunc)(ob3->name, ob1->name)) {
|
||||
ob2 = ob3;
|
||||
}
|
||||
else {
|
||||
/* Check remainder of ports to see if there is a name match on the
|
||||
* same net number (multiple ports tied to the same net)
|
||||
*/
|
||||
struct objlist *ob3;
|
||||
for (ob3 = ob2->next, ++j; ob3 != NULL; ob3 = ob3->next, j++) {
|
||||
if ((IsPort(ob3)) && (ob3->node == ob2->node)) {
|
||||
if ((*matchfunc)(ob3->name, ob1->name)) {
|
||||
ob2 = ob3;
|
||||
if (Debug == 0)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ob3 = NULL;
|
||||
break; /* All pins w/the same node should be together */
|
||||
}
|
||||
}
|
||||
if (ob3 == NULL) {
|
||||
}
|
||||
else {
|
||||
ob3 = NULL;
|
||||
break; /* All pins w/the same node should be together */
|
||||
}
|
||||
}
|
||||
if (ob3 == NULL) {
|
||||
if (Debug == 0) {
|
||||
if (ob2->model.port == -1)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s **Mismatch**", ob2->name);
|
||||
else
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
|
||||
/* Pins with different names are on different nets,
|
||||
* so this should trigger an error return code.
|
||||
*/
|
||||
result = 0;
|
||||
}
|
||||
nomatch = TRUE;
|
||||
/* Pins with different names are on different nets,
|
||||
* so this should trigger an error return code.
|
||||
*/
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (Debug == 0) {
|
||||
for (m = 0; m < right_col_end + 1; m++)
|
||||
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
}
|
||||
else if (nomatch) {
|
||||
Fprintf(stderr, "No matching pin in cell %s for "
|
||||
"cell %s pin %s\n",
|
||||
tc2->name, tc1->name, ob1->name);
|
||||
}
|
||||
else {
|
||||
Fprintf(stdout, "Circuit %s port %d \"%s\""
|
||||
" = cell %s port %d \"%s\"\n",
|
||||
tc1->name, i, obn->name,
|
||||
tc2->name, j, obp->name);
|
||||
tc1->name, i, ob1->name,
|
||||
tc2->name, j, ob2->name);
|
||||
}
|
||||
#ifdef TCL_NETGEN
|
||||
if (dolist) {
|
||||
Tcl_ListObjAppendElement(netgeninterp, plist1,
|
||||
Tcl_NewStringObj(obn->name, -1));
|
||||
Tcl_ListObjAppendElement(netgeninterp, plist2,
|
||||
Tcl_NewStringObj(obp->name, -1));
|
||||
Tcl_NewStringObj(ob1->name, -1));
|
||||
if (nomatch)
|
||||
Tcl_ListObjAppendElement(netgeninterp, plist2,
|
||||
Tcl_NewStringObj("(no matching pin)", -1));
|
||||
else
|
||||
Tcl_ListObjAppendElement(netgeninterp, plist2,
|
||||
Tcl_NewStringObj(ob2->name, -1));
|
||||
}
|
||||
#endif
|
||||
ob2->model.port = i; /* save order */
|
||||
@@ -7681,6 +7702,8 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
/* legal SPICE. */
|
||||
|
||||
ob1 = tc1->cell;
|
||||
|
||||
correspond = (int *)CALLOC((tc1->nodename_cache_maxnodenum + 1), sizeof(int));
|
||||
|
||||
for (i = 0; i < numorig; i++) {
|
||||
bangptr1 = strrchr(ob1->name, '!');
|
||||
@@ -7723,7 +7746,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
(tc2->flags & CELL_PLACEHOLDER)) ||
|
||||
(NodeClasses == NULL))) {
|
||||
|
||||
ob2->model.port = i; /* save order */
|
||||
ob2->model.port = i; /* save order */
|
||||
*(cover + i) = (char)1;
|
||||
|
||||
if (Debug == 0) {
|
||||
@@ -7752,6 +7775,63 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (bangptr2) *bangptr2 = '!';
|
||||
break;
|
||||
}
|
||||
else if ((ob1->node != -1) && (ob2->node != -1)) {
|
||||
/* Check for the case of ports on both sides being shorted
|
||||
* together. That means that the nodes on both sides connect
|
||||
* only to ports, that they connect to the same number of ports,
|
||||
* and that each port pair has a matching name.
|
||||
*/
|
||||
int onlyports = 1;
|
||||
struct objlist *oba, *obb;
|
||||
for (oba = tc1->cell; oba != NULL; oba = oba->next) {
|
||||
if ((oba->node == ob1->node) && (oba->type != PORT)) {
|
||||
onlyports = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (onlyports) {
|
||||
for (obb = tc2->cell; obb != NULL; obb = obb->next) {
|
||||
if ((obb->node == ob2->node) && (obb->type != PORT)) {
|
||||
onlyports = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (onlyports) {
|
||||
if ((correspond[ob1->node] == 0) || (correspond[ob1->node] == ob2->node)) {
|
||||
|
||||
correspond[ob1->node] = ob2->node; /* remember corresponding node */
|
||||
ob2->model.port = i; /* save order */
|
||||
*(cover + i) = (char)1;
|
||||
|
||||
if (Debug == 0) {
|
||||
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
||||
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
||||
snprintf(ostr, left_col_end, "%s", ob1->name);
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
||||
for (m = 0; m < right_col_end + 1; m++)
|
||||
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
}
|
||||
else {
|
||||
Fprintf(stdout, "Circuit %s port %d \"%s\""
|
||||
" = cell %s port %d \"%s\"\n",
|
||||
tc1->name, i, ob1->name,
|
||||
tc2->name, j, ob2->name);
|
||||
}
|
||||
#ifdef TCL_NETGEN
|
||||
if (dolist) {
|
||||
Tcl_ListObjAppendElement(netgeninterp, plist1,
|
||||
Tcl_NewStringObj(ob1->name, -1));
|
||||
Tcl_ListObjAppendElement(netgeninterp, plist2,
|
||||
Tcl_NewStringObj(ob2->name, -1));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (bangptr2) *bangptr2 = '!';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bangptr2) *bangptr2 = '!';
|
||||
j++;
|
||||
@@ -7760,6 +7840,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
ob1 = ob1->next;
|
||||
if (bangptr1) *bangptr1 = '!';
|
||||
}
|
||||
FREE(correspond);
|
||||
|
||||
/* Find the end of the pin list in tc1, for adding proxy pins */
|
||||
|
||||
|
||||
+12
-4
@@ -1017,13 +1017,12 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
char devtype, in_module, in_param;
|
||||
char *eqptr, *matchptr;
|
||||
struct keyvalue *kvlist = NULL;
|
||||
char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN], portname[MAX_STR_LEN], pkey[MAX_STR_LEN];
|
||||
char inst[MAX_STR_LEN], model[MAX_STR_LEN], portname[MAX_STR_LEN], pkey[MAX_STR_LEN];
|
||||
struct nlist *tp;
|
||||
struct objlist *parent, *sobj, *nobj, *lobj, *pobj, *cref;
|
||||
|
||||
inst[MAX_STR_LEN-1] = '\0';
|
||||
model[MAX_STR_LEN-1] = '\0';
|
||||
instname[MAX_STR_LEN-1] = '\0';
|
||||
in_module = (char)0;
|
||||
in_param = (char)0;
|
||||
|
||||
@@ -1899,12 +1898,21 @@ skip_endmodule:
|
||||
|
||||
if (i != -1)
|
||||
snprintf(nodename, MAX_STR_LEN, "%s[%d]", noderoot, i);
|
||||
else
|
||||
else if (lhs != NULL)
|
||||
strncpy(nodename, lhs->name, MAX_STR_LEN - 1);
|
||||
else {
|
||||
Printf("Error: Improper node name \"%s\".\n", noderoot);
|
||||
goto skip_endmodule;
|
||||
}
|
||||
if (j != -1)
|
||||
snprintf(assignname, MAX_STR_LEN, "%s[%d]", assignroot, j);
|
||||
else
|
||||
else if (rhs != NULL)
|
||||
strncpy(assignname, rhs->name, MAX_STR_LEN - 1);
|
||||
else {
|
||||
Printf("Error: Improper assignment name \"%s\".\n",
|
||||
assignroot);
|
||||
goto skip_endmodule;
|
||||
}
|
||||
|
||||
join(nodename, assignname);
|
||||
|
||||
|
||||
Vendored
+699
-418
File diff suppressed because it is too large
Load Diff
Vendored
+1487
-1430
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user