WIP: bug fix for symmetry detection (should consider different pins to break symmetry). Added tests.

This commit is contained in:
Matthias Koefferlein 2020-02-27 00:27:09 +01:00
parent b35429291e
commit a46cd305c6
2 changed files with 144 additions and 32 deletions

View File

@ -3749,14 +3749,16 @@ NetlistComparer::join_symmetric_nodes (db::Circuit *circuit)
}
std::list<std::set<size_t> > symmetry_groups;
std::set<size_t> considered_nodes;
std::set<size_t> visited;
for (std::vector<const NetGraphNode *>::const_iterator np = nodes.begin (); np != nodes.end (); ++np) {
size_t node_id = graph.node_index_for_net (np[0]->net ());
if (considered_nodes.find (node_id) != considered_nodes.end ()) {
if (visited.find (node_id) != visited.end ()) {
continue;
}
std::set<size_t> considered_nodes;
considered_nodes.insert (node_id);
std::set<size_t> symmetry_group;
@ -3764,16 +3766,8 @@ NetlistComparer::join_symmetric_nodes (db::Circuit *circuit)
derive_symmetry_groups (graph, identical_nodes, considered_nodes, symmetry_group, symmetry_groups);
}
visited.insert (considered_nodes.begin (), considered_nodes.end ());
// join the nets
for (std::list<std::set<size_t> >::const_iterator g = symmetry_groups.begin (); g != symmetry_groups.end (); ++g) {
for (std::set<size_t>::const_iterator i = g->begin (); i != g->end (); ++i) {
if (i != g->begin ()) {
circuit->join_nets (const_cast<db::Net *> (graph.net_by_node_index (*g->begin ())), const_cast<db::Net *> (graph.net_by_node_index (*i)));
}
}
}
if (! symmetry_groups.empty () && tl::verbosity () >= 30) {
@ -3789,6 +3783,15 @@ NetlistComparer::join_symmetric_nodes (db::Circuit *circuit)
}
}
// join the nets
for (std::list<std::set<size_t> >::const_iterator g = symmetry_groups.begin (); g != symmetry_groups.end (); ++g) {
for (std::set<size_t>::const_iterator i = g->begin (); i != g->end (); ++i) {
if (i != g->begin ()) {
circuit->join_nets (const_cast<db::Net *> (graph.net_by_node_index (*g->begin ())), const_cast<db::Net *> (graph.net_by_node_index (*i)));
}
}
}
}
}

View File

