diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index 6b536c817..429ea8b7d 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -396,6 +396,22 @@ void Netlist::flatten_circuit (Circuit *circuit) delete circuit; } +void Netlist::flatten () +{ + std::set top_circuits; + size_t ntop = top_circuit_count (); + for (db::Netlist::top_down_circuit_iterator tc = begin_top_down (); tc != end_top_down () && ntop > 0; ++tc) { + top_circuits.insert (tc.operator-> ()); + --ntop; + } + + for (db::Netlist::bottom_up_circuit_iterator c = begin_bottom_up (); c != end_bottom_up(); ++c) { + if (top_circuits.find (c.operator-> ()) == top_circuits.end ()) { + flatten_circuit (c.operator-> ()); + } + } +} + DeviceClass *Netlist::device_class_by_name (const std::string &name) { for (device_class_iterator d = begin_device_classes (); d != end_device_classes (); ++d) { diff --git a/src/db/db/dbNetlist.h b/src/db/db/dbNetlist.h index da26bd399..760fa381f 100644 --- a/src/db/db/dbNetlist.h +++ b/src/db/db/dbNetlist.h @@ -174,6 +174,11 @@ public: */ void flatten_circuit (Circuit *circuit); + /** + * @brief Flattens the netlist + */ + void flatten (); + /** * @brief Begin iterator for the circuits of the netlist (non-const version) */ diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index f229dafb1..9e59ea3c2 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1388,6 +1388,10 @@ Class decl_dbNetlist ("db", "Netlist", "A circuit with references (see \\has_refs?) should not be removed as the " "subcircuits calling it would afterwards point to nothing." ) + + gsi::method ("flatten", &db::Netlist::flatten, + "@brief Flattens all circuits of the netlist\n" + "After calling this method, only the top circuits will remain." + ) + gsi::method ("flatten_circuit", &db::Netlist::flatten_circuit, gsi::arg ("circuit"), "@brief Flattens a subcircuit\n" "This method will substitute all instances (subcircuits) of the given circuit by it's " diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index a4db90bb7..9de025763 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -1188,6 +1188,20 @@ TEST(20_FlattenSubCircuit) " device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" "end;\n" ); + + db::Netlist nl3; + + nl3 = nl; + nl3.flatten (); + + EXPECT_EQ (nl3.to_string (), + "circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);\n" + " device PMOS $1 (S=$5,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device PMOS $2 (S=$5,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device NMOS $3 (S=$4,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + " device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n" + "end;\n" + ); } TEST(21_FlattenSubCircuit2) diff --git a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc index c3303712a..7af1299ea 100644 --- a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc +++ b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc @@ -559,13 +559,15 @@ NetTracerDialog::menu_activated (const std::string &symbol) layer_stack_clicked (); - } else if (symbol == "lay::trace_all_nets") { + } else if (symbol == "lay::trace_all_nets" || symbol == "lay::trace_all_nets_flat") { + + bool flat = symbol == "lay::trace_all_nets_flat"; const lay::CellView &cv = view ()->cellview (view ()->active_cellview_index ()); if (cv.is_valid ()) { db::RecursiveShapeIterator si (cv->layout (), *cv.cell (), std::vector ()); std::auto_ptr l2ndb (new db::LayoutToNetlist (si)); - trace_all_nets (l2ndb.get (), cv); + trace_all_nets (l2ndb.get (), cv, flat); unsigned int l2ndb_index = view ()->add_l2ndb (l2ndb.release ()); view ()->open_l2ndb_browser (l2ndb_index, view ()->index_of_cellview (&cv)); } @@ -1658,7 +1660,7 @@ NetTracerDialog::clear_markers () } void -NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv) +NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv, bool flat) { db::NetTracerData tracer_data; if (! get_net_tracer_setup (cv, tracer_data)) { @@ -1668,6 +1670,10 @@ NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView tracer_data.configure_l2n (*l2ndb); l2ndb->extract_netlist (); + + if (flat) { + l2ndb->netlist ()->flatten (); + } } } diff --git a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.h b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.h index 99479fe87..952ae1bba 100644 --- a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.h +++ b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.h @@ -118,7 +118,7 @@ private: void release_mouse (); db::NetTracerNet *do_trace (const db::DBox &start_search_box, const db::DBox &stop_search_box, bool trace_path); bool get_net_tracer_setup (const lay::CellView &cv, db::NetTracerData &data); - void trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv); + void trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv, bool flat); }; } diff --git a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerPlugin.cc b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerPlugin.cc index 523fce279..f08e93fe0 100644 --- a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerPlugin.cc +++ b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerPlugin.cc @@ -69,7 +69,9 @@ public: lay::PluginDeclaration::get_menu_entries (menu_entries); menu_entries.push_back (lay::MenuEntry ("net_trace_group", "tools_menu.end")); menu_entries.push_back (lay::MenuEntry ("lay::net_trace", "net_trace", "tools_menu.end", tl::to_string (QObject::tr ("Trace Net")))); - menu_entries.push_back (lay::MenuEntry ("lay::trace_all_nets", "trace_all_nets", "tools_menu.end", tl::to_string (QObject::tr ("Trace All Nets")))); + menu_entries.push_back (lay::MenuEntry ("", "trace_all_nets_menu", "tools_menu.end", tl::to_string (QObject::tr ("Trace All Nets")), true)); + menu_entries.push_back (lay::MenuEntry ("lay::trace_all_nets", "trace_all_nets", "tools_menu.trace_all_nets_menu.end", tl::to_string (QObject::tr ("Hierarchical")))); + menu_entries.push_back (lay::MenuEntry ("lay::trace_all_nets_flat", "trace_all_nets_flat", "tools_menu.trace_all_nets_menu.end", tl::to_string (QObject::tr ("Flat")))); menu_entries.push_back (lay::MenuEntry ("lay::edit_layer_stack", "edit_layer_stack", "tools_menu.end", tl::to_string (QObject::tr ("Edit Layer Stack")))); }