Compare commits

...
24 Commits
Author SHA1 Message Date
Tim Edwards ac8956c32e Merge branch 'master' into netgen-1.5 2024-02-20 02:00:03 -05:00
Tim Edwards 202ea0431f Also updated configure (in addition to configure.in) with the
change to remove the "m4" dependency.
2024-02-19 12:46:20 -05:00
Tim Edwards 94754dbc4e Removed the requirement for package "m4" that is in the configuration
script.  It is not needed and doesn't exist in many OS distributions.
2024-02-19 12:41:08 -05:00
Tim Edwards b87f0fd5db Merge branch 'master' into netgen-1.5 2024-02-19 02:00:03 -05:00
Tim Edwards bf67d3c275 Having been given an example by Kareem Farid where the order of
verilog netlists makes a difference to the matching (or failure
thereof), I applied the same in-circuit pin matching as previously
applied to mixtures of SPICE and verilog netlists.  This is clearly
a more robust way to handle pin order differences between parent
and child than was implemented previously.
2024-02-18 15:22:40 -05:00
Tim Edwards 21e9207924 Merge branch 'master' into netgen-1.5 2024-02-10 02:00:02 -05:00
Tim Edwards 62feed812e Corrected an issue that arose due to a change made earlier: A
while back, shorted pins were moved into contiguous positions.
When that method was discovered to cause matching issues, it was
abandoned with a note that doing so might have unintended
consequences because other code might depend on the shorted pins
being contiguous.  Such a case was just found, and corrected.
However, it was also found that shorted pins were still not
completely handled correctly in MatchPins();  a solution was
found that adds such pins to the "permutes" list (which needs to
be done if the shorted pins are to be correctly handled in any
higher level of the hierarchy, if there is one), and the
"permutes" list is then checked by MatchPins() to determine if
pins match because they belong to the same group of shorted
pins.
2024-02-09 21:23:28 -05:00
Tim Edwards 8392721885 Merge branch 'master' into netgen-1.5 2024-02-07 02:00:02 -05:00
Tim Edwards d1c2848e4b Corrected another error in which some simple expressions are
incorrectly evaluated;  "(w+l)" for example treats "w+l" as
a single string instead of three tokens.  Corrected the code
to watch for a failure of strtod() when parsing the expression
at the "+" sign (also for "-").
2024-02-06 16:27:32 -05:00
Tim Edwards 6b0bd4d97b Found an error with the property sorting in which float values
were not compared for sorting in the same way they are compared
for property matching.  The "slop" value was treated as absolute,
not a percentage, so for example a slop of 0.01 on a dimension
of microns would cause all dimensions to be treated as round-off
error, and no sorting would occur.
2024-02-06 15:02:50 -05:00
Tim Edwards 79bab50a79 Merge branch 'master' into netgen-1.5 2024-02-04 02:00:02 -05:00
Tim Edwards d69fbc23bb Added code to handle the problem in which a verilog netlist is read
before its component cells, and the component cells are read in as
SPICE netlists.  Then the original verilog cell and its instances
need to have pins reordered to match the subcircuit definition in
the SPICE netlist.  Otherwise, when verilog and SPICE netlists are
mixed, the order in which the files are read is critical, and
failures due to reading out-of-order are very obscure and nearly
impossible to debug.
2024-02-03 21:21:09 -05:00
Tim Edwards b83800d69b Merge branch 'master' into netgen-1.5 2024-02-03 02:00:02 -05:00
Tim Edwards c7fa0324d9 Added a piece of code that handles implicit pins in verilog by doing
the following:  (1) Checking that the parent cell is verilog,
(2) only running after the two cells themselves have been compared
and matched, then (3) added the missing pin or pins while reordering
pins on instances (note: this may not work if the verilog netlist is
the first passed to netgen;  that case needs to be checked).
2024-02-02 14:51:10 -05:00
Tim Edwards 93b9cf6577 Merge branch 'master' into netgen-1.5 2024-01-04 02:00:02 -05:00
Tim Edwards eb27a18ae3 Corrected two different errors:
(1) When a comment line follows a ".subckt" line, and the comment
    line is empty or all whitespace, then the following line would
    be ignored.  This condition appears to be very specific and
    was solved simply by detecting it and handling it.
