diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index ab6895ef2..d9c3052b4 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -219,35 +219,69 @@ static void deliver_shape (const db::PolygonRef &pr, db::Region ®ion, const T } } +template +static void deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr) +{ + if (pr.obj ().is_box ()) { + shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr)); + } else { + db::Layout *layout = shapes.layout (); + if (layout) { + shapes.insert (db::PolygonRef (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ())); + } else { + shapes.insert (pr.obj ().transformed (pr.trans ()).transformed (tr)); + } + } +} + +template +static void deliver_shapes_of_net_recursive (const db::NetlistExtractor &netex, const db::Net &net, unsigned int layer_id, To &to) +{ + const db::Circuit *circuit = net.circuit (); + tl_assert (circuit != 0); + + db::cell_index_type ci = circuit->cell_index (); + + for (db::recursive_cluster_shape_iterator rci (netex.clusters (), layer_id, ci, net.cluster_id ()); !rci.at_end (); ++rci) { + deliver_shape (*rci, to, rci.trans ()); + } +} + +template +static void deliver_shapes_of_net_nonrecursive (const db::NetlistExtractor &netex, const db::Net &net, unsigned int layer_id, To &to) +{ + const db::Circuit *circuit = net.circuit (); + tl_assert (circuit != 0); + + db::cell_index_type ci = circuit->cell_index (); + + const db::local_cluster &lc = netex.clusters ().clusters_per_cell (ci).cluster_by_id (net.cluster_id ()); + + for (db::local_cluster::shape_iterator s = lc.begin (layer_id); !s.at_end (); ++s) { + deliver_shape (*s, to, db::UnitTrans ()); + } +} + +void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const +{ + unsigned int lid = layer_of (of_layer); + + if (! recursive) { + deliver_shapes_of_net_nonrecursive (m_netex, net, lid, to); + } else { + deliver_shapes_of_net_recursive (m_netex, net, lid, to); + } +} + db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const { unsigned int lid = layer_of (of_layer); std::auto_ptr res (new db::Region ()); if (! recursive) { - - const db::Circuit *circuit = net.circuit (); - tl_assert (circuit != 0); - - db::cell_index_type ci = circuit->cell_index (); - - const db::local_cluster &lc = m_netex.clusters ().clusters_per_cell (ci).cluster_by_id (net.cluster_id ()); - - for (db::local_cluster::shape_iterator s = lc.begin (lid); !s.at_end (); ++s) { - deliver_shape (*s, *res, db::UnitTrans ()); - } - + deliver_shapes_of_net_nonrecursive (m_netex, net, lid, *res); } else { - - const db::Circuit *circuit = net.circuit (); - tl_assert (circuit != 0); - - db::cell_index_type ci = circuit->cell_index (); - - for (db::recursive_cluster_shape_iterator rci (m_netex.clusters (), lid, ci, net.cluster_id ()); !rci.at_end (); ++rci) { - deliver_shape (*rci, *res, rci.trans ()); - } - + deliver_shapes_of_net_recursive (m_netex, net, lid, *res); } return res.release (); diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index 09834dcf1..4efaf4294 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -224,6 +224,17 @@ public: */ db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const; + /** + * @brief Delivers all shapes of a specific net and layer to the given Shapes container. + * + * If "recursive" is true, the returned region will contain the shapes of + * all subcircuits too. + * + * This methods returns a new'd Region. It's the responsibility of the caller + * to delete this object. + */ + void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const; + /** * @brief Finds the net by probing a specific location on the given layer * diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index 6cee2d264..1e47fddc8 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -141,11 +141,16 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", gsi::method ("netlist", &db::LayoutToNetlist::netlist, "@brief gets the netlist extracted (0 if no extraction happened yet)\n" ) + - gsi::factory ("shapes_of_net", &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), + gsi::factory ("shapes_of_net", (db::Region *(db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), "@brief Returns all shapes of a specific net and layer.\n" "If 'recursive'' is true, the returned region will contain the shapes of\n" "all subcircuits too.\n" ) + + gsi::method ("shapes_of_net", (void (db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, db::Shapes &) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), gsi::arg ("to"), + "@brief Sends all shapes of a specific net and layer to the given Shapes container.\n" + "If 'recursive'' is true, the returned region will contain the shapes of\n" + "all subcircuits too.\n" + ) + gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), "@brief Finds the net by probing a specific location on the given layer\n" "\n" diff --git a/src/db/unit_tests/dbLayoutToNetlistTests.cc b/src/db/unit_tests/dbLayoutToNetlistTests.cc index e70ab822c..b1ace3ea0 100644 --- a/src/db/unit_tests/dbLayoutToNetlistTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistTests.cc @@ -148,23 +148,25 @@ static void dump_recursive_nets_to_layout (const db::LayoutToNetlist &l2n, db::L continue; } + bool any = false; + for (std::map::const_iterator m = lmap.begin (); m != lmap.end () && !any; ++m) { + any = !db::recursive_cluster_shape_iterator (l2n.net_clusters (), l2n.layer_of (*m->first), c->cell_index (), n->cluster_id ()).at_end (); + } + + if (!any) { + continue; + } + db::cell_index_type nci = std::numeric_limits::max (); + if (nci == std::numeric_limits::max ()) { + std::string nn = "RNET_" + c->name () + "_" + n->expanded_name (); + nci = ly.add_cell (nn.c_str ()); + cell.insert (db::CellInstArray (db::CellInst (nci), db::Trans ())); + } + for (std::map::const_iterator m = lmap.begin (); m != lmap.end (); ++m) { - - std::auto_ptr shapes (l2n.shapes_of_net (*n, *m->first, true)); - if (shapes->empty ()) { - continue; - } - - if (nci == std::numeric_limits::max ()) { - std::string nn = "RNET_" + c->name () + "_" + n->expanded_name (); - nci = ly.add_cell (nn.c_str ()); - cell.insert (db::CellInstArray (db::CellInst (nci), db::Trans ())); - } - - shapes->insert_into (&ly, nci, m->second); - + l2n.shapes_of_net (*n, *m->first, true, ly.cell (nci).shapes (m->second)); } } diff --git a/testdata/ruby/dbLayoutToNetlist.rb b/testdata/ruby/dbLayoutToNetlist.rb index 59d821ab8..d1a37ef11 100644 --- a/testdata/ruby/dbLayoutToNetlist.rb +++ b/testdata/ruby/dbLayoutToNetlist.rb @@ -120,6 +120,12 @@ END assert_equal(l2n.shapes_of_net(n, rmetal1, true).to_s, "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)") + shapes = RBA::Shapes::new + l2n.shapes_of_net(n, rmetal1, true, shapes) + r = RBA::Region::new + shapes.each { |s| r.insert(s.polygon) } + assert_equal(r.to_s, "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)") + end def test_10_LayoutToNetlistExtractionWithoutDevices