Compare commits

...
17 Commits
Author SHA1 Message Date
Tim Edwards e11dbac384 Merge branch 'master' into netgen-1.5 2022-01-17 03:00:14 -05:00
Tim Edwards bfb01e032f Implemented another change discussed in netgen github issue #47
by Anton Blanchard, which prevents the double-loop in the
PropertyOptimize() routine from continuing the outer loop if
all devices in the run have already been merged.
2022-01-16 14:47:52 -05:00
Tim Edwards d0ec17e442 Implemented a change to the way that netgen generates the subcircuit
summary, so that the summary lists the total number of devices as well
as the number of devices after parallel optimization, in the form
"device_name (M->N)", where "M" is the total number of devices, and
"N" is the number of devices after parallel combination.  This makes
the output somewhat more meaningful to the end user.  Implementation
as discussed in github issue #47.
2022-01-16 14:16:30 -05:00
Tim Edwards 0535128421 Merge branch 'master' into netgen-1.5 2022-01-16 03:00:18 -05:00
Tim Edwards 6195745b45 Modified the parallel combination code so that properties of
parallel devices are prepended rather than appended, which avoids
having to search for the end of what may be a rapidly increasing
linked list of properties.  This reduces the amount of time spent
in the parallel combination code.  Thanks to Anton Blanchard for
pointing out this inefficiency.
2022-01-15 12:06:43 -05:00
Tim Edwards afe0e9f758 Merge branch 'master' into netgen-1.5 2022-01-01 03:00:43 -05:00
Tim Edwards 68ec2b2a7c Modified two print statements to change "%s(%d)" to "%s (%d)" as
is my typographic preference.
2021-12-31 13:30:13 -05:00
Tim Edwards ca49a90ed6 Merged changes from github issue #45 from Mitch Bailey. These changes
speed up the time needed to flatten an instance, and add clarity to the
output by specifying the file number for each cell name being modified
during the pre-match stage.
2021-12-31 12:13:11 -05:00
Tim Edwards e487890641 Merge branch 'master' into netgen-1.5 2021-12-31 03:00:42 -05:00
Tim Edwards e07a5b416a Removed lvs_manager.py, which is a derived file and should not have
ended up in the repository, as pointed out by Mitch Bailey in github
issue #44.  Added lvs_manager.py to .gitignore to prevent that from
happening again in the future.
2021-12-30 09:19:44 -05:00
Tim Edwards bb44d3f827 Merge branch 'master' into netgen-1.5 2021-12-30 03:00:43 -05:00
Tim Edwards 8094740048 Corrected a problem that stems from code that was deprecated and
marked as unneeded, so I simply removed the code rather than
debug the issue, which was that buses got the delimeters erased
for checking but never put back again.  Also:  Modified the verilog
reading code so that if an empty set "()" is given for a pin, then
the initial proxy, which is a single net with the name prefix
"_noconnect_", can be promoted to a bus if further processing
reveals it to be a bus and not a single-bit signal.
2021-12-29 14:31:38 -05:00
Tim Edwards c25c4e1160 Merge branch 'master' into netgen-1.5 2021-12-27 03:00:18 -05:00
Tim Edwards a026d37f11 Corrected a place in the verilog read routine where ob->next is
used when ob may be NULL.  Added a check in front for ob == NULL.
Also:  Changed the disconnected node alert so that it does not
mention nodes marked "port_mismatch_error".  These are disconnected
by definition, will show up in the pin list, and printing them as
"disconnected pins" is just confusing to the end user.
2021-12-26 10:31:48 -05:00
Tim Edwards 8ed4e3cf38 Merge branch 'master' into netgen-1.5 2021-12-20 03:00:02 -05:00
Tim Edwards ab614b63f7 Corrected the last commit (again) because FlattenUnmatched()
should not be called after CreateTwoLists().  CreateTwoLists()
was being called in one case only to print the contents of the
cells, so that part was pulled out into a separate routine.
2021-12-19 16:25:32 -05:00
Tim Edwards 83dce151d8 Made a correction to the last commit. The "FlattenUnmatched()"
routine does not have an exact equivalent in PrematchLists() and
needs to be run beforehand.  This fix keeps FlattenUnmatched()
from being run on all cells at the beginning and restricts it
to being run on the contents of individual cells during matching,
after checking if either of the cells is a black-box.  Avoiding
flattening contents of one side when the other is a black-box
(or simply doesn't contain any subcircuits or devices) prevents
unnecessary flattening of cells that will never get compared.
2021-12-17 20:31:41 -05:00
11 changed files with 240 additions and 177 deletions
+1
View File
@@ -7,6 +7,7 @@ config.log
scripts/config.log
config.status
scripts/config.status
python/lvs_manager.py
*.o
*.so
*~
+1 -1
View File
@@ -1 +1 @@
1.5.212
1.5.219
+51 -63
View File
@@ -372,22 +372,16 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
/* update node numbers in child to unique numbers */
oldmax = 0;
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next)
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) {
if (tmp->node > oldmax) oldmax = tmp->node;
if (nextnode <= oldmax) nextnode = oldmax + 1;
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next)
if (tmp->node <= oldmax && tmp->node > 0) {
if (Debug) Printf("Update node %d --> %d\n", tmp->node, nextnode);
UpdateNodeNumbers(ChildStart, tmp->node, nextnode);
nextnode++;
}
if (tmp->node > 0) tmp->node += (nextnode - 1);
}
nextnode += oldmax;
/* copy nodenumbers of ports from parent */
ob2 = ParentParams;
for (tmp = ChildStart; tmp != NULL; tmp = tmp->next) {
if (IsPort(tmp)) {
if (tmp->node > 0) {
for (tmp = ChildStart; tmp && IsPort(tmp); tmp = tmp->next) {
if (tmp->node > 0) {
if (ob2->node == -1) {
// Before commiting to attaching to a unconnected node, see
@@ -413,17 +407,16 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
Printf("Update node %d --> %d\n", tmp->node, ob2->node);
}
UpdateNodeNumbers(ChildStart, tmp->node, ob2->node);
}
}
/* in pathological cases, the lengths of the port lists may
* change. This is an error, but that is no reason to allow
* the code to core dump. We avoid this by placing a
* superfluous check on ob2->type
*/
if (ob2 != NULL) ob2 = ob2->next;
/* in pathological cases, the lengths of the port lists may
* change. This is an error, but that is no reason to allow
* the code to core dump. We avoid this by placing a
* superfluous check on ob2->type
*/
if (ob2 != NULL) ob2 = ob2->next;
if (ob2 == NULL) break;
}
if (ob2 == NULL) break;
}
/* Using name == NULL to indicate that a .ext file is being */
@@ -1421,11 +1414,27 @@ typedef struct ecomplist {
ECompListPtr next;
} ECompList;
/*----------------------------------------------------------------------*/
/* Determine if a cell contains at least one device or subcircuit */
/*----------------------------------------------------------------------*/
int
HasContents(struct nlist *tc)
{
struct objlist *ob;
for (ob = tc->cell; ob; ob = ob->next)
if (ob->type == FIRSTPIN)
return TRUE;
return FALSE;
}
/*------------------------------------------------------*/
/* Survey the contents of a cell and sort into a hash */
/*------------------------------------------------------*/
int
void
SurveyCell(struct nlist *tc, struct hashdict *compdict, int file1, int file2, int which)
{
struct objlist *ob;
@@ -1433,12 +1442,10 @@ SurveyCell(struct nlist *tc, struct hashdict *compdict, int file1, int file2, in
ECompare *ecomp, *qcomp, *ncomp;
int file = (which == 0) ? file1 : file2;
int ofile = (which == 0) ? file2 : file1;
int retval = FALSE;
char *dstr;
for (ob = tc->cell; ob; ob = ob->next) {
if (ob->type == FIRSTPIN) {
retval = TRUE; /* Cell has at least one device or subcircuit */
tsub = LookupCellFile(ob->model.class, file);
if (tsub->flags & CELL_DUPLICATE) {
// Always register a duplicate under the original name
@@ -1492,7 +1499,6 @@ SurveyCell(struct nlist *tc, struct hashdict *compdict, int file1, int file2, in
if (dstr) *dstr = '[';
}
}
return retval;
}
/*------------------------------------------------------*/
@@ -1540,28 +1546,10 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
listX0 = list0X = NULL;
// Gather information about instances of cell "name1"
hascontents1 = SurveyCell(tc1, &compdict, file1, file2, 0);
SurveyCell(tc1, &compdict, file1, file2, 0);
// Gather information about instances of cell "name2"
hascontents2 = SurveyCell(tc2, &compdict, file1, file2, 1);
// If one cell has no contents, then flattening the other
// isn't going to improve anything, so stop here.
if (!hascontents1 && !hascontents2 && (tc1->flags & CELL_PLACEHOLDER)
&& (tc2->flags & CELL_PLACEHOLDER)) {
goto done;
}
else if (hascontents1 && !hascontents2 && (tc2->flags & CELL_PLACEHOLDER)) {
Fprintf(stdout, "Circuit 2 cell %s is a black box; will not flatten "
"Circuit 1\n", name2);
goto done;
}
else if (hascontents2 && !hascontents1 && (tc1->flags & CELL_PLACEHOLDER)) {
Fprintf(stdout, "Circuit 1 cell %s is a black box; will not flatten "
"Circuit 2\n", name1);
goto done;
}
SurveyCell(tc2, &compdict, file1, file2, 1);
// Find all instances of one cell that have fewer in
// the compared circuit. Check whether subcircuits
@@ -1612,15 +1600,15 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
if (match) {
if (ecomp->cell1 && (ecomp->num1 > 0)) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell1->name,
name1);
name1, file1);
flattenInstancesOf(name1, file1, ecomp->cell1->name);
}
if (ecomp->cell2 && (ecomp->num2 > 0)) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell2->name,
name2);
name2, file2);
flattenInstancesOf(name2, file2, ecomp->cell2->name);
}
modified++;
@@ -1701,9 +1689,9 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
if (match) {
if (ecomp->cell2) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell2->name,
name2);
name2, file2);
flattenInstancesOf(name2, file2, ecomp->cell2->name);
}
modified++;
@@ -1759,9 +1747,9 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
if (match) {
if (ecomp->cell1) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell1->name,
name1);
name1, file1);
flattenInstancesOf(name1, file1, ecomp->cell1->name);
}
modified++;
@@ -1842,9 +1830,9 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
if (found) {
Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s makes a better match\n",
tsub1->name,
tc1->name);
"%s from cell %s (%d) makes a better "
"match\n",
tsub1->name, tc1->name, tc1->file);
/* A current source is an open, while a */
/* resistor or voltage source is a short. */
@@ -1953,9 +1941,9 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
}
if (found) {
Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s makes a better match\n",
tsub2->name,
tc2->name);
"%s from cell %s (%d) makes a better "
"match\n",
tsub2->name, tc2->name, tc2->file);
/* merge node of endpoints */
if (ecomp->cell2->class != CLASS_ISOURCE) {
@@ -2046,8 +2034,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (dstr) *dstr = '[';
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
" makes a better match\n", ecompX0->cell1->name,
name1);
"(%d) makes a better match\n",
ecompX0->cell1->name, name1, file1);
flattenInstancesOf(name1, file1, ecompX0->cell1->name);
ecompX0->num1 = 0;
ecomp0X->num1 += ecompX0->num1;
@@ -2072,8 +2060,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (dstr) *dstr = '[';
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
" makes a better match\n", ecomp0X->cell2->name,
name2);
" (%d) makes a better match\n",
ecomp0X->cell2->name, name2, file2);
flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
ecomp0X->num2 = 0;
ecompX0->num2 += ecomp0X->num2;
+1
View File
@@ -3,5 +3,6 @@
extern int UniquePins(char *name, int filenum);
extern void flattenCell(char *name, int file);
extern int HasContents(struct nlist *);
#endif /* _FLATTEN_H */
+92 -15
View File
@@ -3122,6 +3122,47 @@ struct nlist *LookupPrematchedClass(struct nlist *tc1, int file2)
return tc2;
}
/*----------------------------------------------------------------------*/
/* Scan the property list of a device to find the number of devices */
/* implied by the total of M records. If the device does not have a */
/* property list, then return 1. If any property list does not have an */
/* "M" record, treat it as 1. */
/*----------------------------------------------------------------------*/
int GetNumDevices(struct objlist *ob)
{
int p, found, M = 0;
struct objlist *obs;
struct valuelist *vl;
obs = ob;
if (obs->type != PROPERTY)
for (obs = ob->next; obs && (obs->type != FIRSTPIN) &&
(obs->type != PROPERTY); obs = obs->next);
if ((obs == NULL) || (obs->type != PROPERTY)) return 1;
while (obs && (obs->type == PROPERTY)) {
found = FALSE;
for (p = 0; ; p++) {
vl = &obs->instance.props[p];
if (vl->type == PROP_ENDLIST) break;
if (vl->key == NULL) continue;
if ((*matchfunc)(vl->key, "M")) {
if (vl->type == PROP_DOUBLE)
M += (int)vl->value.dval;
else
M += vl->value.ival;
found = TRUE;
break;
}
}
if (found == FALSE) M++;
obs = obs->next;
}
return M;
}
/*----------------------------------------------------------------------*/
/* Attempt to define FirstElementPass that will generate element */
/* classes by names of pins, which will allow elements with different */
@@ -3143,7 +3184,7 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
struct Element *Esrch, *Ecorr;
struct NodeList *n;
struct nlist *tp1, *tp2, *tp;
int C1, C2, i;
int C1, C2, M1, M2, i;
char *ostr;
int needflat = 0;
#ifdef TCL_NETGEN
@@ -3184,6 +3225,8 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
Esrch->hashval = 1;
C1 = 1;
C2 = 0;
M2 = 0;
M1 = GetNumDevices(Esrch->object);
tp1 = LookupCellFile(Esrch->object->model.class, Circuit1->file);
tp2 = LookupClassEquivalent(Esrch->object->model.class, Circuit1->file,
Circuit2->file);
@@ -3195,6 +3238,7 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
if (tp && tp2 && (tp->classhash == tp2->classhash)) {
Ecorr->hashval = 1;
C2++;
M2 += GetNumDevices(Ecorr->object);
}
}
else if (Ecorr->graph == Circuit1->file) {
@@ -3203,6 +3247,7 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
if (tp && tp1 && (tp->classhash == tp1->classhash)) {
Ecorr->hashval = 1;
C1++;
M1 += GetNumDevices(Ecorr->object);
}
}
}
@@ -3219,10 +3264,19 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
snprintf(ostr, left_col_end, "%s (%d)", Esrch->object->model.class, C1);
if (C2 > 0)
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d)%s", tp2->name, C2,
(C2 == C1) ? "" : " **Mismatch**");
if (M1 == C1)
snprintf(ostr, left_col_end, "%s (%d)", Esrch->object->model.class, C1);
else
snprintf(ostr, left_col_end, "%s (%d->%d)", Esrch->object->model.class,
M1, C1);
if (C2 > 0) {
if (M2 == C2)
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d)%s", tp2->name,
C2, (C2 == C1) ? "" : " **Mismatch**");
else
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d->%d)%s",
tp2->name, M2, C2, (C2 == C1) ? "" : " **Mismatch**");
}
else {
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching element)");
}
@@ -3261,6 +3315,7 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
if (Esrch->graph == Circuit2->file && Esrch->hashval == 0) {
Esrch->hashval = 1;
C2 = 1;
M2 = GetNumDevices(Esrch->object);
tp2 = LookupCellFile(Esrch->object->model.class, Circuit2->file);
tp1 = LookupClassEquivalent(Esrch->object->model.class, Circuit2->file,
Circuit1->file);
@@ -3272,6 +3327,7 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
if (tp->classhash == tp2->classhash) {
Ecorr->hashval = 1;
C2++;
M2 += GetNumDevices(Ecorr->object);
}
}
}
@@ -3287,7 +3343,12 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
snprintf(ostr, left_col_end, "(no matching element)");
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d)", Esrch->object->model.class, C2);
if (C2 == M2)
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d)",
Esrch->object->model.class, C2);
else
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d->%d)",
Esrch->object->model.class, M2, C2);
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
Fprintf(stdout, ostr);
}
@@ -3758,8 +3819,23 @@ void RemoveCompareQueue()
CompareQueue = NULL;
}
/*----------------------------------------------------------------------*/
/* Output a summary of the contents of the two circuits being compared */
/*----------------------------------------------------------------------*/
void DescribeContents(char *name1, int file1, char *name2, int file2)
{
Fprintf(stdout, "\n"); // blank line before new circuit diagnostics in log file
/* print preliminary statistics */
Printf("\nContents of circuit 1: ");
DescribeInstance(name1, file1);
Printf("Contents of circuit 2: ");
DescribeInstance(name2, file2);
Printf("\n");
}
/*----------------------------------*/
/* create an initial data structure */
/* Create an initial data structure */
/*----------------------------------*/
void CreateTwoLists(char *name1, int file1, char *name2, int file2, int dolist)
@@ -3771,14 +3847,6 @@ void CreateTwoLists(char *name1, int file1, char *name2, int file2, int dolist)
ResetState();
Fprintf(stdout, "\n"); // blank line before new circuit diagnostics in log file
/* print preliminary statistics */
Printf("\nContents of circuit 1: ");
DescribeInstance(name1, file1);
Printf("Contents of circuit 2: ");
DescribeInstance(name2, file2);
Printf("\n");
if (file1 == -1)
tc1 = LookupCell(name1);
else
@@ -4853,6 +4921,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
// Now combine records with same properties by summing M (S).
if (comb == FALSE) {
for (i = 0; i < run - 1; i++) {
int nr_empty = 0;
for (j = i + 1; j < run; j++) {
pmatch = 0;
for (p = 1; p < pcount; p++) {
@@ -4976,8 +5045,14 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
vlist[0][i]->value.ival += vlist[0][j]->value.ival;
vlist[0][j]->value.ival = 0;
}
else
nr_empty++;
}
}
// If everything from i to the end of the run has been matched
// and zeroed out, then nothing more can be merged.
if (nr_empty == (run - (i + 1)))
break;
}
}
@@ -7938,6 +8013,7 @@ int Compare(char *cell1, char *cell2)
{
int automorphisms;
DescribeContents(cell1, -1, cell2, -1);
CreateTwoLists(cell1, -1, cell2, -1, 0);
Permute();
while (!Iterate());
@@ -7998,6 +8074,7 @@ void NETCOMP(void)
case 'c':
promptstring("Enter cell 1: ",name);
promptstring("Enter cell 2: ",name2);
DescribeContents(name, -1, name2, -1);
CreateTwoLists(name, -1, name2, -1, 0);
#ifdef DEBUG_ALLOC
PrintCoreStats();
+2
View File
@@ -26,6 +26,7 @@ extern void PrintCoreStats(void);
extern void ResetState(void);
extern void CreateTwoLists(char *name1, int file1, char *name2, int file2,
int dolist);
extern void DescribeContents(char *name1, int file1, char *name2, int file2);
extern int Iterate(void);
extern int VerifyMatching(void);
extern void PrintAutomorphisms(void);
@@ -46,6 +47,7 @@ extern int CreateCompareQueue(char *, int, char *, int);
extern int GetCompareQueueTop(char **, int *, char **, int *);
extern int PeekCompareQueueTop(char **, int *, char **, int *);
extern void RemoveCompareQueue();
extern int FlattenUnmatched(struct nlist *, char *, int, int);
extern void PrintIllegalClasses();
extern void PrintIllegalNodeClasses();
+24 -26
View File
@@ -3337,16 +3337,13 @@ int CombineParallel(char *model, int file)
/* "sob" to it. If "ob" does not have properties, then */
/* create a property record and set property "M" to 1. */
/* Find last non-property record of sob ( = pob) */
/* Find first property record of sob ( = spropfirst) */
/* Find last property record of sob ( = sproplast) */
/* Find last non-property record of sob ( = pob) */
/* Find first property record of sob ( = spropfirst) */
spropfirst = sproplast = NULL;
spropfirst = NULL;
for (ob2 = sob; ob2->type > FIRSTPIN || ob2 == sob; ob2 = ob2->next)
pob = ob2;
if (ob2->type == PROPERTY) spropfirst = ob2;
for (; ob2->type == PROPERTY; ob2 = ob2->next)
sproplast = ob2;
if (spropfirst == NULL) {
/* Create new property instance record if one doesn't exist */
@@ -3372,8 +3369,9 @@ int CombineParallel(char *model, int file)
nob->next = pob->next;
pob->next = nob;
/* Handle case of contiguous entries */
if (lob == pob) lob = nob;
spropfirst = sproplast = nob;
spropfirst = nob;
}
if (propfirst == NULL) {
/* Create new property instance record if one doesn't exist */
@@ -3396,27 +3394,26 @@ int CombineParallel(char *model, int file)
kv->type = PROP_ENDLIST;
kv->value.ival = 0;
/* Append to sob's property list */
nob->next = sproplast->next;
sproplast->next = nob;
if (lob == sproplast) lob = nob;
/* Prepend to sob's property list */
nob->next = pob->next;
pob->next = nob;
/* Handle case of contiguous entries */
if (lob == pob) lob = nob;
}
if (propfirst != NULL) {
else {
// Series/Parallel logic:
// If propfirst has _tag in properties,
// then add an "open" tag at propfirst
add_prop_tag(propfirst, '(');
// If spropfirst has _tag in properties,
// then add an "open" tag at spropfirst
add_prop_tag(spropfirst, '(');
// if spropfirst has _tag in properties then add an "open" tag
// to spropfirst and a "close" tag to propfirst
if (add_prop_tag(spropfirst, '(')) add_prop_tag(propfirst, ')');
// if propfirst has _tag in properties then add an "open" tag
// to propfirst and a "close" tag to spropfirst
if (add_prop_tag(propfirst, '(')) add_prop_tag(spropfirst, ')');
/* Append ob's property list to sob */
proplast->next = sproplast->next;
sproplast->next = propfirst;
if (lob == sproplast) lob = proplast;
/* Prepend ob's property list to sob */
proplast->next = pob->next;
pob->next = propfirst;
}
/* Link up around object to be removed */
@@ -3429,7 +3426,6 @@ int CombineParallel(char *model, int file)
obr = nob;
}
dcnt++;
}
FREE((char *)pstr);
}
@@ -3441,7 +3437,8 @@ int CombineParallel(char *model, int file)
}
HashKill(&devdict);
if (dcnt > 0) {
Fprintf(stdout, "Class %s(%d): Merged %d parallel devices.\n", model, file, dcnt);
Fprintf(stdout, "Class %s (%d): Merged %d parallel devices.\n",
model, file, dcnt);
}
FREE(nodecount);
return dcnt;
@@ -3739,7 +3736,8 @@ int CombineSeries(char *model, int file)
}
FREE(instlist);
if (scnt > 0) {
Fprintf(stdout, "Class %s(%d): Merged %d series devices.\n", model, file, scnt);
Fprintf(stdout, "Class %s (%d): Merged %d series devices.\n",
model, file, scnt);
}
return scnt;
}
+7 -4
View File
@@ -805,11 +805,14 @@ void DescribeInstance(char *name, int file)
/* All black-box modules and placeholders by definition have all */
/* disconnected pins, so don't report those. */
if (!(tp->flags & CELL_PLACEHOLDER) && (tp->class != CLASS_MODULE))
{
//if (disconnectednodes == 0) Fprintf(stderr, "\n");
if ((!(tp->flags & CELL_PLACEHOLDER)) && (tp->class != CLASS_MODULE)) {
// if (disconnectednodes == 0) Fprintf(stderr, "\n");
disconnectednodes++;
Fprintf(stderr, "Cell %s(%d) disconnected node: %s\n", tp->name, tp->file, ob->name);
/* Don't report on ports marked "port_match_error", which is just confusing. */
if (strcmp(ob->name, "port_match_error")) {
Fprintf(stderr, "Cell %s (%d) disconnected node: %s\n",
tp->name, tp->file, ob->name);
}
}
}
}
+8 -8
View File
@@ -940,7 +940,7 @@ skip_ends:
goto baddevice;
}
snprintf(instname, 255, "%s%s", model, inst);
snprintf(instname, 255, "%s:%s", model, inst);
Cell(instname, model, collector, base, emitter);
pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
@@ -1013,7 +1013,7 @@ skip_ends:
goto baddevice;
}
snprintf(instname, 255, "%s%s", model, inst);
snprintf(instname, 255, "%s:%s", model, inst);
Cell(instname, model, drain, gate, source, bulk);
pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
@@ -1104,7 +1104,7 @@ skip_ends:
usemodel = 1;
}
snprintf(instname, 255, "%s%s", model, inst);
snprintf(instname, 255, "%s:%s", model, inst);
if (usemodel)
Cell(instname, model, ctop, cbot);
else
@@ -1197,7 +1197,7 @@ skip_ends:
else
strcpy(model, "r"); /* Use default resistor model */
snprintf(instname, 255, "%s%s", model, inst);
snprintf(instname, 255, "%s:%s", model, inst);
if (usemodel)
Cell(instname, model, rtop, rbot);
else
@@ -1255,7 +1255,7 @@ skip_ends:
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a diode.\n");
goto baddevice;
}
snprintf(instname, 255, "%s%s", model, inst);
snprintf(instname, 255, "%s:%s", model, inst);
Cell(instname, model, anode, cathode);
pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
@@ -1334,7 +1334,7 @@ skip_ends:
else
strcpy(model, "t"); /* Use default xline model */
snprintf(instname, 255, "%s%s", model, inst);
snprintf(instname, 255, "%s:%s", model, inst);
if (usemodel)
Cell(instname, model, node1, node2, node3, node4);
@@ -1417,7 +1417,7 @@ skip_ends:
else
strcpy(model, "l"); /* Use default inductor model */
snprintf(instname, 255, "%s%s", model, inst);
snprintf(instname, 255, "%s:%s", model, inst);
if (usemodel)
Cell(instname, model, end_a, end_b);
else
@@ -1729,7 +1729,7 @@ skip_ends:
/* names. */
if (strncmp(instancename, scan->name, strlen(scan->name))) {
snprintf(subcktname, 99, "%s%s", scan->name, instancename);
snprintf(subcktname, 99, "%s:%s", scan->name, instancename);
strcpy(instancename, subcktname);
}
else {
+20 -50
View File
@@ -1778,54 +1778,6 @@ nextinst:
scan->width = width;
result = GetBus(scan->net, &wb);
if (result == -1) {
/* CHECK: THIS CODE SHOULD BE DELETED, IT IS NOT THE ISSUE */
/* Not bus notation, but check if signal was defined as a bus */
wb.start = wb.end = -1;
minnet = maxnet = -1;
/* Pins should be in index order start->end. Other nodes */
/* should be in order start->end by node number. */
for (bobj = CurrentCell->cell; bobj; bobj = bobj->next) {
if (bobj->type == PORT) {
if ((bptr = strvchr(bobj->name, '[')) != NULL) {
*bptr = '\0';
if (!strcmp(bobj->name, scan->net)) {
*bptr = '[';
if (wb.start == -1)
sscanf(bptr + 1, "%d", &wb.start);
else
sscanf(bptr + 1, "%d", &wb.end);
}
}
}
else if (bobj->type == NODE) {
if ((bptr = strvchr(bobj->name, '[')) != NULL) {
*bptr = '\0';
if (!strcmp(bobj->name, scan->net)) {
if (sscanf(bptr + 1, "%d", &testidx) == 1) {
if (minnet == -1) {
minnet = maxnet = bobj->node;
wb.start = wb.end = testidx;
}
else if (bobj->node < minnet) {
minnet = bobj->node;
wb.start = testidx;
}
else if (bobj->node > maxnet) {
maxnet = bobj->node;
wb.end = testidx;
}
}
}
*bptr = '[';
}
}
}
if (wb.start != -1) result = 0;
}
if (result == 0) {
int match = 0;
int wblen, arraylen;
@@ -1935,7 +1887,25 @@ nextinst:
}
}
else if (portstart != portend) {
Fprintf(stderr, "Error: Single net %s is connected to bus port %s\n",
/* If the name starts with "_noconnect_", then it was an
* auto-generated name that incorrectly assumed a single-bit
* wide signal because it did not have a module prototype.
* Rewrite the noconnect name as an array. This just means
* that the verilog had an empty list "()" and the initial
* assumption was wrong. If not all instances agree on the
* size, then this will eventually generate an error.
*/
if (!strncmp(scan->net, "_noconnect_", 11) &&
(strchr(scan->net, '\[') == NULL) && (width > 1)) {
char *savenet = scan->net;
char *newnet = MALLOC(strlen(scan->net) + 12);
sprintf(newnet, "%s[%d:0]", scan->net, scan->width - 1);
FREE(savenet);
scan->net = newnet;
continue; /* Re-process this entry */
}
else
Fprintf(stderr, "Error: Single net %s is connected to bus port %s\n",
scan->net, scan->name);
}
}
@@ -2117,7 +2087,7 @@ nextinst:
sobj = sobj->next) {
if (sobj->type == FIRSTPIN) {
if (match(sobj->model.class, obptr->model.class)) {
while (sobj->next->type > FIRSTPIN)
while (sobj->next && (sobj->next->type > FIRSTPIN))
sobj = sobj->next;
/* Stop when reaching the current instance */
if (sobj->type == obptr->type + 1) break;
+33 -10
View File
@@ -2095,8 +2095,9 @@ _netcmp_compare(ClientData clientData,
int dohierarchy = FALSE;
int assignonly = FALSE;
int argstart = 1, qresult, llen, result;
int hascontents1, hascontents2;
struct Correspond *nextcomp;
struct nlist *tp;
struct nlist *tp1 = NULL, *tp2 = NULL;
Tcl_Obj *flist = NULL;
if (objc > 1) {
@@ -2139,24 +2140,24 @@ _netcmp_compare(ClientData clientData,
}
else if ((objc - argstart) == 2) {
result = CommonParseCell(interp, objv[argstart], &tp, &fnum1);
result = CommonParseCell(interp, objv[argstart], &tp1, &fnum1);
if (result != TCL_OK) return TCL_ERROR;
else if (fnum1 == -1) {
Tcl_SetResult(interp, "Cannot use wildcard with compare command.\n",
NULL);
return TCL_ERROR;
}
name1 = tp->name;
name1 = tp1->name;
argstart++;
result = CommonParseCell(interp, objv[argstart], &tp, &fnum2);
result = CommonParseCell(interp, objv[argstart], &tp2, &fnum2);
if (result != TCL_OK) return TCL_ERROR;
else if (fnum2 == -1) {
Tcl_SetResult(interp, "Cannot use wildcard with compare command.\n",
NULL);
return TCL_ERROR;
}
name2 = tp->name;
name2 = tp2->name;
if (dohierarchy) {
RemoveCompareQueue();
@@ -2195,12 +2196,34 @@ _netcmp_compare(ClientData clientData,
ConvertGlobals(name2, fnum2);
}
CreateTwoLists(name1, fnum1, name2, fnum2, dolist);
while (PrematchLists(name1, fnum1, name2, fnum2) > 0) {
Fprintf(stdout, "Making another compare attempt.\n");
Printf("Flattened mismatched instances and attempting compare again.\n");
CreateTwoLists(name1, fnum1, name2, fnum2, dolist);
tp1 = LookupCellFile(name1, fnum1);
tp2 = LookupCellFile(name2, fnum2);
hascontents1 = HasContents(tp1);
hascontents2 = HasContents(tp2);
if (hascontents1 && !hascontents2 && (tp2->flags & CELL_PLACEHOLDER)) {
Fprintf(stdout, "Circuit 2 cell %s is a black box; will not flatten "
"Circuit 1\n", name2);
}
else if (hascontents2 && !hascontents1 && (tp1->flags & CELL_PLACEHOLDER)) {
Fprintf(stdout, "Circuit 1 cell %s is a black box; will not flatten "
"Circuit 2\n", name1);
}
else if (hascontents1 || hascontents2) {
FlattenUnmatched(tp1, name1, 1, 0);
FlattenUnmatched(tp2, name2, 1, 0);
DescribeContents(name1, fnum1, name2, fnum2);
while (PrematchLists(name1, fnum1, name2, fnum2) > 0) {
Fprintf(stdout, "Making another compare attempt.\n");
Printf("Flattened mismatched instances and attempting compare again.\n");
FlattenUnmatched(tp1, name1, 1, 0);
FlattenUnmatched(tp2, name2, 1, 0);
DescribeContents(name1, fnum1, name2, fnum2);
}
}
CreateTwoLists(name1, fnum1, name2, fnum2, dolist);
// Return the names of the two cells being compared, if doing "compare
// hierarchical". If "-list" was specified, then append the output