Compare commits

..
12 Commits
Author SHA1 Message Date
Tim Edwards 577dfb5a28 Merge branch 'master' into work 2016-11-11 09:52:19 -05:00
Tim Edwards 46252ad6b9 Update at Fri Nov 11 09:52:18 EST 2016 by tim 2016-11-11 09:52:18 -05:00
Tim Edwards 564fab9667 Corrected an error in which property types were not promoted if
an instance property did not match the cell property type, as
long as the cell property types of the two compared cells matched.
Along with a recent change that left "M" as a type double during
SPICE netlist read-in, this caused "M" mismatches to be ignored,
because the double value was ignored and the integer value was
always zero.
2016-11-11 09:49:37 -05:00
Tim Edwards 0df4190e19 Merge branch 'master' into work 2016-10-26 21:21:10 -04:00
Tim Edwards 2f661ea256 Update at Wed Oct 26 21:21:09 EDT 2016 by tim 2016-10-26 21:21:10 -04:00
Tim Edwards fca075e1ed Disabled the newest unfinished experimental code, which was not
supposed to have been pushed to git yet.
2016-10-26 21:20:42 -04:00
Tim Edwards cc2a5e0ee6 Merge branch 'master' into work 2016-10-25 11:29:17 -04:00
Tim Edwards b7a8d3cfda Update at Tue Oct 25 11:29:17 EDT 2016 by tim 2016-10-25 11:29:17 -04:00
Tim Edwards 0205902baa Changed behavior of property mismatch reporting. This is to help
avoid the problem where non-critical properties cause devices not
to match, resulting in apparent mismatches of matched devices.
The current behavior now prints a statement about each device.
However, the result is still somewhat ambiguous.
2016-10-25 11:26:45 -04:00
Tim Edwards 646b351ee5 Merge branch 'master' into work 2016-10-24 13:43:30 -04:00
Tim Edwards 31a0f10602 Update at Mon Oct 24 13:43:29 EDT 2016 by tim 2016-10-24 13:43:29 -04:00
Tim Edwards a2b1f5c85f Removed all instances of macro INLINE, as this is showing up now
as failing on certain compilers.  This undoubtedly reflects some
change in gcc or the OS setup, but since modern compilers should
be able to figure out for themselves when to inline a subroutine
(or not), the inline hint is somewhat arcane and unnecessary.
2016-10-24 13:42:08 -04:00
10 changed files with 405 additions and 217 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.63
1.5.67
-1
View File
@@ -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!! */
-4
View File
@@ -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 */
{
-9
View File
@@ -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
-3
View File
@@ -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;
+206 -195
View File
@@ -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,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;
}
/*--------------------------------------------------------------*/
-1
View File
@@ -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
View File
@@ -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);
}
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
+1
View File
@@ -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 *);
-3
View File
@@ -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 */