@ -3704,9 +3704,9 @@ TEST(24_NodesRemovedButConnectedInOther)
EXPECT_EQ (good, true);
}
TEST(25_SplitGates)
TEST(25_JoinSymmetricNets)
{
const char *nls1 =
const char *nls =
"circuit NAND2 (A=A,B=B,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=OUT,G=A,D=VDD) (L=0.25,W=1);\n"
" device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=1);\n"
@ -3717,8 +3717,29 @@ TEST(25_SplitGates)
" device NMOS $6 (S=$2,G=B,D=VSS) (L=0.25,W=1);\n"
"end;\n";
nls1 =
"circuit NAND2 (A=A,B=B);\n"
db::Netlist nl;
prep_nl (nl, nls);
db::NetlistComparer comp;
comp.join_symmetric_nodes (nl.circuit_by_name ("NAND2"));
// NOTE $1 and $2 are joined because they are symmetric
EXPECT_EQ (nl.to_string (),
"circuit NAND2 (A=A,B=B,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=OUT,G=A,D=VDD) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device NMOS $3 (S=$1,G=A,D=OUT) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device NMOS $4 (S=$1,G=A,D=OUT) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device NMOS $5 (S=$1,G=B,D=VSS) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device NMOS $6 (S=$1,G=B,D=VSS) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
"end;\n"
)
}
TEST(26_JoinSymmetricNets)
{
const char *nls =
"circuit RESCUBE (A=A,B=B);\n"
" device RES $1 (A=A,B=$1) (R=1000);\n"
" device RES $2 (A=A,B=$2) (R=1000);\n"
" device RES $3 (A=A,B=$3) (R=1000);\n"
@ -3733,25 +3754,113 @@ TEST(25_SplitGates)
" device RES $11 (A=$6,B=B) (R=1000);\n"
"end;\n";
const char *nls2 =
"circuit NAND2 (A=A,B=B,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=OUT,G=A,D=VDD) (L=0.25,W=1);\n"
" device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=1);\n"
" device NMOS $3 (S=$1,G=A,D=OUT) (L=0.25,W=2);\n"
" device NMOS $4 (S=$1,G=B,D=VSS) (L=0.25,W=2);\n"
"end;\n";
db::Netlist nl1, nl2;
prep_nl (nl1, nls1);
prep_nl (nl2, nls2);
db::Netlist nl;
prep_nl (nl, nls);
db::NetlistComparer comp;
comp.join_symmetric_nodes (nl1.circuit_by_name ("NAND2")); // @@@
#if 0
bool good = comp.compare (&nl1, &nl2);
comp.join_symmetric_nodes (nl.circuit_by_name ("RESCUBE"));
std::string txt = logger.text ();
EXPECT_EQ (nl.to_string (),
"circuit RESCUBE (A=A,B=B);\n"
" device RES $1 (A=A,B=$1) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $2 (A=A,B=$1) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $3 (A=A,B=$1) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $4 (A=$1,B=$4) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $5 (A=$1,B=$4) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $6 (A=$1,B=$4) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $7 (A=$1,B=$4) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $8 (A=$1,B=$4) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $9 (A=$1,B=$4) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $10 (A=$4,B=B) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $11 (A=$4,B=B) (R=1000,L=0,W=0,A=0,P=0);\n"
" device RES $12 (A=$4,B=B) (R=1000,L=0,W=0,A=0,P=0);\n"
"end;\n"
)
printf("@@@\n%s", txt.c_str()); fflush(stdout); // @@@
#endif
nl.combine_devices ();
EXPECT_EQ (nl.to_string (),
"circuit RESCUBE (A=A,B=B);\n"
" device RES $10 (A=A,B=B) (R=833.333333333,L=0,W=0,A=0,P=0);\n"
"end;\n"
)
}
TEST(27_DontJoinSymmetricNetsWithPins)
{
const char *nls =
"circuit NAND2 (A=A,B=B,OUT=OUT,VSS=VSS,VDD=VDD,X=$1,Y=$2);\n"
" device PMOS $1 (S=OUT,G=A,D=VDD) (L=0.25,W=1);\n"
" device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=1);\n"
// NOTE: $1 and $2 are separate nets, but can be joined due to symmetry
" device NMOS $3 (S=$1,G=A,D=OUT) (L=0.25,W=1);\n"
" device NMOS $4 (S=$2,G=A,D=OUT) (L=0.25,W=1);\n"
" device NMOS $5 (S=$1,G=B,D=VSS) (L=0.25,W=1);\n"
" device NMOS $6 (S=$2,G=B,D=VSS) (L=0.25,W=1);\n"
"end;\n";
db::Netlist nl;
prep_nl (nl, nls);
db::NetlistComparer comp;
comp.join_symmetric_nodes (nl.circuit_by_name ("NAND2"));
// NOTE $1 and $2 are NOT joined because they have pins
EXPECT_EQ (nl.to_string (),
"circuit NAND2 (A=A,B=B,OUT=OUT,VSS=VSS,VDD=VDD,X=$1,Y=$2);\n"
" device PMOS $1 (S=OUT,G=A,D=VDD) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device NMOS $3 (S=$1,G=A,D=OUT) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device NMOS $4 (S=$2,G=A,D=OUT) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device NMOS $5 (S=$1,G=B,D=VSS) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
" device NMOS $6 (S=$2,G=B,D=VSS) (L=0.25,W=1,AS=0,AD=0,PS=0,PD=0);\n"
"end;\n"
)
}
TEST(28_NoSymmetryDetectionCases)
{
{
const char *nls =
"circuit NAND2 (A=A,B=B,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=OUT,G=A,D=VDD) (L=0.25,W=1);\n"
" device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=1);\n"
// NOTE: $1 and $2 are separate nets, but cannot be joined because of different W
" device NMOS $3 (S=$1,G=A,D=OUT) (L=0.25,W=1);\n"
" device NMOS $4 (S=$2,G=A,D=OUT) (L=0.25,W=1.1);\n"
" device NMOS $5 (S=$1,G=B,D=VSS) (L=0.25,W=1);\n"
" device NMOS $6 (S=$2,G=B,D=VSS) (L=0.25,W=1);\n"
"end;\n";
db::Netlist nl;
prep_nl (nl, nls);
db::NetlistComparer comp;
std::string sref = nl.to_string ();
comp.join_symmetric_nodes (nl.circuit_by_name ("NAND2"));
EXPECT_EQ (nl.to_string (), sref);
}
{
const char *nls =
"circuit NAND2 (A=A,B=B,OUT=OUT,VSS=VSS,VSS2=VSS2,VDD=VDD);\n"
" device PMOS $1 (S=OUT,G=A,D=VDD) (L=0.25,W=1);\n"
" device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=1);\n"
" device NMOS $3 (S=$1,G=A,D=OUT) (L=0.25,W=1);\n"
" device NMOS $4 (S=$2,G=A,D=OUT) (L=0.25,W=1);\n"
// NOTE: $1 and $2 are separate nets, but cannot be joined because of different D connections
" device NMOS $5 (S=$1,G=B,D=VSS) (L=0.25,W=1);\n"
" device NMOS $6 (S=$2,G=B,D=VSS2) (L=0.25,W=1);\n"
"end;\n";
db::Netlist nl;
prep_nl (nl, nls);
db::NetlistComparer comp;
std::string sref = nl.to_string ();
comp.join_symmetric_nodes (nl.circuit_by_name ("NAND2"));
EXPECT_EQ (nl.to_string (), sref);
}
}