mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 14:07:07 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba7004fd5b | ||
|
|
4f315d33d6 | ||
|
|
704bfbc871 | ||
|
|
4457248ecd | ||
|
|
7bee1851fa | ||
|
|
021dfa6e8a | ||
|
|
e4a4621b96 | ||
|
|
1d286f9973 | ||
|
|
3ca77300ac | ||
|
|
6d2ef396ef | ||
|
|
2483b7440f | ||
|
|
236fba18aa | ||
|
|
49c0de0433 | ||
|
|
3b9dca0cf2 | ||
|
|
1272ed22fe | ||
|
|
7d910b616c | ||
|
|
6179ba8cb8 | ||
|
|
b1032f846b | ||
|
|
4c546d1472 | ||
|
|
aaf8fefc1a | ||
|
|
e1aa231db1 | ||
|
|
abaf896f7f | ||
|
|
df8fa29b2f | ||
|
|
e94d25b3f1 | ||
|
|
d14bf70f1c |
@@ -1306,6 +1306,14 @@ int UniquePins(char *name, int filenum)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Structure used below for keeping track of node numbers
|
||||
* belonging to removed nodes.
|
||||
*/
|
||||
struct LinkedNum {
|
||||
int node;
|
||||
struct LinkedNum *next;
|
||||
};
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Callback function for CleanupPins */
|
||||
/* Note that if the first pin of the instance is a */
|
||||
@@ -1318,6 +1326,7 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
struct nlist *ptr;
|
||||
struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob;
|
||||
struct nlist *tc = (struct nlist *)clientdata;
|
||||
struct LinkedNum *newnodenum, *removedNodes = (struct LinkedNum *)NULL;
|
||||
int pinnum;
|
||||
char *saveinst = NULL;
|
||||
|
||||
@@ -1373,6 +1382,15 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
saveinst = ob->instance.name;
|
||||
}
|
||||
if (ob->model.class != NULL) FREE(ob->model.class);
|
||||
|
||||
// Record the net number of the pin being removed, to
|
||||
// check at the end if the net belonged to a pin that
|
||||
// got orphaned.
|
||||
newnodenum = (struct LinkedNum *)MALLOC(sizeof(struct LinkedNum));
|
||||
newnodenum->node = ob->node;
|
||||
newnodenum->next = removedNodes;
|
||||
removedNodes = newnodenum;
|
||||
|
||||
FREE(ob);
|
||||
}
|
||||
else {
|
||||
@@ -1416,6 +1434,28 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
}
|
||||
}
|
||||
|
||||
while (removedNodes != NULL) {
|
||||
int nodenum = removedNodes->node;
|
||||
struct objlist *ob2;
|
||||
|
||||
/* Only concerned with nodes that are in the pin list of ptr->cell */
|
||||
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
|
||||
if (ob->type != PORT) break;
|
||||
if (ob->node == nodenum) break;
|
||||
}
|
||||
if (ob && (ob->type == PORT)) {
|
||||
/* Check if this node number exists only in the port record */
|
||||
for (nob = ob->next; nob != NULL; nob = nob->next)
|
||||
if (nob->node == nodenum) break;
|
||||
if (nob == NULL) {
|
||||
ob->node = -1; /* This pin is now disconnected */
|
||||
}
|
||||
}
|
||||
newnodenum = removedNodes;
|
||||
removedNodes = removedNodes->next;
|
||||
FREE(newnodenum);
|
||||
}
|
||||
|
||||
if (saveinst != NULL) FREE(saveinst);
|
||||
return NULL; /* Keep the search going */
|
||||
}
|
||||
|
||||
+316
-237
@@ -21,6 +21,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for rand(), abs(), etc */
|
||||
#include <stdarg.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <time.h> /* for time() as a seed for random number generator */
|
||||
@@ -1216,7 +1217,8 @@ SortFanoutLists(nlist1, nlist2)
|
||||
f2 -= 1;
|
||||
matched[f1] = -1;
|
||||
total++;
|
||||
if (f2 != f1) {
|
||||
if ((f2 != f1) && (nlist2->flist[f1].permute != 0) &&
|
||||
(nlist2->flist[f2].permute != 0)) {
|
||||
temp = nlist2->flist[f2];
|
||||
nlist2->flist[f2] = nlist2->flist[f1];
|
||||
nlist2->flist[f1] = temp;
|
||||
@@ -1250,7 +1252,8 @@ SortFanoutLists(nlist1, nlist2)
|
||||
f1 -= 1;
|
||||
matched[f2] = -1;
|
||||
total++;
|
||||
if (f1 != f2) {
|
||||
if ((f1 != f2) && (nlist1->flist[f1].permute != 0) &&
|
||||
(nlist1->flist[f2].permute != 0)) {
|
||||
temp = nlist1->flist[f1];
|
||||
nlist1->flist[f1] = nlist1->flist[f2];
|
||||
nlist1->flist[f2] = temp;
|
||||
@@ -1496,6 +1499,112 @@ void SortUnmatchedLists(nlists1, nlists2, n1max, n2max)
|
||||
HashKill(&n2hash);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Output string formatting routines */
|
||||
/* for two-column side-by-side comparisons */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Fill left and right columns with spaces */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
void output_string_fill(char *ostr)
|
||||
{
|
||||
int m;
|
||||
for (m = 0; m < left_col_end; m++) *(ostr + m) = ' ';
|
||||
for (m = left_col_end + 1; m < right_col_end; m++) *(ostr + m) = ' ';
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Write a formatted string in the usual format of sprintf() to */
|
||||
/* the left column. */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
void output_string_left(char *ostr, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(ostr, left_col_end, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Write a formatted string in the usual format of sprintf() to */
|
||||
/* the right column. */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
void output_string_right(char *ostr, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(ostr + left_col_end + 1, left_col_end, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Remove any string breaks within the output string, then */
|
||||
/* print the string to stdout. */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
void output_string_print(char *ostr)
|
||||
{
|
||||
int m;
|
||||
for (m = 0; m < right_col_end + 1; m++)
|
||||
if (*(ostr + m) == '\0')
|
||||
*(ostr + m) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Draw a divider line to the output. If "colbrk" is TRUE, */
|
||||
/* then leave the center character as a vertical bar. */
|
||||
/* Print the divider line to stdout, then reinstate the */
|
||||
/* vertical bar. */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
void output_string_print_divider(char *ostr, char colbrk)
|
||||
{
|
||||
int m;
|
||||
for (m = 0; m < right_col_end; m++) *(ostr + m) = '-';
|
||||
if (colbrk) *(ostr + left_col_end) = '|';
|
||||
output_string_print(ostr);
|
||||
*(ostr + left_col_end) = '|';
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Initialize the output string with an empty line and divider */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
char *output_string_init()
|
||||
{
|
||||
char *ostr = CALLOC(right_col_end + 2, sizeof(char));
|
||||
|
||||
*(ostr + left_col_end) = '|';
|
||||
*(ostr + right_col_end) = '\n';
|
||||
*(ostr + right_col_end + 1) = '\0';
|
||||
|
||||
output_string_fill(ostr);
|
||||
|
||||
return ostr;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Write the header for the comparison output */
|
||||
/* Print the header to stdout. */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
void output_string_print_header(char *ostr, struct nlist *tc1, struct nlist *tc2)
|
||||
{
|
||||
if (tc1)
|
||||
output_string_left(ostr, "Circuit 1: %s", tc1->name);
|
||||
if (tc2)
|
||||
output_string_right(ostr, "Circuit 2: %s", tc2->name);
|
||||
|
||||
output_string_print(ostr);
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------
|
||||
*---------------------------------------------------------------------
|
||||
@@ -1512,9 +1621,9 @@ void FormatIllegalElementClasses()
|
||||
char *permcount;
|
||||
int bytesleft;
|
||||
|
||||
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
||||
permname = CALLOC(right_col_end + 2, sizeof(char));
|
||||
permcount = CALLOC(right_col_end + 2, sizeof(char));
|
||||
ostr = output_string_init();
|
||||
|
||||
found = 0;
|
||||
for (escan = ElementClasses; escan != NULL; escan = escan->next)
|
||||
@@ -1527,15 +1636,7 @@ void FormatIllegalElementClasses()
|
||||
|
||||
/* Print in side-by-side format */
|
||||
|
||||
*(ostr + left_col_end) = '|';
|
||||
*(ostr + right_col_end) = '\n';
|
||||
*(ostr + right_col_end + 1) = '\0';
|
||||
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, "Circuit 1: %s", Circuit1->name);
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "Circuit 2: %s", Circuit2->name);
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print_header(ostr, Circuit1, Circuit2);
|
||||
}
|
||||
found = 1;
|
||||
|
||||
@@ -1579,32 +1680,27 @@ void FormatIllegalElementClasses()
|
||||
Fprintf(stdout, "\n");
|
||||
for (n = 0; n < ((n1 > n2) ? n1 : n2); n++) {
|
||||
if (n != 0) {
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
||||
output_string_fill(ostr);
|
||||
Fprintf(stdout, ostr);
|
||||
} else {
|
||||
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
||||
Fprintf(stdout, ostr);
|
||||
*(ostr + left_col_end) = '|';
|
||||
output_string_print_divider(ostr, FALSE);
|
||||
}
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
||||
output_string_fill(ostr);
|
||||
if (n < n1) {
|
||||
estr = elist1[n]->name;
|
||||
if (*estr == '/') estr++; // Remove leading slash, if any
|
||||
snprintf(ostr, left_col_end, "Instance: %s", estr);
|
||||
output_string_left(ostr, "Instance: %s", estr);
|
||||
}
|
||||
else
|
||||
snprintf(ostr, left_col_end, "(no matching instance)");
|
||||
output_string_left(ostr, "%s", "(no matching instance)");
|
||||
if (n < n2) {
|
||||
estr = elist2[n]->name;
|
||||
if (*estr == '/') estr++; // Remove leading slash, if any
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "Instance: %s", estr);
|
||||
output_string_right(ostr, "Instance: %s", estr);
|
||||
}
|
||||
else
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching instance)");
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_right(ostr, "%s", "(no matching instance)");
|
||||
output_string_print(ostr);
|
||||
|
||||
if (n >= n1)
|
||||
maxf = elist2[n]->fanout;
|
||||
@@ -1616,12 +1712,11 @@ void FormatIllegalElementClasses()
|
||||
|
||||
f1 = f2 = 0;
|
||||
while ((f1 < maxf) || (f2 < maxf)) {
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
||||
output_string_fill(ostr);
|
||||
if (n < n1) {
|
||||
if (f1 < elist1[n]->fanout) {
|
||||
if (elist1[n]->flist[f1].permute == (char)1) {
|
||||
snprintf(ostr, left_col_end, " %s = %d", elist1[n]->flist[f1].name,
|
||||
output_string_left(ostr, " %s = %d", elist1[n]->flist[f1].name,
|
||||
elist1[n]->flist[f1].count);
|
||||
}
|
||||
else {
|
||||
@@ -1643,7 +1738,7 @@ void FormatIllegalElementClasses()
|
||||
sprintf(value, "%d", elist1[n]->flist[f1].count);
|
||||
strcat(permcount, value);
|
||||
strcat(permcount, ")");
|
||||
snprintf(ostr, left_col_end, " %s = %s", permname, permcount);
|
||||
output_string_left(ostr, " %s = %s", permname, permcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1651,7 +1746,7 @@ void FormatIllegalElementClasses()
|
||||
if (n < n2) {
|
||||
if (f2 < elist2[n]->fanout) {
|
||||
if (elist2[n]->flist[f2].permute == (char)1) {
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, " %s = %d", elist2[n]->flist[f2].name,
|
||||
output_string_right(ostr, " %s = %d", elist2[n]->flist[f2].name,
|
||||
elist2[n]->flist[f2].count);
|
||||
}
|
||||
else {
|
||||
@@ -1673,21 +1768,18 @@ void FormatIllegalElementClasses()
|
||||
sprintf(value, "%d", elist2[n]->flist[f2].count);
|
||||
strcat(permcount, value);
|
||||
strcat(permcount, ")");
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, " %s = %s", permname, permcount);
|
||||
output_string_right(ostr, " %s = %s", permname, permcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
f2++;
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
}
|
||||
|
||||
FreeFormattedLists(elist1, numlists1);
|
||||
FreeFormattedLists(elist2, numlists2);
|
||||
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
||||
Fprintf(stdout, ostr);
|
||||
*(ostr + left_col_end) = '|';
|
||||
output_string_print_divider(ostr, FALSE);
|
||||
}
|
||||
|
||||
FREE(ostr);
|
||||
@@ -1875,7 +1967,7 @@ void FormatIllegalNodeClasses()
|
||||
int found, numlists1, numlists2, n1, n2, n, f, i, maxf;
|
||||
char *ostr;
|
||||
|
||||
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
||||
ostr = output_string_init();
|
||||
found = 0;
|
||||
|
||||
/*
|
||||
@@ -1893,15 +1985,7 @@ void FormatIllegalNodeClasses()
|
||||
Fprintf(stdout, "Class fragments follow (with fanout counts):\n");
|
||||
|
||||
/* Print in side-by-side format */
|
||||
*(ostr + left_col_end) = '|';
|
||||
*(ostr + right_col_end) = '\n';
|
||||
*(ostr + right_col_end + 1) = '\0';
|
||||
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, "Circuit 1: %s", Circuit1->name);
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "Circuit 2: %s", Circuit2->name);
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print_header(ostr, Circuit1, Circuit2);
|
||||
}
|
||||
found = 1;
|
||||
|
||||
@@ -1941,26 +2025,21 @@ void FormatIllegalNodeClasses()
|
||||
Fprintf(stdout, "\n");
|
||||
for (n = 0; n < ((n1 > n2) ? n1 : n2); n++) {
|
||||
if (n != 0) {
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
||||
output_string_fill(ostr);
|
||||
Fprintf(stdout, ostr);
|
||||
} else {
|
||||
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
||||
Fprintf(stdout, ostr);
|
||||
*(ostr + left_col_end) = '|';
|
||||
output_string_print_divider(ostr, FALSE);
|
||||
}
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
||||
output_string_fill(ostr);
|
||||
if (n < n1)
|
||||
snprintf(ostr, left_col_end, "Net: %s", nlists1[n]->name);
|
||||
output_string_left(ostr, "Net: %s", nlists1[n]->name);
|
||||
else
|
||||
snprintf(ostr, left_col_end, "(no matching net)");
|
||||
output_string_left(ostr, "%s", "(no matching net)");
|
||||
if (n < n2)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "Net: %s", nlists2[n]->name);
|
||||
output_string_right(ostr, "Net: %s", nlists2[n]->name);
|
||||
else
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching net)");
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_right(ostr, "%s", "(no matching net)");
|
||||
output_string_print(ostr);
|
||||
|
||||
if (n >= n1)
|
||||
maxf = nlists2[n]->fanout;
|
||||
@@ -1971,17 +2050,16 @@ void FormatIllegalNodeClasses()
|
||||
nlists1[n]->fanout : nlists2[n]->fanout;
|
||||
|
||||
for (f = 0; f < maxf; f++) {
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
||||
output_string_fill(ostr);
|
||||
if (n < n1)
|
||||
if (f < nlists1[n]->fanout) {
|
||||
if (nlists1[n]->flist[f].permute <= 1)
|
||||
snprintf(ostr, left_col_end, " %s/%s = %d",
|
||||
output_string_left(ostr, " %s/%s = %d",
|
||||
nlists1[n]->flist[f].model,
|
||||
nlists1[n]->flist[f].name,
|
||||
nlists1[n]->flist[f].count);
|
||||
else {
|
||||
snprintf(ostr, left_col_end, " %s/(%s) = %d",
|
||||
output_string_left(ostr, " %s/(%s) = %d",
|
||||
nlists1[n]->flist[f].model,
|
||||
nlists1[n]->flist[f].name,
|
||||
nlists1[n]->flist[f].count);
|
||||
@@ -1991,28 +2069,25 @@ void FormatIllegalNodeClasses()
|
||||
if (n < n2)
|
||||
if (f < nlists2[n]->fanout) {
|
||||
if (nlists2[n]->flist[f].permute <= 1)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, " %s/%s = %d",
|
||||
output_string_right(ostr, " %s/%s = %d",
|
||||
nlists2[n]->flist[f].model,
|
||||
nlists2[n]->flist[f].name,
|
||||
nlists2[n]->flist[f].count);
|
||||
else {
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, " %s/(%s) = %d",
|
||||
output_string_right(ostr, " %s/(%s) = %d",
|
||||
nlists2[n]->flist[f].model,
|
||||
nlists2[n]->flist[f].name,
|
||||
nlists2[n]->flist[f].count);
|
||||
FREE(nlists2[n]->flist[f].name);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
}
|
||||
|
||||
FreeFormattedLists(nlists1, numlists1);
|
||||
FreeFormattedLists(nlists2, numlists2);
|
||||
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
||||
Fprintf(stdout, ostr);
|
||||
*(ostr + left_col_end) = '|';
|
||||
output_string_print_divider(ostr, FALSE);
|
||||
}
|
||||
FREE(ostr);
|
||||
}
|
||||
@@ -3202,23 +3277,12 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
|
||||
Tcl_Obj *clist1, *clist2;
|
||||
#endif
|
||||
|
||||
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
||||
ostr = output_string_init();
|
||||
|
||||
if (Debug == 0) {
|
||||
Fprintf(stdout, "Subcircuit summary:\n");
|
||||
*(ostr + left_col_end) = '|';
|
||||
*(ostr + right_col_end) = '\n';
|
||||
*(ostr + right_col_end + 1) = '\0';
|
||||
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, "Circuit 1: %s", Circuit1->name);
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "Circuit 2: %s", Circuit2->name);
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = '-';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = '-';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print_header(ostr, Circuit1, Circuit2);
|
||||
output_string_print_divider(ostr, TRUE);
|
||||
}
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
@@ -3272,27 +3336,24 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
|
||||
}
|
||||
|
||||
if (Debug == 0) {
|
||||
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = ' ';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = ' ';
|
||||
output_string_fill(ostr);
|
||||
if (M1 == C1)
|
||||
snprintf(ostr, left_col_end, "%s (%d)", Esrch->object->model.class, C1);
|
||||
output_string_left(ostr, "%s (%d)", Esrch->object->model.class, C1);
|
||||
else
|
||||
snprintf(ostr, left_col_end, "%s (%d->%d)", Esrch->object->model.class,
|
||||
output_string_left(ostr, "%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,
|
||||
output_string_right(ostr, "%s (%d)%s", tp2->name,
|
||||
C2, (C2 == C1) ? "" : " **Mismatch**");
|
||||
else
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d->%d)%s",
|
||||
output_string_right(ostr, "%s (%d->%d)%s",
|
||||
tp2->name, M2, C2, (C2 == C1) ? "" : " **Mismatch**");
|
||||
}
|
||||
else {
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching element)");
|
||||
output_string_right(ostr, "%s", "(no matching element)");
|
||||
}
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
#ifdef TCL_NETGEN
|
||||
if (dolist) {
|
||||
@@ -3351,17 +3412,15 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
|
||||
}
|
||||
|
||||
if (Debug == 0) {
|
||||
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)");
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", "(no matching element)");
|
||||
if (C2 == M2)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d)",
|
||||
output_string_right(ostr, "%s (%d)",
|
||||
Esrch->object->model.class, C2);
|
||||
else
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s (%d->%d)",
|
||||
output_string_right(ostr, "%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);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
#ifdef TCL_NETGEN
|
||||
if (dolist) {
|
||||
@@ -3405,14 +3464,12 @@ int FirstElementPass(struct Element *E, int noflat, int dolist)
|
||||
C1, C2);
|
||||
}
|
||||
else {
|
||||
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, "Number of devices: %d%s", C1, (C1 == C2) ? "" :
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "Number of devices: %d%s", C1, (C1 == C2) ? "" :
|
||||
" **Mismatch**");
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "Number of devices: %d%s", C2, (C1 == C2) ? "" :
|
||||
output_string_right(ostr, "Number of devices: %d%s", C2, (C1 == C2) ? "" :
|
||||
" **Mismatch**");
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
|
||||
#ifdef TCL_NETGEN
|
||||
@@ -3458,23 +3515,14 @@ void FirstNodePass(struct Node *N, int dolist)
|
||||
char *ostr;
|
||||
int i;
|
||||
|
||||
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
||||
|
||||
*(ostr + left_col_end) = '|';
|
||||
*(ostr + right_col_end) = '\n';
|
||||
*(ostr + right_col_end + 1) = '\0';
|
||||
|
||||
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, "Number of nets: %d%s", C1, (C1 == C2) ? "" :
|
||||
ostr = output_string_init();
|
||||
output_string_left(ostr, "Number of nets: %d%s", C1, (C1 == C2) ? "" :
|
||||
" **Mismatch**");
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "Number of nets: %d%s", C2, (C1 == C2) ? "" :
|
||||
output_string_right(ostr, "Number of nets: %d%s", C2, (C1 == C2) ? "" :
|
||||
" **Mismatch**");
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print(ostr);
|
||||
|
||||
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print_divider(ostr, FALSE);
|
||||
|
||||
FREE(ostr);
|
||||
}
|
||||
@@ -5169,26 +5217,34 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
// (if any)
|
||||
|
||||
if (comb == TRUE) {
|
||||
double pd;
|
||||
int mult, cidx = -1;
|
||||
struct valuelist *avl, *cvl = NULL;
|
||||
critval.type = PROP_ENDLIST;
|
||||
critval.value.dval = 0.0;
|
||||
for (i = 0; i < run; i++) {
|
||||
avl = NULL;
|
||||
if (vlist[0][i] == NULL) continue;
|
||||
mult = vlist[0][i]->value.ival;
|
||||
// if (vlist[0][i] == NULL) continue;
|
||||
// mult = vlist[0][i]->value.ival;
|
||||
if (vlist[0][i] == NULL)
|
||||
mult = 1;
|
||||
else
|
||||
mult = vlist[0][i]->value.ival;
|
||||
changed = 0;
|
||||
|
||||
/* For all properties that are not M, S, or crit, */
|
||||
/* combine as specified by the merge type of the property. */
|
||||
|
||||
for (p = 1; p < pcount; p++) {
|
||||
kl = plist[p];
|
||||
vl = vlist[p][i];
|
||||
ctype = clist[p][i];
|
||||
|
||||
/* critical properties never combine, but track them */
|
||||
if ((series == TRUE) && (ctype & MERGE_S_CRIT)) {
|
||||
if ((vl->type != critval.type) || (vl->value.dval != critval.value.dval))
|
||||
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
|
||||
(vl->value.dval + critval.value.dval);
|
||||
if ((vl->type != critval.type) || (pd > kl->slop.dval))
|
||||
{
|
||||
critval.type = vl->type;
|
||||
critval.value = vl->value;
|
||||
@@ -5197,7 +5253,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
continue;
|
||||
}
|
||||
if ((series == FALSE) && (ctype & MERGE_P_CRIT)) {
|
||||
if ((vl->type != critval.type) || (vl->value.dval != critval.value.dval))
|
||||
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
|
||||
(vl->value.dval + critval.value.dval);
|
||||
if ((vl->type != critval.type) || (pd > kl->slop.dval))
|
||||
{
|
||||
critval.type = vl->type;
|
||||
critval.value = vl->value;
|
||||
@@ -5243,6 +5301,11 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
ctype = clist[p][i];
|
||||
|
||||
if (ctype & (MERGE_S_ADD | MERGE_P_ADD)) {
|
||||
if (!vlist[0][i]) {
|
||||
/* Create an entry with M = 0 to force removal */
|
||||
vlist[0][i] = (struct valuelist *)CALLOC(1,
|
||||
sizeof(struct valuelist));
|
||||
}
|
||||
vlist[0][i]->value.ival = 0; /* set M to 0 */
|
||||
if (cvl && (cvl->type == PROP_INTEGER))
|
||||
{
|
||||
@@ -5262,6 +5325,11 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
}
|
||||
}
|
||||
else if (ctype & (MERGE_S_PAR | MERGE_P_PAR)) {
|
||||
if (!vlist[0][i]) {
|
||||
/* Create an entry with M = 0 to force removal */
|
||||
vlist[0][i] = (struct valuelist *)CALLOC(1,
|
||||
sizeof(struct valuelist));
|
||||
}
|
||||
vlist[0][i]->value.ival = 0; /* set M to 0 */
|
||||
/* To do parallel combination, both types need to
|
||||
* be double, so recast them if they are integer.
|
||||
@@ -5987,6 +6055,9 @@ PropertyMatch(struct Element *E1, struct Element *E2,
|
||||
#endif
|
||||
}
|
||||
|
||||
obn1 = ob1->next;
|
||||
obn2 = ob2->next;
|
||||
|
||||
/* Find the first property record of each circuit. obn1, obn2 are */
|
||||
/* the last device record before the properties for each device. */
|
||||
for (tp1 = ob1->next; (tp1 != NULL) && tp1->type > FIRSTPIN; tp1 = tp1->next)
|
||||
@@ -6250,22 +6321,20 @@ PropertyMatch(struct Element *E1, struct Element *E2,
|
||||
int multmatch, count;
|
||||
PropertyCheckMismatch(tp1, tc1, inst1, tp2, tc2,
|
||||
inst2, E1, E2, FALSE, FALSE, &multmatch, NULL);
|
||||
if (multmatch == 1) {
|
||||
/* Final attempt: Reduce M to 1 on both devices */
|
||||
run1 = run2 = 0;
|
||||
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
|
||||
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
|
||||
PropertyOptimize(tp1, tc1, run1, FALSE, TRUE);
|
||||
PropertyOptimize(tp2, tc2, run2, FALSE, TRUE);
|
||||
}
|
||||
else if (multmatch == 2) {
|
||||
run1 = run2 = 0;
|
||||
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
|
||||
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
|
||||
|
||||
if (multmatch == 2) {
|
||||
/* Final attempt: Reduce S to 1 on both devices */
|
||||
run1 = run2 = 0;
|
||||
for (tpc = tp1; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run1++;
|
||||
for (tpc = tp2; tpc && (tpc->type == PROPERTY); tpc = tpc->next) run2++;
|
||||
PropertyOptimize(tp1, tc1, run1, TRUE, TRUE);
|
||||
PropertyOptimize(tp2, tc2, run2, TRUE, TRUE);
|
||||
}
|
||||
else if ((multmatch == 1) || (run1 != run2)) {
|
||||
/* Final attempt: Reduce M to 1 on both devices */
|
||||
PropertyOptimize(tp1, tc1, run1, FALSE, TRUE);
|
||||
PropertyOptimize(tp2, tc2, run2, FALSE, TRUE);
|
||||
}
|
||||
#ifdef TCL_NETGEN
|
||||
mlist =
|
||||
#endif
|
||||
@@ -6503,11 +6572,16 @@ void PrintAutomorphisms(void)
|
||||
* separating out those devices that are connected to matching pins
|
||||
* in each circuit.
|
||||
*
|
||||
* If match_nets == TRUE, then also match internal nets by name. Pins
|
||||
* should always be matched by name without considering nets first;
|
||||
* once all symmetries related to pins have been broken, then matching
|
||||
* symmetries by net can keep the output from looking confusing.
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int ResolveAutomorphsByPin()
|
||||
int ResolveAutomorphsByPin(int match_nets)
|
||||
{
|
||||
struct NodeClass *NC;
|
||||
struct Node *N;
|
||||
@@ -6516,7 +6590,10 @@ int ResolveAutomorphsByPin()
|
||||
int portnum;
|
||||
|
||||
/* Diagnostic */
|
||||
Fprintf(stdout, "Resolving symmetries by pin name.\n");
|
||||
if (match_nets)
|
||||
Fprintf(stdout, "Resolving symmetries by net name.\n");
|
||||
else
|
||||
Fprintf(stdout, "Resolving symmetries by pin name.\n");
|
||||
|
||||
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||
struct Node *N1, *N2;
|
||||
@@ -6540,7 +6617,9 @@ int ResolveAutomorphsByPin()
|
||||
if (N1->hashval != orighash) continue;
|
||||
for (N2 = N1->next; N2 != NULL; N2 = N2->next) {
|
||||
if ((N2->graph != N1->graph) &&
|
||||
(*matchfunc)(N2->object->name, N1->object->name)) {
|
||||
(*matchfunc)(N2->object->name, N1->object->name) &&
|
||||
(N1->object->type == PORT || N2->object->type == PORT)) {
|
||||
|
||||
if (Debug == TRUE)
|
||||
Printf("Symmetry group broken by name match (pin %s)\n", N2->object->name);
|
||||
Magic(newhash);
|
||||
@@ -6939,10 +7018,21 @@ int Permute()
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* update magic numbers */
|
||||
for (NL = E->nodelist; NL != NULL; NL = NL->next)
|
||||
if (NL->pin_magic == one)
|
||||
NL->pin_magic = two;
|
||||
/* Update magic numbers. To ensure that this works */
|
||||
/* regardless of the pin order of the pins in each */
|
||||
/* netlist, always set both pins to the larger of */
|
||||
/* the two pin_magic values. */
|
||||
|
||||
if (one > two) {
|
||||
for (NL = E->nodelist; NL != NULL; NL = NL->next)
|
||||
if (NL->pin_magic == two)
|
||||
NL->pin_magic = one;
|
||||
}
|
||||
else {
|
||||
for (NL = E->nodelist; NL != NULL; NL = NL->next)
|
||||
if (NL->pin_magic == one)
|
||||
NL->pin_magic = two;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7518,6 +7608,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
|
||||
if (ob2->type != PORT) break;
|
||||
else haspins = 1;
|
||||
/* The model.port record for pins will be used to match the pin order
|
||||
* of the cells in each netlist. Make sure the value is reset on
|
||||
* entering this subroutine.
|
||||
*/
|
||||
ob2->model.port = -1;
|
||||
}
|
||||
numnodes = 0;
|
||||
@@ -7546,23 +7640,13 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
}
|
||||
#endif
|
||||
|
||||
ostr = CALLOC(right_col_end + 2, sizeof(char));
|
||||
ostr = output_string_init();
|
||||
|
||||
if (Debug == 0) {
|
||||
/* Format side-by-side comparison of pins */
|
||||
Fprintf(stdout, "\nSubcircuit pins:\n");
|
||||
*(ostr + left_col_end) = '|';
|
||||
*(ostr + right_col_end) = '\n';
|
||||
*(ostr + right_col_end + 1) = '\0';
|
||||
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, "Circuit 1: %s", tc1->name);
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "Circuit 2: %s", tc2->name);
|
||||
for (i = 0; i < right_col_end + 1; i++) if (*(ostr + i) == '\0') *(ostr + i) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
for (i = 0; i < left_col_end; i++) *(ostr + i) = '-';
|
||||
for (i = left_col_end + 1; i < right_col_end; i++) *(ostr + i) = '-';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print_header(ostr, tc1, tc2);
|
||||
output_string_print_divider(ostr, TRUE);
|
||||
}
|
||||
|
||||
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||
@@ -7601,13 +7685,12 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
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);
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", ob1->name);
|
||||
}
|
||||
if ((*matchfunc)(ob1->name, ob2->name)) {
|
||||
if (Debug == 0)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
||||
output_string_right(ostr, "%s", ob2->name);
|
||||
}
|
||||
else {
|
||||
/* Check remainder of ports to see if there is a name match on the
|
||||
@@ -7619,7 +7702,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if ((*matchfunc)(ob3->name, ob1->name)) {
|
||||
ob2 = ob3;
|
||||
if (Debug == 0)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s", ob2->name);
|
||||
output_string_right(ostr, "%s", ob2->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -7627,9 +7710,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (ob3 == NULL) {
|
||||
if (Debug == 0) {
|
||||
if (ob2->model.port == -1)
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "%s **Mismatch**", ob2->name);
|
||||
output_string_right(ostr, "%s **Mismatch**",
|
||||
ob2->name);
|
||||
else
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
|
||||
output_string_right(ostr, "%s", "(no matching pin)");
|
||||
}
|
||||
nomatch = TRUE;
|
||||
/* Pins with different names are on different nets,
|
||||
@@ -7640,9 +7724,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
}
|
||||
|
||||
if (Debug == 0) {
|
||||
for (m = 0; m < right_col_end + 1; m++)
|
||||
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
else if (nomatch) {
|
||||
Fprintf(stderr, "No matching pin in cell %s for "
|
||||
@@ -7681,13 +7763,11 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
// so don't print out the "no pins" entry.
|
||||
|
||||
if (strcmp(obn->name, "(no pins)")) {
|
||||
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, 32, "%s", obn->name);
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
|
||||
for (m = 0; m < right_col_end + 1; m++)
|
||||
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", obn->name);
|
||||
output_string_right(ostr, "(no pin, node is %s)",
|
||||
obp->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -7729,13 +7809,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
|
||||
if (ob1 == NULL) {
|
||||
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", obn->name);
|
||||
snprintf(ostr + left_col_end + 1, left_col_end, "(no matching pin)");
|
||||
for (m = 0; m < right_col_end + 1; m++)
|
||||
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", obn->name);
|
||||
output_string_right(ostr, "%s", "(no matching pin)");
|
||||
output_string_print(ostr);
|
||||
}
|
||||
else {
|
||||
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
|
||||
@@ -7815,13 +7892,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
*(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);
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", ob1->name);
|
||||
output_string_right(ostr, "%s", ob2->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
else {
|
||||
Fprintf(stdout, "Circuit %s port %d \"%s\""
|
||||
@@ -7870,13 +7944,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
*(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);
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", ob1->name);
|
||||
output_string_right(ostr, "%s", ob2->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
else {
|
||||
Fprintf(stdout, "Circuit %s port %d \"%s\""
|
||||
@@ -7934,13 +8005,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
*(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);
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", ob1->name);
|
||||
output_string_right(ostr, "%s", ob2->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
else {
|
||||
Fprintf(stdout, "Circuit %s port %d \"%s\""
|
||||
@@ -7989,16 +8057,38 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (ob2->type != PORT) break;
|
||||
if (ob2->model.port == -1) {
|
||||
|
||||
/* Find this node in NodeClasses and find the corresponding
|
||||
* net in the other circuit, if there is one (NOTE: Needs
|
||||
* refactoring; should not be going through NodeClasses
|
||||
* inside a loop.)
|
||||
*/
|
||||
obn = NULL;
|
||||
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||
for (N2 = NC->nodes; N2 != NULL; N2 = N2->next) {
|
||||
if (N2->graph != Circuit1->file) {
|
||||
obp = N2->object;
|
||||
if (IsPort(obp) && (obp->node == ob2->node)) {
|
||||
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
|
||||
if (N1->graph == Circuit1->file) {
|
||||
obn = N1->object;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Debug == 0) {
|
||||
// See above for reverse case
|
||||
if (strcmp(ob2->name, "(no pins)")) {
|
||||
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, "(no matching pin)");
|
||||
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);
|
||||
output_string_fill(ostr);
|
||||
if (obn == NULL)
|
||||
output_string_left(ostr, "%s", "(no matching pin)");
|
||||
else
|
||||
output_string_left(ostr, "(no pin, node is %s)",
|
||||
obn->name);
|
||||
output_string_right(ostr, "%s", ob2->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -8113,12 +8203,15 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (obn == NULL) ob1->node = -1; /* Make disconnected */
|
||||
}
|
||||
|
||||
/* NOTE: Previously kept the port if model.port is -1; however,
|
||||
* all ports are -1 here so not sure why that was in there. . .
|
||||
*/
|
||||
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0
|
||||
|| (ob1->node < 0 && tc1->class == CLASS_MODULE)
|
||||
|| (ob1->node < 0 && ob1->model.port == -1)) {
|
||||
|| (ob1->node < 0 && tc1->class == CLASS_MODULE)) {
|
||||
|
||||
/* Add a proxy pin to tc2 */
|
||||
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
|
||||
obn->node = -1;
|
||||
if (ob1 == NULL) {
|
||||
obn->name = (char *)MALLOC(15);
|
||||
sprintf(obn->name, "proxy%d", rand() & 0x3ffffff);
|
||||
@@ -8130,24 +8223,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
obn->type = UNKNOWN;
|
||||
obn->model.port = (i - j);
|
||||
obn->instance.name = NULL;
|
||||
obn->node = -1;
|
||||
|
||||
/* Note: Has this pin already been accounted for? */
|
||||
if (Debug == 0) {
|
||||
if (strcmp(ob1->name, "(no pins)")) {
|
||||
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, "(no matching pin)");
|
||||
for (m = 0; m < right_col_end + 1; m++)
|
||||
if (*(ostr + m) == '\0') *(ostr + m) = ' ';
|
||||
Fprintf(stdout, ostr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Fprintf(stderr, "No netlist match for cell %s pin %s\n",
|
||||
tc1->name, ob1->name);
|
||||
}
|
||||
|
||||
if (ob2 == tc2->cell) {
|
||||
obn->next = ob2;
|
||||
@@ -8163,9 +8238,16 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
HashPtrInstall(obn->name, obn, &(tc2->objdict));
|
||||
}
|
||||
|
||||
else if (ob1 != NULL && ob1->type == PORT) {
|
||||
else if (ob1 != NULL && ob1->type == PORT && ob1->node < 0) {
|
||||
/* Disconnected node was not meaningful, has no pin match in */
|
||||
/* the compared circuit, and so should be discarded. */
|
||||
/* the compared circuit, and so should be discarded. This */
|
||||
/* case is not output above, so do it here. */
|
||||
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", ob1->name);
|
||||
output_string_right(ostr, "%s", "(no matching pin)");
|
||||
output_string_print(ostr);
|
||||
|
||||
ob1->node = -2;
|
||||
needclean1 = 1;
|
||||
|
||||
@@ -8178,15 +8260,12 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
}
|
||||
FREE(cover);
|
||||
|
||||
if (Debug == 0) {
|
||||
for (i = 0; i < right_col_end; i++) *(ostr + i) = '-';
|
||||
Fprintf(stdout, ostr);
|
||||
}
|
||||
if (Debug == 0)
|
||||
output_string_print_divider(ostr, FALSE);
|
||||
|
||||
/* Run cleanuppins on circuit 1 */
|
||||
if (needclean1) {
|
||||
if (needclean1)
|
||||
CleanupPins(tc1->name, tc1->file);
|
||||
}
|
||||
|
||||
/* Add proxy pins to all instances of Circuit1 */
|
||||
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ extern void RegroupDataStructures();
|
||||
extern void FormatIllegalElementClasses();
|
||||
extern void FormatIllegalNodeClasses();
|
||||
extern int ResolveAutomorphsByProperty();
|
||||
extern int ResolveAutomorphsByPin();
|
||||
extern int ResolveAutomorphsByPin(int match_nets);
|
||||
extern void SummarizeElementClasses(struct ElementClass *EC);
|
||||
extern int remove_group_tags(struct objlist *ob);
|
||||
|
||||
|
||||
@@ -223,6 +223,7 @@ int matchnocase(char *st1, char *st2)
|
||||
{
|
||||
char *sp1 = st1;
|
||||
char *sp2 = st2;
|
||||
char v1 = FALSE, v2 = FALSE;
|
||||
|
||||
/* In case of a property that does not exist in one netlist, matchnocase()
|
||||
* may be passed a null value, so return 0 to indicate a non-match.
|
||||
@@ -231,11 +232,26 @@ int matchnocase(char *st1, char *st2)
|
||||
*/
|
||||
if (!sp1 || !sp2) return 0;
|
||||
|
||||
/* Verilog back-slash escaped names should match an equivalent non-
|
||||
* back-slashed name. (NOTE: This behavior needs to be added to match().)
|
||||
*/
|
||||
if ((*sp1 == '\\') && (*sp2 != '\\')) {
|
||||
v1 = TRUE;
|
||||
sp1++;
|
||||
}
|
||||
if ((*sp2 == '\\') && (*sp1 != '\\')) {
|
||||
v2 = TRUE;
|
||||
sp2++;
|
||||
}
|
||||
|
||||
while (*sp1 != '\0' && *sp2 != '\0') {
|
||||
if (to_lower[*sp1] != to_lower[*sp2]) break;
|
||||
sp1++;
|
||||
sp2++;
|
||||
}
|
||||
if (v1 && (*sp1 == ' ')) sp1++;
|
||||
if (v2 && (*sp2 == ' ')) sp2++;
|
||||
|
||||
if ((*sp1 != '\0') || (*sp2 != '\0')) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+17
-4
@@ -717,10 +717,12 @@ int GetBus(char *astr, struct bus *wb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Output a Verilog Module. Note that since Verilog does not describe
|
||||
// low-level devices like transistors, capacitors, etc., then this
|
||||
// format is limited to black-box subcircuits. Cells containing any
|
||||
// such low-level devices are ignored.
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
void VerilogModule(struct nlist *tp)
|
||||
{
|
||||
@@ -1833,8 +1835,9 @@ skip_endmodule:
|
||||
}
|
||||
else { /* "assign" */
|
||||
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
|
||||
if (GetBusTok(&wb) == 0) {
|
||||
char *aptr = strvchr(nexttok, '[');
|
||||
char *aptr = strvchr(nexttok, '[');
|
||||
if (((aptr == NULL) && (GetBusTok(&wb) == 0)) ||
|
||||
((aptr != NULL) && (GetBus(aptr, &wb) == 0))) {
|
||||
if (aptr != NULL) {
|
||||
*aptr = '\0';
|
||||
/* Find object of first net in bus */
|
||||
@@ -1852,6 +1855,15 @@ skip_endmodule:
|
||||
}
|
||||
else {
|
||||
lhs = LookupObject(nexttok, CurrentCell);
|
||||
/* Handle the case in which an assignment is made
|
||||
* without first declaring a wire for the signal,
|
||||
* which is considered valid syntax (patch by
|
||||
* Sylvain Munaut).
|
||||
*/
|
||||
if (lhs == NULL) {
|
||||
Node(nexttok);
|
||||
lhs = LookupObject(nexttok, CurrentCell);
|
||||
}
|
||||
strcpy(noderoot, nexttok);
|
||||
}
|
||||
SkipTokComments(VLOG_DELIMITERS);
|
||||
@@ -1900,8 +1912,9 @@ skip_endmodule:
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (GetBusTok(&wb2) == 0) {
|
||||
char *aptr = strvchr(nexttok, '[');
|
||||
char *aptr = strvchr(nexttok, '[');
|
||||
if (((aptr == NULL) && (GetBusTok(&wb2) == 0)) ||
|
||||
((aptr != NULL) && (GetBus(aptr, &wb2) == 0))) {
|
||||
j = wb2.start;
|
||||
if (aptr != NULL) {
|
||||
*aptr = '\0';
|
||||
|
||||
@@ -655,6 +655,11 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
}
|
||||
} elseif {[netgen::print queue] == {} && $result == 0} {
|
||||
set pinMismatch 1
|
||||
} else {
|
||||
# This assumes that proxy pins are added correctly. Previously,
|
||||
# that was not trusted, and so an initial pin mismatch would
|
||||
# always force subcells to be flattened.
|
||||
set doFlatten 0
|
||||
}
|
||||
}
|
||||
if {$doFlatten} {
|
||||
|
||||
+17
-3
@@ -2512,7 +2512,13 @@ _netcmp_run(ClientData clientData,
|
||||
if (automorphisms > 0) {
|
||||
// Next, attempt to resolve automorphisms uniquely by
|
||||
// using the pin names
|
||||
automorphisms = ResolveAutomorphsByPin();
|
||||
automorphisms = ResolveAutomorphsByPin(FALSE);
|
||||
}
|
||||
if (automorphisms > 0) {
|
||||
// Next, attempt to resolve automorphisms uniquely by
|
||||
// using the net names (should only be done after
|
||||
// resolving by pin).
|
||||
automorphisms = ResolveAutomorphsByPin(TRUE);
|
||||
}
|
||||
if (automorphisms > 0) {
|
||||
// Anything left is truly indistinguishable
|
||||
@@ -2522,8 +2528,16 @@ _netcmp_run(ClientData clientData,
|
||||
|
||||
if (automorphisms == -1)
|
||||
Fprintf(stdout, "Netlists do not match.\n");
|
||||
else if (automorphisms == -2)
|
||||
Fprintf(stdout, "Netlists match uniquely with port errors.\n");
|
||||
else if (automorphisms == -2) {
|
||||
Fprintf(stdout, "Netlists match uniquely with port");
|
||||
if (PropertyErrorDetected) {
|
||||
Fprintf(stdout, " and property errors.\n");
|
||||
PrintPropertyResults(dolist);
|
||||
}
|
||||
else {
|
||||
Fprintf(stdout, " errors.\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (automorphisms == 0)
|
||||
Fprintf(stdout, "Netlists match uniquely");
|
||||
|
||||
+123
-80
@@ -36,7 +36,7 @@ exec ${NETGEN_WISH:=wish} "$0" ${1+"$@"}
|
||||
#
|
||||
# set ::tkcon::PRIV(proxy) {wwwproxy:8080 1}
|
||||
#
|
||||
# Or you can set the above variable from within tkcon by calling
|
||||
# Or you can set the above variable from within tkcon by calling
|
||||
#
|
||||
# tkcon master set ::tkcon:PRIV(proxy) wwwproxy:8080
|
||||
#
|
||||
@@ -44,6 +44,8 @@ exec ${NETGEN_WISH:=wish} "$0" ${1+"$@"}
|
||||
if {$tcl_version < 8.0} {
|
||||
return -code error "tkcon requires at least Tcl/Tk8"
|
||||
} else {
|
||||
# Prevent breaking on version 8.5.2
|
||||
# package require -exact Tk $tcl_version
|
||||
package require Tk $tcl_version
|
||||
}
|
||||
|
||||
@@ -59,18 +61,6 @@ foreach pkg [info loaded {}] {
|
||||
}
|
||||
catch {unset pkg file name version}
|
||||
|
||||
# Tk 8.4 makes previously exposed stuff private.
|
||||
# FIX: Update tkcon to not rely on the private Tk code.
|
||||
#
|
||||
if {![llength [info globals tkPriv]]} {
|
||||
::tk::unsupported::ExposePrivateVariable tkPriv
|
||||
}
|
||||
foreach cmd {SetCursor UpDownLine Transpose ScrollPages} {
|
||||
if {![llength [info commands tkText$cmd]]} {
|
||||
::tk::unsupported::ExposePrivateCommand tkText$cmd
|
||||
}
|
||||
}
|
||||
|
||||
# Initialize the ::tkcon namespace
|
||||
#
|
||||
namespace eval ::tkcon {
|
||||
@@ -196,7 +186,7 @@ proc ::tkcon::Init {} {
|
||||
tkcon_puts tkcon_gets observe observe_var unalias which what
|
||||
}
|
||||
version 2.3
|
||||
RCS {RCS: @(#) $Id: tkcon.tcl,v 1.2 2008/05/23 00:20:17 tim Exp $}
|
||||
RCS {RCS: @(#) $Id: tkcon.tcl,v 1.2 2008/04/18 16:28:13 tim Exp $}
|
||||
HEADURL {http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tkcon/tkcon/tkcon.tcl?rev=HEAD}
|
||||
docs "http://tkcon.sourceforge.net/"
|
||||
email {jeff@hobbs.org}
|
||||
@@ -654,7 +644,7 @@ proc ::tkcon::GarbageCollect {} {
|
||||
## ::tkcon::EvalCmd) in turn. Any uncompleted command will not be eval'ed.
|
||||
# ARGS: w - console text widget
|
||||
# Calls: ::tkcon::CmdGet, ::tkcon::CmdSep, ::tkcon::EvalCmd
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Eval {w} {
|
||||
set incomplete [CmdSep [CmdGet $w] cmds last]
|
||||
$w mark set insert end-1c
|
||||
@@ -674,7 +664,7 @@ proc ::tkcon::Eval {w} {
|
||||
# Calls: ::tkcon::Prompt
|
||||
# Outputs: result of command to stdout (or stderr if error occured)
|
||||
# Returns: next event number
|
||||
##
|
||||
##
|
||||
proc ::tkcon::EvalCmd {w cmd} {
|
||||
variable OPT
|
||||
variable PRIV
|
||||
@@ -745,7 +735,7 @@ proc ::tkcon::EvalCmd {w cmd} {
|
||||
$w tag bind $tag <Leave> \
|
||||
[list $w tag configure $tag -underline 0]
|
||||
$w tag bind $tag <ButtonRelease-1> \
|
||||
"if {!\[info exists tkPriv(mouseMoved)\] || !\$tkPriv(mouseMoved)} \
|
||||
"if {!\[info exists ::tk::Priv(mouseMoved)\] || !\$::tk::Priv(mouseMoved)} \
|
||||
{[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}"
|
||||
} else {
|
||||
$w insert output $res\n stderr
|
||||
@@ -905,7 +895,7 @@ proc ::tkcon::EvalSocketClosed {} {
|
||||
## ::tkcon::EvalNamespace - evaluates the args in a particular namespace
|
||||
## This is an override for ::tkcon::EvalAttached for when the user wants
|
||||
## to attach to a particular namespace of the attached interp
|
||||
# ARGS: attached
|
||||
# ARGS: attached
|
||||
# namespace the namespace to evaluate in
|
||||
# args the args to evaluate
|
||||
# RETURNS: the result of the command
|
||||
@@ -933,7 +923,7 @@ proc ::tkcon::Namespaces {{ns ::} {l {}}} {
|
||||
## ::tkcon::CmdGet - gets the current command from the console widget
|
||||
# ARGS: w - console text widget
|
||||
# Returns: text which compromises current command line
|
||||
##
|
||||
##
|
||||
proc ::tkcon::CmdGet w {
|
||||
if {![llength [$w tag nextrange prompt limit end]]} {
|
||||
$w tag add stdin limit end-1c
|
||||
@@ -947,7 +937,7 @@ proc ::tkcon::CmdGet w {
|
||||
# last - varname of any remainder (like an incomplete final command).
|
||||
# If there is only one command, it's placed in this var.
|
||||
# Returns: constituent command info in varnames specified by list & rmd.
|
||||
##
|
||||
##
|
||||
proc ::tkcon::CmdSep {cmd list last} {
|
||||
upvar 1 $list cmds $last inc
|
||||
set inc {}
|
||||
@@ -974,7 +964,7 @@ proc ::tkcon::CmdSep {cmd list last} {
|
||||
## ::tkcon::CmdSplit - splits multiple commands into a list
|
||||
# ARGS: cmd - (possible) multiple command to separate
|
||||
# Returns: constituent commands in a list
|
||||
##
|
||||
##
|
||||
proc ::tkcon::CmdSplit {cmd} {
|
||||
set inc {}
|
||||
set cmds {}
|
||||
@@ -998,7 +988,7 @@ proc ::tkcon::CmdSplit {cmd} {
|
||||
## Called by ::tkcon::EvalCmd
|
||||
# ARGS: w - text widget
|
||||
# Outputs: tag name guaranteed unique in the widget
|
||||
##
|
||||
##
|
||||
proc ::tkcon::UniqueTag {w} {
|
||||
set tags [$w tag names]
|
||||
set idx 0
|
||||
@@ -1011,7 +1001,7 @@ proc ::tkcon::UniqueTag {w} {
|
||||
# ARGS: w - console text widget
|
||||
# size - # of lines to constrain to
|
||||
# Outputs: may delete data in console widget
|
||||
##
|
||||
##
|
||||
proc ::tkcon::ConstrainBuffer {w size} {
|
||||
if {[$w index end] > $size} {
|
||||
$w delete 1.0 [expr {int([$w index end])-$size}].0
|
||||
@@ -1021,7 +1011,7 @@ proc ::tkcon::ConstrainBuffer {w size} {
|
||||
## ::tkcon::Prompt - displays the prompt in the console widget
|
||||
# ARGS: w - console text widget
|
||||
# Outputs: prompt (specified in ::tkcon::OPT(prompt1)) to console
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Prompt {{pre {}} {post {}} {prompt {}}} {
|
||||
variable OPT
|
||||
variable PRIV
|
||||
@@ -1053,7 +1043,7 @@ proc ::tkcon::Prompt {{pre {}} {post {}} {prompt {}}} {
|
||||
}
|
||||
|
||||
## ::tkcon::About - gives about info for tkcon
|
||||
##
|
||||
##
|
||||
proc ::tkcon::About {} {
|
||||
variable OPT
|
||||
variable PRIV
|
||||
@@ -1088,7 +1078,7 @@ proc ::tkcon::About {} {
|
||||
|
||||
## ::tkcon::InitMenus - inits the menubar and popup for the console
|
||||
# ARGS: w - console text widget
|
||||
##
|
||||
##
|
||||
proc ::tkcon::InitMenus {w title} {
|
||||
variable OPT
|
||||
variable PRIV
|
||||
@@ -1521,7 +1511,7 @@ proc ::tkcon::NamespaceMenu m {
|
||||
}
|
||||
}
|
||||
|
||||
## Namepaces List
|
||||
## Namepaces List
|
||||
##
|
||||
proc ::tkcon::NamespacesList {names} {
|
||||
variable PRIV
|
||||
@@ -1894,7 +1884,7 @@ proc ::tkcon::NewSocket {} {
|
||||
## The file is actually sourced in the currently attached's interp
|
||||
# ARGS: fn - (optional) filename to source in
|
||||
# Returns: selected filename ({} if nothing was selected)
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Load { {fn ""} } {
|
||||
set types {
|
||||
{{Tcl Files} {.tcl .tk}}
|
||||
@@ -1913,7 +1903,7 @@ proc ::tkcon::Load { {fn ""} } {
|
||||
## This does not eval in a slave because it's not necessary
|
||||
# ARGS: w - console text widget
|
||||
# fn - (optional) filename to save to
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Save { {fn ""} {type ""} {opt ""} {mode w} } {
|
||||
variable PRIV
|
||||
|
||||
@@ -1983,7 +1973,7 @@ proc ::tkcon::MainInit {} {
|
||||
## Creates a slave interpreter and sources in this script.
|
||||
## All other interpreters also get a command to eval function in the
|
||||
## new interpreter.
|
||||
##
|
||||
##
|
||||
proc ::tkcon::New {} {
|
||||
variable PRIV
|
||||
global argv0 argc argv
|
||||
@@ -2020,7 +2010,7 @@ proc ::tkcon::MainInit {} {
|
||||
## ::tkcon::Exit - full exit OR destroy slave console
|
||||
## This proc should only be called in the main interpreter from a slave.
|
||||
## The master determines whether we do a full exit or just kill the slave.
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Exit {slave args} {
|
||||
variable PRIV
|
||||
variable OPT
|
||||
@@ -2043,7 +2033,7 @@ proc ::tkcon::MainInit {} {
|
||||
## This proc should only be called by the main interpreter. If it is
|
||||
## called from there, it will ask before exiting tkcon. All others
|
||||
## (slaves) will just have their slave interpreter deleted, closing them.
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Destroy {{slave {}}} {
|
||||
variable PRIV
|
||||
|
||||
@@ -2474,7 +2464,7 @@ proc ::tkcon::ErrorHighlight w {
|
||||
$w tag configure $tag -foreground $COLOR(stdout)
|
||||
$w tag bind $tag <Enter> [list $w tag configure $tag -underline 1]
|
||||
$w tag bind $tag <Leave> [list $w tag configure $tag -underline 0]
|
||||
$w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
|
||||
$w tag bind $tag <ButtonRelease-1> "if {!\$::tk::Priv(mouseMoved)} \
|
||||
{[list edit -attach $app -type proc -find $what -- $cmd]}"
|
||||
}
|
||||
set info [string range $info $c1 end]
|
||||
@@ -2503,7 +2493,7 @@ proc ::tkcon::ErrorHighlight w {
|
||||
$w tag configure $tag -foreground $COLOR(proc)
|
||||
$w tag bind $tag <Enter> [list $w tag configure $tag -underline 1]
|
||||
$w tag bind $tag <Leave> [list $w tag configure $tag -underline 0]
|
||||
$w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
|
||||
$w tag bind $tag <ButtonRelease-1> "if {!\$::tk::Priv(mouseMoved)} \
|
||||
{[list edit -attach $app -type proc -- $cmd]}"
|
||||
}
|
||||
}
|
||||
@@ -2513,7 +2503,7 @@ proc ::tkcon::ErrorHighlight w {
|
||||
## This always exists in the main interpreter, and is aliased into
|
||||
## other connected interpreters
|
||||
# ARGS: totally variable, see internal comments
|
||||
##
|
||||
##
|
||||
proc tkcon {cmd args} {
|
||||
global errorInfo
|
||||
|
||||
@@ -2552,8 +2542,8 @@ proc tkcon {cmd args} {
|
||||
## 'congets' a replacement for [gets stdin]
|
||||
# Use the 'gets' alias of 'tkcon_gets' command instead of
|
||||
# calling the *get* methods directly for best compatability
|
||||
if {[llength $args]} {
|
||||
return -code error "wrong # args: must be \"tkcon congets\""
|
||||
if {[llength $args] > 1} {
|
||||
return -code error "wrong # args: must be \"tkcon congets [pfix]\""
|
||||
}
|
||||
tkcon show
|
||||
set old [bind TkConsole <<TkCon_Eval>>]
|
||||
@@ -2561,7 +2551,12 @@ proc tkcon {cmd args} {
|
||||
set w $::tkcon::PRIV(console)
|
||||
# Make sure to move the limit to get the right data
|
||||
$w mark set insert end
|
||||
$w mark set limit insert
|
||||
if {[llength $args]} {
|
||||
$w mark set limit insert
|
||||
$w insert end $args
|
||||
} else {
|
||||
$w mark set limit insert
|
||||
}
|
||||
$w see end
|
||||
vwait ::tkcon::PRIV(wait)
|
||||
set line [::tkcon::CmdGet $w]
|
||||
@@ -2790,21 +2785,27 @@ proc tkcon {cmd args} {
|
||||
## This allows me to capture all stdout/stderr to the console window
|
||||
## This will be renamed to 'puts' at the appropriate time during init
|
||||
##
|
||||
# ARGS: same as usual
|
||||
# ARGS: same as usual
|
||||
# Outputs: the string with a color-coded text tag
|
||||
##
|
||||
##
|
||||
proc tkcon_puts args {
|
||||
set len [llength $args]
|
||||
foreach {arg1 arg2 arg3} $args { break }
|
||||
|
||||
if {$len == 1} {
|
||||
tkcon console insert output "$arg1\n" stdout
|
||||
set sarg $arg1
|
||||
set nl 1
|
||||
set farg stdout
|
||||
} elseif {$len == 2} {
|
||||
if {![string compare $arg1 -nonewline]} {
|
||||
tkcon console insert output $arg2 stdout
|
||||
set sarg $arg2
|
||||
set farg stdout
|
||||
set nl 0
|
||||
} elseif {![string compare $arg1 stdout] \
|
||||
|| ![string compare $arg1 stderr]} {
|
||||
tkcon console insert output "$arg2\n" $arg1
|
||||
set sarg $arg2
|
||||
set farg $arg1
|
||||
set nl 1
|
||||
} else {
|
||||
set len 0
|
||||
}
|
||||
@@ -2812,11 +2813,15 @@ proc tkcon_puts args {
|
||||
if {![string compare $arg1 -nonewline] \
|
||||
&& (![string compare $arg2 stdout] \
|
||||
|| ![string compare $arg2 stderr])} {
|
||||
tkcon console insert output $arg3 $arg2
|
||||
set sarg $arg3
|
||||
set farg $arg2
|
||||
set nl 0
|
||||
} elseif {(![string compare $arg1 stdout] \
|
||||
|| ![string compare $arg1 stderr]) \
|
||||
&& ![string compare $arg3 nonewline]} {
|
||||
tkcon console insert output $arg2 $arg1
|
||||
set sarg $arg2
|
||||
set farg $arg1
|
||||
set nl 0
|
||||
} else {
|
||||
set len 0
|
||||
}
|
||||
@@ -2826,7 +2831,42 @@ proc tkcon_puts args {
|
||||
|
||||
## $len == 0 means it wasn't handled by tkcon above.
|
||||
##
|
||||
if {$len == 0} {
|
||||
|
||||
if {$len != 0} {
|
||||
|
||||
## "poor man's" \r substitution---erase everything on the output
|
||||
## line and print from character after the \r
|
||||
|
||||
set rpt [string last \r $sarg]
|
||||
if {$rpt >= 0} {
|
||||
tkcon console delete "insert linestart" "insert lineend"
|
||||
set sarg [string range $sarg [expr {$rpt + 1}] end]
|
||||
}
|
||||
|
||||
set bpt [string first \b $sarg]
|
||||
if {$bpt >= 0} {
|
||||
set narg [string range $sarg [expr {$bpt + 1}] end]
|
||||
set sarg [string range $sarg 0 [expr {$bpt - 1}]]
|
||||
set nl 0
|
||||
}
|
||||
|
||||
|
||||
if {$nl == 0} {
|
||||
tkcon console insert output $sarg $farg
|
||||
} else {
|
||||
tkcon console insert output "$sarg\n" $farg
|
||||
}
|
||||
|
||||
if {$bpt >= 0} {
|
||||
tkcon console delete "insert -1 char" insert
|
||||
if {$nl == 0} {
|
||||
tkcon_puts $farg $narg nonewline
|
||||
} else {
|
||||
tkcon_puts $farg $narg
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
global errorCode errorInfo
|
||||
if {[catch "tkcon_tcl_puts $args" msg]} {
|
||||
regsub tkcon_tcl_puts $msg puts msg
|
||||
@@ -2849,7 +2889,7 @@ proc tkcon_puts args {
|
||||
## This allows me to capture all stdin input without needing to stdin
|
||||
## This will be renamed to 'gets' at the appropriate time during init
|
||||
##
|
||||
# ARGS: same as gets
|
||||
# ARGS: same as gets
|
||||
# Outputs: same as gets
|
||||
##
|
||||
proc tkcon_gets args {
|
||||
@@ -2873,12 +2913,12 @@ proc tkcon_gets args {
|
||||
}
|
||||
|
||||
## edit - opens a file/proc/var for reading/editing
|
||||
##
|
||||
##
|
||||
# Arguments:
|
||||
# type proc/file/var
|
||||
# what the actual name of the item
|
||||
# Returns: nothing
|
||||
##
|
||||
##
|
||||
proc edit {args} {
|
||||
array set opts {-find {} -type {} -attach {}}
|
||||
while {[string match -* [lindex $args 0]]} {
|
||||
@@ -3030,7 +3070,7 @@ proc echo args { puts [concat $args] }
|
||||
|
||||
## clear - clears the buffer of the console (not the history though)
|
||||
## This is executed in the parent interpreter
|
||||
##
|
||||
##
|
||||
proc clear {{pcnt 100}} {
|
||||
if {![regexp {^[0-9]*$} $pcnt] || $pcnt < 1 || $pcnt > 100} {
|
||||
return -code error \
|
||||
@@ -3048,7 +3088,7 @@ proc clear {{pcnt 100}} {
|
||||
## If called with one arg, returns the alias of that arg (or {} if none)
|
||||
# ARGS: newcmd - (optional) command to bind alias to
|
||||
# args - command and args being aliased
|
||||
##
|
||||
##
|
||||
proc alias {{newcmd {}} args} {
|
||||
if {[string match {} $newcmd]} {
|
||||
set res {}
|
||||
@@ -3065,7 +3105,7 @@ proc alias {{newcmd {}} args} {
|
||||
|
||||
## unalias - unaliases an alias'ed command
|
||||
# ARGS: cmd - command to unbind as an alias
|
||||
##
|
||||
##
|
||||
proc unalias {cmd} {
|
||||
interp alias {} $cmd {}
|
||||
}
|
||||
@@ -3085,7 +3125,7 @@ proc unalias {cmd} {
|
||||
# -- forcibly ends options recognition
|
||||
#
|
||||
# Returns: the values of the requested items in a 'source'able form
|
||||
##
|
||||
##
|
||||
proc dump {type args} {
|
||||
set whine 1
|
||||
set code ok
|
||||
@@ -3637,13 +3677,13 @@ proc observe_var {name el op} {
|
||||
## which - tells you where a command is found
|
||||
# ARGS: cmd - command name
|
||||
# Returns: where command is found (internal / external / unknown)
|
||||
##
|
||||
##
|
||||
proc which cmd {
|
||||
## This tries to auto-load a command if not recognized
|
||||
set types [uplevel 1 [list what $cmd 1]]
|
||||
if {[llength $types]} {
|
||||
set out {}
|
||||
|
||||
|
||||
foreach type $types {
|
||||
switch -- $type {
|
||||
alias { set res "$cmd: aliased to [alias $cmd]" }
|
||||
@@ -3674,7 +3714,7 @@ proc which cmd {
|
||||
## what - tells you what a string is recognized as
|
||||
# ARGS: str - string to id
|
||||
# Returns: id types of command as list
|
||||
##
|
||||
##
|
||||
proc what {str {autoload 0}} {
|
||||
set types {}
|
||||
if {[llength [info commands $str]] || ($autoload && \
|
||||
@@ -3721,7 +3761,7 @@ proc what {str {autoload 0}} {
|
||||
# -long - list in full format "permissions size date filename"
|
||||
# -full - displays / after directories and link paths for links
|
||||
# Returns: a directory listing
|
||||
##
|
||||
##
|
||||
proc dir {args} {
|
||||
array set s {
|
||||
all 0 full 0 long 0
|
||||
@@ -4106,7 +4146,7 @@ proc ::tkcon::Bindings {} {
|
||||
global tcl_platform tk_version
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Elements of tkPriv that are used in this file:
|
||||
# Elements of ::tk::Priv that are used in this file:
|
||||
#
|
||||
# char - Character position on the line; kept in order
|
||||
# to allow moving up or down past short lines while
|
||||
@@ -4131,9 +4171,12 @@ proc ::tkcon::Bindings {} {
|
||||
}
|
||||
|
||||
## Get all Text bindings into TkConsole
|
||||
foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] }
|
||||
foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] }
|
||||
## We really didn't want the newline insertion
|
||||
bind TkConsole <Control-Key-o> {}
|
||||
|
||||
## in 8.6b3, the virtual events <<NextLine>> and <<PrevLine>>
|
||||
# mess up our history feature
|
||||
bind TkConsole <<NextLine>> {}
|
||||
bind TkConsole <<PrevLine>> {}
|
||||
|
||||
@@ -4342,9 +4385,9 @@ proc ::tkcon::Bindings {} {
|
||||
|
||||
bind TkConsole <Control-a> {
|
||||
if {[%W compare {limit linestart} == {insert linestart}]} {
|
||||
tkTextSetCursor %W limit
|
||||
::tk::TextSetCursor %W limit
|
||||
} else {
|
||||
tkTextSetCursor %W {insert linestart}
|
||||
::tk::TextSetCursor %W {insert linestart}
|
||||
}
|
||||
}
|
||||
bind TkConsole <Key-Home> [bind TkConsole <Control-a>]
|
||||
@@ -4368,14 +4411,14 @@ proc ::tkcon::Bindings {} {
|
||||
}
|
||||
bind TkConsole <<TkCon_Previous>> {
|
||||
if {[%W compare {insert linestart} != {limit linestart}]} {
|
||||
tkTextSetCursor %W [tkTextUpDownLine %W -1]
|
||||
::tk::TextSetCursor %W [::tk::TextUpDownLine %W -1]
|
||||
} else {
|
||||
::tkcon::Event -1
|
||||
}
|
||||
}
|
||||
bind TkConsole <<TkCon_Next>> {
|
||||
if {[%W compare {insert linestart} != {end-1c linestart}]} {
|
||||
tkTextSetCursor %W [tkTextUpDownLine %W 1]
|
||||
::tk::TextSetCursor %W [::tk::TextUpDownLine %W 1]
|
||||
} else {
|
||||
::tkcon::Event 1
|
||||
}
|
||||
@@ -4390,7 +4433,7 @@ proc ::tkcon::Bindings {} {
|
||||
}
|
||||
bind TkConsole <<TkCon_Transpose>> {
|
||||
## Transpose current and previous chars
|
||||
if {[%W compare insert > "limit+1c"]} { tkTextTranspose %W }
|
||||
if {[%W compare insert > "limit+1c"]} { ::tk::TextTranspose %W }
|
||||
}
|
||||
bind TkConsole <<TkCon_ClearLine>> {
|
||||
## Clear command line (Unix shell staple)
|
||||
@@ -4408,10 +4451,10 @@ proc ::tkcon::Bindings {} {
|
||||
::tkcon::Insert %W $::tkcon::PRIV(tmp)
|
||||
%W see end
|
||||
}
|
||||
catch {bind TkConsole <Key-Page_Up> { tkTextScrollPages %W -1 }}
|
||||
catch {bind TkConsole <Key-Prior> { tkTextScrollPages %W -1 }}
|
||||
catch {bind TkConsole <Key-Page_Down> { tkTextScrollPages %W 1 }}
|
||||
catch {bind TkConsole <Key-Next> { tkTextScrollPages %W 1 }}
|
||||
catch {bind TkConsole <Key-Page_Up> { ::tk::TextScrollPages %W -1 }}
|
||||
catch {bind TkConsole <Key-Prior> { ::tk::TextScrollPages %W -1 }}
|
||||
catch {bind TkConsole <Key-Page_Down> { ::tk::TextScrollPages %W 1 }}
|
||||
catch {bind TkConsole <Key-Next> { ::tk::TextScrollPages %W 1 }}
|
||||
bind TkConsole <$PRIV(meta)-d> {
|
||||
if {[%W compare insert >= limit]} {
|
||||
%W delete insert {insert wordend}
|
||||
@@ -4429,7 +4472,7 @@ proc ::tkcon::Bindings {} {
|
||||
}
|
||||
bind TkConsole <ButtonRelease-2> {
|
||||
if {
|
||||
(!$tkPriv(mouseMoved) || $tk_strictMotif) &&
|
||||
(!$::tk::Priv(mouseMoved) || $tk_strictMotif) &&
|
||||
![catch {::tkcon::GetSelection %W} ::tkcon::PRIV(tmp)]
|
||||
} {
|
||||
if {[%W compare @%x,%y < limit]} {
|
||||
@@ -4600,7 +4643,7 @@ proc ::tkcon::TagProc w {
|
||||
# c1 - first char of pair
|
||||
# c2 - second char of pair
|
||||
# Calls: ::tkcon::Blink
|
||||
##
|
||||
##
|
||||
proc ::tkcon::MatchPair {w c1 c2 {lim 1.0}} {
|
||||
if {[string compare {} [set ix [$w search -back $c1 insert $lim]]]} {
|
||||
while {
|
||||
@@ -4638,7 +4681,7 @@ proc ::tkcon::MatchPair {w c1 c2 {lim 1.0}} {
|
||||
## The quote to match is assumed to be at the text index 'insert'.
|
||||
# ARGS: w - console text widget
|
||||
# Calls: ::tkcon::Blink
|
||||
##
|
||||
##
|
||||
proc ::tkcon::MatchQuote {w {lim 1.0}} {
|
||||
set i insert-1c
|
||||
set j 0
|
||||
@@ -4664,7 +4707,7 @@ proc ::tkcon::MatchQuote {w {lim 1.0}} {
|
||||
# i2 - end index of blink region
|
||||
# dur - duration in usecs to blink for
|
||||
# Outputs: blinks selected characters in $w
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Blink {w args} {
|
||||
eval [list $w tag add blink] $args
|
||||
after $::tkcon::OPT(blinktime) [list $w] tag remove blink $args
|
||||
@@ -4679,7 +4722,7 @@ proc ::tkcon::Blink {w args} {
|
||||
# ARGS: w - text window in which to insert the string
|
||||
# s - string to insert (usually just a single char)
|
||||
# Outputs: $s to text widget
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Insert {w s} {
|
||||
if {[string match {} $s] || [string match disabled [$w cget -state]]} {
|
||||
return
|
||||
@@ -4695,7 +4738,7 @@ proc ::tkcon::Insert {w s} {
|
||||
$w see insert
|
||||
}
|
||||
|
||||
## ::tkcon::Expand -
|
||||
## ::tkcon::Expand -
|
||||
# ARGS: w - text widget in which to expand str
|
||||
# type - type of expansion (path / proc / variable)
|
||||
# Calls: ::tkcon::Expand(Pathname|Procname|Variable)
|
||||
@@ -4704,7 +4747,7 @@ proc ::tkcon::Insert {w s} {
|
||||
# match equaled the string to expand, then all possible matches
|
||||
# are output to stdout. Triggers bell if no matches are found.
|
||||
# Returns: number of matches found
|
||||
##
|
||||
##
|
||||
proc ::tkcon::Expand {w {type ""}} {
|
||||
set exp "\[^\\\\\]\[\[ \t\n\r\\\{\"$\]"
|
||||
set tmp [$w search -backwards -regexp $exp insert-1c limit-1c]
|
||||
@@ -4743,7 +4786,7 @@ proc ::tkcon::Expand {w {type ""}} {
|
||||
# Calls: ::tkcon::ExpandBestMatch
|
||||
# Returns: list containing longest unique match followed by all the
|
||||
# possible further matches
|
||||
##
|
||||
##
|
||||
proc ::tkcon::ExpandPathname str {
|
||||
set pwd [EvalAttached pwd]
|
||||
# Cause a string like {C:/Program\ Files/} to become "C:/Program Files/"
|
||||
@@ -4825,7 +4868,7 @@ proc ::tkcon::ExpandProcname str {
|
||||
# Calls: ::tkcon::ExpandBestMatch
|
||||
# Returns: list containing longest unique match followed by all the
|
||||
# possible further matches
|
||||
##
|
||||
##
|
||||
proc ::tkcon::ExpandVariable str {
|
||||
if {[regexp {([^\(]*)\((.*)} $str junk ary str]} {
|
||||
## Looks like they're trying to expand an array.
|
||||
@@ -4853,7 +4896,7 @@ proc ::tkcon::ExpandVariable str {
|
||||
## or $e is {}. $e is extra for compatibility with proc below.
|
||||
# ARGS: l - list to find best unique match in
|
||||
# Returns: longest unique match in the list
|
||||
##
|
||||
##
|
||||
proc ::tkcon::ExpandBestMatch2 {l {e {}}} {
|
||||
set s [lindex $l 0]
|
||||
if {[llength $l]>1} {
|
||||
@@ -4873,7 +4916,7 @@ proc ::tkcon::ExpandBestMatch2 {l {e {}}} {
|
||||
# ARGS: l - list to find best unique match in
|
||||
# e - currently best known unique match
|
||||
# Returns: longest unique match in the list
|
||||
##
|
||||
##
|
||||
proc ::tkcon::ExpandBestMatch {l {e {}}} {
|
||||
set ec [lindex $l 0]
|
||||
if {[llength $l]>1} {
|
||||
@@ -5237,7 +5280,7 @@ proc ::tkcon::Retrieve {} {
|
||||
## ::tkcon::Resource - re'source's this script into current console
|
||||
## Meant primarily for my development of this program. It follows
|
||||
## links until the ultimate source is found.
|
||||
##
|
||||
##
|
||||
set ::tkcon::PRIV(SCRIPT) [info script]
|
||||
if {!$::tkcon::PRIV(WWW) && [string compare $::tkcon::PRIV(SCRIPT) {}]} {
|
||||
# we use a catch here because some wrap apps choke on 'file type'
|
||||
|
||||
Reference in New Issue
Block a user