mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-24 15:07:18 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a888502038 | ||
|
|
ea07642172 | ||
|
|
e9da037001 | ||
|
|
7ee50a3f8f | ||
|
|
c16258d4d1 | ||
|
|
c7848c9c02 | ||
|
|
5341d7a5fd | ||
|
|
402e1f0f25 | ||
|
|
8395df633c | ||
|
|
19471275df | ||
|
|
e75f5661e2 | ||
|
|
6554063df3 | ||
|
|
a034fc16d6 | ||
|
|
62fbd422e2 | ||
|
|
4416a380b3 | ||
|
|
d0bae6aff4 | ||
|
|
8a7bb7f2ca | ||
|
|
46394b2000 | ||
|
|
0df6c83df5 | ||
|
|
8996fe03dc | ||
|
|
3fe3bc4cfa | ||
|
|
f3cebd9099 | ||
|
|
6661910672 | ||
|
|
920c6e6928 | ||
|
|
e7a36630f6 | ||
|
|
69780aa048 | ||
|
|
f32b0b34a3 | ||
|
|
2a0ebfde93 | ||
|
|
6e9e6abe98 | ||
|
|
6b731ddd7a | ||
|
|
99e35d8b11 | ||
|
|
65b542f0ab | ||
|
|
b826870be9 | ||
|
|
ed5276d67b | ||
|
|
69c9d85be7 | ||
|
|
ad05d059c7 | ||
|
|
1b2cd1497c | ||
|
|
d9d5a46c6e | ||
|
|
d73b711e3a | ||
|
|
1428580109 | ||
|
|
210dfb25c3 | ||
|
|
27f2ab8b3f | ||
|
|
1be00bbd99 | ||
|
|
03b241a5d4 | ||
|
|
43cebd1ef9 | ||
|
|
0490959b07 | ||
|
|
dc841f3293 | ||
|
|
05bcfede69 | ||
|
|
72ed78e55a | ||
|
|
59bb8a89c0 | ||
|
|
9bdaee652e | ||
|
|
9879b58f83 | ||
|
|
9e3b705fcc | ||
|
|
d2c9129242 | ||
|
|
942f421fa3 | ||
|
|
6bc948d8ba | ||
|
|
c1ad37f05a | ||
|
|
9edefe7d59 | ||
|
|
f6b9629521 | ||
|
|
7b2e01f2af | ||
|
|
224050f153 | ||
|
|
74e8c3e168 | ||
|
|
95a29fcd8c | ||
|
|
723a950fd3 | ||
|
|
e3368cb22a | ||
|
|
f06e6548bb | ||
|
|
72ed19ff36 | ||
|
|
39b8e3d14a | ||
|
|
b63dfa8638 | ||
|
|
f918f33c51 | ||
|
|
63b2e48ea1 | ||
|
|
6e63f49d53 | ||
|
|
419b6de29a | ||
|
|
205cf2aa58 | ||
|
|
52b6766fc8 | ||
|
|
7b0bdd29e8 | ||
|
|
433cbd090a | ||
|
|
3087bd3337 | ||
|
|
b79a29d662 | ||
|
|
bf9c61e412 | ||
|
|
8d34bd372d | ||
|
|
229c2931a8 | ||
|
|
b8da97deb1 | ||
|
|
b7187d5899 | ||
|
|
d27d441c58 | ||
|
|
48c9e6b292 | ||
|
|
ced5846da3 | ||
|
|
b99d33064f | ||
|
|
399472e940 |
+95
-27
@@ -253,7 +253,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
{
|
||||
struct objlist *ParentParams;
|
||||
struct objlist *ParentProps;
|
||||
struct objlist *NextObj;
|
||||
struct objlist *NextObj, *LastObj, *prepp;
|
||||
struct objlist *ChildObjList;
|
||||
struct nlist *ThisCell;
|
||||
struct nlist *ChildCell;
|
||||
@@ -296,21 +296,35 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
while (notdone) {
|
||||
notdone = 0;
|
||||
ParentParams = ThisCell->cell;
|
||||
LastObj = NULL;
|
||||
|
||||
for (ParentParams = ThisCell->cell; ParentParams != NULL;
|
||||
ParentParams = NextObj) {
|
||||
ParentParams = NextObj) {
|
||||
if (Debug) Printf("Parent = %s, type = %d\n",
|
||||
ParentParams->name, ParentParams->type);
|
||||
NextObj = ParentParams->next;
|
||||
if (ParentParams->type != FIRSTPIN) continue;
|
||||
if (!(*matchfunc)(ParentParams->model.class, instance)) continue;
|
||||
if (ParentParams->type != FIRSTPIN) {
|
||||
LastObj = ParentParams;
|
||||
continue;
|
||||
}
|
||||
if (!(*matchfunc)(ParentParams->model.class, instance)) {
|
||||
LastObj = ParentParams;
|
||||
continue;
|
||||
}
|
||||
|
||||
ChildCell = LookupCellFile(ParentParams->model.class, ThisCell->file);
|
||||
if (Debug)
|
||||
Printf(" Flattening instance: %s, primitive = %s\n",
|
||||
ParentParams->instance.name, (ChildCell->class ==
|
||||
CLASS_SUBCKT) ? "no" : "yes");
|
||||
if (ChildCell->class != CLASS_SUBCKT) continue;
|
||||
if (ChildCell == ThisCell) continue; // Avoid infinite loop
|
||||
if (ChildCell->class != CLASS_SUBCKT) {
|
||||
LastObj = ParentParams;
|
||||
continue;
|
||||
}
|
||||
if (ChildCell == ThisCell) {
|
||||
LastObj = ParentParams;
|
||||
continue; // Avoid infinite loop
|
||||
}
|
||||
|
||||
/* Does the parent cell have properties? If so, save a pointer to them */
|
||||
for (ParentProps = ParentParams->next; ParentProps &&
|
||||
@@ -373,10 +387,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
}
|
||||
|
||||
/* in pathological cases, the lengths of the port lists may
|
||||
change. This is an error, but that is no reason to allow
|
||||
the code to core dump. We avoid this by placing a
|
||||
superfluous check on ob2->type
|
||||
*/
|
||||
* change. This is an error, but that is no reason to allow
|
||||
* the code to core dump. We avoid this by placing a
|
||||
* superfluous check on ob2->type
|
||||
*/
|
||||
|
||||
if (ob2 != NULL)
|
||||
ob2 = ob2->next;
|
||||
@@ -497,10 +511,21 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||
for (ob2 = ChildObjList; ob2 && ob2->next != NULL; ob2 = ob2->next) ;
|
||||
}
|
||||
else {
|
||||
/* find ParentParams in ThisCell list */
|
||||
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; ob2=ob2->next);
|
||||
/* find ParentParams in ThisCell list. In most cases, LastObj */
|
||||
/* should be pointing to it. */
|
||||
if (LastObj && (LastObj->next == ParentParams)) {
|
||||
ob2 = LastObj;
|
||||
}
|
||||
else {
|
||||
for (ob2 = LastObj; ob2 && ob2->next != ParentParams; ob2=ob2->next);
|
||||
if (ob2 == NULL) {
|
||||
/* It should not happen that LastObj is ahead of ParentParams */
|
||||
/* but just in case, this long loop will find it. */
|
||||
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; ob2=ob2->next);
|
||||
}
|
||||
}
|
||||
if (ob2)
|
||||
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
|
||||
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
|
||||
}
|
||||
/* now, ob2 is last element in child list, so skip and reclaim parent */
|
||||
|
||||
@@ -1136,9 +1161,10 @@ int UniquePins(char *name, int filenum)
|
||||
struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
{
|
||||
struct nlist *ptr;
|
||||
struct objlist *ob, *obt, *lob, *nob, *firstpin;
|
||||
struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob;
|
||||
struct nlist *tc = (struct nlist *)clientdata;
|
||||
int pinnum;
|
||||
char *saveinst = NULL;
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
if (tc->file != ptr->file) return NULL;
|
||||
@@ -1186,13 +1212,44 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
}
|
||||
|
||||
FREE(ob->name);
|
||||
if (ob->instance.name != NULL) FREE(ob->instance.name);
|
||||
if (ob->instance.name != NULL) {
|
||||
/* Keep a copy of the instance name (see below) */
|
||||
if (saveinst != NULL) FREE(saveinst);
|
||||
saveinst = ob->instance.name;
|
||||
}
|
||||
if (ob->model.class != NULL) FREE(ob->model.class);
|
||||
FREE(ob);
|
||||
}
|
||||
else {
|
||||
lob = ob;
|
||||
ob->type = pinnum++; // Renumber pins in order
|
||||
if ((ob->type == PROPERTY) && (pinnum == 1))
|
||||
{
|
||||
/* If this happens, then all the pins got removed,
|
||||
* and there is probably something very much wrong
|
||||
* with the setup. However, to keep netgen from
|
||||
* blowing up, add back a "proxy(no pins)" record
|
||||
* in front; otherwise we'd have an orphaned
|
||||
* property record.
|
||||
*/
|
||||
pob = GetObject();
|
||||
pob->name = (char *)MALLOC(15);
|
||||
sprintf(pob->name, "proxy(no pins)");
|
||||
pob->model.class = strsave(ob->model.class);
|
||||
if (saveinst != NULL)
|
||||
pob->instance.name = strsave(saveinst);
|
||||
else
|
||||
/* This should never happen */
|
||||
pob->instance.name = strsave("error");
|
||||
pob->type = pinnum++;
|
||||
pob->node = -1;
|
||||
pob->next = ob;
|
||||
lob->next = pob;
|
||||
lob = ob;
|
||||
}
|
||||
else
|
||||
{
|
||||
lob = ob;
|
||||
ob->type = pinnum++; // Renumber pins in order
|
||||
}
|
||||
}
|
||||
ob = nob;
|
||||
obt = obt->next;
|
||||
@@ -1203,6 +1260,8 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
|
||||
}
|
||||
}
|
||||
|
||||
if (saveinst != NULL) FREE(saveinst);
|
||||
return NULL; /* Keep the search going */
|
||||
}
|
||||
|
||||
@@ -1660,7 +1719,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
while (ecomp != NULL) {
|
||||
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
|
||||
((ecomp->cell1->class == CLASS_RES) ||
|
||||
(ecomp->cell1->class == CLASS_VSOURCE))) {
|
||||
(ecomp->cell1->class == CLASS_VSOURCE) ||
|
||||
(ecomp->cell1->class == CLASS_ISOURCE))) {
|
||||
int node1 = -1, node2 = -1;
|
||||
lob = NULL;
|
||||
for (ob1 = tc1->cell; ob1; ) {
|
||||
@@ -1709,11 +1769,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
tsub1->name,
|
||||
tc1->name);
|
||||
|
||||
/* merge node of endpoints */
|
||||
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->node == node2)
|
||||
ob2->node = node1;
|
||||
}
|
||||
/* A current source is an open, while a */
|
||||
/* resistor or voltage source is a short. */
|
||||
|
||||
if (ecomp->cell1->class != CLASS_ISOURCE) {
|
||||
/* merge node of endpoints */
|
||||
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
|
||||
if (ob2->node == node2)
|
||||
ob2->node = node1;
|
||||
}
|
||||
}
|
||||
|
||||
/* snip, snip. Excise this device */
|
||||
if (lob == NULL) {
|
||||
@@ -1765,7 +1830,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
|
||||
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
|
||||
((ecomp->cell2->class == CLASS_RES) ||
|
||||
(ecomp->cell2->class == CLASS_VSOURCE))) {
|
||||
(ecomp->cell2->class == CLASS_VSOURCE) ||
|
||||
(ecomp->cell2->class == CLASS_ISOURCE))) {
|
||||
int node1 = -1, node2 = -1;
|
||||
lob = NULL;
|
||||
for (ob2 = tc2->cell; ob2; ) {
|
||||
@@ -1815,9 +1881,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
|
||||
tc2->name);
|
||||
|
||||
/* merge node of endpoints */
|
||||
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
|
||||
if (ob1->node == node2)
|
||||
ob1->node = node1;
|
||||
if (ecomp->cell2->class != CLASS_ISOURCE) {
|
||||
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
|
||||
if (ob1->node == node2)
|
||||
ob1->node = node1;
|
||||
}
|
||||
}
|
||||
|
||||
/* snip, snip. Excise this device */
|
||||
|
||||
+43
-188
@@ -158,9 +158,6 @@ int right_col_end = 87;
|
||||
/* if TRUE, always partition ALL classes */
|
||||
int ExhaustiveSubdivision = 0;
|
||||
|
||||
/* if TRUE, use fast symmetry breaking to resolve automorphisms */
|
||||
int FastSymmetryBreaking = 1;
|
||||
|
||||
#ifdef TEST
|
||||
static void PrintElement_List(struct Element *E)
|
||||
{
|
||||
@@ -5865,16 +5862,19 @@ int ResolveAutomorphsByProperty()
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResolveAutormorphismsFull --
|
||||
* ResolveAutormorphisms --
|
||||
*
|
||||
* Arbitrarily equivalence one pair of elements within an automorphic class
|
||||
* Do symmetry breaking of automorphisms.
|
||||
*
|
||||
* Arbitrarily equivalence all pairs of elements and nodes within all
|
||||
* automorphic classes, and run to completion.
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int ResolveAutomorphismsFull()
|
||||
int ResolveAutomorphisms()
|
||||
{
|
||||
struct ElementClass *EC;
|
||||
struct Element *E;
|
||||
@@ -5936,172 +5936,6 @@ int ResolveAutomorphismsFull()
|
||||
return(VerifyMatching());
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResolveElementAutomorphismsFast --
|
||||
*
|
||||
* Apply arbitrary symmetry breaking to symmetric element lists, then
|
||||
* iterate exhaustively to resolve all automorphisms.
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int ResolveElementAutomorphismsFast()
|
||||
{
|
||||
struct ElementClass *EC;
|
||||
struct Element *E;
|
||||
int C1, C2;
|
||||
|
||||
for (EC = ElementClasses; EC != NULL; EC = EC->next) {
|
||||
struct Element *E1, *E2;
|
||||
C1 = C2 = 0;
|
||||
E1 = E2 = NULL;
|
||||
for (E = EC->elements; E != NULL; E = E->next) {
|
||||
if (E->graph == Circuit1->file) {
|
||||
C1++;
|
||||
E1 = E;
|
||||
}
|
||||
else {
|
||||
C2++;
|
||||
E2 = E;
|
||||
}
|
||||
}
|
||||
if (C1 == C2 && C1 != 1) {
|
||||
unsigned long newhash;
|
||||
|
||||
/* Do all of them at once. */
|
||||
/* NOTE: If this were to fail for some reason, it would */
|
||||
/* probably be necessary to do this the original slow way */
|
||||
/* which is to rehash one pair at a time and iterate to */
|
||||
/* convergence, and repeat. */
|
||||
|
||||
E1 = E2 = EC->elements;
|
||||
while (E1 != NULL && E2 != NULL) {
|
||||
while (E1->graph != Circuit1->file) E1 = E1->next;
|
||||
while (E2->graph != Circuit2->file) E2 = E2->next;
|
||||
Magic(newhash);
|
||||
E1->hashval = newhash;
|
||||
E2->hashval = newhash;
|
||||
E1 = E1->next;
|
||||
E2 = E2->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FractureElementClass(&ElementClasses);
|
||||
FractureNodeClass(&NodeClasses);
|
||||
ExhaustiveSubdivision = 1;
|
||||
while (!Iterate() && VerifyMatching() != -1);
|
||||
return(VerifyMatching());
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResolveNodeAutomorphismsFast --
|
||||
*
|
||||
* Apply arbitrary symmetry breaking to symmetric node lists, then iterate
|
||||
* exhaustively to resolve all automorphisms. Normally, all automorphisms
|
||||
* should be resolved by ResolveElementAutomorphisms(). It is likely true
|
||||
* that this routine will never run, by definition.
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
|
||||
int ResolveNodeAutomorphismsFast()
|
||||
{
|
||||
struct Node *N;
|
||||
struct NodeClass *NC;
|
||||
int C1, C2;
|
||||
|
||||
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||
struct Node *N1, *N2;
|
||||
C1 = C2 = 0;
|
||||
N1 = N2 = NULL;
|
||||
for (N = NC->nodes; N != NULL; N = N->next) {
|
||||
if (N->graph == Circuit1->file) {
|
||||
C1++;
|
||||
N1 = N;
|
||||
}
|
||||
else {
|
||||
C2++;
|
||||
N2 = N;
|
||||
}
|
||||
}
|
||||
if (C1 == C2 && C1 != 1) {
|
||||
unsigned long newhash;
|
||||
|
||||
/* Do all of them at once */
|
||||
/* NOTE: If this were to fail for some reason, it would */
|
||||
/* probably be necessary to do this the original slow way */
|
||||
/* which is to rehash one pair at a time and iterate to */
|
||||
/* convergence, and repeat. */
|
||||
|
||||
N1 = N2 = NC->nodes;
|
||||
while (N1 != NULL && N2 != NULL) {
|
||||
while (N1->graph != Circuit1->file) N1 = N1->next;
|
||||
while (N2->graph != Circuit2->file) N2 = N2->next;
|
||||
Magic(newhash);
|
||||
N1->hashval = newhash;
|
||||
N2->hashval = newhash;
|
||||
N1 = N1->next;
|
||||
N2 = N2->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FractureElementClass(&ElementClasses);
|
||||
FractureNodeClass(&NodeClasses);
|
||||
ExhaustiveSubdivision = 1;
|
||||
while (!Iterate() && VerifyMatching() != -1);
|
||||
return(VerifyMatching());
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResolveAutormorphisms --
|
||||
*
|
||||
* Do symmetry breaking of automorphisms. If FastSymmetryBreaking is
|
||||
* False (not the default), then run ResolveAutomorphismsFull() (q.v.).
|
||||
* Otherwise, run the fast symmetry breaking method:
|
||||
*
|
||||
* Arbitrarily equivalence all pairs of elements and nodes within all
|
||||
* automorphic classes, and run to completion. Note that this is a
|
||||
* fast version of ResolveAutomorphismsFull(), and can run many orders
|
||||
* of magnitude faster. However, it can also produce an incorrect
|
||||
* result, declaring a global mismatch where none exists. In that
|
||||
* case, the matching should be re-run with ResolveAutomorphismsFull().
|
||||
*
|
||||
* Some investigation needs to be done to determine if there is a way
|
||||
* to execute faster symmetry breaking without the possibility of
|
||||
* producing an incorrect result.
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int ResolveAutomorphisms()
|
||||
{
|
||||
int result;
|
||||
|
||||
if (FastSymmetryBreaking == 0)
|
||||
return ResolveAutomorphismsFull();
|
||||
|
||||
result = ResolveElementAutomorphismsFast();
|
||||
if (result != 0)
|
||||
result = ResolveNodeAutomorphismsFast();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* PermuteSetup -- */
|
||||
/* Add an entry to a cell's "permutes" linked list. */
|
||||
@@ -6715,24 +6549,45 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
|
||||
firstpin = ob;
|
||||
while (tob && (tob->type == PORT || tob->type == UNKNOWN)) {
|
||||
if (tob->type == UNKNOWN) {
|
||||
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
|
||||
obn->name = (char *)MALLOC(strlen(firstpin->instance.name)
|
||||
+ strlen(tob->name) + 2);
|
||||
sprintf(obn->name, "%s/%s", firstpin->instance.name, tob->name);
|
||||
obn->instance.name = strsave(firstpin->instance.name);
|
||||
obn->model.class = strsave(tc->name);
|
||||
obn->type = i++;
|
||||
obn->node = numnodes++;
|
||||
obn->next = ob; // Splice into object list
|
||||
lob->next = obn;
|
||||
lob = obn;
|
||||
/* Do not do anything with (no pins) entries (in the reference cell) */
|
||||
if (strcmp(tob->name, "proxy(no pins)")) {
|
||||
/* But if the target cell instance has proxy(no pins), then reuse
|
||||
* the record and modify it.
|
||||
*/
|
||||
if (!strcmp(ob->name, "proxy(no pins)")) {
|
||||
obn = ob;
|
||||
FREE(ob->name);
|
||||
obn->name = (char *)MALLOC(strlen(ob->instance.name)
|
||||
+ strlen(tob->name) + 2);
|
||||
sprintf(obn->name, "%s/%s", ob->instance.name, tob->name);
|
||||
ob = obn->next;
|
||||
}
|
||||
else {
|
||||
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
|
||||
obn->name = (char *)MALLOC(strlen(firstpin->instance.name)
|
||||
+ strlen(tob->name) + 2);
|
||||
sprintf(obn->name, "%s/%s", firstpin->instance.name, tob->name);
|
||||
obn->instance.name = strsave(firstpin->instance.name);
|
||||
obn->model.class = strsave(tc->name);
|
||||
obn->next = ob; // Splice into object list
|
||||
lob->next = obn;
|
||||
}
|
||||
obn->type = i++;
|
||||
obn->node = numnodes++;
|
||||
lob = obn;
|
||||
|
||||
// Hash the new pin record for "LookupObject()"
|
||||
HashPtrInstall(obn->name, obn, &(ptr->objdict));
|
||||
// Hash the new pin record for "LookupObject()"
|
||||
HashPtrInstall(obn->name, obn, &(ptr->objdict));
|
||||
|
||||
if (tob == tc->cell) {
|
||||
// Rehash the instance in instdict
|
||||
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
|
||||
if (tob == tc->cell) {
|
||||
// Rehash the instance in instdict
|
||||
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
|
||||
}
|
||||
}
|
||||
else {
|
||||
lob = ob;
|
||||
ob->type = i++;
|
||||
ob = ob->next;
|
||||
}
|
||||
}
|
||||
else if (ob == NULL) {
|
||||
|
||||
@@ -7,7 +7,6 @@ extern struct nlist *Circuit1;
|
||||
extern struct nlist *Circuit2;
|
||||
|
||||
extern int ExhaustiveSubdivision;
|
||||
extern int FastSymmetryBreaking;
|
||||
|
||||
extern int left_col_end;
|
||||
extern int right_col_end;
|
||||
|
||||
+42
-7
@@ -2470,7 +2470,8 @@ void CopyProperties(struct objlist *obj_to, struct objlist *obj_from)
|
||||
kvcur->value.ival = 0;
|
||||
|
||||
obj_to->instance.props = kvcopy;
|
||||
obj_to->model.class = strsave(obj_from->model.class);
|
||||
if (obj_from->model.class)
|
||||
obj_to->model.class = strsave(obj_from->model.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3131,6 +3132,9 @@ int remove_group_tags(struct objlist *ob)
|
||||
/* If the device has permutable pins, then duplicate hashes are made */
|
||||
/* for each permutation. */
|
||||
/* */
|
||||
/* If the device has isolated (unconnected) pins, then treat them as */
|
||||
/* all belonging to the same net for the purpose of parallel merging. */
|
||||
/* */
|
||||
/* Return the number of devices merged. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
@@ -3145,6 +3149,7 @@ int CombineParallel(char *model, int file)
|
||||
size_t pcnt;
|
||||
int i, dcnt = 0, hastag;
|
||||
char *pstr, *p2str, *pptr;
|
||||
int *nodecount;
|
||||
struct valuelist *kv;
|
||||
|
||||
if ((tp = LookupCellFile(model, file)) == NULL) {
|
||||
@@ -3154,6 +3159,17 @@ int CombineParallel(char *model, int file)
|
||||
|
||||
InitializeHashTable(&devdict, OBJHASHSIZE);
|
||||
|
||||
/* Make one pass to count the number of times each node number is */
|
||||
/* used. This list indicates which pins are no-connects, so they */
|
||||
/* can be treated as equivalent for the purpose of parallelization. */
|
||||
|
||||
nodecount = (int *)CALLOC((tp->nodename_cache_maxnodenum + 1), sizeof(int));
|
||||
for (ob = tp->cell; ob; ob = ob->next) {
|
||||
if (ob->node >= 0)
|
||||
if (ob->type != NODE)
|
||||
nodecount[ob->node]++;
|
||||
}
|
||||
|
||||
lob = NULL;
|
||||
for (ob = tp->cell; ob; ) {
|
||||
if (ob->type == FIRSTPIN) {
|
||||
@@ -3200,7 +3216,10 @@ int CombineParallel(char *model, int file)
|
||||
pptr += pstr - (char *)2;
|
||||
|
||||
for (ob2 = ob; ob2 && (ob2->type > FIRSTPIN || ob2 == ob); ob2 = ob2->next) {
|
||||
sprintf(pptr, "_%d", ob2->node);
|
||||
if ((ob->node >= 0) && (nodecount[ob->node] == 1))
|
||||
strcat(pptr, "_nc");
|
||||
else
|
||||
sprintf(pptr, "_%d", ob2->node);
|
||||
pptr += strlen(pptr);
|
||||
}
|
||||
|
||||
@@ -3236,11 +3255,26 @@ int CombineParallel(char *model, int file)
|
||||
for (ob2 = ob; ob2 && (ob2->type > FIRSTPIN || ob2 == ob);
|
||||
ob2 = ob2->next) {
|
||||
if (ob2 == pob1)
|
||||
sprintf(pptr, "_%d", pob2->node);
|
||||
{
|
||||
if ((pob2->node >= 0) && (nodecount[pob2->node] == 1))
|
||||
strcat(pptr, "_nc");
|
||||
else
|
||||
sprintf(pptr, "_%d", pob2->node);
|
||||
}
|
||||
else if (ob2 == pob2)
|
||||
sprintf(pptr, "_%d", pob1->node);
|
||||
{
|
||||
if ((pob1->node >= 0) && (nodecount[pob1->node] == 1))
|
||||
strcat(pptr, "_nc");
|
||||
else
|
||||
sprintf(pptr, "_%d", pob1->node);
|
||||
}
|
||||
else
|
||||
sprintf(pptr, "_%d", ob2->node);
|
||||
{
|
||||
if ((ob2->node >= 0) && (nodecount[ob2->node] == 1))
|
||||
strcat(pptr, "_nc");
|
||||
else
|
||||
sprintf(pptr, "_%d", ob2->node);
|
||||
}
|
||||
pptr += strlen(pptr);
|
||||
}
|
||||
HashPtrInstall(p2str, ob, &devdict);
|
||||
@@ -3364,6 +3398,7 @@ int CombineParallel(char *model, int file)
|
||||
if (dcnt > 0) {
|
||||
Fprintf(stdout, "Class %s: Merged %d devices.\n", model, dcnt);
|
||||
}
|
||||
FREE(nodecount);
|
||||
return dcnt;
|
||||
}
|
||||
|
||||
@@ -3583,8 +3618,8 @@ int CombineSeries(char *model, int file)
|
||||
|
||||
/* Excise the 2nd instance. instlist[i][1] remains as the */
|
||||
/* only pointer to it. */
|
||||
for (obp = instlist[i][0]; obp->next->type > FIRSTPIN ||
|
||||
obp->next->type == PROPERTY; obp = obp->next);
|
||||
for (obp = instlist[i][0]; obp->next && (obp->next->type > FIRSTPIN ||
|
||||
obp->next->type == PROPERTY); obp = obp->next);
|
||||
for (ob2 = obp; ob2 && ob2->next != instlist[i][1]; ob2 = ob2->next);
|
||||
|
||||
/* Device may have been moved by the above code. If so, look for */
|
||||
|
||||
@@ -65,6 +65,15 @@ extern void AssignCircuits(char *name1, int file1, char *name2, int file2);
|
||||
/* flatten.c */
|
||||
extern int PrematchLists(char *, int, char *, int);
|
||||
|
||||
/* verilog.c */
|
||||
struct cellstack {
|
||||
char *cellname;
|
||||
struct cellstack *next;
|
||||
};
|
||||
|
||||
void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
|
||||
int blackbox);
|
||||
|
||||
/* Define (enumerate) various device classes, largely based on SPICE */
|
||||
/* model types, mixed with some ext/sim types. */
|
||||
|
||||
|
||||
+1
-2
@@ -192,9 +192,8 @@ struct Permutation {
|
||||
struct Permutation *next;
|
||||
};
|
||||
|
||||
#define OBJHASHSIZE 997 /* the size of the object and instance hash lists */
|
||||
#define OBJHASHSIZE 42073 /* the size of the object and instance hash lists */
|
||||
/* prime numbers are good choices as hash sizes */
|
||||
/* 101 is a good number for IBMPC */
|
||||
|
||||
/* cell definition for hash table */
|
||||
/* NOTE: "file" must come first for the hash matching by name and file */
|
||||
|
||||
+11
-9
@@ -473,15 +473,6 @@ void CleanupSubcell() {
|
||||
SetClass(CLASS_MODULE);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Structure for stacking nested subcircuit definitions */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
struct cellstack {
|
||||
char *cellname;
|
||||
struct cellstack *next;
|
||||
};
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Push a subcircuit name onto the stack */
|
||||
/*------------------------------------------------------*/
|
||||
@@ -874,6 +865,17 @@ skip_ends:
|
||||
}
|
||||
}
|
||||
|
||||
/* Ignore anything in a .CONTROL ... .ENDC block */
|
||||
else if (matchnocase(nexttok, ".CONTROL")) {
|
||||
while (1) {
|
||||
SpiceSkipNewLine();
|
||||
SkipTok(NULL);
|
||||
if (EndParseFile()) break;
|
||||
if (matchnocase(nexttok, ".ENDC"))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Blackbox (library) mode---parse only subcircuits and models;
|
||||
// ignore all components.
|
||||
|
||||
|
||||
+37
-6
@@ -553,9 +553,43 @@ void CleanupModule() {
|
||||
int maxnode = 0;
|
||||
int has_submodules = FALSE;
|
||||
struct objlist *sobj, *nobj, *lobj, *pobj;
|
||||
struct objlist *myLastPort, *object_it, *myNextObject;
|
||||
|
||||
if (CurrentCell == NULL) return;
|
||||
|
||||
myLastPort = NULL;
|
||||
|
||||
/* Reorder objects so that all ports come first, before nodes, because
|
||||
* parts of the code depend on it.
|
||||
*/
|
||||
|
||||
for (object_it = CurrentCell->cell; object_it && object_it->type <= 0;
|
||||
object_it = myNextObject ) {
|
||||
|
||||
myNextObject = object_it->next;
|
||||
if (!myNextObject) // end of list
|
||||
continue;
|
||||
|
||||
if (myLastPort == NULL) {
|
||||
if (object_it->type == PORT) {
|
||||
myLastPort = object_it; // port at begining of list
|
||||
myNextObject = object_it; // otherwise skips one
|
||||
}
|
||||
else if (myNextObject->type == PORT) {
|
||||
object_it->next = myNextObject->next;
|
||||
myNextObject->next = CurrentCell->cell;
|
||||
CurrentCell->cell = myNextObject;
|
||||
myLastPort = myNextObject;
|
||||
}
|
||||
}
|
||||
else if (myNextObject->type == PORT) {
|
||||
object_it->next = myNextObject->next;
|
||||
myNextObject->next = myLastPort->next;
|
||||
myLastPort->next = myNextObject;
|
||||
myLastPort = myNextObject;
|
||||
}
|
||||
}
|
||||
|
||||
for (sobj = CurrentCell->cell; sobj; sobj = sobj->next)
|
||||
if (sobj->node > maxnode)
|
||||
maxnode = sobj->node + 1;
|
||||
@@ -598,11 +632,6 @@ void CleanupModule() {
|
||||
/* Structure for stacking nested module definitions */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
struct cellstack {
|
||||
char *cellname;
|
||||
struct cellstack *next;
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
extern void IncludeVerilog(char *, int, struct cellstack **, int);
|
||||
|
||||
@@ -1946,7 +1975,9 @@ nextinst:
|
||||
sprintf(localnet, "_noconnect_%d_", localcount++);
|
||||
Node(localnet);
|
||||
join(localnet, obptr->name);
|
||||
Fprintf(stderr, "Note: Implicit pin %s\n", obpinname);
|
||||
Fprintf(stderr,
|
||||
"Note: Implicit pin %s in instance %s of %s in cell %s\n",
|
||||
obpinname, locinst, modulename, CurrentCell->name);
|
||||
}
|
||||
else if (GetBus(scan->net, &wb) == 0) {
|
||||
char *bptr2;
|
||||
|
||||
@@ -382,9 +382,6 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
} elseif {$arg == "-blackbox"} {
|
||||
puts stdout "Treating empty subcircuits as black-box cells"
|
||||
netgen::model blackbox on
|
||||
} elseif {$arg == "-full"} {
|
||||
puts stdout "Using full symmetry breaking method"
|
||||
netgen::symmetry full
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-29
@@ -246,8 +246,7 @@ Command netcmp_cmds[] = {
|
||||
"\n "
|
||||
"toggle exhaustive subdivision"},
|
||||
{"symmetry", _netcmp_symmetry,
|
||||
"[fast|full]\n "
|
||||
"apply method for symmetry breaking"},
|
||||
"(deprecated)"},
|
||||
{"restart", _netcmp_restart,
|
||||
"\n "
|
||||
"start over (reset data structures)"},
|
||||
@@ -3982,39 +3981,14 @@ _netcmp_permute(ClientData clientData,
|
||||
/* Formerly: x */
|
||||
/* Results: */
|
||||
/* Side Effects: */
|
||||
/* Notes: Deprecated, retained for compatibility. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
int
|
||||
_netcmp_symmetry(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
char *fastfull[] = {
|
||||
"fast", "full", NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
FAST_IDX, FULL_IDX
|
||||
};
|
||||
int result, index;
|
||||
|
||||
if (objc == 1)
|
||||
index = -1;
|
||||
else {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)fastfull,
|
||||
"option", 0, &index) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
switch(index) {
|
||||
case FAST_IDX:
|
||||
FastSymmetryBreaking = TRUE;
|
||||
break;
|
||||
case FULL_IDX:
|
||||
FastSymmetryBreaking = FALSE;
|
||||
break;
|
||||
}
|
||||
Printf("Symmetry breaking method: %s.\n",
|
||||
FastSymmetryBreaking ? "FAST" : "FULL");
|
||||
|
||||
Printf("Symmetry breaking method has been deprecated.\n");
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user