mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 22:17:22 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0df4190e19 | ||
|
|
2f661ea256 | ||
|
|
fca075e1ed | ||
|
|
cc2a5e0ee6 | ||
|
|
b7a8d3cfda | ||
|
|
0205902baa | ||
|
|
646b351ee5 | ||
|
|
31a0f10602 | ||
|
|
a2b1f5c85f |
@@ -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;
|
||||
|
||||
+205
-197
@@ -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);
|
||||
@@ -3592,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);
|
||||
@@ -3626,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;
|
||||
@@ -3641,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;
|
||||
@@ -3666,184 +3660,198 @@ 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",
|
||||
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");
|
||||
}
|
||||
mismatches++;
|
||||
}
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
ival1 = vl1->value.ival;
|
||||
ival2 = vl2->value.ival;
|
||||
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;
|
||||
|
||||
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",
|
||||
/* 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: %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");
|
||||
|
||||
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_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",
|
||||
if (vl1->type != vl2->type) mismatches++;
|
||||
}
|
||||
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: \"%s\" circuit2: \"%s\" "
|
||||
"(exact match req'd)\n",
|
||||
kl1->key, vl1->value.string, vl2->value.string);
|
||||
}
|
||||
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: %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;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
@@ -730,7 +730,6 @@ char *readbuf;
|
||||
int bytes_in_buffer;
|
||||
char *bufptr;
|
||||
|
||||
INLINE
|
||||
int READ(void *buf, int bytes)
|
||||
{
|
||||
if (bytes_in_buffer >= bytes) {
|
||||
|
||||
+197
@@ -3033,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 *);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user