diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index 0b6631132..c48ce4b40 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -1446,6 +1446,53 @@ void Netlist::purge_nets () } } +void Netlist::make_top_level_pins () +{ + size_t ntop = top_circuit_count (); + for (top_down_circuit_iterator c = begin_top_down (); c != end_top_down () && ntop > 0; ++c, --ntop) { + + Circuit *circuit = *c; + + if (circuit->pin_count () == 0) { + + // create pins for the named nets and connect them + for (Circuit::net_iterator n = circuit->begin_nets (); n != circuit->end_nets (); ++n) { + if (! n->name ().empty () && n->terminal_count () + n->pin_count () > 0) { + Pin pin (n->name ()); + pin = circuit->add_pin (pin); + circuit->connect_pin (pin.id (), n.operator-> ()); + } + } + + } + + } +} + +void Netlist::purge () +{ + // This locking is very important as we do not want to recompute the bottom-up list + // while iterating. + NetlistLocker locker (this); + + for (bottom_up_circuit_iterator c = begin_bottom_up (); c != end_bottom_up (); ++c) { + + Circuit *circuit = *c; + + circuit->purge_nets (); + if (circuit->begin_nets () == circuit->end_nets ()) { + + // No nets left: delete the subcircuits that refer to us and finally delete the circuit + while (circuit->begin_refs () != circuit->end_refs ()) { + delete circuit->begin_refs ().operator-> (); + } + delete circuit; + + } + + } +} + void Netlist::combine_devices () { for (circuit_iterator c = begin_circuits (); c != end_circuits (); ++c) { diff --git a/src/db/db/dbNetlist.h b/src/db/db/dbNetlist.h index cf1016e97..da817218b 100644 --- a/src/db/db/dbNetlist.h +++ b/src/db/db/dbNetlist.h @@ -1984,6 +1984,23 @@ public: */ void purge_nets (); + /** + * @brief Creates pins for top-level circuits + * + * This method will turn all named nets of top-level circuits (such that are not + * referenced by subcircuits) into pins. This method can be used before purge to + * avoid that purge will remove nets which are directly connecting to subcircuits. + */ + void make_top_level_pins (); + + /** + * @brief Purge unused nets, circuits and subcircuits + * + * This method will purge all nets which return "floating". Circuits which don't have any + * nets (or only floating ones) and removed. Their subcircuits are disconnected. + */ + void purge (); + /** * @brief Combine devices * diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 05d492366..91650e852 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -98,12 +98,6 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect net->set_cluster_id (*c); circuit->add_net (net); - if (! clusters.is_root (*c)) { - // a non-root cluster makes a pin - size_t pin_id = make_pin (circuit, net); - c2p.insert (std::make_pair (*c, pin_id)); - } - // make subcircuit connections (also make the subcircuits if required) from the connections of the clusters make_and_connect_subcircuits (circuit, clusters, *c, net, subcircuits, circuits, pins_per_cluster, layout.dbu ()); @@ -121,6 +115,12 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect } } + if (! clusters.is_root (*c)) { + // a non-root cluster makes a pin + size_t pin_id = make_pin (circuit, net); + c2p.insert (std::make_pair (*c, pin_id)); + } + } } diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index 14f6517c4..c148408a3 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -480,17 +480,17 @@ TEST(1_DeviceAndNetExtraction) // compare netlist as string EXPECT_EQ (netlist2string (nl), "Circuit RINGO ():\n" - " XINV2 $1 ($1=$I8,$2=FB,$3=OSC,$4=VSS,$5=VDD)\n" - " XINV2 $2 ($1=FB,$2=$I38,$3=$I19,$4=VSS,$5=VDD)\n" - " XINV2 $3 ($1=$I19,$2=$I39,$3=$I1,$4=VSS,$5=VDD)\n" - " XINV2 $4 ($1=$I1,$2=$I40,$3=$I2,$4=VSS,$5=VDD)\n" - " XINV2 $5 ($1=$I2,$2=$I41,$3=$I3,$4=VSS,$5=VDD)\n" - " XINV2 $6 ($1=$I3,$2=$I42,$3=$I4,$4=VSS,$5=VDD)\n" - " XINV2 $7 ($1=$I4,$2=$I43,$3=$I5,$4=VSS,$5=VDD)\n" - " XINV2 $8 ($1=$I5,$2=$I44,$3=$I6,$4=VSS,$5=VDD)\n" - " XINV2 $9 ($1=$I6,$2=$I45,$3=$I7,$4=VSS,$5=VDD)\n" - " XINV2 $10 ($1=$I7,$2=$I46,$3=$I8,$4=VSS,$5=VDD)\n" - "Circuit INV2 ($1=IN,$2=$2,$3=OUT,$4=$4,$5=$5):\n" + " XINV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD)\n" + " XINV2 $2 (IN=FB,$2=$I38,OUT=$I19,$4=VSS,$5=VDD)\n" + " XINV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$4=VSS,$5=VDD)\n" + " XINV2 $4 (IN=$I1,$2=$I40,OUT=$I2,$4=VSS,$5=VDD)\n" + " XINV2 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD)\n" + " XINV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$4=VSS,$5=VDD)\n" + " XINV2 $7 (IN=$I4,$2=$I43,OUT=$I5,$4=VSS,$5=VDD)\n" + " XINV2 $8 (IN=$I5,$2=$I44,OUT=$I6,$4=VSS,$5=VDD)\n" + " XINV2 $9 (IN=$I6,$2=$I45,OUT=$I7,$4=VSS,$5=VDD)\n" + " XINV2 $10 (IN=$I7,$2=$I46,OUT=$I8,$4=VSS,$5=VDD)\n" + "Circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5):\n" " DPMOS $1 (S=$2,G=IN,D=$5) [L=0.25,W=0.95,AS=0.49875,AD=0.26125]\n" " DPMOS $2 (S=$5,G=$2,D=OUT) [L=0.25,W=0.95,AS=0.26125,AD=0.49875]\n" " DNMOS $3 (S=$2,G=IN,D=$4) [L=0.25,W=0.95,AS=0.49875,AD=0.26125]\n" @@ -502,6 +502,33 @@ TEST(1_DeviceAndNetExtraction) "Circuit TRANS ($1=$1,$2=$2,$3=$3):\n" ); + // doesn't do anything here, but we test that this does not destroy anything: + nl.combine_devices (); + + // make pins for named nets of top-level circuits - this way they are not purged + nl.make_top_level_pins (); + nl.purge (); + + // compare netlist as string + EXPECT_EQ (netlist2string (nl), + "Circuit RINGO (FB=FB,OSC=OSC,VSS=VSS,VDD=VDD):\n" + " XINV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD)\n" + " XINV2 $2 (IN=FB,$2=(null),OUT=$I19,$4=VSS,$5=VDD)\n" + " XINV2 $3 (IN=$I19,$2=(null),OUT=$I1,$4=VSS,$5=VDD)\n" + " XINV2 $4 (IN=$I1,$2=(null),OUT=$I2,$4=VSS,$5=VDD)\n" + " XINV2 $5 (IN=$I2,$2=(null),OUT=$I3,$4=VSS,$5=VDD)\n" + " XINV2 $6 (IN=$I3,$2=(null),OUT=$I4,$4=VSS,$5=VDD)\n" + " XINV2 $7 (IN=$I4,$2=(null),OUT=$I5,$4=VSS,$5=VDD)\n" + " XINV2 $8 (IN=$I5,$2=(null),OUT=$I6,$4=VSS,$5=VDD)\n" + " XINV2 $9 (IN=$I6,$2=(null),OUT=$I7,$4=VSS,$5=VDD)\n" + " XINV2 $10 (IN=$I7,$2=(null),OUT=$I8,$4=VSS,$5=VDD)\n" + "Circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5):\n" + " DPMOS $1 (S=$2,G=IN,D=$5) [L=0.25,W=0.95,AS=0.49875,AD=0.26125]\n" + " DPMOS $2 (S=$5,G=$2,D=OUT) [L=0.25,W=0.95,AS=0.26125,AD=0.49875]\n" + " DNMOS $3 (S=$2,G=IN,D=$4) [L=0.25,W=0.95,AS=0.49875,AD=0.26125]\n" + " DNMOS $4 (S=$4,G=$2,D=OUT) [L=0.25,W=0.95,AS=0.26125,AD=0.49875]\n" + ); + // compare the collected test data std::string au = tl::testsrc ();