mirror of https://github.com/KLayout/klayout.git
WIP: bug fix for symmetry detection (should consider different pins to break symmetry). Added tests.
This commit is contained in:
parent
b35429291e
commit
a46cd305c6
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue