mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 14:07:07 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
577dfb5a28 | ||
|
|
46252ad6b9 | ||
|
|
564fab9667 | ||
|
|
0df4190e19 | ||
|
|
2f661ea256 | ||
|
|
fca075e1ed | ||
|
|
cc2a5e0ee6 | ||
|
|
b7a8d3cfda | ||
|
|
0205902baa | ||
|
|
646b351ee5 | ||
|
|
31a0f10602 | ||
|
|
a2b1f5c85f | ||
|
|
9148edde69 | ||
|
|
bb07a84ae1 | ||
|
|
d753e2c208 | ||
|
|
bd3b88de4a | ||
|
|
668aa38340 |
@@ -20,7 +20,6 @@ int MaxCPUTime = 100; /* max number of seconds to burn */
|
||||
#define MAX_CHANGES_PER_ITER 2
|
||||
|
||||
#if 0
|
||||
/* INLINE */
|
||||
float RandomUniform(void)
|
||||
{
|
||||
/* DANGER! DANGER! Non-portable code below!! */
|
||||
|
||||
@@ -36,7 +36,6 @@ int CountFanoutOK;
|
||||
int CountSwallowedElements;
|
||||
|
||||
|
||||
INLINE
|
||||
int Independent(int E1, int E2)
|
||||
/* return 1 if E1 and E2 share no leaves in common */
|
||||
{
|
||||
@@ -47,7 +46,6 @@ int Independent(int E1, int E2)
|
||||
return(1);
|
||||
}
|
||||
|
||||
INLINE
|
||||
int FanoutOK(int E1, int E2)
|
||||
{
|
||||
int approxfanout;
|
||||
@@ -67,7 +65,6 @@ int FanoutOK(int E1, int E2)
|
||||
}
|
||||
|
||||
|
||||
INLINE
|
||||
int Swallowed(int Parent, int Child)
|
||||
/* returns 1 if Child's fanout is contained in Parent's */
|
||||
{
|
||||
@@ -107,7 +104,6 @@ int SmallEnough(int E1, int E2)
|
||||
}
|
||||
#endif
|
||||
|
||||
INLINE
|
||||
int SuccessfulEmbedding(int E)
|
||||
/* returns 1 if element E is a successful embedding */
|
||||
{
|
||||
|
||||
@@ -117,15 +117,6 @@
|
||||
#define memzero(ptr, len) memset(ptr, 0, len)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef INLINE
|
||||
#ifdef __GNUC__
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif /* __GNUC__ */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYSV_STRING
|
||||
#undef NEED_STRING
|
||||
#endif
|
||||
|
||||
@@ -348,7 +348,6 @@ void PRINTPACKED(unsigned long *mstar)
|
||||
#ifdef IBMPC
|
||||
static unsigned int lochash(unsigned long *mstar)
|
||||
#else
|
||||
INLINE
|
||||
static unsigned long lochash(unsigned long *mstar)
|
||||
#endif
|
||||
{
|
||||
@@ -432,7 +431,6 @@ static struct ex_entry *hashinstall(unsigned long *mstar)
|
||||
return(ex_tab[hashval] = np);
|
||||
}
|
||||
|
||||
/* INLINE */
|
||||
int Exists(int E1, int E2)
|
||||
{
|
||||
int i;
|
||||
@@ -470,7 +468,6 @@ int InitializeExistTest(void)
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* INLINE */
|
||||
void AddToExistSet(int E1, int E2)
|
||||
{
|
||||
int i;
|
||||
|
||||
+232
-213
@@ -1411,7 +1411,6 @@ int ElementListAllocated;
|
||||
int NodeListAllocated;
|
||||
#endif
|
||||
|
||||
INLINE
|
||||
struct Element *GetElement(void)
|
||||
{
|
||||
struct Element *new_element;
|
||||
@@ -1429,14 +1428,12 @@ struct Element *GetElement(void)
|
||||
return(new_element);
|
||||
}
|
||||
|
||||
INLINE
|
||||
void FreeElement(struct Element *old)
|
||||
{
|
||||
old->next = ElementFreeList;
|
||||
ElementFreeList = old;
|
||||
}
|
||||
|
||||
INLINE
|
||||
struct Node *GetNode(void)
|
||||
{
|
||||
struct Node *new_node;
|
||||
@@ -1454,14 +1451,12 @@ struct Node *GetNode(void)
|
||||
return(new_node);
|
||||
}
|
||||
|
||||
INLINE
|
||||
void FreeNode(struct Node *old)
|
||||
{
|
||||
old->next = NodeFreeList;
|
||||
NodeFreeList = old;
|
||||
}
|
||||
|
||||
INLINE
|
||||
struct ElementClass *GetElementClass(void)
|
||||
{
|
||||
struct ElementClass *new_elementclass;
|
||||
@@ -1481,14 +1476,12 @@ struct ElementClass *GetElementClass(void)
|
||||
return(new_elementclass);
|
||||
}
|
||||
|
||||
INLINE
|
||||
void FreeElementClass(struct ElementClass *old)
|
||||
{
|
||||
old->next = ElementClassFreeList;
|
||||
ElementClassFreeList = old;
|
||||
}
|
||||
|
||||
INLINE
|
||||
struct NodeClass *GetNodeClass(void)
|
||||
{
|
||||
struct NodeClass *new_nodeclass;
|
||||
@@ -1508,14 +1501,12 @@ struct NodeClass *GetNodeClass(void)
|
||||
return(new_nodeclass);
|
||||
}
|
||||
|
||||
INLINE
|
||||
void FreeNodeClass(struct NodeClass *old)
|
||||
{
|
||||
old->next = NodeClassFreeList;
|
||||
NodeClassFreeList = old;
|
||||
}
|
||||
|
||||
INLINE
|
||||
struct ElementList *GetElementList(void)
|
||||
{
|
||||
struct ElementList *new_elementlist;
|
||||
@@ -1534,14 +1525,12 @@ struct ElementList *GetElementList(void)
|
||||
return(new_elementlist);
|
||||
}
|
||||
|
||||
INLINE
|
||||
void FreeElementList(struct ElementList *old)
|
||||
{
|
||||
old->next = ElementListFreeList;
|
||||
ElementListFreeList = old;
|
||||
}
|
||||
|
||||
INLINE
|
||||
struct NodeList *GetNodeList(void)
|
||||
{
|
||||
struct NodeList *new_nodelist;
|
||||
@@ -1559,7 +1548,6 @@ struct NodeList *GetNodeList(void)
|
||||
return(new_nodelist);
|
||||
}
|
||||
|
||||
INLINE
|
||||
void FreeNodeList(struct NodeList *old)
|
||||
{
|
||||
old->next = NodeListFreeList;
|
||||
@@ -1834,6 +1822,7 @@ void CreateLists(char *name, short graph)
|
||||
}
|
||||
|
||||
CombineParallel(name, graph);
|
||||
CombineSerial(name, graph);
|
||||
|
||||
Elements = CreateElementList(name, graph);
|
||||
Nodes = CreateNodeList(name, graph);
|
||||
@@ -1962,6 +1951,7 @@ void CreateLists(char *name, short graph)
|
||||
|
||||
ConnectAllNodes(name, graph);
|
||||
CombineParallel(name, graph);
|
||||
CombineSerial(name, graph);
|
||||
|
||||
E = CreateElementList(name, graph);
|
||||
N = CreateNodeList(name, graph);
|
||||
@@ -3337,18 +3327,11 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
vlist = (struct valuelist ***)CALLOC(pcount, sizeof(struct valuelist **));
|
||||
if (m_rec == NULL)
|
||||
vlist[0] = (struct valuelist **)CALLOC(icount, sizeof(struct valuelist *));
|
||||
pcount = 1;
|
||||
|
||||
while (ptop != NULL) {
|
||||
if (ptop->prop == m_rec) {
|
||||
plist[0] = m_rec;
|
||||
vlist[0] = (struct valuelist **)CALLOC(icount,
|
||||
plist[ptop->prop->idx] = ptop->prop;
|
||||
vlist[ptop->prop->idx] = (struct valuelist **)CALLOC(icount,
|
||||
sizeof(struct valuelist *));
|
||||
}
|
||||
else {
|
||||
plist[pcount] = ptop->prop;
|
||||
vlist[pcount++] = (struct valuelist **)CALLOC(icount,
|
||||
sizeof(struct valuelist *));
|
||||
}
|
||||
plink = ptop;
|
||||
FREE(ptop);
|
||||
ptop = plink->next;
|
||||
@@ -3377,6 +3360,17 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
i++;
|
||||
}
|
||||
|
||||
// Check for "M" records with type double and promote them to integer
|
||||
for (i = 0; i < icount; i++) {
|
||||
vl = vlist[0][i];
|
||||
if (vl != NULL) {
|
||||
if (vl->type == PROP_DOUBLE) {
|
||||
vl->type = PROP_INTEGER;
|
||||
vl->value.ival = (int)(vl->value.dval + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now combine records with same properties by summing M.
|
||||
for (i = 0; i < icount - 1; i++) {
|
||||
for (j = 1; j < icount; j++) {
|
||||
@@ -3482,13 +3476,13 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
vlist[0][j] = &nullvl; // Mark this position
|
||||
if (crit >= 0) {
|
||||
vl = vlist[crit][i];
|
||||
if (ctype == MERGE_ADD_CRIT) {
|
||||
if ((vl != NULL) && (ctype == MERGE_ADD_CRIT)) {
|
||||
if (vl->type == PROP_INTEGER)
|
||||
vl->value.ival += vlist[crit][j]->value.ival;
|
||||
else if (vl->type == PROP_DOUBLE)
|
||||
vl->value.dval += vlist[crit][j]->value.dval;
|
||||
}
|
||||
else { /* MERGE_PAR_CRIT */
|
||||
else if (vl != NULL) { /* MERGE_PAR_CRIT */
|
||||
if (vl->type == PROP_INTEGER) {
|
||||
double di = vl->value.ival;
|
||||
double dj = vlist[crit][j]->value.ival;
|
||||
@@ -3508,7 +3502,7 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
else if (vlist[0][i]->value.ival > 0) {
|
||||
if (crit >= 0) {
|
||||
vl = vlist[crit][i];
|
||||
if (ctype == MERGE_ADD_CRIT) {
|
||||
if ((vl != NULL) && (ctype == MERGE_ADD_CRIT)) {
|
||||
if (vl->type == PROP_INTEGER)
|
||||
vl->value.ival += vlist[0][j]->value.ival *
|
||||
vlist[crit][j]->value.ival;
|
||||
@@ -3516,7 +3510,7 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
vl->value.dval += (double)vlist[0][j]->value.ival *
|
||||
vlist[crit][j]->value.dval;
|
||||
}
|
||||
else { /* MERGE_PAR_CRIT */
|
||||
else if (vl != NULL) { /* MERGE_PAR_CRIT */
|
||||
if (vl->type == PROP_INTEGER) {
|
||||
double d = (double)vlist[crit][j]->value.ival /
|
||||
(double)vlist[0][j]->value.ival;
|
||||
@@ -3588,6 +3582,7 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
||||
int mismatches = 0, i, j;
|
||||
int vlstart, islop, t1type, t2type;
|
||||
int mult1, mult2, ival1, ival2;
|
||||
int rval = 1;
|
||||
double pd, dslop, dval1, dval2;
|
||||
|
||||
tc1 = LookupCellFile(ob1->model.class, Circuit1->file);
|
||||
@@ -3622,11 +3617,13 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
||||
if (t1type == PROPERTY) PropertyOptimize(tp1, tc1);
|
||||
if (t2type == PROPERTY) PropertyOptimize(tp2, tc2);
|
||||
|
||||
if (t1type != PROPERTY) {
|
||||
// t1 has no properties. See if t2's properties are required
|
||||
// to be checked. If so, flag t1 as missing required properties
|
||||
while(1) {
|
||||
if (t1type != PROPERTY) {
|
||||
// t1 has no properties. See if t2's properties are required
|
||||
// to be checked. If so, flag t2 instance as unmatched
|
||||
|
||||
for (i = 0;; i++) {
|
||||
mismatches++;
|
||||
for (i = 0;; i++) {
|
||||
vl2 = &(tp2->instance.props[i]);
|
||||
if (vl2->type == PROP_ENDLIST) break;
|
||||
if (vl2 == NULL) continue;
|
||||
@@ -3637,21 +3634,22 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
||||
if (vl2->type == PROP_INTEGER)
|
||||
mult2 = vl2->value.ival;
|
||||
}
|
||||
}
|
||||
if (vl2->type != PROP_ENDLIST) {
|
||||
if (do_print) Fprintf(stdout, "Circuit 2 %s instance %s missing"
|
||||
" required properties.\n",
|
||||
}
|
||||
if (vl2->type != PROP_ENDLIST) {
|
||||
if (do_print) Fprintf(stdout, "Circuit 2 %s instance %s has no"
|
||||
" property match in circuit 1.\n",
|
||||
Circuit2->name, ob2->instance.name);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else if (t2type != PROPERTY) {
|
||||
// t2 has no properties. See if t1's properties are required
|
||||
// to be checked. If so, flag t1 as missing required properties
|
||||
rval = -1;
|
||||
}
|
||||
else
|
||||
rval = 0;
|
||||
}
|
||||
else if (t2type != PROPERTY) {
|
||||
// t2 has no properties. See if t1's properties are required
|
||||
// to be checked. If so, flag t1 instance as unmatched
|
||||
|
||||
for (i = 0;; i++) {
|
||||
mismatches++;
|
||||
for (i = 0;; i++) {
|
||||
vl1 = &(tp1->instance.props[i]);
|
||||
if (vl1->type == PROP_ENDLIST) break;
|
||||
if (vl1 == NULL) continue;
|
||||
@@ -3662,184 +3660,201 @@ int PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print)
|
||||
if (vl1->type == PROP_INTEGER)
|
||||
mult1 = vl1->value.ival;
|
||||
}
|
||||
}
|
||||
if (vl1->type != PROP_ENDLIST) {
|
||||
if (do_print) Fprintf(stdout, "Circuit 1 %s instance %s missing"
|
||||
" required properties.\n",
|
||||
Circuit1->name, ob1->instance.name);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
vlstart = 0;
|
||||
for (i = 0;; i++) {
|
||||
vl1 = &(tp1->instance.props[i]);
|
||||
if (vl1->type == PROP_ENDLIST) break;
|
||||
if (vl1 == NULL) continue;
|
||||
if (vl1->key == NULL) continue;
|
||||
|
||||
/* Check if this is a "property of interest". */
|
||||
kl1 = (struct property *)HashLookup(vl1->key, &(tc1->propdict));
|
||||
if (kl1 == NULL) continue;
|
||||
|
||||
/* Find the matching property in vl2. With luck, they're in order. */
|
||||
|
||||
for (j = vlstart;; j++) {
|
||||
vl2 = &(tp2->instance.props[j]);
|
||||
if (vl2->type == PROP_ENDLIST) break;
|
||||
if ((*matchfunc)(vl1->key, vl2->key)) break;
|
||||
}
|
||||
if (vl2->type == PROP_ENDLIST) continue;
|
||||
if (j == vlstart) vlstart++;
|
||||
|
||||
if (vl2 == NULL) continue;
|
||||
if (vl2->key == NULL) continue;
|
||||
|
||||
/* Both device classes must agree on the properties to compare */
|
||||
kl2 = (struct property *)HashLookup(vl2->key, &(tc2->propdict));
|
||||
if (kl2 == NULL) continue;
|
||||
|
||||
/* Watch out for uninitialized entries in cell def */
|
||||
if (vl1->type == vl2->type) {
|
||||
if (kl1->type == PROP_STRING && kl1->pdefault.string == NULL)
|
||||
SetPropertyDefault(kl1, vl1);
|
||||
if (kl2->type == PROP_STRING && kl2->pdefault.string == NULL)
|
||||
SetPropertyDefault(kl2, vl2);
|
||||
}
|
||||
|
||||
if (vl1->type != vl2->type) {
|
||||
if (kl1->type != vl1->type) PromoteProperty(kl1, vl1);
|
||||
if (kl2->type != vl2->type) PromoteProperty(kl2, vl2);
|
||||
if (vl1->type != vl2->type) PromoteProperty(kl1, vl2);
|
||||
if (vl1->type != vl2->type) PromoteProperty(kl2, vl1);
|
||||
if (do_print && (vl1->type != vl2->type)) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
ob1->instance.name, ob2->instance.name);
|
||||
|
||||
Fprintf(stdout, " %s circuit1: ", kl1->key);
|
||||
switch (vl1->type) {
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
Fprintf(stdout, "%g", vl1->value.dval);
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
Fprintf(stdout, "%d", vl1->value.ival);
|
||||
break;
|
||||
case PROP_STRING:
|
||||
Fprintf(stdout, "\"%s\"", vl1->value.string);
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
Fprintf(stdout, "(unresolved expression)");
|
||||
break;
|
||||
}
|
||||
Fprintf(stdout, " ");
|
||||
switch (vl2->type) {
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
Fprintf(stdout, "%g", vl2->value.dval);
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
Fprintf(stdout, "%d", vl2->value.ival);
|
||||
break;
|
||||
case PROP_STRING:
|
||||
Fprintf(stdout, "\"%s\"", vl2->value.string);
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
Fprintf(stdout, "(unresolved expression)");
|
||||
break;
|
||||
}
|
||||
Fprintf(stdout, " (property type mismatch)\n");
|
||||
}
|
||||
if (vl1->type != vl2->type) mismatches++;
|
||||
if (vl1->type != PROP_ENDLIST) {
|
||||
if (do_print) Fprintf(stdout, "Circuit 1 %s instance %s has no"
|
||||
" property match in Circuit 2.\n",
|
||||
Circuit1->name, ob1->instance.name);
|
||||
rval = -1;
|
||||
}
|
||||
else
|
||||
rval = 0;
|
||||
}
|
||||
else switch (kl1->type) {
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
dval1 = vl1->value.dval;
|
||||
dval2 = vl2->value.dval;
|
||||
else {
|
||||
|
||||
dslop = MAX(kl1->slop.dval, kl2->slop.dval);
|
||||
pd = 2 * fabs(dval1 - dval2) / (dval1 + dval2);
|
||||
if (pd > dslop) {
|
||||
if (do_print) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
vlstart = 0;
|
||||
for (i = 0;; i++) {
|
||||
vl1 = &(tp1->instance.props[i]);
|
||||
if (vl1->type == PROP_ENDLIST) break;
|
||||
if (vl1 == NULL) continue;
|
||||
if (vl1->key == NULL) continue;
|
||||
|
||||
/* Check if this is a "property of interest". */
|
||||
kl1 = (struct property *)HashLookup(vl1->key, &(tc1->propdict));
|
||||
if (kl1 == NULL) continue;
|
||||
|
||||
/* Find the matching property in vl2. With luck, they're in order. */
|
||||
|
||||
for (j = vlstart;; j++) {
|
||||
vl2 = &(tp2->instance.props[j]);
|
||||
if (vl2->type == PROP_ENDLIST) break;
|
||||
if ((*matchfunc)(vl1->key, vl2->key)) break;
|
||||
}
|
||||
if (vl2->type == PROP_ENDLIST) continue;
|
||||
if (j == vlstart) vlstart++;
|
||||
|
||||
if (vl2 == NULL) continue;
|
||||
if (vl2->key == NULL) continue;
|
||||
|
||||
/* Both device classes must agree on the properties to compare */
|
||||
kl2 = (struct property *)HashLookup(vl2->key, &(tc2->propdict));
|
||||
if (kl2 == NULL) continue;
|
||||
|
||||
/* Watch out for uninitialized entries in cell def */
|
||||
if (vl1->type == vl2->type) {
|
||||
if (kl1->type == PROP_STRING && kl1->pdefault.string == NULL)
|
||||
SetPropertyDefault(kl1, vl1);
|
||||
if (kl2->type == PROP_STRING && kl2->pdefault.string == NULL)
|
||||
SetPropertyDefault(kl2, vl2);
|
||||
}
|
||||
|
||||
/* Promote properties as necessary to make sure they all match */
|
||||
if (kl1->type != vl1->type) PromoteProperty(kl1, vl1);
|
||||
if (kl2->type != vl2->type) PromoteProperty(kl2, vl2);
|
||||
if (kl1->type != vl2->type) PromoteProperty(kl1, vl2);
|
||||
if (vl1->type != kl2->type) PromoteProperty(kl2, vl1);
|
||||
|
||||
if (vl1->type != vl2->type) {
|
||||
if (do_print && (vl1->type != vl2->type)) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
ob1->instance.name, ob2->instance.name);
|
||||
Fprintf(stdout, " %s circuit1: %g circuit2: %g ",
|
||||
kl1->key, dval1, dval2);
|
||||
if (vl1->value.dval > 0.0 && vl2->value.dval > 0.0)
|
||||
Fprintf(stdout, "(delta=%.3g%%, cutoff=%.3g%%)\n",
|
||||
100 * pd, 100 * dslop);
|
||||
else
|
||||
Fprintf(stdout, "\n");
|
||||
|
||||
Fprintf(stdout, " %s circuit1: ", kl1->key);
|
||||
switch (vl1->type) {
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
Fprintf(stdout, "%g", vl1->value.dval);
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
Fprintf(stdout, "%d", vl1->value.ival);
|
||||
break;
|
||||
case PROP_STRING:
|
||||
Fprintf(stdout, "\"%s\"", vl1->value.string);
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
Fprintf(stdout, "(unresolved expression)");
|
||||
break;
|
||||
}
|
||||
Fprintf(stdout, " ");
|
||||
switch (vl2->type) {
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
Fprintf(stdout, "%g", vl2->value.dval);
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
Fprintf(stdout, "%d", vl2->value.ival);
|
||||
break;
|
||||
case PROP_STRING:
|
||||
Fprintf(stdout, "\"%s\"", vl2->value.string);
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
Fprintf(stdout, "(unresolved expression)");
|
||||
break;
|
||||
}
|
||||
Fprintf(stdout, " (property type mismatch)\n");
|
||||
}
|
||||
mismatches++;
|
||||
}
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
ival1 = vl1->value.ival;
|
||||
ival2 = vl2->value.ival;
|
||||
}
|
||||
|
||||
islop = MAX(kl1->slop.ival, kl2->slop.ival);
|
||||
if (abs(ival1 - ival2) > islop) {
|
||||
if (do_print) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
else switch (kl1->type) {
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
dval1 = vl1->value.dval;
|
||||
dval2 = vl2->value.dval;
|
||||
|
||||
dslop = MAX(kl1->slop.dval, kl2->slop.dval);
|
||||
pd = 2 * fabs(dval1 - dval2) / (dval1 + dval2);
|
||||
if (pd > dslop) {
|
||||
if (do_print) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
ob1->instance.name, ob2->instance.name);
|
||||
Fprintf(stdout, " %s circuit1: %d circuit2: %d ",
|
||||
kl1->key, ival1, ival2);
|
||||
if (ival1 > 0 && ival2 > 0)
|
||||
Fprintf(stdout, "(delta=%d, cutoff=%d)\n",
|
||||
abs(ival1 - ival2), islop);
|
||||
else
|
||||
Fprintf(stdout, "\n");
|
||||
}
|
||||
mismatches++;
|
||||
}
|
||||
break;
|
||||
case PROP_STRING:
|
||||
islop = MAX(kl1->slop.ival, kl2->slop.ival);
|
||||
if (islop == 0) {
|
||||
if (strcasecmp(vl1->value.string, vl2->value.string)) {
|
||||
if (do_print) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
Fprintf(stdout, " %s circuit1: %g circuit2: %g ",
|
||||
kl1->key, dval1, dval2);
|
||||
if (vl1->value.dval > 0.0 && vl2->value.dval > 0.0)
|
||||
Fprintf(stdout, "(delta=%.3g%%, cutoff=%.3g%%)\n",
|
||||
100 * pd, 100 * dslop);
|
||||
else
|
||||
Fprintf(stdout, "\n");
|
||||
}
|
||||
mismatches++;
|
||||
}
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
ival1 = vl1->value.ival;
|
||||
ival2 = vl2->value.ival;
|
||||
|
||||
islop = MAX(kl1->slop.ival, kl2->slop.ival);
|
||||
if (abs(ival1 - ival2) > islop) {
|
||||
if (do_print) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
ob1->instance.name, ob2->instance.name);
|
||||
Fprintf(stdout, " %s circuit1: \"%s\" circuit2: \"%s\" "
|
||||
"(exact match req'd)\n",
|
||||
kl1->key, vl1->value.string, vl2->value.string);
|
||||
}
|
||||
Fprintf(stdout, " %s circuit1: %d circuit2: %d ",
|
||||
kl1->key, ival1, ival2);
|
||||
if (ival1 > 0 && ival2 > 0)
|
||||
Fprintf(stdout, "(delta=%d, cutoff=%d)\n",
|
||||
abs(ival1 - ival2), islop);
|
||||
else
|
||||
Fprintf(stdout, "\n");
|
||||
}
|
||||
mismatches++;
|
||||
}
|
||||
break;
|
||||
case PROP_STRING:
|
||||
islop = MAX(kl1->slop.ival, kl2->slop.ival);
|
||||
if (islop == 0) {
|
||||
if (strcasecmp(vl1->value.string, vl2->value.string)) {
|
||||
if (do_print) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
ob1->instance.name, ob2->instance.name);
|
||||
Fprintf(stdout, " %s circuit1: \"%s\" "
|
||||
"circuit2: \"%s\" (exact match req'd)\n",
|
||||
kl1->key, vl1->value.string,
|
||||
vl2->value.string);
|
||||
}
|
||||
mismatches++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (strncasecmp(vl1->value.string, vl2->value.string, islop)) {
|
||||
if (do_print) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
ob2->instance.name, ob2->instance.name);
|
||||
Fprintf(stdout, " %s circuit1: \"%s\" "
|
||||
"circuit2: \"%s\" (check to %d chars.)\n",
|
||||
kl1->key, vl1->value.string,
|
||||
vl2->value.string, islop);
|
||||
}
|
||||
mismatches++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
/* Expressions could potentially be compared. . . */
|
||||
if (do_print)
|
||||
Fprintf(stdout, " %s (unresolved expressions.)\n", kl1->key);
|
||||
mismatches++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (strncasecmp(vl1->value.string, vl2->value.string, islop)) {
|
||||
if (do_print) {
|
||||
if (mismatches == 0)
|
||||
Fprintf(stdout, "%s vs. %s:\n",
|
||||
ob2->instance.name, ob2->instance.name);
|
||||
Fprintf(stdout, " %s circuit1: \"%s\" circuit2: \"%s\" "
|
||||
"(check to %d chars.)\n",
|
||||
kl1->key, vl1->value.string, vl2->value.string, islop);
|
||||
}
|
||||
mismatches++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
/* Expressions could potentially be compared. . . */
|
||||
if (do_print)
|
||||
Fprintf(stdout, " %s (unresolved expressions.)\n", kl1->key);
|
||||
mismatches++;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
if ((vl1 == NULL && vl2 != NULL) || (vl1 != NULL && vl2 == NULL))
|
||||
rval = -1; /* Different number of properties of interest */
|
||||
}
|
||||
}
|
||||
if ((vl1 == NULL && vl2 != NULL) || (vl1 != NULL && vl2 == NULL))
|
||||
return -1; /* Different number of properties of interest */
|
||||
|
||||
/* Move to the next property record */
|
||||
|
||||
if (tp1) tp1 = tp1->next;
|
||||
if (tp2) tp2 = tp2->next;
|
||||
t1type = (tp1) ? tp1->type : 0;
|
||||
t2type = (tp2) ? tp2->type : 0;
|
||||
if ((t1type != PROPERTY) && (t2type != PROPERTY)) break;
|
||||
}
|
||||
return mismatches;
|
||||
|
||||
return (rval < 0) ? rval : mismatches;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
@@ -4547,13 +4562,13 @@ int EquivalenceNodes(char *name1, int file1, char *name2, int file2)
|
||||
/* database. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
int IgnoreClass(char *name, int file)
|
||||
int IgnoreClass(char *name, int file, unsigned char type)
|
||||
{
|
||||
struct IgnoreList *newIgnore;
|
||||
|
||||
if ((file == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
IgnoreClass(name, Circuit1->file);
|
||||
IgnoreClass(name, Circuit2->file);
|
||||
IgnoreClass(name, Circuit1->file, type);
|
||||
IgnoreClass(name, Circuit2->file, type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4563,9 +4578,13 @@ int IgnoreClass(char *name, int file)
|
||||
newIgnore->class = (char *)MALLOC(1 + strlen(name));
|
||||
strcpy(newIgnore->class, name);
|
||||
newIgnore->file = file;
|
||||
newIgnore->type = type;
|
||||
|
||||
/* Remove existing classes from database */
|
||||
ClassDelete(name, file);
|
||||
if (type == IGNORE_CLASS)
|
||||
ClassDelete(name, file);
|
||||
else
|
||||
RemoveShorted(name, file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ extern int PermuteForget(char *model, int filenum, char *pin1, char *pin2);
|
||||
extern int EquivalenceElements(char *name1, int file1, char *name2, int file2);
|
||||
extern int EquivalenceNodes(char *name1, int file1, char *name2, int file2);
|
||||
extern int EquivalenceClasses(char *name1, int file1, char *name2, int file2);
|
||||
extern int IgnoreClass(char *name, int file);
|
||||
extern int IgnoreClass(char *name, int file, unsigned char type);
|
||||
extern int MatchPins(struct nlist *tp1, struct nlist *tp2);
|
||||
|
||||
extern int CreateCompareQueue(char *, int, char *, int);
|
||||
|
||||
@@ -730,7 +730,6 @@ char *readbuf;
|
||||
int bytes_in_buffer;
|
||||
char *bufptr;
|
||||
|
||||
INLINE
|
||||
int READ(void *buf, int bytes)
|
||||
{
|
||||
if (bytes_in_buffer >= bytes) {
|
||||
|
||||
+220
-8
@@ -1212,6 +1212,10 @@ void CellDefNoCase(char *name, int file)
|
||||
CurrentCell->flags |= CELL_NOCASE;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Return 0 if class 'name' is not being ignored (per the 'ignore' */
|
||||
/* command); 1 if it is ignored, and 2 if shorted instances should be */
|
||||
/* ignored. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int IsIgnored(char *name, int file)
|
||||
@@ -1223,7 +1227,7 @@ int IsIgnored(char *name, int file)
|
||||
{
|
||||
if ((file == -1) || (ilist->file == -1) || (file == ilist->file))
|
||||
if ((*matchfunc)(ilist->class, nptr))
|
||||
return 1;
|
||||
return ilist->type; /* IGNORE_CLASS or IGNORE_SHORTED */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1361,10 +1365,6 @@ void Instance(char *model, char *instancename)
|
||||
return;
|
||||
}
|
||||
fnum = CurrentCell->file;
|
||||
if (IsIgnored(model, fnum)) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
return;
|
||||
}
|
||||
instanced_cell = LookupCellFile(model, fnum);
|
||||
if (instanced_cell == NULL) {
|
||||
Printf("Attempt to instance undefined model '%s'\n", model);
|
||||
@@ -1504,7 +1504,7 @@ char *Cell(char *inststr, char *model, ...)
|
||||
struct objlist *namedporthead, *namedportp, *namedlisthead, *namedlistp;
|
||||
int portnum, portlist, done;
|
||||
char namedport[512]; /* tmp buffers */
|
||||
int filenum;
|
||||
int filenum, itype, samenode;
|
||||
|
||||
static char *instancename = NULL;
|
||||
char *instnameptr;
|
||||
@@ -1517,7 +1517,7 @@ char *Cell(char *inststr, char *model, ...)
|
||||
filenum = CurrentCell->file;
|
||||
|
||||
if (Debug) Printf(" calling cell: %s\n",model);
|
||||
if (IsIgnored(model, filenum)) {
|
||||
if ((itype = IsIgnored(model, filenum)) == IGNORE_CLASS) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1600,6 +1600,21 @@ char *Cell(char *inststr, char *model, ...)
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* Check for shorted pins */
|
||||
if ((itype == IGNORE_SHORTED) && (head != NULL)) {
|
||||
unsigned char shorted = (unsigned char)1;
|
||||
for (tp = head->next; tp; tp = tp->next) {
|
||||
if (strcasecmp(head->name, tp->name))
|
||||
shorted = (unsigned char)0;
|
||||
break;
|
||||
}
|
||||
if (shorted == (unsigned char)1) {
|
||||
Printf("Instance of '%s' is shorted, ignoring.\n", model);
|
||||
FreeObject(head);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (inststr == NULL) {
|
||||
if (instancename != NULL)
|
||||
FreeString(instancename);
|
||||
@@ -1992,7 +2007,7 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
|
||||
else
|
||||
filenum = CurrentCell->file;
|
||||
|
||||
if (IsIgnored(model, filenum)) {
|
||||
if (IsIgnored(model, filenum) == IGNORE_CLASS) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
return NULL;
|
||||
}
|
||||
@@ -3018,6 +3033,203 @@ void CombineParallel(char *model, int file)
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Find all nodes that are connected to exactly two devices of the same */
|
||||
/* class. Where found, if the device is allowed to combine serially */
|
||||
/* (check properties), then remove the node and merge the devices into */
|
||||
/* one. */
|
||||
/* */
|
||||
/* This routine depends on CombineParallel() being run first so that no */
|
||||
/* parallel devices are reported as serial. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void CombineSerial(char *model, int file)
|
||||
{
|
||||
struct nlist *tp, *tp2;
|
||||
struct objlist ***instlist;
|
||||
struct objlist *ob, *ob2, *obs, *obp, *obn;
|
||||
int i, j;
|
||||
struct valuelist *kv;
|
||||
|
||||
// Work in progress. . .
|
||||
return;
|
||||
|
||||
if ((tp = LookupCellFile(model, file)) == NULL) {
|
||||
Printf("Cell: %s does not exist.\n", model);
|
||||
return;
|
||||
}
|
||||
instlist = (struct objlist ***)CALLOC((tp->nodename_cache_maxnodenum + 1),
|
||||
sizeof(struct objlist **));
|
||||
|
||||
for (ob = tp->cell; ob; ob = ob->next) {
|
||||
if ((ob->type >= FIRSTPIN) && (ob->node >= 0)) {
|
||||
if (ob->type == FIRSTPIN)
|
||||
obp = ob; // Save pointer to first pin of device
|
||||
if (instlist[ob->node] == NULL) {
|
||||
/* Node has not been seen before, so add it to list */
|
||||
instlist[ob->node] = (struct objlist **)CALLOC(2,
|
||||
sizeof(struct objlist *));
|
||||
|
||||
/* For now, simple rule: Device must be a resistor */
|
||||
tp2 = LookupCellFile(ob->model.class, file);
|
||||
if (tp2->class != CLASS_RES)
|
||||
/* invalidate node */
|
||||
instlist[ob->node][0] = NULL;
|
||||
else
|
||||
instlist[ob->node][0] = obp;
|
||||
}
|
||||
else if (instlist[ob->node][0] == NULL) {
|
||||
/* Node is not valid for serial connection */
|
||||
}
|
||||
else if (instlist[ob->node][1] == NULL) {
|
||||
/* Check if first instance is the same type */
|
||||
if ((*matchfunc)(instlist[ob->node][0]->model.class, ob->model.class))
|
||||
instlist[ob->node][1] = obp;
|
||||
else
|
||||
/* invalidate node */
|
||||
instlist[ob->node][0] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i <= tp->nodename_cache_maxnodenum; i++) {
|
||||
if (instlist[i] != NULL) {
|
||||
if ((instlist[i][0] != NULL) && (instlist[i][1] != NULL)) {
|
||||
Fprintf(stdout, "Found serial instances %s and %s\n",
|
||||
instlist[i][0]->instance.name,
|
||||
instlist[i][1]->instance.name);
|
||||
|
||||
/* To maintain knowledge of the topology, each device gets */
|
||||
/* a parameter 'S', string value set to "<node1>/<node2>". */
|
||||
|
||||
for (j = 0; j <= 1; j++) {
|
||||
for (obp = instlist[i][j]; ; obp = obp->next) {
|
||||
int found = FALSE;
|
||||
int k, l;
|
||||
char *nodename1, *nodename2;
|
||||
struct valuelist *kv2;
|
||||
|
||||
nodename1 = tp->nodename_cache[instlist[i][j]->node]->name;
|
||||
nodename2 = tp->nodename_cache[instlist[i][j]->next->node]->name;
|
||||
if (obp->type == PROPERTY) {
|
||||
/* Add to properties */
|
||||
k = 0;
|
||||
for (k = 0; ; k++) {
|
||||
kv = &(obp->instance.props[k]);
|
||||
if (kv->type == PROP_ENDLIST)
|
||||
break;
|
||||
}
|
||||
kv2 = (struct valuelist *)MALLOC((k + 2) *
|
||||
sizeof(struct valuelist));
|
||||
kv2->key = strsave("S");
|
||||
kv2->type = PROP_STRING;
|
||||
/* Value is set to "<node1>/<node2>" */
|
||||
kv2->value.string = (char *)MALLOC(strlen(nodename1) +
|
||||
strlen(nodename2) + 2);
|
||||
sprintf(kv2->value.string, "%s/%s", nodename1, nodename2);
|
||||
|
||||
for (l = 0; l <= k; l++)
|
||||
kv2[l + 1] = obp->instance.props[l];
|
||||
FREE(obp->instance.props);
|
||||
obp->instance.props = kv2;
|
||||
found = TRUE;
|
||||
}
|
||||
if (obp->next == NULL || obp->next->type == FIRSTPIN) {
|
||||
struct objlist *nob;
|
||||
/* No property record, so insert one */
|
||||
if (found == FALSE) {
|
||||
nob = GetObject();
|
||||
nob->type = PROPERTY;
|
||||
nob->name = strsave("properties");
|
||||
nob->node = -2; /* Don't report as disconnected node */
|
||||
nob->model.class = (obp->model.class == NULL) ? NULL :
|
||||
strsave(obp->model.class);
|
||||
nob->instance.props = NewPropValue(2);
|
||||
|
||||
/* Create property record for property "S" */
|
||||
kv = &(nob->instance.props[0]);
|
||||
kv->key = strsave("S");
|
||||
kv->type = PROP_STRING;
|
||||
/* Value is set to "<node1>/<node2>" */
|
||||
kv->value.string = (char *)MALLOC(strlen(nodename1) +
|
||||
strlen(nodename2) + 2);
|
||||
sprintf(kv->value.string, "%s/%s", nodename1, nodename2);
|
||||
|
||||
/* End of property list */
|
||||
kv = &(nob->instance.props[1]);
|
||||
kv->key = NULL;
|
||||
kv->type = PROP_ENDLIST;
|
||||
kv->value.ival = 0;
|
||||
|
||||
nob->next = obp->next;
|
||||
obp->next = nob;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine these two instances and remove node i */
|
||||
for (ob2 = instlist[i][0]; ob2; ob2 = ob2->next) {
|
||||
if (ob2->node == i)
|
||||
break;
|
||||
}
|
||||
for (obs = instlist[i][1]; obs; obs = obs->next) {
|
||||
if (obs->node != i) {
|
||||
ob2->node = obs->node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Excise the 2nd instance. instlist[i][1] remains as the */
|
||||
/* only pointer to it. */
|
||||
for (obp = instlist[i][0]; obp->next->type != FIRSTPIN; obp = obp->next);
|
||||
for (ob2 = obp; ob2->next != instlist[i][1]; ob2 = ob2->next);
|
||||
for (obs = ob2->next; obs->next && obs->next->type != FIRSTPIN;
|
||||
obs = obs->next);
|
||||
ob2->next = obs->next;
|
||||
if (obs->next) obs->next = NULL; // Terminate 2nd instance record
|
||||
|
||||
/* Move property record(s) of the 2nd device to the first */
|
||||
for (obs = instlist[i][1]; obs && obs->type != PROPERTY; obs = obs->next);
|
||||
while (obs && (obs->type == PROPERTY)) {
|
||||
obn = obs->next;
|
||||
obs->next = obp->next;
|
||||
obp->next = obs;
|
||||
obs = obn;
|
||||
}
|
||||
|
||||
/* If 2nd device appears anywhere else in the serial device */
|
||||
/* list, replace it with the 1st device. */
|
||||
for (j = i + 1; j <= tp->nodename_cache_maxnodenum; j++) {
|
||||
if (instlist[j][0] == instlist[i][1])
|
||||
instlist[j][0] = instlist[i][0];
|
||||
if (instlist[j][1] == instlist[i][1])
|
||||
instlist[j][1] = instlist[i][0];
|
||||
}
|
||||
|
||||
/* Free 2nd device's object */
|
||||
for (obs = instlist[i][1]; obs && obs->type != PROPERTY; ) {
|
||||
obn = obs->next;
|
||||
FreeObjectAndHash(obs, tp);
|
||||
obs = obn;
|
||||
}
|
||||
|
||||
/* Free node i and remove from object hash */
|
||||
for (obp = tp->cell; obp->next; obp = obp->next) {
|
||||
if ((obp->next->type == NODE) && (obp->next->node == i)) {
|
||||
obn = obp->next;
|
||||
obp->next = obp->next->next;
|
||||
FreeObjectAndHash(obn, tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
FREE(instlist[i]);
|
||||
}
|
||||
}
|
||||
FREE(instlist);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@ extern void ConvertGlobals(char *name, int fnum);
|
||||
extern int CleanupPins(char *name, int fnum);
|
||||
extern void ConnectAllNodes(char *model, int fnum);
|
||||
extern void CombineParallel(char *model, int fnum);
|
||||
extern void CombineSerial(char *model, int fnum);
|
||||
extern int NoDisconnectedNodes;
|
||||
extern int PropertyKeyMatch(char *, char *);
|
||||
extern int PropertyValueMatch(char *, char *);
|
||||
|
||||
+66
-1
@@ -340,6 +340,71 @@ void CellRehash(char *name, char *newname, int file)
|
||||
|
||||
struct nlist *OldCell;
|
||||
|
||||
int removeshorted(struct hashlist *p, int file)
|
||||
{
|
||||
struct nlist *ptr;
|
||||
struct objlist *ob, *lob, *nob, *tob;
|
||||
unsigned char shorted;
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
|
||||
if ((file != -1) && (ptr->file != file)) return;
|
||||
|
||||
lob = NULL;
|
||||
for (ob = ptr->cell; ob != NULL;) {
|
||||
nob = ob->next;
|
||||
if ((ob->type == FIRSTPIN) && (ob->model.class != NULL)) {
|
||||
if ((*matchfunc)(ob->model.class, OldCell->name)) {
|
||||
shorted = (unsigned char)1;
|
||||
for (tob = nob; tob->type > FIRSTPIN; tob = tob->next) {
|
||||
if (tob->node != ob->node) {
|
||||
shorted = (unsigned char)0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shorted == (unsigned char)0) {
|
||||
lob = ob;
|
||||
ob = nob;
|
||||
continue;
|
||||
}
|
||||
HashDelete(ob->instance.name, &(ptr->instdict));
|
||||
while (1) {
|
||||
FreeObjectAndHash(ob, ptr);
|
||||
ob = nob;
|
||||
if (ob == NULL) break;
|
||||
nob = ob->next;
|
||||
if (ob->type != PROPERTY && ob->type <= FIRSTPIN) break;
|
||||
}
|
||||
if (lob == NULL)
|
||||
ptr->cell = ob;
|
||||
else
|
||||
lob->next = ob;
|
||||
}
|
||||
else {
|
||||
lob = ob;
|
||||
ob = nob;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lob = ob;
|
||||
ob = nob;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove shorted instances of class "class" from the database */
|
||||
|
||||
void RemoveShorted(char *class, int file)
|
||||
{
|
||||
if (file == -1)
|
||||
OldCell = LookupCell(class);
|
||||
else
|
||||
OldCell = LookupCellFile(class, file);
|
||||
|
||||
if (OldCell == NULL) return;
|
||||
RecurseCellFileHashTable(removeshorted, file);
|
||||
}
|
||||
|
||||
int deleteclass(struct hashlist *p, int file)
|
||||
{
|
||||
struct nlist *ptr;
|
||||
@@ -360,7 +425,7 @@ int deleteclass(struct hashlist *p, int file)
|
||||
ob = nob;
|
||||
if (ob == NULL) break;
|
||||
nob = ob->next;
|
||||
if (ob->type <= FIRSTPIN) break;
|
||||
if (ob->type != PROPERTY && ob->type <= FIRSTPIN) break;
|
||||
}
|
||||
if (lob == NULL)
|
||||
ptr->cell = ob;
|
||||
|
||||
@@ -159,9 +159,16 @@ extern struct objlist *LastPlaced;
|
||||
struct IgnoreList {
|
||||
char *class;
|
||||
int file;
|
||||
unsigned char type;
|
||||
struct IgnoreList *next;
|
||||
};
|
||||
|
||||
/* Types used by IgnoreList above */
|
||||
|
||||
#define IGNORE_NONE (unsigned char)0
|
||||
#define IGNORE_CLASS (unsigned char)1
|
||||
#define IGNORE_SHORTED (unsigned char)2
|
||||
|
||||
/* Record structure for handling pin permutations in a cell */
|
||||
/* Linked list structure allows multiple permutations per cell. */
|
||||
|
||||
|
||||
@@ -315,7 +315,6 @@ void PrintE(FILE *outfile, int E)
|
||||
|
||||
|
||||
#if 0
|
||||
INLINE
|
||||
int UsedLeaves(int E1, int E2)
|
||||
/* returns the number of leaves in E1 + E2, which are assumed independent */
|
||||
{
|
||||
@@ -327,7 +326,6 @@ int UsedLeaves(int E1, int E2)
|
||||
#endif
|
||||
|
||||
|
||||
INLINE
|
||||
int CommonNodes(int E1, int E2, int IncludeGlobals)
|
||||
/* returns the number of nodes that E1 and E2 share */
|
||||
/* if IncludeGlobals == 0, do not count large connectivity nodes */
|
||||
@@ -350,7 +348,6 @@ int CommonNodes(int E1, int E2, int IncludeGlobals)
|
||||
return(result);
|
||||
}
|
||||
|
||||
INLINE
|
||||
int GlobalNodes(int E)
|
||||
/* return the number of global nodes that E contacts */
|
||||
/* for now, global nodes are just cell ports */
|
||||
|
||||
@@ -1530,6 +1530,8 @@ skip_ends:
|
||||
|
||||
else if (toupper(nexttok[0]) == 'X') { /* subcircuit instances */
|
||||
char instancename[100], subcktname[100];
|
||||
int itype;
|
||||
|
||||
instancename[99] = '\0';
|
||||
subcktname[99] = '\0';
|
||||
|
||||
@@ -1602,6 +1604,34 @@ skip_ends:
|
||||
if (scan->next != NULL) scan = scan->next;
|
||||
tail->next = NULL;
|
||||
|
||||
/* Check for ignored class */
|
||||
|
||||
if ((itype = IsIgnored(subcktname, filenum)) == IGNORE_CLASS) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for shorted pins */
|
||||
|
||||
if ((itype == IGNORE_SHORTED) && (head != NULL)) {
|
||||
unsigned char shorted = (unsigned char)1;
|
||||
struct portelement *p;
|
||||
for (p = head->next; p; p = p->next) {
|
||||
if (strcasecmp(head->name, p->name))
|
||||
shorted = (unsigned char)0;
|
||||
break;
|
||||
}
|
||||
if (shorted == (unsigned char)1) {
|
||||
Printf("Instance of '%s' is shorted, ignoring.\n", subcktname);
|
||||
while (head) {
|
||||
p = head->next;
|
||||
FREE(head);
|
||||
head = p;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create cell name and revise instance name based on the cell name */
|
||||
/* For clarity, if "instancename" does not contain the cellname, */
|
||||
/* then prepend the cellname to the instance name. HOWEVER, if any */
|
||||
@@ -1658,6 +1688,7 @@ skip_ends:
|
||||
}
|
||||
|
||||
/* nexttok is now NULL, scan->name points to class */
|
||||
|
||||
Instance(subcktname, instancename);
|
||||
pobj = LinkProperties(subcktname, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
|
||||
+10
-3
@@ -2518,10 +2518,10 @@ _netcmp_ignore(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"class", NULL
|
||||
"class", "shorted", NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
CLASS_IDX
|
||||
CLASS_IDX, SHORTED_IDX
|
||||
};
|
||||
int result, index;
|
||||
int file = -1;
|
||||
@@ -2542,7 +2542,14 @@ _netcmp_ignore(ClientData clientData,
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "[class] valid_cellname");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
IgnoreClass(name, file);
|
||||
switch (index) {
|
||||
case CLASS_IDX:
|
||||
IgnoreClass(name, file, IGNORE_CLASS);
|
||||
break;
|
||||
case SHORTED_IDX:
|
||||
IgnoreClass(name, file, IGNORE_SHORTED);
|
||||
break;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user