mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-25 07:27:44 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f2ab31143 | ||
|
|
08485d28a7 | ||
|
|
45164bbf98 | ||
|
|
2ee286efb4 | ||
|
|
46cb8d6637 | ||
|
|
dae6919d4f | ||
|
|
017bdc6e48 | ||
|
|
2825b786b7 | ||
|
|
b371af9235 | ||
|
|
0af8c7ad49 | ||
|
|
b5432d139b | ||
|
|
0aa20dcf62 | ||
|
|
0e958bd45c | ||
|
|
7cbf15aab1 | ||
|
|
b59196fa81 | ||
|
|
1de6f88f1e | ||
|
|
6e6e9fb73f | ||
|
|
33fed391fd | ||
|
|
e84700a607 | ||
|
|
5f5248b3d0 | ||
|
|
0bee21ccc8 | ||
|
|
80f9263004 | ||
|
|
c269f1de89 | ||
|
|
edb50746cb | ||
|
|
4443826f9e | ||
|
|
f2368ca223 | ||
|
|
a60dac6124 | ||
|
|
ee93d52a26 | ||
|
|
bbe645f0ab | ||
|
|
ba7004fd5b | ||
|
|
4f315d33d6 | ||
|
|
704bfbc871 | ||
|
|
4457248ecd | ||
|
|
7bee1851fa | ||
|
|
021dfa6e8a | ||
|
|
e4a4621b96 | ||
|
|
1d286f9973 | ||
|
|
3ca77300ac | ||
|
|
6d2ef396ef | ||
|
|
2483b7440f | ||
|
|
236fba18aa | ||
|
|
49c0de0433 | ||
|
|
3b9dca0cf2 |
@@ -22,6 +22,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#ifdef IBMPC
|
||||
#include <stdlib.h> /* for strtol on PC */
|
||||
|
||||
+93
-14
@@ -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 */
|
||||
}
|
||||
@@ -1716,6 +1756,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
flattenInstancesOf(name1, file1, ecomp->cell1->name);
|
||||
modified1++;
|
||||
}
|
||||
else if (ecomp->cell1 && (ecomp->num1 > 0)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
" would make a better match but is prohibited.\n",
|
||||
ecomp->cell1->name, name1, file1);
|
||||
}
|
||||
if (ecomp->cell2 && (ecomp->num2 > 0) &&
|
||||
(!(ecomp->cell2->flags & CELL_PLACEHOLDER))) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
@@ -1724,6 +1769,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
flattenInstancesOf(name2, file2, ecomp->cell2->name);
|
||||
modified2++;
|
||||
}
|
||||
else if (ecomp->cell2 && (ecomp->num2 > 0)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
" would make a better match but is prohibited.\n",
|
||||
ecomp->cell2->name, name2, file2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset or apply the count adjustments */
|
||||
@@ -1814,6 +1864,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
flattenInstancesOf(name2, file2, ecomp->cell2->name);
|
||||
modified2++;
|
||||
}
|
||||
else if (ecomp->cell2) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
" would make a better match but is prohibited.\n",
|
||||
ecomp->cell2->name, name2, file2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1880,6 +1935,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
flattenInstancesOf(name1, file1, ecomp->cell1->name);
|
||||
modified1++;
|
||||
}
|
||||
else if (ecomp->cell1) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
|
||||
" would make a better match but is prohibited.\n",
|
||||
ecomp->cell1->name, name1, file1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2231,13 +2291,23 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
ecompX0->cell1->file, &compdict);
|
||||
if (dstr) *dstr = '[';
|
||||
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
"(%d) makes a better match\n",
|
||||
ecompX0->cell1->name, name1, file1);
|
||||
flattenInstancesOf(name1, file1, ecompX0->cell1->name);
|
||||
ecompX0->num1 = 0;
|
||||
ecomp0X->num1 += ecompX0->num1;
|
||||
modified1++;
|
||||
if (!(ecompX0->cell1->flags & CELL_PLACEHOLDER)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell"
|
||||
" %s (%d) makes a better match\n",
|
||||
ecompX0->cell1->name, name1, file1);
|
||||
flattenInstancesOf(name1, file1,
|
||||
ecompX0->cell1->name);
|
||||
ecompX0->num1 = 0;
|
||||
ecomp0X->num1 += ecompX0->num1;
|
||||
modified1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Fprintf(stdout, "Flattening instances of %s in "
|
||||
"cell %s (%d) would make a better "
|
||||
"match but is prohibited.\n",
|
||||
ecompX0->cell1->name, name1, file1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2257,13 +2327,22 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
ecomp0X->cell2->file, &compdict);
|
||||
if (dstr) *dstr = '[';
|
||||
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell %s"
|
||||
" (%d) makes a better match\n",
|
||||
ecomp0X->cell2->name, name2, file2);
|
||||
flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
|
||||
ecomp0X->num2 = 0;
|
||||
ecompX0->num2 += ecomp0X->num2;
|
||||
modified2++;
|
||||
if (!(ecomp0X->cell2->flags & CELL_PLACEHOLDER)) {
|
||||
Fprintf(stdout, "Flattening instances of %s in cell"
|
||||
" %s (%d) makes a better match\n",
|
||||
ecomp0X->cell2->name, name2, file2);
|
||||
flattenInstancesOf(name2, file2,
|
||||
ecomp0X->cell2->name);
|
||||
ecomp0X->num2 = 0;
|
||||
ecompX0->num2 += ecomp0X->num2;
|
||||
modified2++;
|
||||
}
|
||||
else {
|
||||
Fprintf(stdout, "Flattening instances of %s in "
|
||||
"cell %s (%d) would make a better "
|
||||
"match but is prohibited.\n",
|
||||
ecompX0->cell2->name, name2, file2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+367
-49
@@ -1217,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;
|
||||
@@ -1251,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;
|
||||
@@ -5216,14 +5218,23 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
|
||||
if (comb == TRUE) {
|
||||
double pd;
|
||||
int hascrit = FALSE;
|
||||
int mult, cidx = -1;
|
||||
struct valuelist *avl, *cvl = NULL;
|
||||
struct valuelist **avl, **cvl;
|
||||
struct valuelist *cvlp;
|
||||
|
||||
critval.type = PROP_ENDLIST;
|
||||
critval.value.dval = 0.0;
|
||||
|
||||
/* Track properties separately so that multiple properties can be
|
||||
* added together (e.g., area and perimeter)
|
||||
*/
|
||||
avl = (struct valuelist **)CALLOC(pcount, sizeof(struct valuelist *));
|
||||
cvl = (struct valuelist **)CALLOC(pcount, sizeof(struct valuelist *));
|
||||
|
||||
for (i = 0; i < run; i++) {
|
||||
avl = NULL;
|
||||
// if (vlist[0][i] == NULL) continue;
|
||||
// mult = vlist[0][i]->value.ival;
|
||||
for (p = 0; p < pcount; p++) avl[p] = NULL;
|
||||
|
||||
if (vlist[0][i] == NULL)
|
||||
mult = 1;
|
||||
else
|
||||
@@ -5240,6 +5251,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
|
||||
/* critical properties never combine, but track them */
|
||||
if ((series == TRUE) && (ctype & MERGE_S_CRIT)) {
|
||||
hascrit = TRUE;
|
||||
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
|
||||
(vl->value.dval + critval.value.dval);
|
||||
if ((vl->type != critval.type) || (pd > kl->slop.dval))
|
||||
@@ -5251,6 +5263,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
continue;
|
||||
}
|
||||
if ((series == FALSE) && (ctype & MERGE_P_CRIT)) {
|
||||
hascrit = TRUE;
|
||||
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
|
||||
(vl->value.dval + critval.value.dval);
|
||||
if ((vl->type != critval.type) || (pd > kl->slop.dval))
|
||||
@@ -5284,19 +5297,30 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
}
|
||||
}
|
||||
if (ctype & (MERGE_S_ADD | MERGE_P_ADD | MERGE_S_PAR | MERGE_P_PAR))
|
||||
avl = vl;
|
||||
avl[p] = vl;
|
||||
}
|
||||
if (cidx == i) cvl = avl;
|
||||
if (hascrit == FALSE) cidx = 0; /* No critical property */
|
||||
|
||||
/* Each time a new critical value is found, set the location */
|
||||
/* of the property record that will collect the summation or */
|
||||
/* parallel combination of values. */
|
||||
if (cidx == i) {
|
||||
for (p = 1; p < pcount; p++) {
|
||||
cvl[p] = avl[p];
|
||||
}
|
||||
}
|
||||
|
||||
/* Sorting should have put all records with the same critical */
|
||||
/* value together sequentially. So if there are still */
|
||||
/* multiple property records, then merge them into the first */
|
||||
/* record with the same critical property value. */
|
||||
/* record with the same critical property value. If no */
|
||||
/* critical value exists, then all records can be merged. */
|
||||
|
||||
if ((i > 0) && (cidx >= 0) && (cidx < i)) {
|
||||
for (p = 1; p < pcount; p++) {
|
||||
vl = vlist[p][i];
|
||||
ctype = clist[p][i];
|
||||
cvlp = cvl[p];
|
||||
|
||||
if (ctype & (MERGE_S_ADD | MERGE_P_ADD)) {
|
||||
if (!vlist[0][i]) {
|
||||
@@ -5305,21 +5329,21 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
sizeof(struct valuelist));
|
||||
}
|
||||
vlist[0][i]->value.ival = 0; /* set M to 0 */
|
||||
if (cvl && (cvl->type == PROP_INTEGER))
|
||||
if (cvlp && (cvlp->type == PROP_INTEGER))
|
||||
{
|
||||
if (vl->type == PROP_INTEGER)
|
||||
cvl->value.ival += vl->value.ival;
|
||||
cvlp->value.ival += vl->value.ival;
|
||||
else {
|
||||
cvl->type = PROP_DOUBLE;
|
||||
cvl->value.dval = (double)cvl->value.ival + vl->value.dval;
|
||||
cvlp->type = PROP_DOUBLE;
|
||||
cvlp->value.dval = (double)cvlp->value.ival + vl->value.dval;
|
||||
}
|
||||
}
|
||||
else if ((cvl && vl->type == PROP_DOUBLE))
|
||||
else if ((cvlp && vl->type == PROP_DOUBLE))
|
||||
{
|
||||
if (vl->type == PROP_INTEGER)
|
||||
cvl->value.dval += (double)vl->value.ival;
|
||||
cvlp->value.dval += (double)vl->value.ival;
|
||||
else
|
||||
cvl->value.dval += vl->value.dval;
|
||||
cvlp->value.dval += vl->value.dval;
|
||||
}
|
||||
}
|
||||
else if (ctype & (MERGE_S_PAR | MERGE_P_PAR)) {
|
||||
@@ -5329,21 +5353,22 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
sizeof(struct valuelist));
|
||||
}
|
||||
vlist[0][i]->value.ival = 0; /* set M to 0 */
|
||||
/* To do parallel combination, both types need to
|
||||
/* Parallel value combination: (X * Y) / (X + Y)
|
||||
* To do parallel combination, both types need to
|
||||
* be double, so recast them if they are integer.
|
||||
*/
|
||||
if (vl->type == PROP_INTEGER) {
|
||||
vl->type = PROP_DOUBLE;
|
||||
vl->value.dval = (double)(vl->value.ival);
|
||||
}
|
||||
if (cvl && (cvl->type == PROP_INTEGER)) {
|
||||
cvl->type = PROP_DOUBLE;
|
||||
cvl->value.dval = (double)cvl->value.ival;
|
||||
if (cvlp && (cvlp->type == PROP_INTEGER)) {
|
||||
cvlp->type = PROP_DOUBLE;
|
||||
cvlp->value.dval = (double)cvlp->value.ival;
|
||||
}
|
||||
if ((cvl && (vl->type == PROP_DOUBLE))) {
|
||||
cvl->value.dval =
|
||||
sqrt(cvl->value.dval * cvl->value.dval
|
||||
+ vl->value.dval * vl->value.dval);
|
||||
if ((cvlp && (vl->type == PROP_DOUBLE))) {
|
||||
cvlp->value.dval =
|
||||
(vl->value.dval * cvlp->value.dval) /
|
||||
(vl->value.dval + cvlp->value.dval);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5355,6 +5380,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
|
||||
Printf("Combined %d parallel devices.\n", changed);
|
||||
}
|
||||
}
|
||||
|
||||
FREE(avl);
|
||||
FREE(cvl);
|
||||
}
|
||||
|
||||
// Remove entries with M (S) = 0
|
||||
@@ -6053,6 +6081,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)
|
||||
@@ -6567,11 +6598,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;
|
||||
@@ -6580,7 +6616,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;
|
||||
@@ -6604,7 +6643,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);
|
||||
@@ -7003,10 +7044,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7504,6 +7556,12 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
|
||||
else {
|
||||
lob = ob;
|
||||
ob->type = i++;
|
||||
if (ob->model.class == NULL) {
|
||||
ob->model.class = strsave(tc->name);
|
||||
}
|
||||
if (ob->instance.name == NULL) {
|
||||
ob->instance.name = strsave(firstpin->instance.name);
|
||||
}
|
||||
ob = ob->next;
|
||||
}
|
||||
tob = tob->next;
|
||||
@@ -7569,6 +7627,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
int hasproxy1 = 0, hasproxy2 = 0;
|
||||
int needclean1 = 0, needclean2 = 0;
|
||||
int nomatch = 0;
|
||||
int P1, P2;
|
||||
int filenum = -1;
|
||||
int *correspond;
|
||||
char *ostr;
|
||||
@@ -7582,6 +7641,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;
|
||||
@@ -7597,6 +7660,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
return 2;
|
||||
}
|
||||
|
||||
correspond = (int *)CALLOC((tc1->nodename_cache_maxnodenum + 1), sizeof(int));
|
||||
cover = (char *)CALLOC(numnodes, sizeof(char));
|
||||
numorig = numnodes;
|
||||
|
||||
@@ -7735,7 +7799,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (strcmp(obn->name, "(no pins)")) {
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", obn->name);
|
||||
output_string_right(ostr, "(no pin, node is %s",
|
||||
output_string_right(ostr, "(no pin, node is %s)",
|
||||
obp->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
@@ -7815,8 +7879,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
|
||||
ob1 = tc1->cell;
|
||||
|
||||
correspond = (int *)CALLOC((tc1->nodename_cache_maxnodenum + 1), sizeof(int));
|
||||
|
||||
for (i = 0; i < numorig; i++) {
|
||||
bangptr1 = strrchr(ob1->name, '!');
|
||||
if (bangptr1 && (*(bangptr1 + 1) == '\0'))
|
||||
@@ -7937,7 +7999,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (bangptr2) *bangptr2 = '!';
|
||||
break;
|
||||
}
|
||||
else {
|
||||
else if (IsPort(ob1) && IsPort(ob2)) {
|
||||
struct Permutation *permute1, *permute2;
|
||||
struct objlist *ob1a = NULL, *ob2a = NULL;
|
||||
|
||||
@@ -7947,30 +8009,28 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
*/
|
||||
for (permute1 = tc1->permutes; permute1; permute1 = permute1->next) {
|
||||
if ((*matchfunc)(ob1->name, permute1->pin1)) {
|
||||
ob1a = LookupObject(permute1->pin1, tc1);
|
||||
ob2a = LookupObject(permute1->pin2, tc2);
|
||||
break;
|
||||
}
|
||||
else if ((*matchfunc)(ob1->name, permute1->pin2)) {
|
||||
ob1a = LookupObject(permute1->pin2, tc1);
|
||||
ob2a = LookupObject(permute1->pin1, tc2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (permute2 = tc2->permutes; permute2; permute2 = permute2->next) {
|
||||
if ((*matchfunc)(ob2->name, permute2->pin1)) {
|
||||
ob2a = LookupObject(permute2->pin1, tc2);
|
||||
ob1a = LookupObject(permute2->pin2, tc1);
|
||||
break;
|
||||
}
|
||||
else if ((*matchfunc)(ob2->name, permute2->pin2)) {
|
||||
ob2a = LookupObject(permute2->pin2, tc2);
|
||||
ob1a = LookupObject(permute2->pin1, tc1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ob1a && ob2a) {
|
||||
if ((ob1->node == ob1a->node) && (ob2->node == ob2a->node)) {
|
||||
/* This should be enough to prove equivalency */
|
||||
if ((correspond[ob1->node] == 0) || (correspond[ob1->node] == ob2->node)) {
|
||||
|
||||
correspond[ob1->node] = ob2->node; /* remember corresponding node */
|
||||
if ((correspond[ob1->node] == 0) ||
|
||||
(correspond[ob1->node] == ob2->node)) {
|
||||
ob2->model.port = i; /* save order */
|
||||
*(cover + i) = (char)1;
|
||||
|
||||
@@ -8027,11 +8087,36 @@ 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)")) {
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", "(no matching pin)");
|
||||
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);
|
||||
}
|
||||
@@ -8111,6 +8196,14 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
hasproxy1 = 1;
|
||||
|
||||
HashPtrInstall(obn->name, obn, &(tc1->objdict));
|
||||
|
||||
/* If this is a black-box circuit, then the pin has not been output */
|
||||
if (NodeClasses == NULL) {
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", "(no matching pin)");
|
||||
output_string_right(ostr, "%s", ob2->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8148,12 +8241,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);
|
||||
@@ -8165,7 +8261,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;
|
||||
|
||||
if (ob2 == tc2->cell) {
|
||||
obn->next = ob2;
|
||||
@@ -8179,11 +8274,26 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
hasproxy2 = 1;
|
||||
|
||||
HashPtrInstall(obn->name, obn, &(tc2->objdict));
|
||||
|
||||
/* If this is a black-box circuit, then the pin has not been output */
|
||||
if (NodeClasses == NULL) {
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", ob1->name);
|
||||
output_string_right(ostr, "%s", "(no matching pin)");
|
||||
output_string_print(ostr);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -8199,6 +8309,38 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (Debug == 0)
|
||||
output_string_print_divider(ostr, FALSE);
|
||||
|
||||
/* Catch errors where disconnected ports get effectively hidden by */
|
||||
/* pin permutations. */
|
||||
|
||||
if (result == 1) {
|
||||
int found = 0;
|
||||
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||
P1 = P2 = 0;
|
||||
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
|
||||
if (N1->graph == Circuit2->file)
|
||||
if (IsPort(N1->object)) P2++;
|
||||
if (N1->graph == Circuit1->file)
|
||||
if (IsPort(N1->object)) P1++;
|
||||
}
|
||||
if (P1 != P2) {
|
||||
if (found == 0)
|
||||
Fprintf(stdout, "\nPort connection errors found:\n");
|
||||
found = 1;
|
||||
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
|
||||
obn = N1->object;
|
||||
|
||||
if (IsPort(obn))
|
||||
Fprintf(stdout, " %s (%d)\n", obn->name, N1->graph);
|
||||
else
|
||||
Fprintf(stdout, " %s (%d) (no port)\n", obn->name, N1->graph);
|
||||
if (N1->graph == Circuit1->file)
|
||||
correspond[obn->node] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found == 1) Fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
/* Run cleanuppins on circuit 1 */
|
||||
if (needclean1)
|
||||
CleanupPins(tc1->name, tc1->file);
|
||||
@@ -8411,6 +8553,182 @@ int EquivalentElement(char *name, struct nlist *circuit, struct objlist **retobj
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Structure and definitins used by derivedprops() */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
enum DerivedType {area_type, perimeter_type};
|
||||
|
||||
typedef struct _derivedpropdata {
|
||||
struct nlist *cell;
|
||||
int fnum;
|
||||
char *pwidth;
|
||||
char *plength;
|
||||
enum DerivedType type;
|
||||
} DerivedPropData;
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* derivedprops --- Callback function for a recursive */
|
||||
/* search over all cells with a pointer clientdata. */
|
||||
/* The pointer is a DerivedPropData structure that */
|
||||
/* contains the information needed to determine how to */
|
||||
/* generate an "area" or "perimeter" property based on */
|
||||
/* the device length and width. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
struct nlist *derivedprops(struct hashlist *p, void *clientdata)
|
||||
{
|
||||
struct nlist *ptr;
|
||||
struct objlist *ob;
|
||||
struct valuelist *vl, *newvlist;
|
||||
struct nlist *tc;
|
||||
struct property *prop;
|
||||
int i;
|
||||
double valuew, valuel, valuea = 0.0, valuep = 0.0;
|
||||
int haswidth = FALSE, haslength = FALSE;
|
||||
int hasarea = FALSE, hasperimeter = FALSE;
|
||||
|
||||
DerivedPropData *dpd = (DerivedPropData *)clientdata;
|
||||
|
||||
tc = dpd->cell;
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
if (ptr->file != tc->file) return NULL;
|
||||
|
||||
/* Search all instances in the cell for properties, find those matching
|
||||
* the cell class to be modified, and create a new derived property for
|
||||
* area or perimeter for that instance.
|
||||
*/
|
||||
|
||||
for (ob = ptr->cell; ob; ob = ob->next) {
|
||||
if (ob->type == PROPERTY) {
|
||||
if ((*matchfunc)(ob->model.class, tc->name)) {
|
||||
for (i = 0;; i++) {
|
||||
vl = &(ob->instance.props[i]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
prop = (struct property *)HashLookup(vl->key, &(tc->propdict));
|
||||
if (prop != NULL) {
|
||||
if ((*matchfunc)(vl->key, dpd->pwidth)) {
|
||||
haswidth = TRUE;
|
||||
if (vl->type == PROP_DOUBLE)
|
||||
valuew = vl->value.dval;
|
||||
else if (vl->type == PROP_INTEGER)
|
||||
valuew = (double)vl->value.ival;
|
||||
else
|
||||
haswidth = FALSE;
|
||||
}
|
||||
else if ((*matchfunc)(vl->key, dpd->plength)) {
|
||||
haslength = TRUE;
|
||||
if (vl->type == PROP_DOUBLE)
|
||||
valuel = vl->value.dval;
|
||||
else if (vl->type == PROP_INTEGER)
|
||||
valuel = (double)vl->value.ival;
|
||||
else
|
||||
haslength = FALSE;
|
||||
}
|
||||
else if ((dpd->type == area_type)
|
||||
&& ((*matchfunc)(vl->key, "area"))) {
|
||||
hasarea = TRUE;
|
||||
}
|
||||
else if ((dpd->type == perimeter_type)
|
||||
&& ((*matchfunc)(vl->key, "perimeter"))) {
|
||||
hasperimeter = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (haslength && haswidth) {
|
||||
|
||||
/* Once the property names for device width and length have
|
||||
* been found, and the values recorded, add the area or
|
||||
* perimeter value to the property list for the instance,
|
||||
* unless the instance already has the property.
|
||||
*/
|
||||
newvlist = (struct valuelist *)CALLOC(i + 1, sizeof(struct valuelist));
|
||||
vl = &newvlist[i];
|
||||
vl->key = NULL;
|
||||
vl->type = PROP_ENDLIST;
|
||||
vl->value.ival = 0;
|
||||
|
||||
vl = &newvlist[--i];
|
||||
if ((dpd->type == area_type) && (!hasarea)) {
|
||||
valuea = valuew * valuel;
|
||||
vl->key = strsave("area");
|
||||
vl->type = PROP_DOUBLE;
|
||||
vl->value.dval = valuea;
|
||||
|
||||
} else if ((dpd->type == perimeter_type) && (!hasperimeter)) {
|
||||
valuep = 2 * (valuew + valuel);
|
||||
vl->key = strsave("perimeter");
|
||||
vl->type = PROP_DOUBLE;
|
||||
vl->value.dval = valuep;
|
||||
}
|
||||
for (--i; i >= 0; i--) {
|
||||
vl = &newvlist[i];
|
||||
vl->key = ob->instance.props[i].key;
|
||||
vl->type = ob->instance.props[i].type;
|
||||
vl->value = ob->instance.props[i].value;
|
||||
}
|
||||
FREE(ob->instance.props);
|
||||
ob->instance.props = newvlist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Create a new "area" or "perimeter" property in all */
|
||||
/* instances of a given device, based on the specified */
|
||||
/* names for the width and length parameters. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
void
|
||||
DeriveProperty(struct nlist *tc, int fnum, char *pwidth, char *plength,
|
||||
enum DerivedType type)
|
||||
{
|
||||
DerivedPropData dpd;
|
||||
|
||||
dpd.pwidth = pwidth;
|
||||
dpd.plength = plength;
|
||||
dpd.fnum = fnum;
|
||||
dpd.cell = tc;
|
||||
dpd.type = type;
|
||||
|
||||
/* Create the new derived property in the cell. */
|
||||
if (type == area_type)
|
||||
PropertyDouble(tc->name, fnum, "area", 0.01, 0.0);
|
||||
else if (type == perimeter_type)
|
||||
PropertyDouble(tc->name, fnum, "perimeter", 0.01, 0.0);
|
||||
else
|
||||
return;
|
||||
|
||||
/* Find all instances of the cell and add the derived property */
|
||||
RecurseCellHashTable2(derivedprops, (void *)(&dpd));
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Create a new "area" property in all instances of a */
|
||||
/* given device, based on the specified width and */
|
||||
/* length parameter names. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
void
|
||||
DeriveAreaProperty(struct nlist *tp, int fnum, char *pwidth, char *plength)
|
||||
{
|
||||
DeriveProperty(tp, fnum, pwidth, plength, area_type);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Create a new "perimeter" property in all instances */
|
||||
/* of a given device, based on the specified width and */
|
||||
/* length parameter names. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
void
|
||||
DerivePerimeterProperty(struct nlist *tp, int fnum, char *pwidth, char *plength)
|
||||
{
|
||||
DeriveProperty(tp, fnum, pwidth, plength, perimeter_type);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Flatten the two cells at the top of the compare */
|
||||
/* queue. */
|
||||
|
||||
+3
-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);
|
||||
|
||||
@@ -70,6 +70,8 @@ extern int remove_group_tags(struct objlist *ob);
|
||||
#ifdef TCL_NETGEN
|
||||
extern int EquivalentNode();
|
||||
extern int EquivalentElement();
|
||||
extern void DeriveAreaProperty();
|
||||
extern void DerivePerimeterProperty();
|
||||
|
||||
extern void enable_interrupt();
|
||||
extern void disable_interrupt();
|
||||
|
||||
+20
-4
@@ -302,7 +302,7 @@ int GetNextLineNoNewline(char *delimiter)
|
||||
{
|
||||
char *newbuf;
|
||||
int testc;
|
||||
int nested = 0;
|
||||
static int nested = 0;
|
||||
int llen;
|
||||
|
||||
if (feof(infile)) return -1;
|
||||
@@ -329,6 +329,11 @@ int GetNextLineNoNewline(char *delimiter)
|
||||
llen = strlen(line);
|
||||
}
|
||||
while (llen == linesize - 1) {
|
||||
/* Note that in the rare case where a newline is in the last buffer
|
||||
* position, we're done.
|
||||
*/
|
||||
if (*(line + llen - 1) == '\n') break;
|
||||
|
||||
newbuf = (char *)MALLOC(linesize + 501);
|
||||
strcpy(newbuf, line);
|
||||
FREE(line);
|
||||
@@ -599,7 +604,7 @@ void SpiceTokNoNewline(void)
|
||||
{
|
||||
int contline;
|
||||
|
||||
if ((nexttok = strdtok(NULL, WHITESPACE_DELIMITER, NULL)) != NULL) return;
|
||||
if ((nexttok = strdtok0(NULL, WHITESPACE_DELIMITER, NULL, FALSE)) != NULL) return;
|
||||
|
||||
while (nexttok == NULL) {
|
||||
contline = getc(infile);
|
||||
@@ -701,7 +706,7 @@ void SpiceSkipNewLine(void)
|
||||
/* the boundary between two-character and one-character delimiters. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
char *strdtok(char *pstring, char *delim1, char *delim2)
|
||||
char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog)
|
||||
{
|
||||
static char *stoken = NULL;
|
||||
static char *sstring = NULL;
|
||||
@@ -746,7 +751,7 @@ char *strdtok(char *pstring, char *delim1, char *delim2)
|
||||
/* should know whether it is parsing SPICE or verilog and handle the syntax */
|
||||
/* accordingly (needs to be done). */
|
||||
|
||||
if (*s == '\\') {
|
||||
if (isverilog && (*s == '\\')) {
|
||||
s++;
|
||||
while (*s != '\0') {
|
||||
if ((*s == ' ') || ((*s == '\\') && (*(s + 1) == '\0'))) {
|
||||
@@ -817,6 +822,17 @@ char *strdtok(char *pstring, char *delim1, char *delim2)
|
||||
return sstring;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* strdtok() is the original string tokenizer. It calls strdtok0() */
|
||||
/* with isverilog=TRUE, so that tokens are parsed as (potentially) */
|
||||
/* verilog names, which includes verilog backslash notation. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
char *strdtok(char *pstring, char *delim1, char *delim2)
|
||||
{
|
||||
return strdtok0(pstring, delim1, delim2, TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void InputParseError(FILE *f)
|
||||
|
||||
@@ -36,6 +36,7 @@ extern struct hashdict *definitions;
|
||||
|
||||
extern char *nexttok;
|
||||
#define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a))
|
||||
extern char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog);
|
||||
extern char *strdtok(char *pstring, char *delim1, char *delim2);
|
||||
extern char *GetLineAtTok();
|
||||
extern void SkipTok(char *delimiter);
|
||||
|
||||
+4
-1
@@ -2248,7 +2248,10 @@ int PromoteProperty(struct property *prop, struct valuelist *vl,
|
||||
if (prop == NULL || vl == NULL) return -1;
|
||||
if (prop->type == vl->type) return 1; /* Nothing to do */
|
||||
result = 0;
|
||||
if (prop->type == PROP_EXPRESSION) {
|
||||
/* If vl is an expression but prop is not, then try to reduce
|
||||
* the expression in vl.
|
||||
*/
|
||||
if (vl->type == PROP_EXPRESSION) {
|
||||
ReduceOneExpression(vl, ob, tc, FALSE);
|
||||
}
|
||||
switch (prop->type) {
|
||||
|
||||
+11
-2
@@ -532,8 +532,14 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
|
||||
SkipTok(NULL); /* get the next token */
|
||||
if ((EndParseFile()) && (nexttok == NULL)) break;
|
||||
if (nexttok == NULL) break;
|
||||
|
||||
if (nexttok[0] == '*') SkipNewLine(NULL);
|
||||
/* Handle comment lines. Note that some variants of CDL format
|
||||
* use "*." for information that is transparent to SPICE simulators.
|
||||
* Handle "*.GLOBAL" entries. All others are ignored.
|
||||
*/
|
||||
if ((nexttok[0] == '*') && (!matchnocase(nexttok, "*.GLOBAL")))
|
||||
SkipNewLine(NULL);
|
||||
|
||||
else if (matchnocase(nexttok, ".SUBCKT")) {
|
||||
SpiceTokNoNewline();
|
||||
@@ -821,7 +827,10 @@ skip_ends:
|
||||
|
||||
// Handle some commonly-used cards
|
||||
|
||||
else if (matchnocase(nexttok, ".GLOBAL")) {
|
||||
/* .GLOBAL and *.GLOBAL. Note that *.GLOBAL is excepted from comment-line
|
||||
* handling, above, so any line starting with '*' is "*.GLOBAL".
|
||||
*/
|
||||
else if (matchnocase(nexttok, ".GLOBAL") || (nexttok[0] == '*')) {
|
||||
while (nexttok != NULL) {
|
||||
int numnodes = 0;
|
||||
SpiceTokNoNewline();
|
||||
|
||||
+24
-9
@@ -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';
|
||||
@@ -2601,13 +2614,15 @@ nextinst:
|
||||
if (scan == NULL) {
|
||||
char localnet[MAX_STR_LEN];
|
||||
|
||||
/* Assume an implicit unconnected pin */
|
||||
sprintf(localnet, "_noconnect_%d_", localcount++);
|
||||
Node(localnet);
|
||||
join(localnet, obptr->name);
|
||||
Fprintf(stdout,
|
||||
/* Assume an implicit unconnected pin, unless there are no pins */
|
||||
if (strcmp(obpinname, "(no pins)")) {
|
||||
sprintf(localnet, "_noconnect_%d_", localcount++);
|
||||
Node(localnet);
|
||||
join(localnet, obptr->name);
|
||||
Fprintf(stdout,
|
||||
"Note: Implicit pin %s in instance %s of %s in cell %s\n",
|
||||
obpinname, locinst, modulename, CurrentCell->name);
|
||||
}
|
||||
}
|
||||
else if (GetBus(scan->net, &wb) == 0) {
|
||||
char *bptr2;
|
||||
|
||||
@@ -477,6 +477,18 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
set cell2 [lindex $clist2 $cidx]
|
||||
}
|
||||
|
||||
# The "noflat" list is non-file-specific, so run on each file.
|
||||
foreach cell $noflat {
|
||||
set cidx [lsearch -regexp $clist1 ^$cell$]
|
||||
if {$cidx >= 0} {
|
||||
netgen::flatten prohibit "$fnum1 $cell"
|
||||
}
|
||||
set cidx [lsearch -regexp $clist2 ^$cell$]
|
||||
if {$cidx >= 0} {
|
||||
netgen::flatten prohibit "$fnum2 $cell"
|
||||
}
|
||||
}
|
||||
|
||||
netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2"
|
||||
|
||||
if {$setupfile == ""} {
|
||||
@@ -594,6 +606,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
lappend properr [lindex $endval 0]
|
||||
} elseif {$uresult == -2} { ;# unmatched pins
|
||||
set doCheckFlatten 1
|
||||
} elseif {$uresult == -4} { ;# unmatched pins and properties
|
||||
lappend properr [lindex $endval 0]
|
||||
set doCheckFlatten 1
|
||||
}
|
||||
} else {
|
||||
# not equivalent
|
||||
@@ -655,6 +670,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} {
|
||||
|
||||
+187
-129
@@ -47,10 +47,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* Tcl 8.4 compatibility */
|
||||
/*-----------------------*/
|
||||
|
||||
#ifndef CONST84
|
||||
#define CONST84
|
||||
#endif
|
||||
|
||||
Tcl_Interp *netgeninterp;
|
||||
Tcl_Interp *consoleinterp;
|
||||
int ColumnBase = 0;
|
||||
@@ -60,47 +56,47 @@ extern int PropertyErrorDetected;
|
||||
|
||||
/* Function prototypes for all Tcl command callbacks */
|
||||
|
||||
int _netgen_readnet(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_readlib(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_canonical(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_writenet(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_flatten(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_nodes(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_elements(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_debug(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_protochip(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_instances(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_contents(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_describe(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_cells(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_ports(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_model(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_leaves(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_quit(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_reinit(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_log(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_readnet(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_readlib(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_canonical(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_writenet(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_flatten(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_nodes(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_elements(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_debug(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_protochip(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_instances(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_contents(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_describe(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_cells(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_ports(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_model(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_leaves(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_quit(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_reinit(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netgen_log(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
#ifdef HAVE_MALLINFO
|
||||
int _netgen_printmem(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_printmem(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
#endif
|
||||
int _netgen_help(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_matching(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_compare(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_iterate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_summary(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_print(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_format(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_run(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_verify(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_automorphs(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_equate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||
int _netgen_help(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_matching(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_compare(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_iterate(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_summary(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_print(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_format(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_run(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_verify(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_automorphs(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_equate(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
|
||||
|
||||
typedef struct _Cmd {
|
||||
char *name;
|
||||
@@ -399,7 +395,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
|
||||
Tcl_ResetResult(interp);
|
||||
|
||||
/* Is 1st argument a special keyword? */
|
||||
if (Tcl_GetIndexFromObj(interp, tobj, (CONST84 char **)suboptions,
|
||||
if (Tcl_GetIndexFromObj(interp, tobj, (const char **)suboptions,
|
||||
"special", 0, &index) == TCL_OK) {
|
||||
switch (index) {
|
||||
case CIRCUIT1_IDX:
|
||||
@@ -455,7 +451,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
|
||||
|
||||
/* Check if 2nd item is a reserved keyword */
|
||||
if (Tcl_GetIndexFromObj(interp, fobj,
|
||||
(CONST84 char **)suboptions,
|
||||
(const char **)suboptions,
|
||||
"special", 0, &index) == TCL_OK) {
|
||||
switch (index) {
|
||||
case CIRCUIT1_IDX:
|
||||
@@ -580,7 +576,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
|
||||
} else {
|
||||
/* Only one name given; check if it matches subOption */
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv, (CONST84 char **)suboptions,
|
||||
if (Tcl_GetIndexFromObj(interp, objv, (const char **)suboptions,
|
||||
"special", 0, &index) == TCL_OK) {
|
||||
|
||||
switch (index) {
|
||||
@@ -665,7 +661,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
|
||||
|
||||
int
|
||||
_netgen_canonical(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
int result;
|
||||
struct nlist *np;
|
||||
@@ -704,7 +700,7 @@ _netgen_canonical(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_readnet(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *formats[] = {
|
||||
"automatic", "ext", "extflat", "sim", "prm", "ntk", "spice",
|
||||
@@ -741,7 +737,7 @@ _netgen_readnet(ClientData clientData,
|
||||
return TCL_ERROR;
|
||||
}
|
||||
else if (objc > 1) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats,
|
||||
"format", 0, &index) != TCL_OK) {
|
||||
if (objc == 3)
|
||||
|
||||
@@ -850,7 +846,7 @@ _netgen_readnet(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_readlib(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *formats[] = {
|
||||
"actel", "spice", "xilinx", NULL
|
||||
@@ -883,7 +879,7 @@ _netgen_readlib(ClientData clientData,
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "format [file]");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats,
|
||||
"format", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -930,7 +926,7 @@ _netgen_readlib(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_writenet(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *formats[] = {
|
||||
"ext", "sim", "ntk", "actel",
|
||||
@@ -949,7 +945,7 @@ _netgen_writenet(ClientData clientData,
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "format file");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats,
|
||||
"format", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1017,11 +1013,11 @@ _netgen_writenet(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_flatten(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *repstr, *file;
|
||||
int result, llen, filenum;
|
||||
struct nlist *tp, *tp2;
|
||||
struct nlist *tp, *tp2, *tptop;
|
||||
|
||||
if ((objc < 2) || (objc > 4)) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?class? valid_cellname");
|
||||
@@ -1035,7 +1031,7 @@ _netgen_flatten(ClientData clientData,
|
||||
if (objc >= 3) {
|
||||
char *argv = Tcl_GetString(objv[1]);
|
||||
if (!strcmp(argv, "class")) {
|
||||
tp = GetTopCell(filenum);
|
||||
tptop = GetTopCell(filenum);
|
||||
|
||||
if (objc == 4) {
|
||||
int numflat;
|
||||
@@ -1046,7 +1042,7 @@ _netgen_flatten(ClientData clientData,
|
||||
}
|
||||
else {
|
||||
Printf("Flattening instances of %s in cell %s within file %s\n",
|
||||
repstr, tp2->name, tp->name);
|
||||
repstr, tp2->name, tptop->name);
|
||||
numflat = flattenInstancesOf(tp2->name, filenum, repstr);
|
||||
if (numflat == 0) {
|
||||
Tcl_SetResult(interp, "No instances found to flatten.", NULL);
|
||||
@@ -1055,15 +1051,19 @@ _netgen_flatten(ClientData clientData,
|
||||
}
|
||||
}
|
||||
else {
|
||||
Printf("Flattening instances of %s in file %s\n", repstr, tp->name);
|
||||
Printf("Flattening instances of %s in file %s\n", repstr, tptop->name);
|
||||
FlattenInstancesOf(repstr, filenum);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv, "prohibit") || !strcmp(argv, "deny")) {
|
||||
tp = GetTopCell(filenum);
|
||||
Printf("Will not flatten instances of %s in file %s\n", repstr, tp->name);
|
||||
/* Mark cell as placeholder so it will not be flattened */
|
||||
tp->flags |= CELL_PLACEHOLDER;
|
||||
tptop = GetTopCell(filenum);
|
||||
if (tp == NULL)
|
||||
Printf("Error: Cell %s does not exist.\n", repstr);
|
||||
else {
|
||||
Printf("Will not flatten instances of %s in file %s\n", repstr, tptop->name);
|
||||
/* Mark cell as placeholder so it will not be flattened */
|
||||
tp->flags |= CELL_PLACEHOLDER;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "class valid_cellname");
|
||||
@@ -1087,7 +1087,7 @@ _netgen_flatten(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_nodes(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *estr = NULL, *istr = NULL, *cstr, *fstr;
|
||||
char *optstart;
|
||||
@@ -1205,7 +1205,7 @@ _netgen_nodes(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_elements(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *nstr = NULL, *cstr;
|
||||
struct objlist * (*ListSave)();
|
||||
@@ -1300,7 +1300,7 @@ _netgen_elements(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_debug(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *yesno[] = {
|
||||
"on", "off", NULL
|
||||
@@ -1314,7 +1314,7 @@ _netgen_debug(ClientData clientData,
|
||||
if (objc == 1)
|
||||
index = YES_IDX;
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
index = CMD_IDX;
|
||||
}
|
||||
@@ -1349,7 +1349,7 @@ _netgen_debug(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_protochip(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
|
||||
@@ -1369,7 +1369,7 @@ _netgen_protochip(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_instances(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *repstr;
|
||||
int result;
|
||||
@@ -1399,7 +1399,7 @@ _netgen_instances(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_contents(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *repstr;
|
||||
int result;
|
||||
@@ -1428,7 +1428,7 @@ _netgen_contents(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_describe(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *repstr;
|
||||
int file = -1;
|
||||
@@ -1458,7 +1458,7 @@ _netgen_describe(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_cells(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *repstr, *filename = NULL;
|
||||
char *optstart;
|
||||
@@ -1545,7 +1545,7 @@ _netgen_cells(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_model(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
struct nlist *tp, *tp2;
|
||||
char *model, *retclass;
|
||||
@@ -1597,7 +1597,7 @@ _netgen_model(ClientData clientData,
|
||||
if (objc == 3) {
|
||||
nports = NumberOfPorts(tp->name, fnum);
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)modelclasses,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)modelclasses,
|
||||
"class", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1767,7 +1767,7 @@ wrongNumPorts:
|
||||
|
||||
int
|
||||
_netgen_ports(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *repstr;
|
||||
int result;
|
||||
@@ -1797,7 +1797,7 @@ _netgen_ports(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_leaves(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *repstr;
|
||||
int result;
|
||||
@@ -1833,7 +1833,7 @@ _netgen_leaves(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_quit(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
|
||||
@@ -1861,7 +1861,7 @@ _netgen_quit(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_reinit(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
|
||||
@@ -1881,7 +1881,7 @@ _netgen_reinit(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_log(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *yesno[] = {
|
||||
"start", "end", "reset", "suspend", "resume", "file", "echo", "put", NULL
|
||||
@@ -1898,7 +1898,7 @@ _netgen_log(ClientData clientData,
|
||||
index = (LoggingFile) ? RESUME_IDX : START_IDX;
|
||||
}
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2025,7 +2025,7 @@ _netgen_log(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_printmem(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
|
||||
@@ -2047,7 +2047,7 @@ _netgen_printmem(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_format(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
int col1_width = 41, col2_width = 41;
|
||||
|
||||
@@ -2108,7 +2108,7 @@ _netcmp_format(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_compare(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *name1, *name2, *file1, *file2, *optstart;
|
||||
int fnum1, fnum2, dolist = 0;
|
||||
@@ -2285,7 +2285,7 @@ _netcmp_compare(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_iterate(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
|
||||
@@ -2309,7 +2309,7 @@ _netcmp_iterate(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_summary(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"nodes", "elements", NULL
|
||||
@@ -2324,7 +2324,7 @@ _netcmp_summary(ClientData clientData,
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 2) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2350,7 +2350,7 @@ _netcmp_summary(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_print(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"nodes", "elements", "queue", NULL
|
||||
@@ -2388,16 +2388,16 @@ _netcmp_print(ClientData clientData,
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc >= 2) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
if ((objc == 2) && (Tcl_GetIndexFromObj(interp, objv[1],
|
||||
(CONST84 char **)classes, "class", 0, &class) != TCL_OK)) {
|
||||
(const char **)classes, "class", 0, &class) != TCL_OK)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (objc == 3 && index != QUEUE_IDX) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)classes,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)classes,
|
||||
"class", 0, &class) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2441,7 +2441,7 @@ _netcmp_print(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_run(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"converge", "resolve", NULL
|
||||
@@ -2468,7 +2468,7 @@ _netcmp_run(ClientData clientData,
|
||||
if (objc == 1)
|
||||
index = RESOLVE_IDX;
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -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
|
||||
@@ -2566,6 +2572,7 @@ _netcmp_run(ClientData clientData,
|
||||
/* 0: not verified */
|
||||
/* -1: no elements or nodes */
|
||||
/* -3: verified with property error */
|
||||
/* -4: verified with property and port errors */
|
||||
/* equiv option */
|
||||
/* -2: pin mismatch */
|
||||
/* */
|
||||
@@ -2578,7 +2585,7 @@ _netcmp_run(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_verify(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"nodes", "elements", "properties", "only", "all", "equivalent", "unique", NULL
|
||||
@@ -2610,7 +2617,7 @@ _netcmp_verify(ClientData clientData,
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 2) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2667,8 +2674,12 @@ _netcmp_verify(ClientData clientData,
|
||||
else if (automorphisms == -2) {
|
||||
if (index == EQUIV_IDX)
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
|
||||
else if (index == UNIQUE_IDX)
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-2));
|
||||
else if (index == UNIQUE_IDX) {
|
||||
if (PropertyErrorDetected == 0)
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-2));
|
||||
else
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-4));
|
||||
}
|
||||
else if (index > 0)
|
||||
Fprintf(stdout, "Circuits match uniquely with port errors.\n");
|
||||
}
|
||||
@@ -2763,7 +2774,7 @@ _netcmp_verify(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_automorphs(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
|
||||
@@ -2784,7 +2795,7 @@ _netcmp_automorphs(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_convert(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *cellname;
|
||||
int filenum = -1;
|
||||
@@ -2814,7 +2825,7 @@ _netcmp_convert(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_global(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *filename, *cellname, *pattern;
|
||||
int numchanged = 0, p, fnum, llen, result;
|
||||
@@ -2851,7 +2862,7 @@ _netcmp_global(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_ignore(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"class", "shorted", NULL
|
||||
@@ -2865,7 +2876,7 @@ _netcmp_ignore(ClientData clientData,
|
||||
char *name = NULL, *name2 = NULL;
|
||||
|
||||
if (objc >= 3) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
|
||||
"option", 0, &index) == TCL_OK) {
|
||||
objc--;
|
||||
objv++;
|
||||
@@ -2899,7 +2910,7 @@ _netcmp_ignore(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_equate(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"nodes", "elements", "classes", "pins", NULL
|
||||
@@ -2944,7 +2955,7 @@ _netcmp_equate(ClientData clientData,
|
||||
return TCL_ERROR;
|
||||
}
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -3413,7 +3424,7 @@ _netcmp_equate(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_property(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
int fnum, i, llen;
|
||||
struct nlist *tp;
|
||||
@@ -3422,13 +3433,21 @@ _netcmp_property(ClientData clientData,
|
||||
double dval;
|
||||
int ival, argstart;
|
||||
|
||||
char *topoptions[] = {
|
||||
"default", "series", "serial", "parallel", "topology", NULL
|
||||
};
|
||||
enum TopOptionIdx {
|
||||
TOP_DEFAULT_IDX, TOP_SERIES_IDX, TOP_SERIAL_IDX, TOP_PARALLEL_IDX,
|
||||
TOP_TOPOLOGY_IDX
|
||||
};
|
||||
|
||||
char *options[] = {
|
||||
"add", "create", "remove", "delete", "tolerance", "merge", "serial",
|
||||
"series", "parallel", "associate", "topology", NULL
|
||||
"series", "parallel", "associate", "derive", NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX,
|
||||
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX, ASSOCIATE_IDX, TOPOLOGY_IDX
|
||||
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX, ASSOCIATE_IDX, DERIVE_IDX
|
||||
};
|
||||
int result, index, idx2;
|
||||
|
||||
@@ -3463,6 +3482,14 @@ _netcmp_property(ClientData clientData,
|
||||
COMB_NONE_IDX, COMB_PAR_IDX, COMB_ADD_IDX, COMB_CRITICAL_IDX
|
||||
};
|
||||
|
||||
char *deriveoptions[] = {
|
||||
"area", "perimeter", NULL
|
||||
};
|
||||
|
||||
enum DeriveOptionIdx {
|
||||
AREA_IDX, PERIMETER_IDX
|
||||
};
|
||||
|
||||
char *yesno[] = {
|
||||
"on", "yes", "true", "enable", "allow",
|
||||
"off", "no", "false", "disable", "prohibit", NULL
|
||||
@@ -3477,8 +3504,13 @@ _netcmp_property(ClientData clientData,
|
||||
"strict", "relaxed", NULL
|
||||
};
|
||||
|
||||
/* Don't need to check return value */
|
||||
index = -1;
|
||||
Tcl_GetIndexFromObj(interp, objv[1], (const char **)topoptions,
|
||||
"option", 0, &index);
|
||||
|
||||
/* Check for special command "property default" */
|
||||
if ((objc == 2) && (!strcmp(Tcl_GetString(objv[1]), "default"))) {
|
||||
if ((objc == 2) && (index == TOP_DEFAULT_IDX)) {
|
||||
|
||||
/* For each FET device, do "merge {w add_critical}" and */
|
||||
/* "remove as ad ps pd". This allows parallel devices */
|
||||
@@ -3525,7 +3557,7 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if ((objc == 3) && (!strcmp(Tcl_GetString(objv[1]), "parallel"))) {
|
||||
else if ((objc == 3) && (index == TOP_PARALLEL_IDX)) {
|
||||
if (!strcmp(Tcl_GetString(objv[2]), "none")) {
|
||||
GlobalParallelNone = TRUE;
|
||||
SetParallelCombine(FALSE);
|
||||
@@ -3547,8 +3579,7 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if ((objc == 3) && ((!strcmp(Tcl_GetString(objv[1]), "series")) ||
|
||||
(!strcmp(Tcl_GetString(objv[1]), "serial")))) {
|
||||
else if ((objc == 3) && ((index == TOP_SERIES_IDX) || (index == TOP_SERIAL_IDX))) {
|
||||
if (!strcmp(Tcl_GetString(objv[2]), "none")) {
|
||||
SetSeriesCombine(FALSE);
|
||||
}
|
||||
@@ -3562,7 +3593,7 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if ((objc > 1) && (!strcmp(Tcl_GetString(objv[1]), "topology"))) {
|
||||
else if ((objc > 1) && (index == TOP_TOPOLOGY_IDX)) {
|
||||
if (objc == 2) {
|
||||
if (ExactTopology)
|
||||
Tcl_SetResult(interp, "Strict topology property matching.",
|
||||
@@ -3573,7 +3604,7 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
else if (objc == 3) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2],
|
||||
(CONST84 char **)topo,
|
||||
(const char **)topo,
|
||||
"topology", 0, &idx2) == TCL_OK) {
|
||||
if (idx2 == 0)
|
||||
ExactTopology = TRUE;
|
||||
@@ -3632,7 +3663,7 @@ _netcmp_property(ClientData clientData,
|
||||
Tcl_SetObjResult(interp, tobj1);
|
||||
}
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)options,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)options,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
index = ADD_IDX;
|
||||
argstart = 2;
|
||||
@@ -3665,7 +3696,7 @@ _netcmp_property(ClientData clientData,
|
||||
// Each value must be a list of two, or a yes/no answer.
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i],
|
||||
(CONST84 char **)yesno,
|
||||
(const char **)yesno,
|
||||
"combine", 0, &idx2) == TCL_OK) {
|
||||
if (idx2 <= 4) { /* true, enable, etc. */
|
||||
if (index == SERIAL_IDX || index == SERIES_IDX)
|
||||
@@ -3697,7 +3728,7 @@ _netcmp_property(ClientData clientData,
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
result = Tcl_GetIndexFromObj(interp, tobj2,
|
||||
(CONST84 char **)combineoptions,
|
||||
(const char **)combineoptions,
|
||||
"combine_type", 0, &idx2);
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
@@ -3782,7 +3813,7 @@ _netcmp_property(ClientData clientData,
|
||||
/* {key, type} or {key, tolerance} duplet */
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, tobj2,
|
||||
(CONST84 char **)suboptions,
|
||||
(const char **)suboptions,
|
||||
"type", 0, &idx2) != TCL_OK) {
|
||||
Tcl_ResetResult(interp);
|
||||
if (Tcl_GetDoubleFromObj(interp, tobj2, &dval)
|
||||
@@ -3826,7 +3857,7 @@ _netcmp_property(ClientData clientData,
|
||||
/* {key, type, tolerance} triplet */
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, tobj2,
|
||||
(CONST84 char **)suboptions,
|
||||
(const char **)suboptions,
|
||||
"type", 0, &idx2) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
|
||||
@@ -3969,7 +4000,7 @@ _netcmp_property(ClientData clientData,
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
result = Tcl_GetIndexFromObj(interp, tobj2,
|
||||
(CONST84 char **)mergeoptions,
|
||||
(const char **)mergeoptions,
|
||||
"merge_type", 0, &idx2);
|
||||
if (result != TCL_OK) return result;
|
||||
|
||||
@@ -4008,6 +4039,32 @@ _netcmp_property(ClientData clientData,
|
||||
}
|
||||
break;
|
||||
|
||||
case DERIVE_IDX:
|
||||
/* Create a derived property. For now, this just creates
|
||||
* "area" or "perimeter" properties. There may not (?)
|
||||
* be enough cause to make other ones. Unlike other
|
||||
* "property" options, this option causes the whole circuit
|
||||
* database to be searched for the device in question, and
|
||||
* the new property is added.
|
||||
*/
|
||||
if (objc < 6) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "{area|perimeter width length}");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
result = Tcl_GetIndexFromObj(interp, objv[3],
|
||||
(const char **)deriveoptions,
|
||||
"area|perimeter", 0, &idx2);
|
||||
if (result != TCL_OK) return result;
|
||||
switch (idx2) {
|
||||
case AREA_IDX:
|
||||
DeriveAreaProperty(tp, fnum, Tcl_GetString(objv[4]),
|
||||
Tcl_GetString(objv[5]));
|
||||
break;
|
||||
case PERIMETER_IDX:
|
||||
DerivePerimeterProperty(tp, fnum, Tcl_GetString(objv[4]),
|
||||
Tcl_GetString(objv[5]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -4027,7 +4084,7 @@ _netcmp_property(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_permute(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *model, *pin1, *pin2;
|
||||
char *permuteclass[] = {
|
||||
@@ -4048,7 +4105,7 @@ _netcmp_permute(ClientData clientData,
|
||||
index = DEFLT_IDX;
|
||||
}
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)permuteclass,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)permuteclass,
|
||||
"permute class", 0, &index) != TCL_OK) {
|
||||
if (objc != 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?valid_cellname pin1 pin2?");
|
||||
@@ -4168,7 +4225,7 @@ _netcmp_permute(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_symmetry(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
Printf("Symmetry breaking method has been deprecated.\n");
|
||||
return TCL_OK;
|
||||
@@ -4184,7 +4241,7 @@ _netcmp_symmetry(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_exhaustive(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *yesno[] = {
|
||||
"on", "off", NULL
|
||||
@@ -4197,7 +4254,7 @@ _netcmp_exhaustive(ClientData clientData,
|
||||
if (objc == 1)
|
||||
index = -1;
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno,
|
||||
"option", 0, &index) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -4226,7 +4283,7 @@ _netcmp_exhaustive(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_restart(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
if (objc != 1) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
|
||||
@@ -4246,7 +4303,7 @@ _netcmp_restart(ClientData clientData,
|
||||
|
||||
int
|
||||
_netgen_help(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
int n;
|
||||
|
||||
@@ -4277,7 +4334,7 @@ _netgen_help(ClientData clientData,
|
||||
|
||||
int
|
||||
_netcmp_matching(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"nodes", "elements", NULL
|
||||
@@ -4299,7 +4356,7 @@ _netcmp_matching(ClientData clientData,
|
||||
name = Tcl_GetString(objv[1]);
|
||||
}
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
|
||||
"option", 0, &index) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -4465,7 +4522,7 @@ char *Tcl_Strdup(const char *s)
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
int _tkcon_interrupt(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
InterruptPending = 1;
|
||||
return TCL_OK;
|
||||
@@ -4513,7 +4570,8 @@ int Tclnetgen_Init(Tcl_Interp *interp)
|
||||
}
|
||||
for (n = 0; netcmp_cmds[n].name != NULL; n++) {
|
||||
sprintf(keyword, "netgen::%s", netcmp_cmds[n].name);
|
||||
Tcl_CreateObjCommand(interp, keyword, netcmp_cmds[n].handler,
|
||||
Tcl_CreateObjCommand(interp, keyword,
|
||||
(Tcl_ObjCmdProc *)netcmp_cmds[n].handler,
|
||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
||||
}
|
||||
|
||||
|
||||
+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