mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-27 16:36:42 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4a4621b96 | ||
|
|
1d286f9973 | ||
|
|
3ca77300ac | ||
|
|
6d2ef396ef | ||
|
|
2483b7440f | ||
|
|
236fba18aa | ||
|
|
49c0de0433 | ||
|
|
3b9dca0cf2 | ||
|
|
1272ed22fe | ||
|
|
7d910b616c |
@@ -1306,6 +1306,14 @@ int UniquePins(char *name, int filenum)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Structure used below for keeping track of node numbers
|
||||
* belonging to removed nodes.
|
||||
*/
|
||||
struct LinkedNum {
|
||||
int node;
|
||||
struct LinkedNum *next;
|
||||
};
|
||||
|
||||
/*------------------------------------------------------*/
|
||||
/* Callback function for CleanupPins */
|
||||
/* Note that if the first pin of the instance is a */
|
||||
@@ -1318,6 +1326,7 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
struct nlist *ptr;
|
||||
struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob;
|
||||
struct nlist *tc = (struct nlist *)clientdata;
|
||||
struct LinkedNum *newnodenum, *removedNodes = (struct LinkedNum *)NULL;
|
||||
int pinnum;
|
||||
char *saveinst = NULL;
|
||||
|
||||
@@ -1373,6 +1382,15 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
saveinst = ob->instance.name;
|
||||
}
|
||||
if (ob->model.class != NULL) FREE(ob->model.class);
|
||||
|
||||
// Record the net number of the pin being removed, to
|
||||
// check at the end if the net belonged to a pin that
|
||||
// got orphaned.
|
||||
newnodenum = (struct LinkedNum *)MALLOC(sizeof(struct LinkedNum));
|
||||
newnodenum->node = ob->node;
|
||||
newnodenum->next = removedNodes;
|
||||
removedNodes = newnodenum;
|
||||
|
||||
FREE(ob);
|
||||
}
|
||||
else {
|
||||
@@ -1416,6 +1434,28 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
|
||||
}
|
||||
}
|
||||
|
||||
while (removedNodes != NULL) {
|
||||
int nodenum = removedNodes->node;
|
||||
struct objlist *ob2;
|
||||
|
||||
/* Only concerned with nodes that are in the pin list of ptr->cell */
|
||||
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
|
||||
if (ob->type != PORT) break;
|
||||
if (ob->node == nodenum) break;
|
||||
}
|
||||
if (ob && (ob->type == PORT)) {
|
||||
/* Check if this node number exists only in the port record */
|
||||
for (nob = ob->next; nob != NULL; nob = nob->next)
|
||||
if (nob->node == nodenum) break;
|
||||
if (nob == NULL) {
|
||||
ob->node = -1; /* This pin is now disconnected */
|
||||
}
|
||||
}
|
||||
newnodenum = removedNodes;
|
||||
removedNodes = removedNodes->next;
|
||||
FREE(newnodenum);
|
||||
}
|
||||
|
||||
if (saveinst != NULL) FREE(saveinst);
|
||||
return NULL; /* Keep the search going */
|
||||
}
|
||||
|
||||
+58
-10
@@ -6567,11 +6567,16 @@ void PrintAutomorphisms(void)
|
||||
* separating out those devices that are connected to matching pins
|
||||
* in each circuit.
|
||||
*
|
||||
* If match_nets == TRUE, then also match internal nets by name. Pins
|
||||
* should always be matched by name without considering nets first;
|
||||
* once all symmetries related to pins have been broken, then matching
|
||||
* symmetries by net can keep the output from looking confusing.
|
||||
*
|
||||
* Return value is the same as VerifyMatching()
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int ResolveAutomorphsByPin()
|
||||
int ResolveAutomorphsByPin(int match_nets)
|
||||
{
|
||||
struct NodeClass *NC;
|
||||
struct Node *N;
|
||||
@@ -6580,7 +6585,10 @@ int ResolveAutomorphsByPin()
|
||||
int portnum;
|
||||
|
||||
/* Diagnostic */
|
||||
Fprintf(stdout, "Resolving symmetries by pin name.\n");
|
||||
if (match_nets)
|
||||
Fprintf(stdout, "Resolving symmetries by net name.\n");
|
||||
else
|
||||
Fprintf(stdout, "Resolving symmetries by pin name.\n");
|
||||
|
||||
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||
struct Node *N1, *N2;
|
||||
@@ -6604,7 +6612,9 @@ int ResolveAutomorphsByPin()
|
||||
if (N1->hashval != orighash) continue;
|
||||
for (N2 = N1->next; N2 != NULL; N2 = N2->next) {
|
||||
if ((N2->graph != N1->graph) &&
|
||||
(*matchfunc)(N2->object->name, N1->object->name)) {
|
||||
(*matchfunc)(N2->object->name, N1->object->name) &&
|
||||
(N1->object->type == PORT || N2->object->type == PORT)) {
|
||||
|
||||
if (Debug == TRUE)
|
||||
Printf("Symmetry group broken by name match (pin %s)\n", N2->object->name);
|
||||
Magic(newhash);
|
||||
@@ -7582,6 +7592,10 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
for (ob2 = tc2->cell; ob2 != NULL; ob2 = ob2->next) {
|
||||
if (ob2->type != PORT) break;
|
||||
else haspins = 1;
|
||||
/* The model.port record for pins will be used to match the pin order
|
||||
* of the cells in each netlist. Make sure the value is reset on
|
||||
* entering this subroutine.
|
||||
*/
|
||||
ob2->model.port = -1;
|
||||
}
|
||||
numnodes = 0;
|
||||
@@ -7735,7 +7749,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (strcmp(obn->name, "(no pins)")) {
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", obn->name);
|
||||
output_string_right(ostr, "(no pin, node is %s",
|
||||
output_string_right(ostr, "(no pin, node is %s)",
|
||||
obp->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
@@ -8027,11 +8041,36 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (ob2->type != PORT) break;
|
||||
if (ob2->model.port == -1) {
|
||||
|
||||
/* Find this node in NodeClasses and find the corresponding
|
||||
* net in the other circuit, if there is one (NOTE: Needs
|
||||
* refactoring; should not be going through NodeClasses
|
||||
* inside a loop.)
|
||||
*/
|
||||
obn = NULL;
|
||||
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||
for (N2 = NC->nodes; N2 != NULL; N2 = N2->next) {
|
||||
if (N2->graph != Circuit1->file) {
|
||||
obp = N2->object;
|
||||
if (IsPort(obp) && (obp->node == ob2->node)) {
|
||||
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
|
||||
if (N1->graph == Circuit1->file) {
|
||||
obn = N1->object;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Debug == 0) {
|
||||
// See above for reverse case
|
||||
if (strcmp(ob2->name, "(no pins)")) {
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", "(no matching pin)");
|
||||
if (obn == NULL)
|
||||
output_string_left(ostr, "%s", "(no matching pin)");
|
||||
else
|
||||
output_string_left(ostr, "(no pin, node is %s)",
|
||||
obn->name);
|
||||
output_string_right(ostr, "%s", ob2->name);
|
||||
output_string_print(ostr);
|
||||
}
|
||||
@@ -8148,12 +8187,15 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
if (obn == NULL) ob1->node = -1; /* Make disconnected */
|
||||
}
|
||||
|
||||
/* NOTE: Previously kept the port if model.port is -1; however,
|
||||
* all ports are -1 here so not sure why that was in there. . .
|
||||
*/
|
||||
if (ob1 == NULL || ob1->type != PORT || ob1->node >= 0
|
||||
|| (ob1->node < 0 && tc1->class == CLASS_MODULE)
|
||||
|| (ob1->node < 0 && ob1->model.port == -1)) {
|
||||
|| (ob1->node < 0 && tc1->class == CLASS_MODULE)) {
|
||||
|
||||
/* Add a proxy pin to tc2 */
|
||||
obn = (struct objlist *)CALLOC(1, sizeof(struct objlist));
|
||||
obn->node = -1;
|
||||
if (ob1 == NULL) {
|
||||
obn->name = (char *)MALLOC(15);
|
||||
sprintf(obn->name, "proxy%d", rand() & 0x3ffffff);
|
||||
@@ -8165,7 +8207,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
obn->type = UNKNOWN;
|
||||
obn->model.port = (i - j);
|
||||
obn->instance.name = NULL;
|
||||
obn->node = -1;
|
||||
|
||||
if (ob2 == tc2->cell) {
|
||||
obn->next = ob2;
|
||||
@@ -8181,9 +8222,16 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
|
||||
HashPtrInstall(obn->name, obn, &(tc2->objdict));
|
||||
}
|
||||
|
||||
else if (ob1 != NULL && ob1->type == PORT) {
|
||||
else if (ob1 != NULL && ob1->type == PORT && ob1->node < 0) {
|
||||
/* Disconnected node was not meaningful, has no pin match in */
|
||||
/* the compared circuit, and so should be discarded. */
|
||||
/* the compared circuit, and so should be discarded. This */
|
||||
/* case is not output above, so do it here. */
|
||||
|
||||
output_string_fill(ostr);
|
||||
output_string_left(ostr, "%s", ob1->name);
|
||||
output_string_right(ostr, "%s", "(no matching pin)");
|
||||
output_string_print(ostr);
|
||||
|
||||
ob1->node = -2;
|
||||
needclean1 = 1;
|
||||
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ extern void RegroupDataStructures();
|
||||
extern void FormatIllegalElementClasses();
|
||||
extern void FormatIllegalNodeClasses();
|
||||
extern int ResolveAutomorphsByProperty();
|
||||
extern int ResolveAutomorphsByPin();
|
||||
extern int ResolveAutomorphsByPin(int match_nets);
|
||||
extern void SummarizeElementClasses(struct ElementClass *EC);
|
||||
extern int remove_group_tags(struct objlist *ob);
|
||||
|
||||
|
||||
@@ -223,6 +223,7 @@ int matchnocase(char *st1, char *st2)
|
||||
{
|
||||
char *sp1 = st1;
|
||||
char *sp2 = st2;
|
||||
char v1 = FALSE, v2 = FALSE;
|
||||
|
||||
/* In case of a property that does not exist in one netlist, matchnocase()
|
||||
* may be passed a null value, so return 0 to indicate a non-match.
|
||||
@@ -231,11 +232,26 @@ int matchnocase(char *st1, char *st2)
|
||||
*/
|
||||
if (!sp1 || !sp2) return 0;
|
||||
|
||||
/* Verilog back-slash escaped names should match an equivalent non-
|
||||
* back-slashed name. (NOTE: This behavior needs to be added to match().)
|
||||
*/
|
||||
if ((*sp1 == '\\') && (*sp2 != '\\')) {
|
||||
v1 = TRUE;
|
||||
sp1++;
|
||||
}
|
||||
if ((*sp2 == '\\') && (*sp1 != '\\')) {
|
||||
v2 = TRUE;
|
||||
sp2++;
|
||||
}
|
||||
|
||||
while (*sp1 != '\0' && *sp2 != '\0') {
|
||||
if (to_lower[*sp1] != to_lower[*sp2]) break;
|
||||
sp1++;
|
||||
sp2++;
|
||||
}
|
||||
if (v1 && (*sp1 == ' ')) sp1++;
|
||||
if (v2 && (*sp2 == ' ')) sp2++;
|
||||
|
||||
if ((*sp1 != '\0') || (*sp2 != '\0')) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+17
-4
@@ -717,10 +717,12 @@ int GetBus(char *astr, struct bus *wb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Output a Verilog Module. Note that since Verilog does not describe
|
||||
// low-level devices like transistors, capacitors, etc., then this
|
||||
// format is limited to black-box subcircuits. Cells containing any
|
||||
// such low-level devices are ignored.
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
void VerilogModule(struct nlist *tp)
|
||||
{
|
||||
@@ -1833,8 +1835,9 @@ skip_endmodule:
|
||||
}
|
||||
else { /* "assign" */
|
||||
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
|
||||
if (GetBusTok(&wb) == 0) {
|
||||
char *aptr = strvchr(nexttok, '[');
|
||||
char *aptr = strvchr(nexttok, '[');
|
||||
if (((aptr == NULL) && (GetBusTok(&wb) == 0)) ||
|
||||
((aptr != NULL) && (GetBus(aptr, &wb) == 0))) {
|
||||
if (aptr != NULL) {
|
||||
*aptr = '\0';
|
||||
/* Find object of first net in bus */
|
||||
@@ -1852,6 +1855,15 @@ skip_endmodule:
|
||||
}
|
||||
else {
|
||||
lhs = LookupObject(nexttok, CurrentCell);
|
||||
/* Handle the case in which an assignment is made
|
||||
* without first declaring a wire for the signal,
|
||||
* which is considered valid syntax (patch by
|
||||
* Sylvain Munaut).
|
||||
*/
|
||||
if (lhs == NULL) {
|
||||
Node(nexttok);
|
||||
lhs = LookupObject(nexttok, CurrentCell);
|
||||
}
|
||||
strcpy(noderoot, nexttok);
|
||||
}
|
||||
SkipTokComments(VLOG_DELIMITERS);
|
||||
@@ -1900,8 +1912,9 @@ skip_endmodule:
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (GetBusTok(&wb2) == 0) {
|
||||
char *aptr = strvchr(nexttok, '[');
|
||||
char *aptr = strvchr(nexttok, '[');
|
||||
if (((aptr == NULL) && (GetBusTok(&wb2) == 0)) ||
|
||||
((aptr != NULL) && (GetBus(aptr, &wb2) == 0))) {
|
||||
j = wb2.start;
|
||||
if (aptr != NULL) {
|
||||
*aptr = '\0';
|
||||
|
||||
@@ -655,6 +655,11 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
}
|
||||
} elseif {[netgen::print queue] == {} && $result == 0} {
|
||||
set pinMismatch 1
|
||||
} else {
|
||||
# This assumes that proxy pins are added correctly. Previously,
|
||||
# that was not trusted, and so an initial pin mismatch would
|
||||
# always force subcells to be flattened.
|
||||
set doFlatten 0
|
||||
}
|
||||
}
|
||||
if {$doFlatten} {
|
||||
|
||||
+7
-1
@@ -2512,7 +2512,13 @@ _netcmp_run(ClientData clientData,
|
||||
if (automorphisms > 0) {
|
||||
// Next, attempt to resolve automorphisms uniquely by
|
||||
// using the pin names
|
||||
automorphisms = ResolveAutomorphsByPin();
|
||||
automorphisms = ResolveAutomorphsByPin(FALSE);
|
||||
}
|
||||
if (automorphisms > 0) {
|
||||
// Next, attempt to resolve automorphisms uniquely by
|
||||
// using the net names (should only be done after
|
||||
// resolving by pin).
|
||||
automorphisms = ResolveAutomorphsByPin(TRUE);
|
||||
}
|
||||
if (automorphisms > 0) {
|
||||
// Anything left is truly indistinguishable
|
||||
|
||||
Reference in New Issue
Block a user