Some enhancments + test update

1. Be more careful with net names
Net names are used now for sorting the graph nodes, but not for
strict compare. This is useful to derive swappable pins for
blackbox circuits.

2. Be more careful with pins from schematic netlist
Pins from schematic netlist without a corresponding pin on the layer
side are treated as mandatory unless connected to a trivial net.
Pins connecting to non-trivial nets inside the subcircuit are always
considered mandatory.
This way schematic pins enforce corresponding layout pins.
On the other hand, layout pins connecting to trivial nets inside
the subcircuit are considered non-mandatory.
This commit is contained in:
Matthias Koefferlein 2021-07-18 22:34:02 +02:00
parent 51d117e379
commit 2c8d065eb3
3 changed files with 260 additions and 110 deletions

View File

@ -917,12 +917,12 @@ public:
/**
* @brief Builds a node for a net
*/
NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id);
NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id);
/**
* @brief Builds a virtual node for a subcircuit
*/
NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id);
NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id);
void expand_subcircuit_nodes (NetGraph *graph);
@ -970,8 +970,18 @@ public:
void apply_net_index (const std::map<const db::Net *, size_t> &ni);
bool operator< (const NetGraphNode &node) const;
bool operator== (const NetGraphNode &node) const;
bool less (const NetGraphNode &node, bool with_name) const;
bool equal (const NetGraphNode &node, bool with_name) const;
bool operator== (const NetGraphNode &node) const
{
return equal (node, false);
}
bool operator< (const NetGraphNode &node) const
{
return less (node, false);
}
void swap (NetGraphNode &other)
{
@ -1009,13 +1019,13 @@ private:
* @brief Compares edges as "less"
* Edge comparison is based on the pins attached (name of the first pin).
*/
static bool net_less (const db::Net *a, const db::Net *b);
static bool net_less (const db::Net *a, const db::Net *b, bool with_name);
/**
* @brief Compares edges as "equal"
* See edge_less for the comparison details.
*/
static bool edge_equal (const db::Net *a, const db::Net *b);
static bool net_equal (const db::Net *a, const db::Net *b, bool with_name);
};
// --------------------------------------------------------------------------------------------------------------------
@ -1038,7 +1048,7 @@ struct CompareNodePtr
{
bool operator() (const std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> &a, const std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> &b) const
{
return *a.first < *b.first;
return a.first->less (*b.first, true);
}
};
@ -1072,7 +1082,7 @@ public:
/**
* @brief Builds the net graph
*/
void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper);
void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper, size_t *unique_pin_id);
/**
* @brief Gets the node index for the given net
@ -1223,7 +1233,7 @@ private:
// --------------------------------------------------------------------------------------------------------------------
NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id)
NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id)
: mp_net (net), m_other_net_index (invalid_id)
{
if (! net) {
@ -1262,8 +1272,10 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego
// isolated pins are ignored, others are considered for the matching
if (net->pin_count () == 0 && net->terminal_count () == 0 && net->subcircuit_pin_count () == 1) {
continue;
} else if (! unique_pin_id) {
continue;
} else {
pin_id = unique_pin_id++;
pin_id = (*unique_pin_id)++;
}
} else {
@ -1340,7 +1352,7 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego
}
}
NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, size_t &unique_pin_id)
NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, size_t *unique_pin_id)
: mp_net (0), m_other_net_index (invalid_id)
{
std::map<const db::Net *, size_t> n2entry;
@ -1373,8 +1385,10 @@ NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circui
// isolated pins are ignored, others are considered for the matching
if (net_at_pin->pin_count () == 0 && net_at_pin->terminal_count () == 0 && net_at_pin->subcircuit_pin_count () == 1) {
continue;
} else if (! unique_pin_id) {
continue;
} else {
pin_id = unique_pin_id++;
pin_id = (*unique_pin_id)++;
}
} else {
@ -1517,7 +1531,7 @@ NetGraphNode::apply_net_index (const std::map<const db::Net *, size_t> &ni)
}
bool
NetGraphNode::operator< (const NetGraphNode &node) const
NetGraphNode::less (const NetGraphNode &node, bool with_name) const
{
if (m_edges.size () != node.m_edges.size ()) {
return m_edges.size () < node.m_edges.size ();
@ -1529,13 +1543,13 @@ NetGraphNode::operator< (const NetGraphNode &node) const
}
if (m_edges.empty ()) {
// do a more detailed analysis on the nets involved
return net_less (net (), node.net ());
return net_less (net (), node.net (), with_name);
}
return false;
}
bool
NetGraphNode::operator== (const NetGraphNode &node) const
NetGraphNode::equal (const NetGraphNode &node, bool with_name) const
{
if (m_edges.size () != node.m_edges.size ()) {
return false;
@ -1547,13 +1561,13 @@ NetGraphNode::operator== (const NetGraphNode &node) const
}
if (m_edges.empty ()) {
// do a more detailed analysis on the edges
return edge_equal (net (), node.net ());
return net_equal (net (), node.net (), with_name);
}
return true;
}
bool
NetGraphNode::net_less (const db::Net *a, const db::Net *b)
NetGraphNode::net_less (const db::Net *a, const db::Net *b, bool with_name)
{
if ((a != 0) != (b != 0)) {
return (a != 0) < (b != 0);
@ -1564,14 +1578,11 @@ NetGraphNode::net_less (const db::Net *a, const db::Net *b)
if (a->pin_count () != b->pin_count ()) {
return a->pin_count () < b->pin_count ();
}
if (a->pin_count () == 0) {
return true;
}
return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), a->begin_pins ()->pin ()->name (), b->begin_pins ()->pin ()->name ()) < 0;
return with_name ? name_compare (a, b) < 0 : false;
}
bool
NetGraphNode::edge_equal (const db::Net *a, const db::Net *b)
NetGraphNode::net_equal (const db::Net *a, const db::Net *b, bool with_name)
{
if ((a != 0) != (b != 0)) {
return false;
@ -1582,10 +1593,7 @@ NetGraphNode::edge_equal (const db::Net *a, const db::Net *b)
if (a->pin_count () != b->pin_count ()) {
return false;
}
if (a->pin_count () == 0) {
return true;
}
return db::Netlist::name_compare (combined_case_sensitive (a->netlist (), b->netlist ()), a->begin_pins ()->pin ()->name (), b->begin_pins ()->pin ()->name ()) == 0;
return with_name ? name_compare (a, b) == 0 : true;
}
// --------------------------------------------------------------------------------------------------------------------
@ -1871,7 +1879,7 @@ private:
// NetGraph implementation
void
NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper)
NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper, size_t *unique_pin_id)
{
tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("Building net graph for circuit: ")) + c->name ());
@ -1880,8 +1888,6 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci
m_nodes.clear ();
m_net_index.clear ();
size_t unique_pin_id = Transition::first_unique_pin_id ();
// create a dummy node for a null net
m_nodes.push_back (NetGraphNode (0, device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper, unique_pin_id));
@ -3613,16 +3619,21 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
db::NetGraph g1, g2;
size_t unique_pin_id = Transition::first_unique_pin_id ();
// NOTE: for normalization we map all subcircuits of c1 to c2.
// Also, pin swapping will only happen there.
if (options ()->debug_netgraph) {
tl::info << "Netlist graph:";
}
g1.build (c1, device_categorizer, circuit_categorizer, device_filter, &c12_circuit_and_pin_mapping, &circuit_pin_mapper);
g1.build (c1, device_categorizer, circuit_categorizer, device_filter, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, (size_t *)0);
if (options ()->debug_netgraph) {
tl::info << "Other netlist graph:";
}
g2.build (c2, device_categorizer, circuit_categorizer, device_filter, &c22_circuit_and_pin_mapping, &circuit_pin_mapper);
// NOTE: the second netlist graph is the reference (schematic). We treat it a little more carefully by using pins from subcircuits which
// lead to passive nets but connect to non-trivial nets on the outside. This is done by specifying a unique_pin_id counter for the last argument.
g2.build (c2, device_categorizer, circuit_categorizer, device_filter, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, &unique_pin_id);
// Match dummy nodes for null nets
g1.identify (0, 0);
@ -4287,14 +4298,19 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG
bool mapped = true, valid = true;
std::vector<std::pair<size_t, size_t> > k = compute_subcircuit_key_for_this (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, mapped, valid);
if (! mapped || ! valid) {
if (! mapped) {
if (mp_logger) {
mp_logger->subcircuit_mismatch (sc.operator-> (), 0);
}
good = false;
} else {
} else if (valid) {
// TODO: report devices which cannot be distinguished topologically?
subcircuit_map.insert (std::make_pair (k, std::make_pair (sc.operator-> (), sc_cat)));
} else {
// emit a mismatch event but do not consider that an error - this may happen if the circuit has been dropped intentionally (e.g. via cells)
if (mp_logger) {
mp_logger->subcircuit_mismatch (sc.operator-> (), 0);
}
}
}
@ -4584,7 +4600,7 @@ NetlistComparer::join_symmetric_nets (db::Circuit *circuit)
db::NetGraph graph;
db::CircuitCategorizer circuit_categorizer;
db::DeviceCategorizer device_categorizer;
graph.build (circuit, device_categorizer, circuit_categorizer, device_filter, &circuit_and_pin_mapping, &circuit_pin_mapper);
graph.build (circuit, device_categorizer, circuit_categorizer, device_filter, &circuit_and_pin_mapping, &circuit_pin_mapper, (size_t *) 0);
// sort the nodes so we can easily identify the identical ones (in terms of topology)
// nodes are identical if the attached devices and circuits are of the same kind and with the same parameters

View File

@ -1140,17 +1140,17 @@ TEST(3_GlobalNetConnections)
CHECKPOINT ();
db::compare_netlist (_this, *l2n.netlist (),
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n"
" subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n"
" subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n"
" subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n"
" subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n"
" subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n"
" subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n"
" subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n"
" subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n"
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n"
"end;\n"
"circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n"
" subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);\n"
" subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n"
"circuit INV2PAIR ($2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n"
" subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6);\n"
" subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6);\n"
"end;\n"
"circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n"
"circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"

View File

@ -1984,6 +1984,7 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy)
"match_pins $1 $0\n"
"match_pins $2 $2\n"
"match_pins $3 $3\n"
"subcircuit_mismatch $2 (null)\n"
"match_subcircuits $3 $1\n"
"match_subcircuits $1 $2\n"
"end_circuit TOP TOP MATCH"
@ -3931,25 +3932,6 @@ TEST(21_BusLikeAmbiguousConnections)
TEST(22_NodesRemoved)
{
const char *nls1 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n"
" subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n"
" subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n"
" subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n"
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n"
"end;\n"
"circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n"
" subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n"
" subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n"
"end;\n"
"circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
const char *nls2 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n"
" subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n"
@ -3968,6 +3950,25 @@ TEST(22_NodesRemoved)
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
const char *nls2 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n"
" subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n"
" subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n"
" subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n"
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n"
"end;\n"
"circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n"
" subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n"
" subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n"
"end;\n"
"circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
db::Netlist nl1, nl2;
prep_nl (nl1, nls1);
prep_nl (nl2, nls2);
@ -3980,6 +3981,79 @@ TEST(22_NodesRemoved)
std::string txt = logger.text ();
EXPECT_EQ (txt,
"begin_circuit INV2 INV2\n"
"match_nets VDD VDD\n"
"match_nets OUT OUT\n"
"match_nets $3 $3\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets $1 (null)\n"
"match_nets BULK (null)\n"
"match_pins IN IN\n"
"match_pins $2 $1\n"
"match_pins OUT OUT\n"
"match_pins VSS VSS\n"
"match_pins VDD VDD\n"
"match_pins $0 (null)\n"
"match_pins BULK (null)\n"
"match_devices $1 $1\n"
"match_devices $2 $2\n"
"match_devices $3 $3\n"
"match_devices $4 $4\n"
"end_circuit INV2 INV2 MATCH\n"
"begin_circuit INV2PAIR INV2PAIR\n"
"match_nets $I2 $I2\n"
"match_nets $I6 $I5\n"
"match_nets $I5 $I4\n"
"match_nets $I4 $I6\n"
"match_nets $I3 $I3\n"
"match_nets $I7 $I7\n"
"match_nets $I8 $I8\n"
"match_nets BULK (null)\n"
"match_nets $I1 (null)\n"
"match_pins $1 $0\n"
"match_pins $2 $1\n"
"match_pins $3 $2\n"
"match_pins $4 $3\n"
"match_pins $5 $4\n"
"match_pins BULK (null)\n"
"match_pins $6 (null)\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"end_circuit INV2PAIR INV2PAIR MATCH\n"
"begin_circuit RINGO RINGO\n"
"match_nets OSC OSC\n"
"match_nets $I7 $I7\n"
"match_nets $I6 $I6\n"
"match_nets $I5 $I5\n"
"match_nets $I13 $I21\n"
"match_nets FB FB\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets $I22 $I22\n"
"match_nets $I23 $I23\n"
"match_nets $I24 $I24\n"
"match_nets $I25 $I25\n"
"match_pins FB FB\n"
"match_pins OSC OSC\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"match_subcircuits $3 $3\n"
"match_subcircuits $4 $4\n"
"match_subcircuits $5 $5\n"
"end_circuit RINGO RINGO MATCH"
);
EXPECT_EQ (good, true);
logger.clear ();
good = comp.compare (&nl2, &nl1);
txt = logger.text ();
// additional nodes are not ignored when they come from the reference side (second)
EXPECT_EQ (txt,
"begin_circuit INV2 INV2\n"
"match_nets VDD VDD\n"
@ -4028,24 +4102,28 @@ TEST(22_NodesRemoved)
"match_nets $I5 $I5\n"
"match_nets $I21 $I13\n"
"match_nets FB FB\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets $I22 $I22\n"
"match_nets $I23 $I23\n"
"match_nets $I24 $I24\n"
"match_nets $I25 $I25\n"
"net_mismatch VDD (null)\n"
"net_mismatch VSS (null)\n"
"net_mismatch (null) VDD\n"
"net_mismatch (null) VSS\n"
"match_pins FB FB\n"
"match_pins OSC OSC\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"match_subcircuits $3 $3\n"
"match_subcircuits $4 $4\n"
"match_subcircuits $5 $5\n"
"end_circuit RINGO RINGO MATCH"
"match_pins VDD (null)\n"
"match_pins VSS (null)\n"
"match_pins (null) VDD\n"
"match_pins (null) VSS\n"
"subcircuit_mismatch $1 $1\n"
"subcircuit_mismatch $2 $2\n"
"subcircuit_mismatch $3 $3\n"
"subcircuit_mismatch $4 $4\n"
"subcircuit_mismatch $5 $5\n"
"end_circuit RINGO RINGO NOMATCH"
);
EXPECT_EQ (good, true);
EXPECT_EQ (good, false);
}
TEST(23_NodesRemovedWithError)
@ -4150,25 +4228,6 @@ TEST(23_NodesRemovedWithError)
TEST(24_NodesRemovedButConnectedInOther)
{
const char *nls1 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n"
" subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n"
" subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n"
" subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n"
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n"
"end;\n"
"circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n"
" subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n"
" subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n"
"end;\n"
"circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
const char *nls2 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n"
" subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n"
@ -4189,6 +4248,25 @@ TEST(24_NodesRemovedButConnectedInOther)
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
const char *nls2 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n"
" subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n"
" subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n"
" subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n"
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n"
"end;\n"
"circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n"
" subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n"
" subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n"
"end;\n"
"circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
db::Netlist nl1, nl2;
prep_nl (nl1, nls1);
prep_nl (nl2, nls2);
@ -4208,15 +4286,15 @@ TEST(24_NodesRemovedButConnectedInOther)
"match_nets $3 $3\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets (null) $1\n"
"match_nets (null) BULK\n"
"match_nets $1 (null)\n"
"match_nets BULK (null)\n"
"match_pins IN IN\n"
"match_pins $1 $2\n"
"match_pins $2 $1\n"
"match_pins OUT OUT\n"
"match_pins VSS VSS\n"
"match_pins VDD VDD\n"
"match_pins (null) $0\n"
"match_pins (null) BULK\n"
"match_pins $0 (null)\n"
"match_pins BULK (null)\n"
"match_devices $1 $1\n"
"match_devices $2 $2\n"
"match_devices $3 $3\n"
@ -4224,21 +4302,21 @@ TEST(24_NodesRemovedButConnectedInOther)
"end_circuit INV2 INV2 MATCH\n"
"begin_circuit INV2PAIR INV2PAIR\n"
"match_nets $I2 $I2\n"
"match_nets $I5 $I6\n"
"match_nets $I4 $I5\n"
"match_nets $I6 $I4\n"
"match_nets $I6 $I5\n"
"match_nets $I5 $I4\n"
"match_nets $I4 $I6\n"
"match_nets $I3 $I3\n"
"match_nets $I7 $I7\n"
"match_nets $I8 $I8\n"
"match_nets (null) BULK\n"
"match_nets (null) $I1\n"
"match_pins $0 $1\n"
"match_pins $1 $2\n"
"match_pins $2 $3\n"
"match_pins $3 $4\n"
"match_pins $4 $5\n"
"match_pins (null) BULK\n"
"match_pins (null) $6\n"
"match_nets BULK (null)\n"
"match_nets $I1 (null)\n"
"match_pins $1 $0\n"
"match_pins $2 $1\n"
"match_pins $3 $2\n"
"match_pins $4 $3\n"
"match_pins $5 $4\n"
"match_pins BULK (null)\n"
"match_pins $6 (null)\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"end_circuit INV2PAIR INV2PAIR MATCH\n"
@ -4247,7 +4325,7 @@ TEST(24_NodesRemovedButConnectedInOther)
"match_nets $I7 $I7\n"
"match_nets $I6 $I6\n"
"match_nets $I5 $I5\n"
"match_nets $I21 $I13\n"
"match_nets $I13 $I21\n"
"match_nets FB FB\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
@ -4267,6 +4345,62 @@ TEST(24_NodesRemovedButConnectedInOther)
"end_circuit RINGO RINGO MATCH"
);
EXPECT_EQ (good, true);
logger.clear ();
good = comp.compare (&nl2, &nl1);
txt = logger.text ();
// NOTE: additional nets are ignored in the first netlist but not from the second
EXPECT_EQ (txt,
"begin_circuit INV2 INV2\n"
"match_nets VDD VDD\n"
"match_nets OUT OUT\n"
"match_nets $3 $3\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets (null) $1\n"
"match_nets (null) BULK\n"
"match_pins IN IN\n"
"match_pins $1 $2\n"
"match_pins OUT OUT\n"
"match_pins VSS VSS\n"
"match_pins VDD VDD\n"
"match_pins (null) $0\n"
"match_pins (null) BULK\n"
"match_devices $1 $1\n"
"match_devices $2 $2\n"
"match_devices $3 $3\n"
"match_devices $4 $4\n"
"end_circuit INV2 INV2 MATCH\n"
"begin_circuit INV2PAIR INV2PAIR\n"
"match_nets $I2 $I2\n"
"match_nets $I5 $I6\n"
"match_nets $I8 $I8\n"
"match_nets $I7 $I7\n"
"net_mismatch $I6 $I4\n"
"net_mismatch $I4 (null)\n"
"net_mismatch $I3 (null)\n"
"net_mismatch (null) BULK\n"
"net_mismatch (null) $I5\n"
"net_mismatch (null) $I3\n"
"net_mismatch (null) $I1\n"
"match_pins $0 $1\n"
"match_pins $1 $2\n"
"match_pins $4 $5\n"
"pin_mismatch $2 (null)\n"
"pin_mismatch $3 (null)\n"
"pin_mismatch (null) BULK\n"
"pin_mismatch (null) $3\n"
"pin_mismatch (null) $4\n"
"pin_mismatch (null) $6\n"
"subcircuit_mismatch $1 $1\n"
"subcircuit_mismatch $2 $2\n"
"end_circuit INV2PAIR INV2PAIR NOMATCH\n"
"circuit_skipped RINGO RINGO"
);
EXPECT_EQ (good, false);
}
TEST(25_JoinSymmetricNets)