(2) Occasionally the "M" parameter of a subcircuit will be recorded
    as type double, and this was not being anticipated by the code
    that checks if "M=1" matches a corresponding entry with no "M"
    parameter.  Simple fix to check the condition where the "M"
    parameter is type double.
2024-01-03 21:21:03 -05:00
Tim Edwards bf53d52970 Merge branch 'master' into netgen-1.5 2023-12-04 02:00:02 -05:00
Tim Edwards 1817f4dd6a Corrected the LDDL_FLAGS setting for Mac OS, which is to replace
"-flat_namespace -undefined suppress -noprebind" to "-undefined
dynamic_lookup" which is what was done in magic, which has a
similar structure to netgen.
2023-12-03 20:32:05 -05:00
Tim Edwards 4250525e19 Merge branch 'master' into netgen-1.5 2023-11-21 02:00:01 -05:00
Tim Edwards a7e859fcde Corrected an error in parallel_sort and series_sort that does not
move to the start index before relinking the sorted entries.  That
will cause properties to be lost whenever the start index is greater
than zero.  Not sure why this hasn't been caught previously, or
whether other errors are involved here.
2023-11-20 10:38:41 -05:00
Tim Edwards c1ed4ce49e Merge branch 'master' into netgen-1.5 2023-10-28 02:00:04 -04:00
Tim Edwards 6d23844483 Corrected an error in the flattening routine that will cause the
"flatten" command to crash if there are black-box subcircuits in
the netlist.
2023-10-27 10:35:27 -04:00
Tim Edwards cc84364263 Added code to the netgen Tcl startup script to grab the PDK_ROOT
variable used with open_pdks, so that PDK references can be made
independent of the local filesystem.
2023-10-27 09:54:21 -04:00
Tim Edwards 00b906c109 Corrected an error in the previous commit which made primitive
devices from a .prm file into class "subckt" when they should be
class "module" (because they are primitives).  Otherwise, netgen
will crash when attempting to flatten them.
2023-10-27 09:38:14 -04:00
11 changed files with 300 additions and 135 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.261
1.5.271
+6 -12
View File
@@ -462,11 +462,6 @@ void simCell(char *name, int filenum)
return;
}
/* Check procedure disabled because new extensions to .sim format
* allow 'x' records to represent low-level components that are
* modeled as SPICE subcircuits.
*/
#if 0
/* check to see that all children have been dumped */
ob = tp->cell;
while (ob != NULL) {
@@ -478,7 +473,6 @@ void simCell(char *name, int filenum)
}
ob = ob->next;
}
#endif
SetExtension(FileName, name, SIM_EXTENSION);
if (!OpenFile(FileName, 0)) {
@@ -603,7 +597,7 @@ void simCell(char *name, int filenum)
FlushString(" %g\n", v);
break;
case CLASS_SUBCKT: case CLASS_MODULE:
case CLASS_MODULE:
*writeLine = 'x';
*(writeLine + 1) = '\0';
mult = 1;
@@ -812,7 +806,7 @@ char *ReadPrm(char *fname, int *fnum)
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "nf", 0, 1);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_SUBCKT);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
@@ -833,7 +827,7 @@ char *ReadPrm(char *fname, int *fnum)
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "nf", 0, 1);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_SUBCKT);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
@@ -855,7 +849,7 @@ char *ReadPrm(char *fname, int *fnum)
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_SUBCKT);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
@@ -877,7 +871,7 @@ char *ReadPrm(char *fname, int *fnum)
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_SUBCKT);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum); /* Reopen */
}
@@ -893,7 +887,7 @@ char *ReadPrm(char *fname, int *fnum)
Port("anode");
Port("cathode");
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_SUBCKT);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum); /* Reopen */
}
+6 -3
View File
@@ -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");
@@ -1231,6 +1230,10 @@ int UniquePins(char *name, int filenum)
* Removed the code 9/1/2023. But---Not sure if any code depends
* on shorted pins being adjacent.
*/
/* When two pins are shorted, they are by definition permutable */
PermuteSetup(ThisCell->name, ThisCell->file, ob->name,
firstport[ob->node]->name);
continue;
}
else {
+139 -20
View File
@@ -4204,6 +4204,28 @@ static int compsort(const void *p1, const void *p2)
return (s1->value > s2->value) ? 1 : 0;
}
/*--------------------------------------------------------------*/
/* compdsort() is like compsort() but uses the definition for */
/* "slop" used for type double instead of type integer. */
/*--------------------------------------------------------------*/
static int compdsort(const void *p1, const void *p2)
{
propsort *s1, *s2;
double smax, ddiff;
s1 = (propsort *)p1;
s2 = (propsort *)p2;
smax = fmax(s1->slop, s2->slop);
ddiff = fabs(s1->value - s2->value) /
fabs(s1->value + s2->value);
if (ddiff <= smax)
return (s1->avalue > s2->avalue) ? 1 : 0;
else
return (s1->value > s2->value) ? 1 : 0;
}
/*--------------------------------------------------------------*/
/* Sort properties of ob1 starting at property idx1 up to */
/* property (idx1 + run). Use series critical property for */
@@ -4221,7 +4243,8 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
struct valuelist *vl, *sl;
int i, p, sval, merge_type;
// double cval, slop;
int has_crit;
int (*sortfunc)() = compsort;
int has_crit, is_float;
char ca, co;
double tval, tslop;
double aval, pval, oval, aslop, pslop;
@@ -4241,6 +4264,7 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
for (i = 0; i < run; i++) {
has_crit = FALSE;
merge_type = MERGE_NONE;
is_float = FALSE;
ca = co = (char)0;
for (p = 0;; p++) {
@@ -4273,6 +4297,8 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
else {
tval = vl->value.dval;
tslop = kl->slop.dval;
sortfunc = compdsort;
is_float = TRUE;
}
if (kl->merge & MERGE_S_CRIT) {
@@ -4327,10 +4353,11 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
obn = obp; /* Link from last property */
qsort(&proplist[0], run, sizeof(propsort), compsort);
qsort(&proplist[0], run, sizeof(propsort), sortfunc);
// Re-sort list
obp = ob1;
for (i = 0; i < idx1; i++) obp = obp->next;
for (i = 0; i < run; i++) {
obp->next = proplist[i].ob;
obp = obp->next;
@@ -4416,6 +4443,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
propsort *proplist;
struct property *kl;
struct valuelist *vl;
int (*sortfunc)() = compsort;
int i, p, mval, merge_type;
int has_crit;
char ca, co;
@@ -4476,6 +4504,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
else {
tval = vl->value.dval;
tslop = kl->slop.dval;
sortfunc = compdsort;
}
if (kl->merge & MERGE_P_CRIT) {
@@ -4530,10 +4559,11 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
obn = obp; /* Link from last property */
qsort(&proplist[0], run, sizeof(propsort), compsort);
qsort(&proplist[0], run, sizeof(propsort), sortfunc);
// Re-sort list
obp = ob1;
for (i = 0; i < idx1; i++) obp = obp->next;
for (i = 0; i < run; i++) {
obp->next = proplist[i].ob;
obp = obp->next;
@@ -6122,7 +6152,9 @@ PropertyMatch(struct Element *E1, struct Element *E2,
if (kl2 != NULL)
break; // Property is required
}
else if (vl2->value.ival != 1)
else if ((vl2->type == PROP_INTEGER) && (vl2->value.ival != 1))
break; // Property M != 1 or S != 1 is a mismatch.
else if ((vl2->type == PROP_DOUBLE) && (vl2->value.dval != 1))
break; // Property M != 1 or S != 1 is a mismatch.
}
if (vl2->type != PROP_ENDLIST) {
@@ -7180,7 +7212,7 @@ int reorderpins(struct hashlist *p, int file)
{
struct nlist *ptr;
struct nlist *tc2 = Circuit2;
struct objlist *ob, *ob2, *firstpin;
struct objlist *ob, *ob2, *firstpin, *oblast, *newob;
int i, numports, *nodes, unordered;
char **names;
@@ -7232,6 +7264,7 @@ int reorderpins(struct hashlist *p, int file)
names[ob2->model.port] = ob->name;
}
oblast = ob;
ob = ob->next;
ob2 = ob2->next;
if (i < numports - 1) {
@@ -7239,7 +7272,34 @@ int reorderpins(struct hashlist *p, int file)
Fprintf(stderr, "Instance of %s has only "
"%d of %d ports\n",
tc2->name, i + 1, numports);
break;
if (ptr->flags & CELL_VERILOG) {
/* If parent cell is verilog, and the cells
* have been matched, then the instance can
* be assumed to be using an implicit pin.
*/
Fprintf(stderr, "Assuming implicit verilog pin \"%s\".\n",
ob2->name);
newob = (struct objlist *)CALLOC(1,
sizeof(struct objlist));
newob->name = (char *)MALLOC(strlen(oblast->instance.name)
+ strlen(ob2->name) + 2);
sprintf(newob->name, "%s/%s",
oblast->instance.name, ob2->name);
newob->type = oblast->type + 1;
newob->model.class = strsave(oblast->model.class);
newob->instance.name = strsave(oblast->instance.name);
newob->flags = 0;
ptr->nodename_cache_maxnodenum++;
newob->node = ptr->nodename_cache_maxnodenum;
newob->next = ob;
oblast->next = newob; /* Splice into object list */
/* Fill in the missing entries */
nodes[ob2->model.port] = newob->node;
names[ob2->model.port] = newob->name;
ob = newob;
}
else
break;
}
else if (ob2 == NULL || ob2->type != PORT) {
Fprintf(stderr, "Instance of %s has "
@@ -7441,6 +7501,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
int hasproxy1 = 0, hasproxy2 = 0;
int needclean1 = 0, needclean2 = 0;
int nomatch = 0;
int filenum = -1;
int *correspond;
char *ostr;
#ifdef TCL_NETGEN
@@ -7558,10 +7619,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
break;
}
}
else {
ob3 = NULL;
break; /* All pins w/the same node should be together */
}
}
if (ob3 == NULL) {
if (Debug == 0) {
@@ -7609,15 +7666,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
ob2->model.port = i; /* save order */
*(cover + i) = (char)1;
/* If there are multiple pins on the same net, cycle through them; */
/* otherwise, move to the next entry in the partition. */
if (ob1->next && (ob1->next->type == PORT) && (ob1->next->node == ob1->node)) {
ob1 = ob1->next;
ob2 = tc2->cell; /* Restart search for matching pin */
i++;
}
else
break;
break;
}
}
if (ob2 == NULL) {
@@ -7843,6 +7892,72 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (bangptr2) *bangptr2 = '!';
break;
}
else {
struct Permutation *permute1, *permute2;
struct objlist *ob1a = NULL, *ob2a = NULL;
/* Check the permutation list. If any permutable pin
* matches, and both nodes equal the nodes of their
* pin permutations, then the pins also match.
*/
for (permute1 = tc1->permutes; permute1; permute1 = permute1->next) {
if ((*matchfunc)(ob1->name, permute1->pin1)) {
ob1a = LookupObject(permute1->pin1, tc1);
break;
}
else if ((*matchfunc)(ob1->name, permute1->pin2)) {
ob1a = LookupObject(permute1->pin2, tc1);
break;
}
}
for (permute2 = tc2->permutes; permute2; permute2 = permute2->next) {
if ((*matchfunc)(ob2->name, permute2->pin1)) {
ob2a = LookupObject(permute2->pin1, tc2);
break;
}
else if ((*matchfunc)(ob2->name, permute2->pin2)) {
ob2a = LookupObject(permute2->pin2, tc2);
break;
}
}
if (ob1a && ob2a) {
if ((ob1->node == ob1a->node) && (ob2->node == ob2a->node)) {
/* This should be enough to prove equivalency */
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 = '!';
@@ -8118,7 +8233,11 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
/* Reorder pins in Circuit2 instances to match Circuit1 */
RecurseCellFileHashTable(reorderpins, Circuit2->file);
if (Circuit2 != NULL)
filenum = Circuit2->file;
else
filenum = tc2->file;
RecurseCellFileHashTable(reorderpins, filenum);
/* Reorder pins in Circuit2 cell to match Circuit1 */
/* Unlike the instance records, the structures are swapped, */
+14 -2
View File
@@ -587,6 +587,12 @@ void SkipTokNoNewline(char *delimiter)
/* */
/* Modified 3/30/2015 to include the condition where a comment line is */
/* in the middle of a series of continuation lines. */
/* */
/* Modified 1/3/2024 to avoid skipping two lines if a line has only the */
/* comment character '*' followed by a newline. It seems that '\n' is */
/* being ignored in WHITESPACE_DELIMITER, but it's easier to write the */
/* code to find the exception rather than track down the problem in */
/* GetNextLine(). */
/*----------------------------------------------------------------------*/
void SpiceTokNoNewline(void)
@@ -598,8 +604,14 @@ void SpiceTokNoNewline(void)
while (nexttok == NULL) {
contline = getc(infile);
if (contline == '*') {
GetNextLine(WHITESPACE_DELIMITER);
SkipNewLine(NULL);
char testline = ' ';
while ((testline == ' ') || (testline == '\t'))
testline = getc(infile);
if (testline != '\n') {
ungetc(testline, infile);
GetNextLine(WHITESPACE_DELIMITER);
SkipNewLine(NULL);
}
continue;
}
else if (contline != '+') {
+6 -2
View File
@@ -300,7 +300,9 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
tstr = sstr - 1;
numlast = 1;
}
break;
/* But might not be. . . */
if ((dval != 0) || (sstr > estr))
break;
}
/* Not a number, so must be arithmetic */
*tstr = '\0';
@@ -320,7 +322,9 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
tstr = sstr - 1;
numlast = 1;
}
break;
/* But might not be. . . */
if ((dval != 0) || (sstr > estr))
break;
}
/* Not a number, so must be arithmetic */
*tstr = '\0';
+75 -6
View File
@@ -43,6 +43,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "print.h"
#include "query.h"
#include "objlist.h"
#include "netcmp.h"
// Global storage for parameters from .PARAM
struct hashdict spiceparams;
@@ -519,7 +520,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
char *eqptr, devtype, in_subckt;
struct keyvalue *kvlist = NULL;
char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN];
struct nlist *tp;
struct nlist *tp, *tpsave;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj;
inst[MAX_STR_LEN-1] = '\0';
@@ -557,6 +558,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum);
tpsave = NULL;
/* Check for name conflict with duplicate cell names */
/* This may mean that the cell was used before it was */
@@ -595,11 +597,46 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
tp = LookupCellFile(nexttok, filenum);
}
else if (tp != NULL) { /* Make a new definition for an empty cell */
FreePorts(nexttok);
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
CellDef(model, filenum);
tp = LookupCellFile(model, filenum);
update = 1; /* Will need to update existing instances */
/* Handle issue with SPICE read after verilog, where a placeholder
* was created from the verilog. (1) If the pin names are "1", "2",
* "3", then this is a SPICE placeholder, and just remove the CellDef
* and re-create it. Otherwise, create new cell "_PLACEHOLDER_".
* (2) After encountering .ends, run MatchPins between the two cells.
* (3) delete the original cell and rename the new cell.
*/
int i = 1;
char pname[10];
for (pobj = tp->cell; pobj && pobj->type == PORT; pobj = pobj->next) {
sprintf(pname, "%d", i);
if (!matchnocase(pobj->name, pname)) break;
i++;
}
if ((pobj == NULL) || (pobj->type != PORT)) {
/* This is a SPICE placeholder created because the cell was instanced
* before it was defined. However, the pins can be assumed to be in
* the correct order, and pin reordering does not need to be done.
*/
FreePorts(nexttok);
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
CellDef(model, filenum);
tp = LookupCellFile(model, filenum);
update = 1; /* Will need to update existing instances */
}
else {
/* This is (probably) a verilog placeholder created because the
* verilog was read before the (SPICE) definitions. The verilog
* netlist should have named the pins of the parent cell. However,
* there is no guarantee the order of pins is correct. The MatchPins()
* routine from netcmp.c can be used here to match the cell against
* the placeholder, and reorder the pins in all instances to match.
* Note that we cannot just reorder the SPICE pins to match the
* verilog order, because there may be other SPICE netlists which
* instance the cell with the correct SPICE port order.
*/
tpsave = tp;
CellDef("_PLACEHOLDER_", filenum);
tp = LookupCellFile("_PLACEHOLDER_", filenum);
}
}
else if (tp == NULL) { /* Completely new cell, no name conflict */
CellDef(model, filenum);
@@ -691,6 +728,38 @@ skip_ends:
if (*CellStackPtr) PopStack(CellStackPtr);
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
SkipNewLine(NULL);
if (tpsave != NULL) {
struct nlist *tpplace;
char *savename;
/* Handle a placeholder from a verilog file that has been replaced
* by a netlist with pins in a different order. The pins need to
* be matched, corrected in the original cell and all instances,
* and the new cell deleted.
*/
Printf("Verilog placeholder %s replaced by SPICE definition\n",
tpsave->name);
tpplace = LookupCellFile("_PLACEHOLDER_", filenum);
/* MatchPins is part of netcmp and normally Circuit2 is the
* circuit being matched, so set Circuit2 to the original
* verilog black-box cell, and MatchPins() will force its
* pins to be rearranged to match the SPICE definition just
* read.
*/
Circuit2 = tpsave;
MatchPins(tpplace, tpsave, 0);
savename = strsave(tpsave->name);
/* Now the original verilog black-box cell can be removed */
FreePorts(savename);
CellDelete(savename, filenum);
/* And _PLACEHOLDER_ is renamed to the original name of the cell. */
CellRehash("_PLACEHOLDER_", savename, filenum);
tpsave = NULL;
Circuit2 = NULL;
FREE(savename);
}
}
else if (matchnocase(nexttok, ".MODEL")) {
unsigned char class = CLASS_SUBCKT;
+38 -30
View File
@@ -57,6 +57,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "netfile.h"
#include "print.h"
#include "hash.h"
#include "netcmp.h"
// See netfile.c for explanation of delimiters. 'X'
// separates single-character delimiters from two-character delimiters.
@@ -1018,7 +1019,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
char *eqptr, *matchptr;
struct keyvalue *kvlist = NULL;
char inst[MAX_STR_LEN], model[MAX_STR_LEN], portname[MAX_STR_LEN], pkey[MAX_STR_LEN];
struct nlist *tp;
struct nlist *tp, *tpsave;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj, *cref;
inst[MAX_STR_LEN-1] = '\0';
@@ -1152,6 +1153,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum);
tpsave = NULL;
hasports = (char)0;
/* Check for name conflict with duplicate cell names */
@@ -1191,35 +1193,9 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
tp = LookupCellFile(nexttok, filenum);
}
else if (tp != NULL) { /* Cell exists, but as a placeholder */
struct nlist *tptmp = NULL;
char ctemp[8];
int n = 0;
/* This redefines a placeholder module to an unused temporary cell name */
while (1) {
sprintf(ctemp, "%d", n);
tptmp = LookupCellFile(ctemp, filenum);
if (tptmp == NULL) break;
n++;
}
CellRehash(nexttok, ctemp, filenum);
tptmp = LookupCellFile(ctemp, filenum);
/* Create a new module definition */
CellDef(model, filenum);
tp = LookupCellFile(model, filenum);
/* Find an instance of this module in the netlist */
cref = FindInstanceOf(tp);
if ((cref != NULL) && (cref->name != NULL)) {
hasports = (char)1;
/* Copy ports from the original parent cell to the new parent cell */
for (pobj = tptmp->cell; pobj && (pobj->type == PORT); pobj = pobj->next)
Port(pobj->name);
}
/* Remove the original cell definition */
FreePorts(ctemp);
CellDelete(ctemp, filenum); /* This removes any PLACEHOLDER flag */
tpsave = tp;
CellDef("_PLACEHOLDER_", filenum);
tp = LookupCellFile("_PLACEHOLDER_", filenum);
}
else if (tp == NULL) { /* Completely new cell, no name conflict */
CellDef(model, filenum);
@@ -1428,6 +1404,38 @@ skip_endmodule:
if (*CellStackPtr) PopStack(CellStackPtr);
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
SkipNewLine(VLOG_DELIMITERS);
if (tpsave != NULL) {
struct nlist *tpplace;
char *savename;
/* Handle a placeholder from a verilog file that has been replaced
* by a netlist with pins in a different order. The pins need to
* be matched, corrected in the original cell and all instances,
* and the new cell deleted.
*/
Printf("Verilog placeholder module %s replaced by module definition\n",
tpsave->name);
tpplace = LookupCellFile("_PLACEHOLDER_", filenum);
/* MatchPins is part of netcmp and normally Circuit2 is the
* circuit being matched, so set Circuit2 to the original
* verilog black-box cell, and MatchPins() will force its
* pins to be rearranged to match the module definition just
* read.
*/
Circuit2 = tpsave;
MatchPins(tpplace, tpsave, 0);
savename = strsave(tpsave->name);
/* Now the original verilog black-box cell can be removed */
FreePorts(savename);
CellDelete(savename, filenum);
/* And _PLACEHOLDER_ is renamed to the original name of the cell. */
CellRehash("_PLACEHOLDER_", savename, filenum);
tpsave = NULL;
Circuit2 = NULL;
FREE(savename);
}
}
else if (match(nexttok, "`include")) {
+1 -52
View File
@@ -668,7 +668,6 @@ XMKMF
HAVE_PYTHON3
EGREP
GREP
M4
RANLIB
INSTALL_DATA
INSTALL_SCRIPT
@@ -3702,56 +3701,6 @@ else
fi
for ac_prog in gm4 gnum4 m4
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_M4+:} false; then :
$as_echo_n "(cached) " >&6
else
case $M4 in
[\\/]* | ?:[\\/]*)
ac_cv_path_M4="$M4" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_M4="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
M4=$ac_cv_path_M4
if test -n "$M4"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
$as_echo "$M4" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$M4" && break
done
test -n "$M4" || M4="no"
if test x$M4 = xno; then
as_fn_error $? "M4 is required" "$LINENO" 5
fi
if test "$CPP" = "$CC -E" ; then
CPP="$CPP -x c"
@@ -6302,7 +6251,7 @@ fi
*darwin*)
SHDLIB_EXT=".dylib"
LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind"
LDDL_FLAGS="-dynamiclib -undefined dynamic_lookup"
LDFLAGS="${LDFLAGS} ${LIB_SPECS}"
CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common"
;;
+1 -7
View File
@@ -26,12 +26,6 @@ AC_ISC_POSIX
AC_PROG_INSTALL
AC_PROG_RANLIB
dnl GNU M4 is preferred due to some of the option switches.
AC_PATH_PROGS([M4], [gm4 gnum4 m4], [no])
if test x$M4 = xno; then
AC_MSG_ERROR([M4 is required])
fi
dnl check size of pointer for correct behavior on 64-bit systems
dnl If the C preprocessor is GCC, we need to force the flag to
dnl assert that input files are of type C, or else the preprocessing
@@ -1033,7 +1027,7 @@ fi
*darwin*)
SHDLIB_EXT=".dylib"
LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind"
LDDL_FLAGS="-dynamiclib -undefined dynamic_lookup"
LDFLAGS="${LDFLAGS} ${LIB_SPECS}"
CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common"
;;
+13
View File
@@ -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.