From 33c858924f9338956feb2b31f165fba88f3d4f29 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 16 Feb 2023 23:49:24 +0100 Subject: [PATCH] Some LEF reader fixes based on the complete sample --- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 18 +- .../lefdef/db_plugin/dbLEFDEFImporter.h | 23 ++ .../lefdef/db_plugin/dbLEFImporter.cc | 250 +++++++++++++----- .../lefdef/db_plugin/dbLEFImporter.h | 1 + .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 7 + 5 files changed, 225 insertions(+), 74 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index bc9fac2c7..031b34726 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -1990,7 +1990,11 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderS void LEFDEFImporter::error (const std::string &msg) { - throw LEFDEFReaderException (msg, int (mp_stream->line_number ()), m_cellname, m_fn); + if (m_sections.empty ()) { + throw LEFDEFReaderException (msg, int (mp_stream->line_number ()), m_cellname, m_fn); + } else { + throw LEFDEFReaderException (msg + tl::sprintf (tl::to_string (tr (" (inside %s)")), tl::join (m_sections, "/")), int (mp_stream->line_number ()), m_cellname, m_fn); + } } void @@ -2140,6 +2144,18 @@ LEFDEFImporter::get () return r; } +void +LEFDEFImporter::enter_section (const std::string &name) +{ + m_sections.push_back (name); +} + +void +LEFDEFImporter::leave_section () +{ + m_sections.pop_back (); +} + const std::string & LEFDEFImporter::next () { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index beb161fb3..84fdc7525 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -1706,8 +1706,31 @@ private: db::property_names_id_type m_pin_prop_name_id; db::LEFDEFReaderOptions m_options; int m_warn_level; + std::vector m_sections; + + friend class LEFDEFSection; const std::string &next (); + void enter_section (const std::string &name); + void leave_section (); +}; + +class DB_PLUGIN_PUBLIC LEFDEFSection +{ +public: + LEFDEFSection (LEFDEFImporter *importer, const std::string &name) + : mp_importer (importer) + { + mp_importer->enter_section (name); + } + + ~LEFDEFSection () + { + mp_importer->leave_section (); + } + +private: + LEFDEFImporter *mp_importer; }; class DB_PLUGIN_PUBLIC LEFDEFReader diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 12f7cb6b4..4b136bb7e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -388,9 +388,7 @@ LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, Laye } else if (test ("PROPERTY")) { // skip properties - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } else { // stop at unknown token @@ -406,7 +404,7 @@ LEFImporter::read_nondefaultrule (db::Layout &layout) // read NONDEFAULTRULE sections std::string n = get (); - while (! test ("END") || ! test (n)) { + while (! test ("END")) { if (test ("LAYER")) { @@ -419,9 +417,7 @@ LEFImporter::read_nondefaultrule (db::Layout &layout) test (";"); m_nondefault_widths[n][l] = std::make_pair (w, w); } else { - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } } @@ -432,12 +428,25 @@ LEFImporter::read_nondefaultrule (db::Layout &layout) read_viadef (layout, n); } else { - while (! at_end () && ! test (";")) { - take (); + + std::string token = get (); + + if (token == "SPACING") { + // read over sections we do not need + while (! at_end () && ! test ("END")) { + skip_entry (); + } + test (token); + } else if (token != ";") { + // read over lines we do not need + skip_entry (); } + } } + + test (n); } void @@ -557,6 +566,13 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc get_double (); test (";"); + } else if (test ("FOREIGN")) { + + // undocumented + while (! at_end () && ! test (";")) { + take (); + } + } else if (test ("LAYER")) { layer_name = get (); @@ -631,9 +647,7 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc } else if (test ("PROPERTY")) { // skip properties - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } else { // stop at unknown token @@ -663,7 +677,7 @@ LEFImporter::read_viadef (Layout &layout, const std::string &nondefaultrule) ViaDesc &via_desc = m_vias[n]; - while (test ("DEFAULT") || test ("TOPOFSTACKONLY")) + while (test ("DEFAULT") || test ("TOPOFSTACKONLY") || test("GENERATED")) ; test (";"); @@ -746,55 +760,51 @@ LEFImporter::read_layer (Layout & /*layout*/) // blocks following a semicolon take (); if (test ("FREQUENCY")) { - while (! test ("TABLEENTRIES")) { + while (! at_end () && ! test ("TABLEENTRIES")) { take (); } } - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } else if (test ("PROPERTY")) { - std::string name = get (); - tl::Variant value = get (); + while (! test (";") && ! at_end ()) { - if (name == "LEF58_MINWIDTH") { + std::string name = get (); + tl::Variant value = get (); - // Cadence extension - tl::Extractor ex (value.to_string ()); - double v = 0.0; - if (ex.test ("MINWIDTH") && ex.try_read (v)) { - if (ex.test ("WRONGDIRECTION")) { - wmin_wrongdir = v; - } else { - wmin = v; + if (name == "LEF58_MINWIDTH") { + + // Cadence extension + tl::Extractor ex (value.to_string ()); + double v = 0.0; + if (ex.test ("MINWIDTH") && ex.try_read (v)) { + if (ex.test ("WRONGDIRECTION")) { + wmin_wrongdir = v; + } else { + wmin = v; + } } - } - } else if (name == "LEF58_WIDTH") { + } else if (name == "LEF58_WIDTH") { - // Cadence extension - tl::Extractor ex (value.to_string ()); - double v = 0.0; - if (ex.test ("WIDTH") && ex.try_read (v)) { - if (ex.test ("WRONGDIRECTION")) { - w_wrongdir = v; - } else { - w = v; + // Cadence extension + tl::Extractor ex (value.to_string ()); + double v = 0.0; + if (ex.test ("WIDTH") && ex.try_read (v)) { + if (ex.test ("WRONGDIRECTION")) { + w_wrongdir = v; + } else { + w = v; + } } + } } - expect (";"); - } else { - - while (! at_end () && ! test (";")) { - take (); - } - + skip_entry (); } } @@ -865,6 +875,8 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("PIN")) { + LEFDEFSection section (this, "PIN"); + std::string pn = get (); std::string dir; @@ -881,6 +893,8 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("PORT")) { + LEFDEFSection section (this, "PORT"); + // produce pin labels // TODO: put a label on every single object? std::string label = pn; @@ -916,9 +930,7 @@ LEFImporter::read_macro (Layout &layout) expect ("END"); } else { - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } } @@ -926,12 +938,19 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("FOREIGN")) { + LEFDEFSection section (this, "FOREIGN"); + std::string cn = get (); db::Point vec; db::FTrans ft; if (! peek (";")) { - vec = get_point (1.0 / layout.dbu ()); + if (test ("(")) { + vec = get_point (1.0 / layout.dbu ()); + expect (")"); + } else { + vec = get_point (1.0 / layout.dbu ()); + } ft = get_orient (true); } @@ -940,7 +959,7 @@ LEFImporter::read_macro (Layout &layout) if (options ().macro_resolution_mode () != 1) { if (! foreign_name.empty ()) { - error (tl::to_string (tr ("Duplicate FOREIGN definition"))); + warn (tl::to_string (tr ("Duplicate FOREIGN definition"))); } // What is the definition of the FOREIGN transformation? @@ -956,6 +975,8 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("OBS")) { + LEFDEFSection section (this, "OBS"); + if (reader_state ()->tech_comp ()->produce_obstructions ()) { read_geometries (mg, layout.dbu (), Obstructions); } else { @@ -966,8 +987,10 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("DENSITY")) { + LEFDEFSection section (this, "DENSITY"); + // read over DENSITY statements - while (! test ("END")) { + while (! at_end () && ! test ("END")) { if (test ("LAYER")) { get (); expect (";"); @@ -980,17 +1003,27 @@ LEFImporter::read_macro (Layout &layout) } } - expect ("END"); - } else if (test ("FIXEDMASK")) { mg->set_fixedmask (true); expect (";"); } else { - while (! at_end () && ! test (";")) { - take (); + + std::string token = get (); + LEFDEFSection section (this, token); + + if (token == "TIMING") { + // read over sections we do not need + while (! at_end () && ! test ("END")) { + skip_entry (); + } + test (token); + } else if (token != ";") { + // read over lines we do not need + skip_entry (); } + } } @@ -1031,17 +1064,16 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("UNITS")) { - // read over SPACING sections - while (! test ("END")) { + LEFDEFSection section (this, "UNITS"); + + while (! at_end () && ! test ("END")) { if (test ("DATABASE")) { expect ("MICRONS"); // TODO: what to do with that value /* dbu_mic = */ get_double (); expect (";"); } else { - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } } @@ -1049,44 +1081,105 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("SPACING")) { + LEFDEFSection section (this, "SPACING"); + // read over SPACING sections - while (! test ("END") || ! test ("SPACING")) { - take (); + while (! at_end () && ! test ("END")) { + skip_entry (); } + test ("SPACING"); + } else if (test ("PROPERTYDEFINITIONS")) { + LEFDEFSection section (this, "PROPERTYDEFINITIONS"); + // read over PROPERTYDEFINITIONS sections - while (! test ("END") || ! test ("PROPERTYDEFINITIONS")) { - take (); + while (! at_end () && ! test ("END")) { + skip_entry (); } + test ("PROPERTYDEFINITIONS"); + } else if (test ("NONDEFAULTRULE")) { + LEFDEFSection section (this, "NONDEFAULTRULE"); + read_nondefaultrule (layout); } else if (test ("SITE")) { - // read over SITE sections + LEFDEFSection section (this, "NONDEFAULTRULE"); + + // read over SITE or VIARULE sections std::string n = get (); - while (! test ("END") || ! test (n)) { - take (); + while (! at_end () && ! test ("END")) { + skip_entry (); } + test (n); + } else if (test ("VIARULE")) { - // read over VIARULE sections + LEFDEFSection section (this, "VIARULE"); + + // read over SITE or VIARULE sections std::string n = get (); - while (! test ("END") || ! test (n)) { - take (); + while (! at_end () && ! test ("END")) { + skip_entry (); } + test (n); + + } else if (test ("NOISETABLE")) { + + LEFDEFSection section (this, "NOISETABLE"); + + // read over NOISETABLE sections + while (! at_end () && ! test ("END")) { + skip_entry (); + } + + test ("NOISETABLE"); + + } else if (test ("IRDROP")) { + + LEFDEFSection section (this, "IRDROP"); + + // read over IRDROP sections + while (! at_end () && ! test ("END")) { + skip_entry (); + } + + test ("IRDROP"); + + } else if (test ("ARRAY")) { + + LEFDEFSection section (this, "ARRAY"); + + // read over ARRAY sections + std::string n = get (); + while (! at_end () && ! test ("END")) { + if (test ("FLOORPLAN")) { + while (! at_end () && ! test ("END")) { + skip_entry (); + } + } else { + skip_entry (); + } + } + + test (n); + } else if (test ("VIA")) { + LEFDEFSection section (this, "VIA"); read_viadef (layout, std::string ()); } else if (test ("BEGINEXT")) { + LEFDEFSection section (this, "BEGINEXT"); + // read over BEGINEXT sections while (! test ("ENDEXT")) { take (); @@ -1094,21 +1187,32 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("LAYER")) { + LEFDEFSection section (this, "LAYER"); read_layer (layout); } else if (test ("MACRO")) { + LEFDEFSection section (this, "MACRO"); read_macro (layout); } else { - while (! at_end () && ! test (";")) { - take (); - } + + // read over entries we do not need + skip_entry (); + } } } +void +LEFImporter::skip_entry () +{ + while (! at_end () && ! test (";")) { + take (); + } +} + void LEFImporter::finish_lef (db::Layout &layout) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h index 266b887aa..5c6402af4 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h @@ -152,6 +152,7 @@ private: void read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc &desc, const std::string &n, double dbu); void read_layer (Layout &layout); void read_macro (Layout &layout); + void skip_entry (); }; } diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 328feedcc..09b435dfb 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -317,6 +317,12 @@ TEST(lef7) run_test (_this, "lef7", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", options); } +TEST(lef8) +{ + // this is rather a smoke test and throws a number of warnings + run_test (_this, "lef8", "lef:tech.lef+lef:a.lef", "au.oas.gz", default_options ()); +} + TEST(def1) { run_test (_this, "def1", "lef:in.lef+def:in.def", "au2.oas.gz", default_options ()); @@ -418,6 +424,7 @@ TEST(def15) TEST(def16) { + // this is rather a smoke test db::LEFDEFReaderOptions opt = default_options (); opt.set_macro_resolution_mode (1); run_test (_this, "def16", "lef:a.lef+lef:tech.lef+def:a.def", "au.oas.gz", opt);