From 604a634bf167ec760daef4e86f9ed5f660968149 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 3 Mar 2019 18:10:52 +0100 Subject: [PATCH] Generalization of layout index for LayoutToNetlist --- src/db/db/dbDeepShapeStore.cc | 19 +++++ src/db/db/dbDeepShapeStore.h | 8 ++ src/db/db/dbLayoutToNetlist.cc | 82 +++++++++++--------- src/db/db/dbLayoutToNetlist.h | 22 +----- src/db/db/dbLayoutToNetlistReader.cc | 2 - src/db/db/dbNetlistDeviceExtractor.cc | 8 +- src/db/db/dbNetlistDeviceExtractor.h | 2 +- src/db/db/dbNetlistExtractor.cc | 6 +- src/db/db/dbNetlistExtractor.h | 2 +- src/db/unit_tests/dbNetlistExtractorTests.cc | 18 ++--- src/drc/drc/built-in-macros/drc.lym | 2 +- 11 files changed, 95 insertions(+), 76 deletions(-) diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index eb04f1813..b02a5e4f1 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -481,6 +481,25 @@ DeepShapeStore::layout_for_iter (const db::RecursiveShapeIterator &si, const db: } } +void DeepShapeStore::make_layout (unsigned int layout_index, const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans) +{ + tl_assert (m_layout_map.find (std::make_pair (si, trans)) == m_layout_map.end ()); + + while (m_layouts.size () <= layout_index) { + m_layouts.push_back (0); + } + + m_layouts[layout_index] = new LayoutHolder (trans); + + db::Layout &layout = m_layouts[layout_index]->layout; + layout.hier_changed_event.add (this, &DeepShapeStore::invalidate_hier); + if (si.layout ()) { + layout.dbu (si.layout ()->dbu () / trans.mag ()); + } + + m_layout_map[std::make_pair (si, trans)] = layout_index; +} + DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count, const db::ICplxTrans &trans) { if (max_area_ratio == 0.0) { diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index 455b2705f..425aa467c 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -283,6 +283,14 @@ public: */ std::pair layer_for_flat (size_t region_id) const; + /** + * @brief Creates a layout with the given iterator and transformation for the given index + * + * This method is intended for classes that need more control over the layouts per index + * (LayoutToNetlist). + */ + void make_layout (unsigned int layout_index, const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans = db::ICplxTrans ()); + /** * @brief Inserts a polygon layer into the deep shape store * diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 07600bf5a..a820acb9e 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -30,46 +30,51 @@ namespace db { -static const unsigned int singular_layout_index = 0; - // the iterator provides the hierarchical selection (enabling/disabling cells etc.) LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter) - : m_iter (iter), m_netlist_extracted (false), m_is_flat (false) + : m_iter (iter), m_layout_index (0), m_netlist_extracted (false), m_is_flat (false) { // check the iterator if (iter.has_complex_region () || iter.region () != db::Box::world ()) { throw tl::Exception (tl::to_string (tr ("The netlist extractor cannot work on clipped layouts"))); } + mp_internal_dss.reset (new db::DeepShapeStore ()); + mp_dss.reset (mp_internal_dss.get ()); + + // the dummy layer acts as a reference holder for the layout + // NOTE: this probably can be done better + db::RecursiveShapeIterator empty_iter = iter; + empty_iter.set_layers (std::vector ()); + m_dummy_layer = dss ().create_polygon_layer (empty_iter); + init (); } LayoutToNetlist::LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index) - : mp_dss (dss), m_netlist_extracted (false), m_is_flat (false) + : mp_dss (dss), m_layout_index (layout_index), m_netlist_extracted (false), m_is_flat (false) { - m_iter = db::RecursiveShapeIterator (dss->layout (layout_index), dss->initial_cell (layout_index), std::set ()); + if (dss->is_valid_layout_index (m_layout_index)) { + m_iter = db::RecursiveShapeIterator (dss->layout (m_layout_index), dss->initial_cell (m_layout_index), std::set ()); + } init (); } -LayoutToNetlist::LayoutToNetlist (db::DeepShapeStore *dss) - : mp_dss (dss), m_netlist_extracted (false), m_is_flat (false) -{ - init (); -} - LayoutToNetlist::LayoutToNetlist (const std::string &topcell_name, double dbu) : m_iter (), m_netlist_extracted (false), m_is_flat (true) { mp_internal_dss.reset (new db::DeepShapeStore (topcell_name, dbu)); mp_dss.reset (mp_internal_dss.get ()); + m_layout_index = 0 ; init (); } LayoutToNetlist::LayoutToNetlist () - : m_iter (), mp_internal_dss (new db::DeepShapeStore ()), mp_dss (mp_internal_dss.get ()), m_netlist_extracted (false), m_is_flat (false) + : m_iter (), mp_internal_dss (new db::DeepShapeStore ()), mp_dss (mp_internal_dss.get ()), m_layout_index (0), + m_netlist_extracted (false), m_is_flat (false) { init (); } @@ -86,11 +91,6 @@ LayoutToNetlist::~LayoutToNetlist () void LayoutToNetlist::init () { - if (! mp_dss.get ()) { - mp_internal_dss.reset (new db::DeepShapeStore ()); - mp_dss.reset (mp_internal_dss.get ()); - } - dss ().set_text_enlargement (1); dss ().set_text_property_name (tl::Variant ("LABEL")); } @@ -184,7 +184,7 @@ void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, co if (! mp_netlist.get ()) { mp_netlist.reset (new db::Netlist ()); } - extractor.extract(dss (), layers, *mp_netlist, m_net_clusters); + extractor.extract (dss (), m_layout_index, layers, *mp_netlist, m_net_clusters); } void LayoutToNetlist::connect (const db::Region &l) @@ -261,7 +261,7 @@ void LayoutToNetlist::extract_netlist (bool join_nets_by_label) } db::NetlistExtractor netex; - netex.extract_nets(dss (), m_conn, *mp_netlist, m_net_clusters, join_nets_by_label); + netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters, join_nets_by_label); m_netlist_extracted = true; } @@ -273,30 +273,40 @@ void LayoutToNetlist::set_netlist_extracted () const db::Layout *LayoutToNetlist::internal_layout () const { - return &dss ().const_layout (); + ensure_layout (); + return &dss ().const_layout (m_layout_index); } const db::Cell *LayoutToNetlist::internal_top_cell () const { - return &dss ().const_initial_cell (); -} - -void LayoutToNetlist::ensure_internal_layout () -{ - if (dss ().layouts () == 0) { - // the dummy layer acts as a reference holder for the layout - m_dummy_layer = dss ().create_polygon_layer (db::RecursiveShapeIterator ()); - } + ensure_layout (); + return &dss ().const_initial_cell (m_layout_index); } db::Layout *LayoutToNetlist::internal_layout () { - return &dss ().layout (); + ensure_layout (); + return &dss ().layout (m_layout_index); } db::Cell *LayoutToNetlist::internal_top_cell () { - return &dss ().initial_cell (); + ensure_layout (); + return &dss ().initial_cell (m_layout_index); +} + +void LayoutToNetlist::ensure_layout () const +{ + if (! dss ().is_valid_layout_index (m_layout_index)) { + + LayoutToNetlist *non_const_this = const_cast (this); + non_const_this->dss ().make_layout (m_layout_index, db::RecursiveShapeIterator ()); + + // the dummy layer acts as a reference holder for the layout + unsigned int dummy_layer_index = non_const_this->dss ().layout (m_layout_index).insert_layer (); + non_const_this->m_dummy_layer = db::DeepLayer (& non_const_this->dss (), m_layout_index, dummy_layer_index); + + } } void LayoutToNetlist::register_layer (const db::Region ®ion, const std::string &n) @@ -317,7 +327,7 @@ void LayoutToNetlist::register_layer (const db::Region ®ion, const std::strin if (! delegate) { if (region.empty ()) { - dl = dss ().empty_layer (); + dl = dss ().empty_layer (m_layout_index); } else { throw tl::Exception (tl::to_string (tr ("Layer is not a deep region and cannot be registered with name: ")) + n); } @@ -394,7 +404,7 @@ db::DeepLayer LayoutToNetlist::deep_layer_of (const db::Region ®ion) const return lff.second; } else if (region.empty ()) { // provide a substitute empty layer for empty - return dss ().empty_layer (); + return dss ().empty_layer (m_layout_index); } else { throw (tl::Exception (tl::to_string (tr ("Non-hierarchical layers cannot be used in netlist extraction")))); } @@ -418,7 +428,7 @@ db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell } } - return dss ().cell_mapping_to_original (singular_layout_index, &layout, cell.cell_index (), &device_cells); + return dss ().cell_mapping_to_original (m_layout_index, &layout, cell.cell_index (), &device_cells); } db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell) @@ -869,10 +879,10 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); } - db::Layout &ly = dss ().layout (); + db::Layout &ly = dss ().layout (m_layout_index); double dbu = ly.dbu (); - db::DeepLayer dl (&dss (), singular_layout_index, ly.insert_layer ()); + db::DeepLayer dl (&dss (), m_layout_index, ly.insert_layer ()); for (db::Layout::bottom_up_const_iterator cid = ly.begin_bottom_up (); cid != ly.end_bottom_up (); ++cid) { diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index e85ec4a68..95649d014 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -93,20 +93,7 @@ public: * NOTE: if using make_layer, these new layers will be created in the DSS * given in this constructor. */ - LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index); - - /** - * @brief Alternative constructor using an external deep shape storage - * - * This constructor allows using an external DSS. It's intended to be used - * with existing DSS instances. Existing layers can be registered with - * "register_layer". The LayoutToNetlist object will hold a weak reference - * to the DSS but not own the DSS. - * - * NOTE: this version cannot create layers but just register layers - * which are present inside the DSS given as the argument. - */ - LayoutToNetlist (db::DeepShapeStore *dss); + LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index = 0); /** * @brief Alternative constructor for flat mode @@ -338,11 +325,6 @@ public: */ db::Cell *internal_top_cell (); - /** - * @brief Ensures the internal layout is made - */ - void ensure_internal_layout (); - /** * @brief Gets the connectivity object */ @@ -533,6 +515,7 @@ private: db::RecursiveShapeIterator m_iter; std::auto_ptr mp_internal_dss; tl::weak_ptr mp_dss; + unsigned int m_layout_index; db::Connectivity m_conn; db::hier_clusters m_net_clusters; std::auto_ptr mp_netlist; @@ -560,6 +543,7 @@ private: void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap, const ICplxTrans &tr) const; void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const Net *net, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap, const ICplxTrans &tr) const; db::DeepLayer deep_layer_of (const db::Region ®ion) const; + void ensure_layout () const; }; } diff --git a/src/db/db/dbLayoutToNetlistReader.cc b/src/db/db/dbLayoutToNetlistReader.cc index fe67bab1d..6dcefdade 100644 --- a/src/db/db/dbLayoutToNetlistReader.cc +++ b/src/db/db/dbLayoutToNetlistReader.cc @@ -159,8 +159,6 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n) int version = 0; std::string description; - // TODO: there probably is a more efficient way to force the layout inside l2n to be made - l2n->ensure_internal_layout (); tl_assert (l2n->internal_layout ()); l2n->internal_layout ()->dbu (1.0); // mainly for testing diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index b219fe1a3..50d265cb3 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -123,7 +123,7 @@ static void insert_into_region (const db::PolygonRef &s, const db::ICplxTrans &t region.insert (s.obj ().transformed (tr * db::ICplxTrans (s.trans ()))); } -void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, const NetlistDeviceExtractor::input_layers &layer_map, db::Netlist &nl, hier_clusters_type &clusters) +void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layout_index, const NetlistDeviceExtractor::input_layers &layer_map, db::Netlist &nl, hier_clusters_type &clusters) { initialize (&nl); @@ -147,14 +147,14 @@ void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, const NetlistDevi layers.push_back (alias.second.layer ()); } else if (l->second->empty ()) { // provide a substitute empty layer - layers.push_back (dss.empty_layer ().layer ()); + layers.push_back (dss.empty_layer (layout_index).layer ()); } else { throw tl::Exception (tl::sprintf (tl::to_string (tr ("Invalid region passed to input layer '%s' for device extraction: must be of deep region kind")), ld->name)); } } else { - if (&dr->deep_layer ().layout () != &dss.layout () || &dr->deep_layer ().initial_cell () != &dss.initial_cell ()) { + if (&dr->deep_layer ().layout () != &dss.layout (layout_index) || &dr->deep_layer ().initial_cell () != &dss.initial_cell (layout_index)) { throw tl::Exception (tl::sprintf (tl::to_string (tr ("Invalid region passed to input layer '%s' for device extraction: not originating from the same source")), ld->name)); } @@ -164,7 +164,7 @@ void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, const NetlistDevi } - extract_without_initialize (dss.layout (), dss.initial_cell (), clusters, layers); + extract_without_initialize (dss.layout (layout_index), dss.initial_cell (layout_index), clusters, layers); } void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector &layers, db::Netlist *nl, hier_clusters_type &clusters) diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index 12a4ce280..eba997f58 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -266,7 +266,7 @@ public: * named regions for input. These regions need to be of deep region type and * originate from the same layout than the DeepShapeStore. */ - void extract (DeepShapeStore &dss, const input_layers &layers, Netlist &netlist, hier_clusters_type &clusters); + void extract (DeepShapeStore &dss, unsigned int layout_index, const input_layers &layers, Netlist &netlist, hier_clusters_type &clusters); /** * @brief Gets the error iterator, begin diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 904d703bb..e8ba2bade 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -58,11 +58,11 @@ build_net_name_equivalence (const db::Layout *layout, db::property_names_id_type } void -NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, bool join_nets_by_label) +NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layout_index, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, bool join_nets_by_label) { mp_clusters = &clusters; - mp_layout = &dss.const_layout (); - mp_cell = &dss.const_initial_cell (); + mp_layout = &dss.const_layout (layout_index); + mp_cell = &dss.const_initial_cell (layout_index); // gets the text annotation property ID - // this is how the texts are passed for annotating the net names diff --git a/src/db/db/dbNetlistExtractor.h b/src/db/db/dbNetlistExtractor.h index 73bdb9467..edbe6a1c6 100644 --- a/src/db/db/dbNetlistExtractor.h +++ b/src/db/db/dbNetlistExtractor.h @@ -82,7 +82,7 @@ public: * @brief Extract the nets * See the class description for more details. */ - void extract_nets (const db::DeepShapeStore &dss, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, bool join_nets_by_label = true); + void extract_nets (const db::DeepShapeStore &dss, unsigned int layout_index, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, bool join_nets_by_label = true); private: hier_clusters_type *mp_clusters; diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index 3b03ea926..4713081aa 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -218,12 +218,12 @@ TEST(1_DeviceAndNetExtraction) dl["SD"] = &rpsd; dl["G"] = &rpgate; dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes - pmos_ex.extract (dss, dl, nl, cl); + pmos_ex.extract (dss, 0, dl, nl, cl); dl["SD"] = &rnsd; dl["G"] = &rngate; dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes - nmos_ex.extract (dss, dl, nl, cl); + nmos_ex.extract (dss, 0, dl, nl, cl); // perform the net extraction @@ -253,7 +253,7 @@ TEST(1_DeviceAndNetExtraction) // extract the nets - net_ex.extract_nets (dss, conn, nl, cl); + net_ex.extract_nets (dss, 0, conn, nl, cl); // debug layers produced for nets // 202/0 -> Active @@ -430,12 +430,12 @@ TEST(2_DeviceAndNetExtractionFlat) dl["SD"] = &rpsd; dl["G"] = &rpgate; dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes - pmos_ex.extract (dss, dl, nl, cl); + pmos_ex.extract (dss, 0, dl, nl, cl); dl["SD"] = &rnsd; dl["G"] = &rngate; dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes - nmos_ex.extract (dss, dl, nl, cl); + nmos_ex.extract (dss, 0, dl, nl, cl); // perform the net extraction @@ -466,7 +466,7 @@ TEST(2_DeviceAndNetExtractionFlat) // extract the nets // don't use "join_nets_by_label" because the flattened texts will spoil everything - net_ex.extract_nets (dss, conn, nl, cl, false); + net_ex.extract_nets (dss, 0, conn, nl, cl, false); // debug layers produced for nets // 202/0 -> Active @@ -664,12 +664,12 @@ TEST(3_DeviceAndNetExtractionWithImplicitConnections) dl["SD"] = &rpsd; dl["G"] = &rpgate; dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes - pmos_ex.extract (dss, dl, nl, cl); + pmos_ex.extract (dss, 0, dl, nl, cl); dl["SD"] = &rnsd; dl["G"] = &rngate; dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes - nmos_ex.extract (dss, dl, nl, cl); + nmos_ex.extract (dss, 0, dl, nl, cl); // perform the net extraction @@ -699,7 +699,7 @@ TEST(3_DeviceAndNetExtractionWithImplicitConnections) // extract the nets - net_ex.extract_nets (dss, conn, nl, cl); + net_ex.extract_nets (dss, 0, conn, nl, cl); EXPECT_EQ (all_net_names_unique (nl), true); diff --git a/src/drc/drc/built-in-macros/drc.lym b/src/drc/drc/built-in-macros/drc.lym index b0032387c..bfe9eca5d 100644 --- a/src/drc/drc/built-in-macros/drc.lym +++ b/src/drc/drc/built-in-macros/drc.lym @@ -3772,7 +3772,7 @@ CODE # Multiple diode specifications are allowed. Just add them # to the antenna_check call. # - # The error shapes produced by the antenna check are a copy + # The error shapes produced by the antenna check are copies # of the metal shapes on the metal layers of each network # violating the antenna rule.