From 5c27fedfe524c743a0e38ae25729e2331f0d0665 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 17 May 2025 00:44:15 +0200 Subject: [PATCH] Debugging and bug fixes. The 'big example' from issue 2014 now works --- src/db/db/dbCommonReader.cc | 9 ++- src/db/db/dbCommonReader.h | 2 +- .../lefdef/db_plugin/dbDEFImporter.cc | 39 +++------ .../lefdef/db_plugin/dbDEFImporter.h | 16 +--- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 79 ++++++++++++++++++- .../lefdef/db_plugin/dbLEFDEFImporter.h | 31 ++++++++ .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 43 ++-------- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 7 +- 8 files changed, 139 insertions(+), 87 deletions(-) diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc index bf21fa5fc..b1becdcfb 100644 --- a/src/db/db/dbCommonReader.cc +++ b/src/db/db/dbCommonReader.cc @@ -314,8 +314,13 @@ CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_ind } void -CommonReaderBase::init () +CommonReaderBase::start () { + m_id_map.clear (); + m_name_map.clear (); + m_temp_cells.clear (); + m_name_for_id.clear (); + m_layer_map_out.clear (); m_multi_mapping_placeholders.clear (); m_layer_cache.clear (); @@ -621,7 +626,7 @@ void CommonReader::init (const LoadLayoutOptions &options) { ReaderBase::init (options); - CommonReaderBase::init (); + CommonReaderBase::start (); db::CommonReaderOptions common_options = options.get_options (); set_conflict_resolution_mode (common_options.cell_conflict_resolution); diff --git a/src/db/db/dbCommonReader.h b/src/db/db/dbCommonReader.h index 7433cafe3..1a7dafcdf 100644 --- a/src/db/db/dbCommonReader.h +++ b/src/db/db/dbCommonReader.h @@ -207,7 +207,7 @@ public: /** * @brief Re-initialize: clears the tables and caches */ - void init (); + void start (); /** * @brief Sets a value indicating whether to create layers diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index b91bd458f..3aa4d79c7 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -53,24 +53,11 @@ struct DEFImporterGroup }; DEFImporter::DEFImporter (int warn_level) - : LEFDEFImporter (warn_level), - m_lef_importer (warn_level) + : LEFDEFImporter (warn_level) { // .. nothing yet .. } -void -DEFImporter::read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state) -{ - m_lef_importer.read (stream, layout, state); -} - -void -DEFImporter::finish_lef (db::Layout &layout) -{ - m_lef_importer.finish_lef (layout); -} - void DEFImporter::read_polygon (db::Polygon &poly, double scale) { @@ -112,7 +99,7 @@ DEFImporter::read_rect (db::Polygon &poly, double scale) std::pair DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu) { - std::pair wxy = m_lef_importer.layer_width (ln, rulename); + std::pair wxy = reader_state ()->lef_importer ().layer_width (ln, rulename); db::Coord wx = db::coord_traits::rounded (wxy.first / dbu); db::Coord wy = db::coord_traits::rounded (wxy.second / dbu); @@ -127,7 +114,7 @@ DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::st } } - std::pair min_wxy = m_lef_importer.min_layer_width (ln); + std::pair min_wxy = reader_state ()->lef_importer ().min_layer_width (ln); db::Coord min_wx = db::coord_traits::rounded (min_wxy.first / dbu); db::Coord min_wy = db::coord_traits::rounded (min_wxy.second / dbu); @@ -769,7 +756,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C unsigned int mask_cut = (mask / 10) % 10; unsigned int mask_bottom = mask % 10; - db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &reader_state ()->lef_importer ()); if (cell) { if (nx <= 1 && ny <= 1) { design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); @@ -953,7 +940,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool std::map::const_iterator vd = m_via_desc.find (vn); if (vd != m_via_desc.end ()) { - db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &reader_state ()->lef_importer ()); if (cell) { design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), pt))); } @@ -1130,7 +1117,7 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) std::string ln = get (); - if (m_lef_importer.is_routing_layer (ln)) { + if (reader_state ()->lef_importer ().is_routing_layer (ln)) { if (seen_layers.find (ln) == seen_layers.end ()) { @@ -1145,7 +1132,7 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) } - } else if (m_lef_importer.is_cut_layer (ln)) { + } else if (reader_state ()->lef_importer ().is_cut_layer (ln)) { geo_based_vg->set_maskshift_layer (1, ln); has_cut_geometry = true; @@ -1336,7 +1323,7 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale) std::map::const_iterator vd = m_via_desc.find (vn); if (vd != m_via_desc.end ()) { std::string nondefaultrule; - db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &reader_state ()->lef_importer ()); if (cell) { design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (pt))); } @@ -1549,7 +1536,7 @@ DEFImporter::read_fills (db::Layout &layout, db::Cell &design, double scale) std::map::const_iterator vd = m_via_desc.find (vn); if (vd != m_via_desc.end ()) { std::string nondefaultrule; - db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &reader_state ()->lef_importer ()); if (cell) { ensure_fill_cell (layout, design, fill_cell).insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (pt))); } @@ -1613,8 +1600,8 @@ DEFImporter::read_components (db::Layout &layout, std::list::const_iterator m = m_lef_importer.macros ().find (model); - if (m == m_lef_importer.macros ().end ()) { + std::map::const_iterator m = reader_state ()->lef_importer ().macros ().find (model); + if (m == reader_state ()->lef_importer ().macros ().end ()) { error (tl::to_string (tr ("Macro not found in LEF file: ")) + model); } @@ -1660,7 +1647,7 @@ DEFImporter::read_components (db::Layout &layout, std::list ct = reader_state ()->macro_cell (model, layout, m_component_maskshift, string2masks (maskshift), m->second, &m_lef_importer); + std::pair ct = reader_state ()->macro_cell (model, layout, m_component_maskshift, string2masks (maskshift), m->second, &reader_state ()->lef_importer ()); if (ct.first) { db::CellInstArray inst (db::CellInst (ct.first->cell_index ()), db::Trans (ft.rot (), d) * ct.second); instances.push_back (std::make_pair (inst_name, inst)); @@ -1684,7 +1671,7 @@ DEFImporter::do_read (db::Layout &layout) std::list groups; std::list > instances; - m_via_desc = m_lef_importer.vias (); + m_via_desc = reader_state ()->lef_importer ().vias (); m_styles.clear (); m_design_name.clear (); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 0b824e403..56e7568f8 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -48,26 +48,12 @@ public: /** * @brief Default constructor */ - DEFImporter (int warn_level = 1); - - /** - * @brief Read the given LEF file prior to the DEF file - * - * This method reads the layout specified into the given layout. - * Multiple LEF files can be read. - */ - void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state); - - /** - * @brief Provided for test purposes - */ - void finish_lef (Layout &layout); + DEFImporter (int warn_level); protected: void do_read (db::Layout &layout); private: - LEFImporter m_lef_importer; std::map > m_nondefault_widths; std::map m_via_desc; std::map m_styles; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index bb93be064..8776f6827 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -22,9 +22,11 @@ #include "dbLEFDEFImporter.h" +#include "dbLEFImporter.h" #include "dbLayoutUtils.h" #include "dbTechnology.h" #include "dbShapeProcessor.h" +#include "dbCellMapping.h" #include "tlStream.h" #include "tlProgress.h" @@ -958,6 +960,7 @@ LEFDEFReaderOptions::set_lef_context_enabled (bool f) { if (f != m_lef_context_enabled) { mp_reader_state.reset (0); + m_lef_context_enabled = f; } } @@ -1036,8 +1039,8 @@ LEFDEFReaderState::init (Layout &layout, const std::string &base_path, const Loa reader.read (*new_layout, options); if (fabs (new_layout->dbu () / layout.dbu () - 1.0) > db::epsilon) { - tl::warn << tl::sprintf (tl::to_string (tr ("DBU of macro layout file '%s' does not match reader DBU (layout DBU is %.12g, reader DBU is set to %.12g)")), - *lp, new_layout->dbu (), layout.dbu ()); + warn (tl::sprintf (tl::to_string (tr ("DBU of macro layout file '%s' does not match reader DBU (layout DBU is %.12g, reader DBU is set to %.12g)")), + *lp, new_layout->dbu (), layout.dbu ())); } } @@ -1063,6 +1066,33 @@ LEFDEFReaderState::warn (const std::string &msg, int warn_level) } } +void +LEFDEFReaderState::ensure_lef_importer (int warn_level) +{ + if (! mp_lef_importer.get ()) { + mp_lef_importer.reset (new db::LEFImporter (warn_level)); + } +} + +db::LEFImporter & +LEFDEFReaderState::lef_importer () +{ + tl_assert (mp_lef_importer.get () != 0); + return *mp_lef_importer; +} + +void +LEFDEFReaderState::read_lef (tl::InputStream &stream, db::Layout &layout) +{ + lef_importer ().read (stream, layout, *this); +} + +void +LEFDEFReaderState::finish_lef (db::Layout &layout) +{ + lef_importer ().finish_lef (layout); +} + void LEFDEFReaderState::register_layer (const std::string &ln) { @@ -1774,11 +1804,56 @@ std::set LEFDEFReaderState::open_layer_uncached(db::Layout &layout } } +void +LEFDEFReaderState::start () +{ + CommonReaderBase::start (); + + m_foreign_cells.clear (); +} + void LEFDEFReaderState::finish (db::Layout &layout) { CommonReaderBase::finish (layout); + // Resolve unresolved COMPONENT cells + + db::cell_index_type seen = std::numeric_limits::max (); + + for (std::vector::const_iterator m = macro_layouts ().begin (); m != macro_layouts ().end (); ++m) { + + std::vector target_cells, source_cells; + + // collect the cells to pull in + for (std::map::iterator f = m_foreign_cells.begin (); f != m_foreign_cells.end (); ++f) { + if (f->second != seen) { + std::pair cp = (*m)->cell_by_name (f->first.c_str ()); + if (cp.first) { + target_cells.push_back (f->second); + source_cells.push_back (cp.second); + layout.cell (f->second).set_ghost_cell (false); + f->second = seen; + } + } + } + + db::CellMapping cm; + cm.create_multi_mapping_full (layout, target_cells, **m, source_cells); + layout.copy_tree_shapes (**m, cm); + + } + + // Warn about cells that could not be resolved + for (std::map::iterator f = m_foreign_cells.begin (); f != m_foreign_cells.end (); ++f) { + if (f->second != seen && layout.cell (f->second).is_ghost_cell ()) { + warn (tl::sprintf (tl::to_string (tr ("Could not find a substitution layout for foreign cell '%s'")), + f->first)); + } + } + + // Create the layers + int lnum = 0; std::set used_numbers; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 9fa0e6d04..fc75c5c63 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -46,6 +46,7 @@ namespace db class LEFDEFReaderState; class LEFDEFImporter; +class LEFImporter; struct MacroDesc; /** @@ -1325,8 +1326,15 @@ public: */ void register_layer (const std::string &l); + /** + * @brief Start reading a file + * After the file is read, "finish" needs to be called. + */ + void start (); + /** * @brief Finish, i.e. assign GDS layer numbers to the layers + * This is the counterpart for "start". */ void finish (db::Layout &layout); @@ -1390,6 +1398,28 @@ public: */ void warn (const std::string &msg, int warn_level = 1); + /** + * @brief Ensures the LEF importer for DEF reading is available + */ + void ensure_lef_importer (int warn_level); + + /** + * @brief Gets the LEF importer for DEF reading + */ + db::LEFImporter &lef_importer (); + + /** + * @brief Reads a LEF file into the LEF importer + * + * Multiple LEF files can be read. + */ + void read_lef (tl::InputStream &stream, db::Layout &layout); + + /** + * @brief Provided for test purposes + */ + void finish_lef (db::Layout &layout); + /** * @brief Gets a value indicating whether the given LEF file was already read */ @@ -1510,6 +1540,7 @@ private: std::set m_lef_files_read; std::vector m_macro_layouts; tl::shared_collection m_macro_layout_object_holder; + std::unique_ptr mp_lef_importer; std::set open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask); db::cell_index_type foreign_cell(Layout &layout, const std::string &name); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 0985b0531..7dad8a35e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -138,6 +138,9 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti state = &local_state; } + state->ensure_lef_importer (warn_level ()); + state->start (); + // Configure the conflict resolution mode db::CommonReaderOptions common_options = options.get_options (); state->set_conflict_resolution_mode (common_options.cell_conflict_resolution); @@ -186,7 +189,7 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti tl::InputStream lef_stream (norm_lp); tl::log << tl::to_string (tr ("Reading")) << " " << *lp; - importer.read_lef (lef_stream, layout, *state); + state->read_lef (lef_stream, layout); state->register_lef_file (norm_lp); @@ -219,7 +222,7 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti tl::InputStream lef_stream (norm_lp); tl::log << tl::to_string (tr ("Reading")) << " " << lp; - importer.read_lef (lef_stream, layout, *state); + state->read_lef (lef_stream, layout); state->register_lef_file (norm_lp); @@ -236,42 +239,6 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source (); importer.read (m_stream, layout, *state); - // Resolve unresolved COMPONENT cells - - std::map foreign_cells = state->foreign_cells (); - db::cell_index_type seen = std::numeric_limits::max (); - - for (std::vector::const_iterator m = state->macro_layouts ().begin (); m != state->macro_layouts ().end (); ++m) { - - std::vector target_cells, source_cells; - - // collect the cells to pull in - for (std::map::iterator f = foreign_cells.begin (); f != foreign_cells.end (); ++f) { - if (f->second != seen) { - std::pair cp = (*m)->cell_by_name (f->first.c_str ()); - if (cp.first) { - target_cells.push_back (f->second); - source_cells.push_back (cp.second); - layout.cell (f->second).set_ghost_cell (false); - f->second = seen; - } - } - } - - db::CellMapping cm; - cm.create_multi_mapping_full (layout, target_cells, **m, source_cells); - layout.copy_tree_shapes (**m, cm); - - } - - // Warn about cells that could not be resolved - for (std::map::iterator f = foreign_cells.begin (); f != foreign_cells.end (); ++f) { - if (f->second != seen && layout.cell (f->second).is_ghost_cell ()) { - importer.warn (tl::sprintf (tl::to_string (tr ("Could not find a substitution layout for foreign cell '%s'")), - f->first)); - } - } - } state->finish (layout); diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index a493959b6..a7448f1e7 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -61,10 +61,11 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f db::LoadLayoutOptions other_options; db::LEFDEFReaderState ld (&options); + ld.ensure_lef_importer (1); ld.init (layout, fn_path, other_options); ld.set_conflict_resolution_mode (cc_mode); - db::DEFImporter imp; + db::DEFImporter imp (1); bool any_def = false; bool any_lef = false; @@ -95,7 +96,7 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f fn += f; tl::InputStream stream (fn); - imp.read_lef (stream, layout, ld); + ld.read_lef (stream, layout); any_lef = true; @@ -136,7 +137,7 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f } if (! any_def && any_lef) { - imp.finish_lef (layout); + ld.finish_lef (layout); } ld.finish (layout);