From 44503faceae9080c76b46a01da84bec5044fbd01 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 18:57:07 +0200 Subject: [PATCH 01/43] Attempt to auto-import .map files for LEF/DEF reader. Probably needs adjustment. --- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 78 ++++++++--- .../lefdef/db_plugin/dbLEFDEFImporter.h | 8 ++ .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 125 +++++++++++++++++- 3 files changed, 190 insertions(+), 21 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 430a31f25..d61efba16 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -147,18 +147,25 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer { if (purpose == Outline || purpose == PlacementBlockage || purpose == Region) { + // NOTE: the canonical name is independent from the tech component's settings + // as is "(name)". It's used for implementing the automatic map file import + // feature. std::string ld; + std::string canonical_name; bool produce; if (purpose == Outline) { produce = mp_tech_comp->produce_cell_outlines (); ld = mp_tech_comp->cell_outline_layer (); + canonical_name = "(OUTLINE)"; } else if (purpose == Region) { produce = mp_tech_comp->produce_regions (); ld = mp_tech_comp->region_layer (); + canonical_name = "(REGION)"; } else { produce = mp_tech_comp->produce_placement_blockages (); ld = mp_tech_comp->placement_blockage_layer (); + canonical_name = "(BLK)"; } if (! produce) { @@ -178,10 +185,9 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer if (ll.first) { - // create the layer if it is not part of the layout yet. - if (! layout.is_valid_layer (ll.second)) { - layout.insert_layer (ll.second, m_layer_map.mapping (ll.second)); - } + return ll; + + } else if ((ll = m_layer_map.logical (db::LayerProperties (canonical_name), layout)).first) { return ll; @@ -199,67 +205,99 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer } else { + if (mp_tech_comp) { + bool produce = true; + switch (purpose) { + case Routing: + default: + produce = mp_tech_comp->produce_routing (); + break; + case ViaGeometry: + produce = mp_tech_comp->produce_via_geometry (); + break; + case Label: + produce = mp_tech_comp->produce_labels (); + break; + case Pins: + produce = mp_tech_comp->produce_pins (); + break; + case Obstructions: + produce = mp_tech_comp->produce_obstructions (); + break; + case Blockage: + produce = mp_tech_comp->produce_blockages (); + break; + } + if (! produce) { + return std::make_pair (false, 0); + } + } + + // Note: "name" is the decorated name as provided by the tech component's + // x_suffix specifications. As this is a variable entity, we also provide + // a canonical name of the form "(layer,purpose)" where purpose is a + // predefined suffix. The canonical name is the last fallback. Hence this + // allows importing layer mapping files as canonical name mapping. std::string name (n); - bool produce = true; int dt = 0; + std::string canonical_purpose; + if (mp_tech_comp) { switch (purpose) { case Routing: default: - produce = mp_tech_comp->produce_routing (); name += mp_tech_comp->routing_suffix (); + canonical_purpose = "NET"; dt += mp_tech_comp->routing_datatype (); break; case ViaGeometry: - produce = mp_tech_comp->produce_via_geometry (); name += mp_tech_comp->via_geometry_suffix (); dt += mp_tech_comp->via_geometry_datatype (); + canonical_purpose = "VIA"; break; case Label: - produce = mp_tech_comp->produce_labels (); name += mp_tech_comp->labels_suffix (); dt += mp_tech_comp->labels_datatype (); + canonical_purpose = "LABEL"; break; case Pins: - produce = mp_tech_comp->produce_pins (); name += mp_tech_comp->pins_suffix (); dt += mp_tech_comp->pins_datatype (); + canonical_purpose = "PIN"; break; case Obstructions: - produce = mp_tech_comp->produce_obstructions (); name += mp_tech_comp->obstructions_suffix (); dt += mp_tech_comp->obstructions_datatype (); + canonical_purpose = "OBS"; break; case Blockage: - produce = mp_tech_comp->produce_blockages (); name += mp_tech_comp->blockages_suffix (); dt += mp_tech_comp->blockages_datatype (); + canonical_purpose = "BLK"; break; } } - if (! produce) { - return std::make_pair (false, 0); - } + std::string canonical_name = std::string ("(") + n + "," + canonical_purpose + ")"; std::pair ll = m_layer_map.logical (name, layout); if (ll.first) { - // create the layer if it is not part of the layout yet. - if (! layout.is_valid_layer (ll.second)) { - layout.insert_layer (ll.second, m_layer_map.mapping (ll.second)); - } + return ll; + } else if ((ll = m_layer_map.logical (db::LayerProperties (canonical_name), layout)).first) { + + // final fallback: try canonical name return ll; } else { - std::pair ll_raw = m_layer_map.logical (n, layout); + ll = m_layer_map.logical (n, layout); int ln = -1; - if (ll_raw.first && (ln = layout.get_properties (ll_raw.second).layer) >= 0) { + if (ll.first && (ln = layout.get_properties (ll.second).layer) >= 0) { m_layer_map.map (db::LayerProperties (name), layout.layers (), db::LayerProperties (ln, dt, name)); m_layer_map.prepare (layout); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 8058accd0..0cfc38f2b 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -518,6 +518,14 @@ public: return m_layer_map; } + /** + * @brief Get the layer map (non-const version) + */ + db::LayerMap &layer_map () + { + return m_layer_map; + } + /** * @brief Create a new layer or return the index of the given layer */ diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index d9b10b28a..fa2e9adb5 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -77,6 +77,124 @@ static bool is_def_format (const std::string &fn) return false; } +/** + * @brief Reads a map file + * + * NOTE: this is rather experimental ... no idea what is the specification of + * the map file. + */ +static void +read_map_file (const std::string &path, db::LEFDEFLayerDelegate &layers) +{ + tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path; + + db::LayerMap &lm = layers.layer_map (); + unsigned int n = lm.next_index (); + + tl::InputFile file (path); + tl::InputStream file_stream (file); + tl::TextInputStream ts (file_stream); + + std::map purpose_translation; + purpose_translation ["LEFPIN"] = "PIN"; + purpose_translation ["LEFOBS"] = "OBS"; + purpose_translation ["SPNET"] = "NET"; + purpose_translation ["NET"] = "NET"; + purpose_translation ["VIA"] = "VIA"; + + while (! ts.at_end ()) { + + const std::string &l = ts.get_line (); + + tl::Extractor ex (l.c_str ()); + if (ex.at_end () || ex.test ("#")) { + + // ignore empty of comment lines + + } else { + + std::string w1, w2; + int layer = 0, datatype = 0; + + if (ex.try_read_word (w1) && ex.try_read_word (w2, "._$,/:") && ex.try_read (layer) && ex.try_read (datatype)) { + + if (w1 == "DIEAREA") { + + std::string canonical_name = "(OUTLINE)"; + lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype)); + + } else if (w1 == "NAME") { + + std::vector purposes = tl::split (w2, ","); + for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { + std::string canonical_name = std::string ("(") + tl::split (*p, "/").front () + ",LABEL)"; + lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype)); + } + + } else { + + std::vector purposes = tl::split (w2, ","); + for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { + std::map::const_iterator i = purpose_translation.find (*p); + if (i != purpose_translation.end ()) { + std::string canonical_name = std::string ("(") + w1 + "," + i->second + ")"; + lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype)); + } + } + + } + + } + + } + + } +} + +/** + * @brief Imports a .map file present next to the input files + */ +static void +import_map_file_heuristics (const std::string &main_path, db::LEFDEFLayerDelegate &layers) +{ + std::string input_dir = tl::absolute_path (main_path); + if (! tl::file_exists (input_dir)) { + return; + } + + std::string bn = tl::basename (tl::filename (main_path)); + std::vector map_files; + std::string map_file_exact; + + std::vector entries = tl::dir_entries (input_dir); + for (std::vector::const_iterator e = entries.begin (); e != entries.end (); ++e) { + + if (tl::to_lower_case (tl::extension (*e)) == "map") { + + if (tl::basename (*e) == bn) { + map_file_exact = *e; + } else { + map_files.push_back (*e); + } + + } + + } + + try { + if (! map_file_exact.empty ()) { + read_map_file (tl::combine_path (input_dir, map_file_exact), layers); + tl::log << layers.layer_map ().to_string_file_format (); // @@@ + } else if (map_files.size () == 1) { + read_map_file (tl::combine_path (input_dir, map_files.front ()), layers); + tl::log << layers.layer_map ().to_string_file_format (); // @@@ + } + } catch (tl::Exception &ex) { + // ignore read errors on map file (this is a heuristics!) + tl::error << ex.msg (); + } +} + class LEFDEFReader : public db::ReaderBase { @@ -125,6 +243,9 @@ private: // Take the layer map and the "read all layers" flag from the reader options - hence we override the db::LEFDEFLayerDelegate layers (lefdef_options); + + import_map_file_heuristics (m_stream.absolute_path (), layers); + layers.prepare (layout); layout.dbu (lefdef_options->dbu ()); @@ -163,9 +284,11 @@ private: } - // Additionally read all LEF files next to the DEF file + // Additionally read all LEF files next to the DEF file and if there is a single .map file + // or one with the same name than the input file with ".map" suffix, try to read this one too. std::string input_dir = tl::absolute_path (m_stream.absolute_path ()); + if (tl::file_exists (input_dir)) { std::vector entries = tl::dir_entries (input_dir); From d328901799c25c822001d9853651daf5b2a64b2f Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 21:01:19 +0200 Subject: [PATCH 02/43] DEF reader fix: TAPER has to disable NONDEFAULTRULE for the segment --- .../streamers/lefdef/db_plugin/dbDEFImporter.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 5ee27d495..b5efc29b8 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -475,12 +475,13 @@ DEFImporter::do_read (db::Layout &layout) take (); } - taperrule.clear (); - do { std::string ln = get (); + taperrule.clear (); + const std::string *rulename = 0; + db::Coord w = 0; if (specialnets) { w = db::coord_traits::rounded (get_double () * scale); @@ -507,8 +508,10 @@ DEFImporter::do_read (db::Layout &layout) while (true) { if (test ("TAPER")) { taperrule.clear (); + rulename = &taperrule; } else if (test ("TAPERRULE")) { taperrule = get (); + rulename = &taperrule; } else if (test ("STYLE")) { sn = get_long (); } else { @@ -520,8 +523,7 @@ DEFImporter::do_read (db::Layout &layout) if (! specialnets) { - const std::string *rulename = &taperrule; - if (rulename->empty ()) { + if (! rulename) { rulename = &nondefaultrule; } From e15d99e4dadba06d1b8b8394f5a8ea6770dd3d7c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 21:01:53 +0200 Subject: [PATCH 03/43] LEF reader fix: determine routing layers for vias without VIARULE from involved layers --- .../lefdef/db_plugin/dbLEFImporter.cc | 28 ++++++++++++++++++- .../lefdef/db_plugin/dbLEFImporter.h | 1 + 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 95506ff67..d39e27e84 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -602,7 +602,24 @@ LEFImporter::do_read (db::Layout &layout) test (";"); } - read_geometries (layout, cell, ViaGeometry); + std::map bboxes; + read_geometries (layout, cell, ViaGeometry, &bboxes); + + // determine m1 and m2 layers + + std::vector routing_layers; + for (std::map::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) { + if (m_routing_layers.find (b->first) != m_routing_layers.end ()) { + routing_layers.push_back (b->first); + } + } + + if (routing_layers.size () == 2) { + via_desc.m1 = routing_layers[0]; + via_desc.m2 = routing_layers[1]; + } else { + warn ("Can't determine routing layers for via: " + n); + } reset_cellname (); @@ -631,6 +648,15 @@ LEFImporter::do_read (db::Layout &layout) if (test ("END")) { expect (ln); break; + } else if (test ("TYPE")) { + if (test ("ROUTING")) { + m_routing_layers.insert (ln); + } else if (test ("CUT")) { + m_cut_layers.insert (ln); + } else { + get (); + } + expect (";"); } else if (test ("WIDTH")) { double w = get_double (); m_default_widths.insert (std::make_pair (ln, w)); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h index 9811d9bfc..b07af42e7 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h @@ -106,6 +106,7 @@ private: std::map m_macros_by_name; std::map m_macro_bboxes_by_name; std::map m_vias; + std::set m_routing_layers, m_cut_layers; std::vector get_iteration (db::Layout &layout); void read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map *collect_bboxes = 0, properties_id_type prop_id = 0); From 67a1c0ba257562268a044ae04d0497bc12fa816a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 21:20:17 +0200 Subject: [PATCH 04/43] Updated implementation of mapping file reader for LEF/DEF. --- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index fa2e9adb5..bbe626736 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -125,23 +125,53 @@ read_map_file (const std::string &path, db::LEFDEFLayerDelegate &layers) } else if (w1 == "NAME") { + // converts a line like + // "NAME M1/PINS,M2/PINS ..." + // into a canonical name mapping like + // "(M1/LABELS): M1.LABEL" + // "(M2/LABELS): M2.LABEL" + + std::vector layers; std::vector purposes = tl::split (w2, ","); for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { - std::string canonical_name = std::string ("(") + tl::split (*p, "/").front () + ",LABEL)"; - lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype)); + layers.push_back (tl::split (*p, "/").front ()); } + std::string final_name = std::string ("(") + tl::join (layers, "/") + ",LABEL)"; + for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { + std::string canonical_name = std::string ("(") + *l + ",LABEL)"; + lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name)); + } + ++n; + } else { + // converts a line like + // "M1 SPNET,NET,PINS,LEFPINS ..." + // into a canonical name mapping like + // "(M1,NET): M1.NET/PINS" + // "(M1,PINS): M1.NET/PINS" + // (separating, translating and recombing the purposes) + + std::vector translated_purposes; std::vector purposes = tl::split (w2, ","); for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { std::map::const_iterator i = purpose_translation.find (*p); if (i != purpose_translation.end ()) { - std::string canonical_name = std::string ("(") + w1 + "," + i->second + ")"; - lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype)); + translated_purposes.push_back (i->second); } } + std::sort (translated_purposes.begin (), translated_purposes.end ()); + translated_purposes.erase (std::unique (translated_purposes.begin (), translated_purposes.end ()), translated_purposes.end ()); + std::string final_name = w1 + "." + tl::join (translated_purposes, "/"); + + for (std::vector::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) { + std::string canonical_name = std::string ("(") + w1 + "," + *p + ")"; + lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name)); + } + ++n; + } } From dd63b727f80b26887e09727ab420dadca0aa66cf Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 21:23:12 +0200 Subject: [PATCH 05/43] Another update of the map file reader for LEF/DEF --- src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index bbe626736..5ef4104b5 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -137,7 +137,7 @@ read_map_file (const std::string &path, db::LEFDEFLayerDelegate &layers) layers.push_back (tl::split (*p, "/").front ()); } - std::string final_name = std::string ("(") + tl::join (layers, "/") + ",LABEL)"; + std::string final_name = tl::join (layers, "/") + ".LABEL"; for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { std::string canonical_name = std::string ("(") + *l + ",LABEL)"; lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name)); From ee3ee5bd8e1f82eff7c1788a2aaa9d174a1af41d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 21:25:49 +0200 Subject: [PATCH 06/43] Another update of the map file reader for LEF/DEF --- src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 5ef4104b5..bd79bb5af 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -120,7 +120,7 @@ read_map_file (const std::string &path, db::LEFDEFLayerDelegate &layers) if (w1 == "DIEAREA") { - std::string canonical_name = "(OUTLINE)"; + std::string canonical_name = "OUTLINE"; lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype)); } else if (w1 == "NAME") { From 8796b65ddbe714c6ab798f4107c078e63d56d2c0 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 21:52:51 +0200 Subject: [PATCH 07/43] DEF reader patched: after via continue with the new metal layer with the width given by the rule. --- .../lefdef/db_plugin/dbDEFImporter.cc | 47 +++++++++++-------- .../lefdef/db_plugin/dbDEFImporter.h | 1 + 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index b5efc29b8..bc29cf01b 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -136,6 +136,25 @@ struct Group std::vector comp_match; }; +db::Coord +DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu) +{ + double w = db::coord_traits::rounded (m_lef_importer.layer_width (ln, rulename, 0.0) / dbu); + + // try to find local nondefault rule + if (! rulename.empty ()) { + std::map >::const_iterator nd = m_nondefault_widths.find (rulename); + if (nd != m_nondefault_widths.end ()) { + std::map::const_iterator ld = nd->second.find (ln); + if (ld != nd->second.end ()) { + w = ld->second; + } + } + } + + return w; +} + void DEFImporter::do_read (db::Layout &layout) { @@ -521,29 +540,14 @@ DEFImporter::do_read (db::Layout &layout) } - if (! specialnets) { - - if (! rulename) { - rulename = &nondefaultrule; - } - - w = db::coord_traits::rounded (m_lef_importer.layer_width (ln, *rulename, 0.0) / layout.dbu ()); - - // try to find local nondefault rule - if (! rulename->empty ()) { - std::map >::const_iterator nd = m_nondefault_widths.find (*rulename); - if (nd != m_nondefault_widths.end ()) { - std::map::const_iterator ld = nd->second.find (ln); - if (ld != nd->second.end ()) { - w = ld->second; - } - } - } - + if (! rulename) { + rulename = &nondefaultrule; } db::Coord def_ext = 0; + if (! specialnets) { + w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); def_ext = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, w * 0.5 * layout.dbu ()) / layout.dbu ()); } @@ -733,6 +737,11 @@ DEFImporter::do_read (db::Layout &layout) } } + if (! specialnets) { + w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); + def_ext = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, w * 0.5 * layout.dbu ()) / layout.dbu ()); + } + // continue a segment with the current point and the new layer if (pts.size () > 1) { pts.erase (pts.begin (), pts.end () - 1); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 112098cbc..083b9b4d2 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -66,6 +66,7 @@ private: db::FTrans get_orient (bool optional); void read_polygon (db::Polygon &poly, double scale); void read_rect (db::Polygon &poly, double scale); + db::Coord get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu); }; } From fd0b07f0cdad51770012e2cec81f9be2a0eeb741 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 22:14:07 +0200 Subject: [PATCH 08/43] MERGE: strmxor could not identify layers when one has a name and the other does not (but both have numbers) --- src/buddies/src/bd/strmxor.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/buddies/src/bd/strmxor.cc b/src/buddies/src/bd/strmxor.cc index 8c4b03a33..0e1286bb5 100644 --- a/src/buddies/src/bd/strmxor.cc +++ b/src/buddies/src/bd/strmxor.cc @@ -140,7 +140,7 @@ struct XORData double tile_size; db::Layout *output_layout; db::cell_index_type output_cell; - std::map > l2l_map; + std::map, db::LPLogicalLessFunc> l2l_map; std::map, ResultDescriptor> *results; }; @@ -299,7 +299,7 @@ BD_PUBLIC int strmxor (int argc, char *argv[]) throw tl::Exception ("'" + top_b + "' is not a valid cell name in second layout"); } - std::map > l2l_map; + std::map, db::LPLogicalLessFunc> l2l_map; for (db::Layout::layer_iterator l = layout_a.begin_layers (); l != layout_a.end_layers (); ++l) { l2l_map.insert (std::make_pair (*(*l).second, std::make_pair (-1, -1))).first->second.first = (*l).first; From 0ae97279d829875ddaed0993de4c3bfa0b5cb7b6 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 29 Mar 2020 23:13:22 +0200 Subject: [PATCH 09/43] Added optional MASK specification to VIA's RECT and POLYGON elements --- .../streamers/lefdef/db_plugin/dbDEFImporter.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index bc29cf01b..cc2010c58 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -914,6 +914,11 @@ DEFImporter::do_read (db::Layout &layout) std::string ln = get (); + if (test ("+")) { + expect ("MASK"); + get_long (); + } + std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; polygons.push_back (db::Polygon ()); read_polygon (polygons.back (), scale); @@ -922,6 +927,11 @@ DEFImporter::do_read (db::Layout &layout) std::string ln = get (); + if (test ("+")) { + expect ("MASK"); + get_long (); + } + std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; polygons.push_back (db::Polygon ()); read_rect (polygons.back (), scale); From 2c60338ae855870f725d9bedc8da2d0c864cf924 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 31 Mar 2020 21:56:13 +0200 Subject: [PATCH 10/43] Added DO .. BY .. STEP to vias in SPECIALNETS in DEF reader, added one more private testcase --- .../lefdef/db_plugin/dbDEFImporter.cc | 29 +++++++++++++++++- ...LEFDEFImport.cc => dbLEFDEFImportTests.cc} | 15 +++++++-- .../lefdef/unit_tests/unit_tests.pro | 2 +- testdata/lefdef/doxy_vias/.test.def.swp | Bin 0 -> 12288 bytes testdata/lefdef/doxy_vias/au.oas.gz | Bin 0 -> 254 bytes testdata/lefdef/doxy_vias/test.def | 19 ++++++++++++ 6 files changed, 60 insertions(+), 5 deletions(-) rename src/plugins/streamers/lefdef/unit_tests/{dbLEFDEFImport.cc => dbLEFDEFImportTests.cc} (96%) create mode 100644 testdata/lefdef/doxy_vias/.test.def.swp create mode 100644 testdata/lefdef/doxy_vias/au.oas.gz create mode 100644 testdata/lefdef/doxy_vias/test.def diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index cc2010c58..842b3287a 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -727,9 +727,36 @@ DEFImporter::do_read (db::Layout &layout) std::string vn = get (); db::FTrans ft = get_orient (true /*optional*/); + db::Coord dx = 0, dy = 0; + long nx = 1, ny = 1; + + if (specialnets && test ("DO")) { + + nx = std::max (0l, get_long ()); + test ("BY"); + ny = std::max (0l, get_long ()); + test ("STEP"); + dx = db::coord_traits::rounded (get_double () * scale); + dy = db::coord_traits::rounded (get_double () * scale); + + if (nx < 0) { + dx = -dx; + nx = -nx; + } + if (ny < 0) { + dy = -dy; + ny = -ny; + } + + } + std::map::const_iterator vd = via_desc.find (vn); if (vd != via_desc.end () && ! pts.empty ()) { - design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); + if (nx <= 1 && ny <= 1) { + design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); + } else { + design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())), db::Vector (dx, 0), db::Vector (0, dy), (unsigned long) nx, (unsigned long) ny)); + } if (ln == vd->second.m1) { ln = vd->second.m2; } else if (ln == vd->second.m2) { diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImport.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc similarity index 96% rename from src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImport.cc rename to src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 367802008..14cc6fcac 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImport.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -240,11 +240,16 @@ TEST(19) } TEST(20) +{ + run_test (_this, "def11", "lef:test.lef+def:test.def", "au.oas.gz", default_options ()); +} + +TEST(100) { run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false); } -TEST(21) +TEST(101) { db::LEFDEFReaderOptions opt = default_options (); opt.set_produce_pin_names (true); @@ -252,7 +257,7 @@ TEST(21) run_test (_this, "issue-489", "lef:in.lef+def:in.def", "au.oas", opt, false); } -TEST(22) +TEST(102) { db::LEFDEFReaderOptions opt = default_options (); opt.set_produce_pin_names (true); @@ -260,8 +265,12 @@ TEST(22) run_test (_this, "issue-489b", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", opt, false); } -TEST(23) +TEST(103) { run_test (_this, "issue-517", "def:in.def", "au.oas.gz", default_options (), false); } +TEST(104) +{ + run_test (_this, "doxy_vias", "def:test.def", "au.oas.gz", default_options (), false); +} diff --git a/src/plugins/streamers/lefdef/unit_tests/unit_tests.pro b/src/plugins/streamers/lefdef/unit_tests/unit_tests.pro index 93529fc7f..3958da4b2 100644 --- a/src/plugins/streamers/lefdef/unit_tests/unit_tests.pro +++ b/src/plugins/streamers/lefdef/unit_tests/unit_tests.pro @@ -6,7 +6,7 @@ TARGET = lefdef_tests include($$PWD/../../../../lib_ut.pri) SOURCES = \ - dbLEFDEFImport.cc + dbLEFDEFImportTests.cc INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common diff --git a/testdata/lefdef/doxy_vias/.test.def.swp b/testdata/lefdef/doxy_vias/.test.def.swp new file mode 100644 index 0000000000000000000000000000000000000000..fcf20729c47ae24ef815046334aa97146874bc6f GIT binary patch literal 12288 zcmeI2&yEs75XK9SCacDMff6sf*$guSyGp`oU^;FmGT_XBS^tqyAdrPH%3$Q8F}{LF z6W_y=M-M)LH{->-PoQ59kPr`ec2k{vJyX?RS9Sjq4g{V$UESnr$svquM8l8oo*cb> zRCu2eO_MAejgz@q+BHV0HA&KJmhLiP?e(UheLhK+vqff4lX*6HVP}JR)=#p;o(zWl z!O-r{UM+hs(K%l!A@z^SvMdCIz)k{-Y-m;Ys8V+GkNVBx4c@=r*||j)g@6zc0zyCt z2mv7=1cZPPxL5?Tv_NlgrAzB;?XRDOzn<$*9zs9}2mv7=1cZPP5CTF#2nYcoAOwWK ze@Gzd6aCyH3a;Sr`2BzL{r~q>qF>N==qvOI`T#wLM$iMO0$qlFVDC5R3-lQ}hsMwu zWa{37WC#HvAOwVf5D)@FKnMr{As_^Vzy%JUCcncx52cp?=sD$cS;^XP(%FM#dz=O=;X7V*;W&{dCX&~Q- znF-7X)7&f|Q<#~7B5)Qjqo_3_10&N0mIZ7RnP)PIS~4**Jz(Czd6VTMqo^e_Bhv)t z3Ct%MPcrf{2>xJf_{g%rg6Ut)9#)ZR7KRIl9 Date: Tue, 31 Mar 2020 23:07:42 +0200 Subject: [PATCH 11/43] Bugfix LEF/DEF reader: via needs to change the layer also if it's inside a DEF. Added more test cases. --- .../lefdef/db_plugin/dbDEFImporter.cc | 19 +++++++++++++ .../lefdef/db_plugin/dbLEFImporter.h | 16 +++++++++++ .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 5 ++++ testdata/lefdef/doxy_vias/.test.def.swp | Bin 12288 -> 0 bytes testdata/lefdef/doxy_vias/test.def | 9 ++++++ testdata/lefdef/specialnets_geo/au.oas.gz | Bin 0 -> 337 bytes testdata/lefdef/specialnets_geo/test.def | 26 ++++++++++++++++++ testdata/lefdef/specialnets_geo/test.lef | 24 ++++++++++++++++ 8 files changed, 99 insertions(+) delete mode 100644 testdata/lefdef/doxy_vias/.test.def.swp create mode 100644 testdata/lefdef/specialnets_geo/au.oas.gz create mode 100644 testdata/lefdef/specialnets_geo/test.def create mode 100644 testdata/lefdef/specialnets_geo/test.lef diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 842b3287a..81dc153dd 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -967,6 +967,25 @@ DEFImporter::do_read (db::Layout &layout) } + if (vd.m1.empty () && vd.m2.empty ()) { + + // analyze the layers to find the metals + std::vector routing_layers; + for (std::map >::const_iterator b = geometry.begin (); b != geometry.end (); ++b) { + if (m_lef_importer.is_routing_layer (b->first)) { + routing_layers.push_back (b->first); + } + } + + if (routing_layers.size () == 2) { + vd.m1 = routing_layers[0]; + vd.m2 = routing_layers[1]; + } else { + warn ("Can't determine routing layers for via: " + n); + } + + } + test (";"); if (has_via_rule && top && cut && bottom) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h index b07af42e7..59ee3e5d2 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h @@ -86,6 +86,22 @@ public: */ double layer_ext (const std::string &layer, double def_ext = 0.0) const; + /** + * @brief Returns true if the given layer is a routing layer + */ + bool is_routing_layer (const std::string &layer) const + { + return m_routing_layers.find (layer) != m_routing_layers.end (); + } + + /** + * @brief Returns true if the given layer is a cut layer + */ + bool is_cut_layer (const std::string &layer) const + { + return m_cut_layers.find (layer) != m_cut_layers.end (); + } + /** * @brief Gets a map of the vias defined in this LEF file * diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 14cc6fcac..472a29f0b 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -274,3 +274,8 @@ TEST(104) { run_test (_this, "doxy_vias", "def:test.def", "au.oas.gz", default_options (), false); } + +TEST(105) +{ + run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); +} diff --git a/testdata/lefdef/doxy_vias/.test.def.swp b/testdata/lefdef/doxy_vias/.test.def.swp deleted file mode 100644 index fcf20729c47ae24ef815046334aa97146874bc6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2&yEs75XK9SCacDMff6sf*$guSyGp`oU^;FmGT_XBS^tqyAdrPH%3$Q8F}{LF z6W_y=M-M)LH{->-PoQ59kPr`ec2k{vJyX?RS9Sjq4g{V$UESnr$svquM8l8oo*cb> zRCu2eO_MAejgz@q+BHV0HA&KJmhLiP?e(UheLhK+vqff4lX*6HVP}JR)=#p;o(zWl z!O-r{UM+hs(K%l!A@z^SvMdCIz)k{-Y-m;Ys8V+GkNVBx4c@=r*||j)g@6zc0zyCt z2mv7=1cZPPxL5?Tv_NlgrAzB;?XRDOzn<$*9zs9}2mv7=1cZPP5CTF#2nYcoAOwWK ze@Gzd6aCyH3a;Sr`2BzL{r~q>qF>N==qvOI`T#wLM$iMO0$qlFVDC5R3-lQ}hsMwu zWa{37WC#HvAOwVf5D)@FKnMr{As_^Vzy%JUCcncx52cp?=sD$cSg=2kMp6)^LKc{;`ev0*$|hMV0#G{nc# z&y|^lnSlqH!_DMt$jk^7gwjC15i>KG52m?UK&CJ=0Y%^}UPe)CMg~SEn*dFDQA=h< zrj!(8V^K>cMkWmnQBht7!3T^d7)1`VFsxw`d&tPo#Q@~Ws55Xd@-v7kFfvVGKEWs} zYQVy>h;0Ge3btcBH&|rFHZt>zh%f>bg5)e%*iSJXVmiUpz<-YE7}FW1EsR%~K*C5` j)-b`lmY+%s4ADO literal 0 HcmV?d00001 diff --git a/testdata/lefdef/specialnets_geo/test.def b/testdata/lefdef/specialnets_geo/test.def new file mode 100644 index 000000000..2874f0491 --- /dev/null +++ b/testdata/lefdef/specialnets_geo/test.def @@ -0,0 +1,26 @@ + +VERSION 5.8 ; +DIVIDERCHAR "/" ; +BUSBITCHARS "[]" ; +DESIGN chip_top ; +UNITS DISTANCE MICRONS 1000 ; +DIEAREA ( 0 0 ) ( 300 300 ) ; +STYLES 2 ; +- STYLE 1 ( 30 10 ) ( 10 30 ) ( -10 30 ) ( -30 10 ) ( -30 -10 ) ( -10 -30 ) ( 10 -30 ) ( 30 -10 ) ; +END STYLES +VIAS 1 ; + - VIA1_dummy + + RECT M1 ( -20 -15 ) ( 20 15 ) + + RECT VIA1 ( -10 -10 ) ( 10 10 ) + + RECT M2 ( -25 -25 ) ( 25 25 ) ; +END VIAS +SPECIALNETS 1 ; +- dummy + + POLYGON M1 ( 300 0 ) ( 300 50 ) ( 350 50 ) ( 400 100 ) ( 400 0 ) + + POLYGON M2 ( 300 150 ) ( 300 200 ) ( 350 200 ) ( 400 250 ) ( 400 150 ) + + RECT M1 ( 0 0 ) ( 100 200 ) + + ROUTED M1 30 ( 0 0 15 ) ( 100 0 0 ) VIA1_dummy ( 100 100 10 ) + + ROUTED M2 50 + SHAPE RING + STYLE 1 ( 0 100 ) ( 100 200 ) ( 200 200 ) +; +END SPECIALNETS +END DESIGN diff --git a/testdata/lefdef/specialnets_geo/test.lef b/testdata/lefdef/specialnets_geo/test.lef new file mode 100644 index 000000000..da907c86d --- /dev/null +++ b/testdata/lefdef/specialnets_geo/test.lef @@ -0,0 +1,24 @@ +VERSION 5.8 ; +BUSBITCHARS "[]" ; +DIVIDERCHAR "/" ; + +UNITS + DATABASE MICRONS 1000 ; +END UNITS + +MANUFACTURINGGRID 0.001 ; + +LAYER M1 + TYPE ROUTING ; +END M1 + +LAYER VIA1 + TYPE CUT ; +END VIA1 + +LAYER M2 + TYPE ROUTING ; + WIDTH 0.05 ; +END M2 + +END LIBRARY From 4a24b727d541c8cb0f00179bae9f40d4159d7973 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 4 Apr 2020 00:40:01 +0200 Subject: [PATCH 12/43] Tried to implement MINWIDTH .. WRONGDIRECTION in LEF58_MINWIDTH property --- .../lefdef/db_plugin/dbDEFImporter.cc | 94 ++- .../lefdef/db_plugin/dbDEFImporter.h | 3 +- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 18 +- .../lefdef/db_plugin/dbLEFDEFImporter.h | 10 + .../lefdef/db_plugin/dbLEFImporter.cc | 784 ++++++++++-------- .../lefdef/db_plugin/dbLEFImporter.h | 12 + .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 9 +- testdata/lefdef/wrongdirection/au.oas.gz | Bin 0 -> 299 bytes testdata/lefdef/wrongdirection/test.def | 19 + testdata/lefdef/wrongdirection/test.lef | 41 + 10 files changed, 623 insertions(+), 367 deletions(-) create mode 100644 testdata/lefdef/wrongdirection/au.oas.gz create mode 100644 testdata/lefdef/wrongdirection/test.def create mode 100644 testdata/lefdef/wrongdirection/test.lef diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 81dc153dd..fb1953cda 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -136,10 +136,10 @@ struct Group std::vector comp_match; }; -db::Coord +std::pair DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu) { - double w = db::coord_traits::rounded (m_lef_importer.layer_width (ln, rulename, 0.0) / dbu); + db::Coord w = db::coord_traits::rounded (m_lef_importer.layer_width (ln, rulename, 0.0) / dbu); // try to find local nondefault rule if (! rulename.empty ()) { @@ -152,7 +152,34 @@ DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::st } } - return w; + std::pair min_wxy = m_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); + + return std::make_pair (std::max (w, min_wx), std::max (w, min_wy)); +} + +std::pair +DEFImporter::get_def_ext (const std::string &ln, const std::pair &wxy, double dbu) +{ + if (wxy.first == wxy.second) { + db::Coord de = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, wxy.first * 0.5 * dbu) / dbu); + return std::make_pair (de, de); + } else { +#if 0 + // This implementation picks the default extension according to the real width + // NOTE: the swapping of x and y for the default extension is intended. For horizontal lines, the + // extension is in x direction but corresponds to a wire width of a vertical wire and vice versa. + db::Coord dex = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, wxy.second * 0.5 * dbu) / dbu); + db::Coord dey = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, wxy.first * 0.5 * dbu) / dbu); + return std::make_pair (dex, dey); +#else + // This implementation picks the default extension according to the specified wire width (which is the minimum + // of wx and wy) + db::Coord de = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, std::min (wxy.first, wxy.second) * 0.5 * dbu) / dbu); + return std::make_pair (de, de); +#endif + } } void @@ -501,9 +528,10 @@ DEFImporter::do_read (db::Layout &layout) taperrule.clear (); const std::string *rulename = 0; - db::Coord w = 0; + std::pair w (0, 0); if (specialnets) { - w = db::coord_traits::rounded (get_double () * scale); + db::Coord n = db::coord_traits::rounded (get_double () * scale); + w = std::make_pair (n, n); } const db::Polygon *style = 0; @@ -544,11 +572,11 @@ DEFImporter::do_read (db::Layout &layout) rulename = &nondefaultrule; } - db::Coord def_ext = 0; + std::pair def_ext (0, 0); if (! specialnets) { w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, w * 0.5 * layout.dbu ()) / layout.dbu ()); + def_ext = get_def_ext (ln, w, layout.dbu ()); } std::map::const_iterator s = styles.find (sn); @@ -556,7 +584,7 @@ DEFImporter::do_read (db::Layout &layout) style = &s->second; } - std::vector ext; + std::vector > ext; std::vector pts; double x = 0.0, y = 0.0; @@ -629,11 +657,12 @@ DEFImporter::do_read (db::Layout &layout) y = get_double (); } pts.push_back (db::Point (db::DPoint (x * scale, y * scale))); - db::Coord e = def_ext; + std::pair ee = def_ext; if (! peek (")")) { - e = db::coord_traits::rounded (get_double () * scale); + db::Coord e = db::coord_traits::rounded (get_double () * scale); + ee.first = ee.second = e; } - ext.push_back (e); + ext.push_back (ee); test (")"); @@ -648,8 +677,11 @@ DEFImporter::do_read (db::Layout &layout) // Use the default style (octagon "pen" for non-manhattan segments, paths for // horizontal/vertical segments). + // Manhattan paths are stitched together from two-point paths if they - db::Coord e = std::max (ext.front (), ext.back ()); + std::pair e = std::max (ext.front (), ext.back ()); + bool is_isotropic = (e.first == e.second && w.first == w.second); + bool was_path = false; std::vector::const_iterator pt = pts.begin (); while (pt != pts.end ()) { @@ -657,11 +689,27 @@ DEFImporter::do_read (db::Layout &layout) std::vector::const_iterator pt0 = pt; do { ++pt; - } while (pt != pts.end () && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); + } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); - if (pt - pt0 > 1) { + if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { - db::Path p (pt0, pt, w, pt0 == pts.begin () ? e : 0, pt == pts.end () ? e : 0, false); + if (pt - pt0 == 1) { + ++pt; + } + + db::Coord wxy, wxy_perp, exy; + + if (pt0->x () == pt0 [1].x ()) { + wxy = w.second; + wxy_perp = w.first; + exy = e.second; + } else { + wxy = w.first; + wxy_perp = w.second; + exy = e.first; + } + + db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); if (prop_id != 0) { design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); } else { @@ -674,10 +722,16 @@ DEFImporter::do_read (db::Layout &layout) --pt; - } else if (pt != pts.end ()) { + was_path = true; - db::Coord s = (w + 1) / 2; - db::Coord t = db::Coord (ceil (w * (M_SQRT2 - 1) / 2)); + } else { + + if (! is_isotropic) { + warn("Anisotropic wire widths not supported for diagonal wires"); + } + + db::Coord s = (w.first + 1) / 2; + db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); db::Point octagon[8] = { db::Point (-s, t), @@ -700,6 +754,8 @@ DEFImporter::do_read (db::Layout &layout) design.shapes (dl.second).insert (p); } + was_path = false; + } } @@ -766,7 +822,7 @@ DEFImporter::do_read (db::Layout &layout) if (! specialnets) { w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, w * 0.5 * layout.dbu ()) / layout.dbu ()); + def_ext = get_def_ext (ln, w, layout.dbu ()); } // continue a segment with the current point and the new layer diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 083b9b4d2..fa4a377a4 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -66,7 +66,8 @@ private: db::FTrans get_orient (bool optional); void read_polygon (db::Polygon &poly, double scale); void read_rect (db::Polygon &poly, double scale); - db::Coord get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu); + std::pair get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu); + std::pair get_def_ext (const std::string &ln, const std::pair &wxy, double dbu); }; } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index d61efba16..eb895007b 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -531,7 +531,23 @@ LEFDEFImporter::expect (const std::string &token) } } -double +void +LEFDEFImporter::expect (const std::string &token1, const std::string &token2) +{ + if (! test (token1) && ! test (token2)) { + error ("Expected token: " + token1 + " or " + token2); + } +} + +void +LEFDEFImporter::expect (const std::string &token1, const std::string &token2, const std::string &token3) +{ + if (! test (token1) && ! test (token2) && ! test (token3)) { + error ("Expected token: " + token1 + ", " + token2 + " or " + token3); + } +} + +double LEFDEFImporter::get_double () { if (m_last_token.empty ()) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 0cfc38f2b..fe4e40b6b 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -642,6 +642,16 @@ protected: */ void expect (const std::string &token); + /** + * @brief Test whether the next token matches one of the given ones and raise an error if it does not + */ + void expect (const std::string &token1, const std::string &token2); + + /** + * @brief Test whether the next token matches one of the given ones and raise an error if it does not + */ + void expect (const std::string &token, const std::string &token2, const std::string &token3); + /** * @brief Gets the next token */ diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index d39e27e84..f43d905fb 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -65,6 +65,17 @@ LEFImporter::layer_ext (const std::string &layer, double def_ext) const } } +std::pair +LEFImporter::min_layer_width (const std::string &layer) const +{ + std::map >::const_iterator l = m_min_widths.find (layer); + if (l != m_min_widths.end ()) { + return l->second; + } else { + return std::make_pair (0.0, 0.0); + } +} + double LEFImporter::layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width) const { @@ -360,6 +371,431 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p } } +void +LEFImporter::read_nondefaultrule (db::Layout & /*layout*/) +{ + // read NONDEFAULTRULE sections + std::string n = get (); + + while (! test ("END") || ! test (n)) { + + if (test ("LAYER")) { + + std::string l = get (); + + // read the width for the layer + while (! test ("END")) { + if (test ("WIDTH")) { + double w = get_double (); + test (";"); + m_nondefault_widths[n][l] = w; + } else { + while (! test (";")) { + take (); + } + } + } + + test (l); + + } else if (test ("VIA")) { + + // ignore VIA statements + std::string v = get (); + while (! test ("END") || ! test (v)) { + take (); + } + + } else { + while (! test (";")) { + take (); + } + } + + } +} + +void +LEFImporter::read_viadef_by_rule (Layout &layout, db::Cell &cell, ViaDesc &via_desc, const std::string & /*n*/) +{ + db::Vector cutsize, cutspacing; + db::Vector be, te; + db::Vector bo, to; + db::Point offset; + int rows = 1, columns = 1; + std::string pattern; + + std::vector > > geometry; + geometry.push_back (std::pair > ()); + geometry.push_back (std::pair > ()); + geometry.push_back (std::pair > ()); + + while (! test ("END")) { + + double x, y; + + if (test ("CUTSIZE")) { + + x = get_double (); + y = get_double (); + cutsize = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); + + test (";"); + + } else if (test ("CUTSPACING")) { + + x = get_double (); + y = get_double (); + cutspacing = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); + + test (";"); + + } else if (test ("ORIGIN")) { + + x = get_double (); + y = get_double (); + offset = db::Point (db::DPoint (x / layout.dbu (), y / layout.dbu ())); + + test (";"); + + } else if (test ("ENCLOSURE")) { + + x = get_double (); + y = get_double (); + be = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); + + x = get_double (); + y = get_double (); + te = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); + + test (";"); + + } else if (test ("OFFSET")) { + + x = get_double (); + y = get_double (); + bo = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); + + x = get_double (); + y = get_double (); + to = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); + + test (";"); + + } else if (test ("ROWCOL")) { + + rows = get_long (); + columns = get_long (); + + test (";"); + + } else if (test ("PATTERN")) { + + pattern = get (); + + test (";"); + + } else if (test ("LAYERS")) { + + via_desc.m1 = geometry[0].first = get (); + geometry[1].first = get (); + via_desc.m2 = geometry[2].first = get (); + + test (";"); + + } else { + + while (! test (";")) { + take (); + } + + } + + } + + create_generated_via (geometry [0].second, geometry [1].second, geometry [2].second, + cutsize, cutspacing, be, te, bo, to, offset, rows, columns, pattern); + + for (std::vector > >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { + std::pair dl = open_layer (layout, g->first, ViaGeometry); + if (dl.first) { + for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { + cell.shapes (dl.second).insert (*p); + } + } + } +} + +void +LEFImporter::read_viadef_by_geometry (Layout &layout, db::Cell &cell, ViaDesc &via_desc, const std::string &n) +{ + // ignore resistance spec + if (test ("RESISTANCE")) { + get_double (); + test (";"); + } + + std::map bboxes; + read_geometries (layout, cell, ViaGeometry, &bboxes); + + // determine m1 and m2 layers + + std::vector routing_layers; + for (std::map::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) { + if (m_routing_layers.find (b->first) != m_routing_layers.end ()) { + routing_layers.push_back (b->first); + } + } + + if (routing_layers.size () == 2) { + via_desc.m1 = routing_layers[0]; + via_desc.m2 = routing_layers[1]; + } else { + warn ("Can't determine routing layers for via: " + n); + } + + reset_cellname (); + + expect ("END"); +} + +void +LEFImporter::read_viadef (Layout &layout) +{ + std::string n = get (); + + // produce a cell for vias + std::string cellname = "VIA_" + n; + db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ())); + + ViaDesc &via_desc = m_vias[n]; + via_desc.cell = &cell; + + while (test ("DEFAULT") || test ("TOPOFSTACKONLY")) + ; + test (";"); + + if (test ("VIARULE")) { + read_viadef_by_rule (layout, cell, via_desc, n); + } else { + read_viadef_by_geometry (layout, cell, via_desc, n); + } + + test ("VIA"); + expect (n); +} + +void +LEFImporter::read_layer (Layout & /*layout*/) +{ + std::string ln = get (); + double wmin = 0.0, wmin_wrongdir = 0.0; + bool is_horizontal = true; + + register_layer (ln); + + // just extract the width from the layer - we need that as the default width for paths + while (! at_end ()) { + + if (test ("END")) { + + expect (ln); + break; + + } else if (test ("TYPE")) { + + if (test ("ROUTING")) { + m_routing_layers.insert (ln); + } else if (test ("CUT")) { + m_cut_layers.insert (ln); + } else { + get (); + } + expect (";"); + + } else if (test ("WIDTH")) { + + double w = get_double (); + m_default_widths.insert (std::make_pair (ln, w)); + expect (";"); + + } else if (test ("DIRECTION")) { + + if (test ("HORIZONTAL")) { + is_horizontal = true; + } else { + expect ("VERTICAL", "DIAG45", "DIAG135"); + } + + } else if (test ("WIREEXTENSION")) { + + double w = get_double (); + m_default_ext.insert (std::make_pair (ln, w)); + expect (";"); + + } else if (test ("ACCURRENTDENSITY")) { + + // ACCURRENTDENSITY needs some special attention because it can contain nested WIDTH + // blocks following a semicolon + take (); + if (test ("FREQUENCY")) { + while (! test ("TABLEENTRIES")) { + take (); + } + } + while (! test (";")) { + take (); + } + + } else if (test ("PROPERTY")) { + + std::string name = get (); + tl::Variant value = get (); + + if (name == "LEF58_MINWIDTH") { + + // Cadence extension + tl::Extractor ex (value.to_string ()); + double mw = 0.0; + if (ex.test ("MINWIDTH") && ex.try_read (mw)) { + if (ex.test ("WRONGDIRECTION")) { + wmin_wrongdir = mw; + } else { + wmin = mw; + } + } + + } + + } else { + + while (! test (";")) { + take (); + } + + } + } + + if (wmin > 0.0 || wmin_wrongdir > 0.0) { + + if (! is_horizontal) { + std::swap (wmin, wmin_wrongdir); + } + + m_min_widths.insert (std::make_pair (ln, std::make_pair (wmin, wmin_wrongdir))); + + } +} + +void +LEFImporter::read_macro (Layout &layout) +{ + std::string mn = get (); + set_cellname (mn); + + db::Cell &cell = layout.cell (layout.add_cell (mn.c_str ())); + + m_macros_by_name.insert (std::make_pair (mn, &cell)); + + db::Point origin; + db::Vector size; + + // read the macro + while (! at_end ()) { + + if (test ("END")) { + expect (mn); + break; + + } else if (test ("ORIGIN")) { + + double x = get_double (); + double y = get_double (); + expect (";"); + origin = db::Point (db::DPoint (x / layout.dbu (), y / layout.dbu ())); + + } else if (test ("SIZE")) { + + double x = get_double (); + test ("BY"); + double y = get_double (); + expect (";"); + size = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); + + } else if (test ("PIN")) { + + std::string pn = get (); + std::string dir; + + while (! at_end ()) { + if (test ("END")) { + break; + } else if (test ("DIRECTION")) { + dir = get (); + test (";"); + } else if (test ("PORT")) { + + // produce pin labels + // TODO: put a label on every single object? + std::string label = pn; + /* don't add the direction currently, a name is sufficient + if (! dir.empty ()) { + label += ":"; + label += dir; + } + */ + + db::properties_id_type prop_id = 0; + if (produce_pin_props ()) { + db::PropertiesRepository::properties_set props; + props.insert (std::make_pair (pin_prop_name_id (), tl::Variant (label))); + prop_id = layout.properties_repository ().properties_id (props); + } + + std::map bboxes; + read_geometries (layout, cell, Pins, &bboxes, prop_id); + + for (std::map ::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) { + std::pair dl = open_layer (layout, b->first, Label); + if (dl.first) { + cell.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ()))); + } + } + + expect ("END"); + + } else { + while (! test (";")) { + take (); + } + } + } + + expect (pn); + + } else if (test ("OBS")) { + + read_geometries (layout, cell, Obstructions); + expect ("END"); + + } else { + while (! test (";")) { + take (); + } + } + + } + + std::pair dl = open_layer (layout, std::string (), Outline); + if (dl.first) { + cell.shapes (dl.second).insert (db::Box (-origin, -origin + size)); + } + + m_macro_bboxes_by_name.insert (std::make_pair (mn, db::Box (-origin, -origin + size))); + + reset_cellname (); +} + void LEFImporter::do_read (db::Layout &layout) { @@ -414,45 +850,7 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("NONDEFAULTRULE")) { - // read NONDEFAULTRULE sections - std::string n = get (); - - while (! test ("END") || ! test (n)) { - - if (test ("LAYER")) { - - std::string l = get (); - - // read the width for the layer - while (! test ("END")) { - if (test ("WIDTH")) { - double w = get_double (); - test (";"); - m_nondefault_widths[n][l] = w; - } else { - while (! test (";")) { - take (); - } - } - } - - test (l); - - } else if (test ("VIA")) { - - // ignore VIA statements - std::string v = get (); - while (! test ("END") || ! test (v)) { - take (); - } - - } else { - while (! test (";")) { - take (); - } - } - - } + read_nondefaultrule (layout); } else if (test ("SITE")) { @@ -472,163 +870,7 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("VIA")) { - std::string n = get (); - - // produce a cell for vias - std::string cellname = "VIA_" + n; - db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ())); - - ViaDesc &via_desc = m_vias[n]; - via_desc.cell = &cell; - - while (test ("DEFAULT") || test ("TOPOFSTACKONLY")) - ; - test (";"); - - if (test ("VIARULE")) { - - db::Vector cutsize, cutspacing; - db::Vector be, te; - db::Vector bo, to; - db::Point offset; - int rows = 1, columns = 1; - std::string pattern; - - std::vector > > geometry; - geometry.push_back (std::pair > ()); - geometry.push_back (std::pair > ()); - geometry.push_back (std::pair > ()); - - while (! test ("END")) { - - double x, y; - - if (test ("CUTSIZE")) { - - x = get_double (); - y = get_double (); - cutsize = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); - - test (";"); - - } else if (test ("CUTSPACING")) { - - x = get_double (); - y = get_double (); - cutspacing = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); - - test (";"); - - } else if (test ("ORIGIN")) { - - x = get_double (); - y = get_double (); - offset = db::Point (db::DPoint (x / layout.dbu (), y / layout.dbu ())); - - test (";"); - - } else if (test ("ENCLOSURE")) { - - x = get_double (); - y = get_double (); - be = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); - - x = get_double (); - y = get_double (); - te = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); - - test (";"); - - } else if (test ("OFFSET")) { - - x = get_double (); - y = get_double (); - bo = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); - - x = get_double (); - y = get_double (); - to = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); - - test (";"); - - } else if (test ("ROWCOL")) { - - rows = get_long (); - columns = get_long (); - - test (";"); - - } else if (test ("PATTERN")) { - - pattern = get (); - - test (";"); - - } else if (test ("LAYERS")) { - - via_desc.m1 = geometry[0].first = get (); - geometry[1].first = get (); - via_desc.m2 = geometry[2].first = get (); - - test (";"); - - } else { - - while (! test (";")) { - take (); - } - - } - - } - - create_generated_via (geometry [0].second, geometry [1].second, geometry [2].second, - cutsize, cutspacing, be, te, bo, to, offset, rows, columns, pattern); - - for (std::vector > >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { - std::pair dl = open_layer (layout, g->first, ViaGeometry); - if (dl.first) { - for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { - cell.shapes (dl.second).insert (*p); - } - } - } - - } else { - - // ignore resistance spec - if (test ("RESISTANCE")) { - get_double (); - test (";"); - } - - std::map bboxes; - read_geometries (layout, cell, ViaGeometry, &bboxes); - - // determine m1 and m2 layers - - std::vector routing_layers; - for (std::map::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) { - if (m_routing_layers.find (b->first) != m_routing_layers.end ()) { - routing_layers.push_back (b->first); - } - } - - if (routing_layers.size () == 2) { - via_desc.m1 = routing_layers[0]; - via_desc.m2 = routing_layers[1]; - } else { - warn ("Can't determine routing layers for via: " + n); - } - - reset_cellname (); - - expect ("END"); - - } - - test ("VIA"); - expect (n); + read_viadef (layout); } else if (test ("BEGINEXT")) { @@ -639,157 +881,11 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("LAYER")) { - std::string ln = get (); - - register_layer (ln); - - // just extract the width from the layer - we need that as the default width for paths - while (! at_end ()) { - if (test ("END")) { - expect (ln); - break; - } else if (test ("TYPE")) { - if (test ("ROUTING")) { - m_routing_layers.insert (ln); - } else if (test ("CUT")) { - m_cut_layers.insert (ln); - } else { - get (); - } - expect (";"); - } else if (test ("WIDTH")) { - double w = get_double (); - m_default_widths.insert (std::make_pair (ln, w)); - expect (";"); - } else if (test ("WIREEXTENSION")) { - double w = get_double (); - m_default_ext.insert (std::make_pair (ln, w)); - expect (";"); - } else if (test ("ACCURRENTDENSITY")) { - // ACCURRENTDENSITY needs some special attention because it can contain nested WIDTH - // blocks following a semicolon - take (); - if (test ("FREQUENCY")) { - while (! test ("TABLEENTRIES")) { - take (); - } - } - while (! test (";")) { - take (); - } - } else { - while (! test (";")) { - take (); - } - } - } + read_layer (layout); } else if (test ("MACRO")) { - std::string mn = get (); - set_cellname (mn); - - db::Cell &cell = layout.cell (layout.add_cell (mn.c_str ())); - - m_macros_by_name.insert (std::make_pair (mn, &cell)); - - db::Point origin; - db::Vector size; - - // read the macro - while (! at_end ()) { - - if (test ("END")) { - expect (mn); - break; - - } else if (test ("ORIGIN")) { - - double x = get_double (); - double y = get_double (); - expect (";"); - origin = db::Point (db::DPoint (x / layout.dbu (), y / layout.dbu ())); - - } else if (test ("SIZE")) { - - double x = get_double (); - test ("BY"); - double y = get_double (); - expect (";"); - size = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ())); - - } else if (test ("PIN")) { - - std::string pn = get (); - std::string dir; - - while (! at_end ()) { - if (test ("END")) { - break; - } else if (test ("DIRECTION")) { - dir = get (); - test (";"); - } else if (test ("PORT")) { - - // produce pin labels - // TODO: put a label on every single object? - std::string label = pn; - /* don't add the direction currently, a name is sufficient - if (! dir.empty ()) { - label += ":"; - label += dir; - } - */ - - db::properties_id_type prop_id = 0; - if (produce_pin_props ()) { - db::PropertiesRepository::properties_set props; - props.insert (std::make_pair (pin_prop_name_id (), tl::Variant (label))); - prop_id = layout.properties_repository ().properties_id (props); - } - - std::map bboxes; - read_geometries (layout, cell, Pins, &bboxes, prop_id); - - for (std::map ::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) { - std::pair dl = open_layer (layout, b->first, Label); - if (dl.first) { - cell.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ()))); - } - } - - expect ("END"); - - } else { - while (! test (";")) { - take (); - } - } - } - - expect (pn); - - } else if (test ("OBS")) { - - read_geometries (layout, cell, Obstructions); - expect ("END"); - - } else { - while (! test (";")) { - take (); - } - } - - } - - std::pair dl = open_layer (layout, std::string (), Outline); - if (dl.first) { - cell.shapes (dl.second).insert (db::Box (-origin, -origin + size)); - } - - m_macro_bboxes_by_name.insert (std::make_pair (mn, db::Box (-origin, -origin + size))); - - reset_cellname (); + read_macro (layout); } else { while (! test (";")) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h index 59ee3e5d2..7bc672639 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h @@ -86,6 +86,11 @@ public: */ double layer_ext (const std::string &layer, double def_ext = 0.0) const; + /** + * @brief Gets the minimum wire width in x and y direction for the given layer name + */ + std::pair min_layer_width (const std::string &layer) const; + /** * @brief Returns true if the given layer is a routing layer */ @@ -119,6 +124,7 @@ private: std::map > m_nondefault_widths; std::map m_default_widths; std::map m_default_ext; + std::map > m_min_widths; std::map m_macros_by_name; std::map m_macro_bboxes_by_name; std::map m_vias; @@ -126,6 +132,12 @@ private: std::vector get_iteration (db::Layout &layout); void read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map *collect_bboxes = 0, properties_id_type prop_id = 0); + void read_nondefaultrule (Layout &layout); + void read_viadef (Layout &layout); + void read_viadef_by_rule (Layout &layout, db::Cell &cell, ViaDesc &desc, const std::string &n); + void read_viadef_by_geometry (Layout &layout, db::Cell &cell, ViaDesc &desc, const std::string &n); + void read_layer (Layout &layout); + void read_macro (Layout &layout); }; } diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 472a29f0b..249bf79ed 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -270,12 +270,17 @@ TEST(103) run_test (_this, "issue-517", "def:in.def", "au.oas.gz", default_options (), false); } -TEST(104) +TEST(104_doxy_vias) { run_test (_this, "doxy_vias", "def:test.def", "au.oas.gz", default_options (), false); } -TEST(105) +TEST(105_specialnets_geo) { run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); } + +TEST(106_wrongdirection) +{ + run_test (_this, "wrongdirection", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); +} diff --git a/testdata/lefdef/wrongdirection/au.oas.gz b/testdata/lefdef/wrongdirection/au.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..92712cdd35f285ef718c6de232e8e6a867ee7412 GIT binary patch literal 299 zcmV+`0o48Z@2gEzO`uOm$ zl%y7yu=54SySoI(2L$;CxCVtpadV`e6x2%H5}W5Ub~Rs*KF+5JO9d_4VJnOT5>$Q)h=L73}ThcUzizz x`~!9it9++>;H$H2hUFp>cS0|0)(y5dj*004&uh)Mte literal 0 HcmV?d00001 diff --git a/testdata/lefdef/wrongdirection/test.def b/testdata/lefdef/wrongdirection/test.def new file mode 100644 index 000000000..e533260cf --- /dev/null +++ b/testdata/lefdef/wrongdirection/test.def @@ -0,0 +1,19 @@ +VERSION 5.8 ; +DIVIDERCHAR "/" ; +BUSBITCHARS "[]" ; +DESIGN test ; +UNITS DISTANCE MICRONS 1000 ; +DIEAREA ( 0 0 ) ( 10000 10000 ) ; +NONDEFAULTRULES 1 ; + - ndr + + HARDSPACING + + LAYER M3 WIDTH 500 SPACING 500 +; +END NONDEFAULTRULES +NETS 1 ; + - net_b + + NONDEFAULTRULE ndr + + ROUTED M3 ( 0 0 ) ( 2000 0 ) via34 ( * 2000 ) ( 4000 * ) ( * 4000 ) + ; +END NETS +END DESIGN diff --git a/testdata/lefdef/wrongdirection/test.lef b/testdata/lefdef/wrongdirection/test.lef new file mode 100644 index 000000000..36b5ae01c --- /dev/null +++ b/testdata/lefdef/wrongdirection/test.lef @@ -0,0 +1,41 @@ +VERSION 5.8 ; +BUSBITCHARS "[]" ; +DIVIDERCHAR "/" ; + +UNITS + DATABASE MICRONS 1000 ; +END UNITS + +MANUFACTURINGGRID 0.001 ; + +PROPERTYDEFINITIONS + LAYER LEF58_MINWIDTH STRING ; +END PROPERTYDEFINITIONS + +LAYER M3 + TYPE ROUTING ; + DIRECTION VERTICAL ; + WIDTH 0.6 ; +END M3 + +LAYER VIA3 + TYPE CUT ; +END VIA3 + +LAYER M4 + TYPE ROUTING ; + DIRECTION HORIZONTAL ; + WIDTH 0.5 ; + PROPERTY LEF58_MINWIDTH "MINWIDTH 1.0 WRONGDIRECTION ; " ; +END M4 + +VIA via34 + LAYER M3 ; + RECT -0.4 -0.3 0.4 0.3 ; + LAYER VIA3 ; + RECT -0.3 -0.25 0.3 0.25 ; + LAYER M4 ; + RECT -1.00 -0.5 1.00 0.5 ; +END via34 + +END LIBRARY From f11a3a0dd5e1f2a34a0b2ffdced8b95ebc924704 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 4 Apr 2020 18:48:25 +0200 Subject: [PATCH 13/43] Bugfix: MINWIDTH ... WRONGDIRECTION wasn't considering DIRECTION VERTICAL Added/updated some tests, some refactoring. --- .../lefdef/db_plugin/dbDEFImporter.cc | 165 +++++++++--------- .../lefdef/db_plugin/dbDEFImporter.h | 4 +- .../lefdef/db_plugin/dbLEFImporter.cc | 68 ++++++-- .../lefdef/db_plugin/dbLEFImporter.h | 6 +- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 11 ++ testdata/lefdef/scanchain/au.oas.gz | Bin 0 -> 153 bytes testdata/lefdef/scanchain/test.def | 32 ++++ testdata/lefdef/specialwidths/au.oas.gz | Bin 0 -> 316 bytes testdata/lefdef/specialwidths/test.def | 19 ++ testdata/lefdef/specialwidths/test.lef | 43 +++++ 10 files changed, 245 insertions(+), 103 deletions(-) create mode 100644 testdata/lefdef/scanchain/au.oas.gz create mode 100644 testdata/lefdef/scanchain/test.def create mode 100644 testdata/lefdef/specialwidths/au.oas.gz create mode 100644 testdata/lefdef/specialwidths/test.def create mode 100644 testdata/lefdef/specialwidths/test.lef diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index fb1953cda..cdbaf91e9 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -139,15 +139,17 @@ struct Group std::pair DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu) { - db::Coord w = db::coord_traits::rounded (m_lef_importer.layer_width (ln, rulename, 0.0) / dbu); + std::pair wxy = m_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); // try to find local nondefault rule if (! rulename.empty ()) { - std::map >::const_iterator nd = m_nondefault_widths.find (rulename); + std::map >::const_iterator nd = m_nondefault_widths.find (rulename); if (nd != m_nondefault_widths.end ()) { - std::map::const_iterator ld = nd->second.find (ln); + std::map::const_iterator ld = nd->second.find (ln); if (ld != nd->second.end ()) { - w = ld->second; + wx = wy = ld->second; } } } @@ -156,30 +158,87 @@ DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::st db::Coord min_wx = db::coord_traits::rounded (min_wxy.first / dbu); db::Coord min_wy = db::coord_traits::rounded (min_wxy.second / dbu); - return std::make_pair (std::max (w, min_wx), std::max (w, min_wy)); + return std::make_pair (std::max (wx, min_wx), std::max (wy, min_wy)); } std::pair DEFImporter::get_def_ext (const std::string &ln, const std::pair &wxy, double dbu) { - if (wxy.first == wxy.second) { - db::Coord de = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, wxy.first * 0.5 * dbu) / dbu); - return std::make_pair (de, de); - } else { -#if 0 - // This implementation picks the default extension according to the real width - // NOTE: the swapping of x and y for the default extension is intended. For horizontal lines, the - // extension is in x direction but corresponds to a wire width of a vertical wire and vice versa. - db::Coord dex = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, wxy.second * 0.5 * dbu) / dbu); - db::Coord dey = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, wxy.first * 0.5 * dbu) / dbu); - return std::make_pair (dex, dey); -#else - // This implementation picks the default extension according to the specified wire width (which is the minimum - // of wx and wy) - db::Coord de = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, std::min (wxy.first, wxy.second) * 0.5 * dbu) / dbu); - return std::make_pair (de, de); -#endif + // This implementation assumes the "preferred width" is controlling the default extension and it is + // identical to the minimum effective width. This is true if "LEF58_MINWIDTH" with "WRONGDIRECTION" is + // used in the proposed way. Which is to specify a larger width for the "wrong" direction. + db::Coord de = db::coord_traits::rounded (m_lef_importer.layer_ext (ln, std::min (wxy.first, wxy.second) * 0.5 * dbu) / dbu); + return std::make_pair (de, de); +} + +void +DEFImporter::read_diearea (db::Layout &layout, db::Cell &design, double scale) +{ + std::vector points; + + while (! test (";")) { + test ("("); + double x = get_double (); + double y = get_double (); + points.push_back (db::DPoint (x * scale, y * scale)); + test (")"); } + + if (points.size () >= 2) { + + // create outline shape + std::pair dl = open_layer (layout, std::string (), Outline); + if (dl.first) { + if (points.size () == 2) { + design.shapes (dl.second).insert (db::Box (db::DBox (points [0], points [1]))); + } else { + db::DPolygon p; + p.assign_hull (points.begin (), points.end ()); + design.shapes (dl.second).insert (db::Polygon (p)); + } + } + + } +} + +void +DEFImporter::read_nondefaultrules (double scale) +{ + // read NONDEFAULTRULES sections + get_long (); + expect (";"); + + while (test ("-")) { + + std::string n = get (); + + while (test ("+")) { + + if (test ("LAYER")) { + + std::string l = get (); + + // read the width for the layer + if (test ("WIDTH")) { + double w = get_double () * scale; + m_nondefault_widths[n][l] = db::coord_traits::rounded (w); + } + + } + + // parse over the rest + while (! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + + } + + test (";"); + + } + + test ("END"); + test ("NONDEFAULTRULES"); } void @@ -231,31 +290,7 @@ DEFImporter::do_read (db::Layout &layout) } else if (test ("DIEAREA")) { - std::vector points; - - while (! test (";")) { - test ("("); - double x = get_double (); - double y = get_double (); - points.push_back (db::DPoint (x * scale, y * scale)); - test (")"); - } - - if (points.size () >= 2) { - - // create outline shape - std::pair dl = open_layer (layout, std::string (), Outline); - if (dl.first) { - if (points.size () == 2) { - design.shapes (dl.second).insert (db::Box (db::DBox (points [0], points [1]))); - } else { - db::DPolygon p; - p.assign_hull (points.begin (), points.end ()); - design.shapes (dl.second).insert (db::Polygon (p)); - } - } - - } + read_diearea (layout, design, scale); } else if (test ("PROPERTYDEFINITIONS")) { // read over PROPERTYDEFINITIONS sections @@ -265,41 +300,7 @@ DEFImporter::do_read (db::Layout &layout) } else if (test ("NONDEFAULTRULES")) { - // read NONDEFAULTRULES sections - get_long (); - expect (";"); - - while (test ("-")) { - - std::string n = get (); - - while (test ("+")) { - - if (test ("LAYER")) { - - std::string l = get (); - - // read the width for the layer - if (test ("WIDTH")) { - double w = get_double () * scale; - m_nondefault_widths[n][l] = w; - } - - } - - // parse over the rest - while (! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } - - } - - test (";"); - - } - - test ("END"); - test ("NONDEFAULTRULES"); + read_nondefaultrules (scale); } else if (test ("REGIONS")) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index fa4a377a4..4fa08fbc3 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -61,13 +61,15 @@ protected: private: LEFImporter m_lef_importer; - std::map > m_nondefault_widths; + std::map > m_nondefault_widths; db::FTrans get_orient (bool optional); void read_polygon (db::Polygon &poly, double scale); void read_rect (db::Polygon &poly, double scale); std::pair get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu); std::pair get_def_ext (const std::string &ln, const std::pair &wxy, double dbu); + void read_diearea (db::Layout &layout, db::Cell &design, double scale); + void read_nondefaultrules (double scale); }; } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index f43d905fb..cb5995b1d 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -76,12 +76,12 @@ LEFImporter::min_layer_width (const std::string &layer) const } } -double -LEFImporter::layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width) const +std::pair +LEFImporter::layer_width (const std::string &layer, const std::string &nondefaultrule, const std::pair &def_width) const { - std::map >::const_iterator nd = m_nondefault_widths.find (nondefaultrule); + std::map > >::const_iterator nd = m_nondefault_widths.find (nondefaultrule); - std::map::const_iterator l; + std::map >::const_iterator l; bool has_width = false; if (! nondefaultrule.empty () && nd != m_nondefault_widths.end ()) { @@ -185,9 +185,9 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p } w = 0.0; - std::map::const_iterator dw = m_default_widths.find (layer_name); + std::map >::const_iterator dw = m_default_widths.find (layer_name); if (dw != m_default_widths.end ()) { - w = dw->second; + w = dw->second.first; } while (! test (";")) { @@ -388,7 +388,7 @@ LEFImporter::read_nondefaultrule (db::Layout & /*layout*/) if (test ("WIDTH")) { double w = get_double (); test (";"); - m_nondefault_widths[n][l] = w; + m_nondefault_widths[n][l] = std::make_pair (w, w); } else { while (! test (";")) { take (); @@ -590,7 +590,8 @@ LEFImporter::read_layer (Layout & /*layout*/) { std::string ln = get (); double wmin = 0.0, wmin_wrongdir = 0.0; - bool is_horizontal = true; + double w = 0.0, w_wrongdir = 0.0; + bool is_horizontal = false; register_layer (ln); @@ -615,8 +616,12 @@ LEFImporter::read_layer (Layout & /*layout*/) } else if (test ("WIDTH")) { - double w = get_double (); - m_default_widths.insert (std::make_pair (ln, w)); + w = get_double (); + expect (";"); + + } else if (test ("MINWIDTH")) { + + wmin = get_double (); expect (";"); } else if (test ("DIRECTION")) { @@ -629,8 +634,8 @@ LEFImporter::read_layer (Layout & /*layout*/) } else if (test ("WIREEXTENSION")) { - double w = get_double (); - m_default_ext.insert (std::make_pair (ln, w)); + double v = get_double (); + m_default_ext.insert (std::make_pair (ln, v)); expect (";"); } else if (test ("ACCURRENTDENSITY")) { @@ -656,17 +661,32 @@ LEFImporter::read_layer (Layout & /*layout*/) // Cadence extension tl::Extractor ex (value.to_string ()); - double mw = 0.0; - if (ex.test ("MINWIDTH") && ex.try_read (mw)) { + double v = 0.0; + if (ex.test ("MINWIDTH") && ex.try_read (v)) { if (ex.test ("WRONGDIRECTION")) { - wmin_wrongdir = mw; + wmin_wrongdir = v; } else { - wmin = mw; + wmin = v; + } + } + + } 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; } } } + expect (";"); + } else { while (! test (";")) { @@ -676,9 +696,23 @@ LEFImporter::read_layer (Layout & /*layout*/) } } + if (w > 0.0 || w_wrongdir > 0.0) { + + if (w_wrongdir == 0.0) { + w_wrongdir = w; + } else if (! is_horizontal) { + std::swap (w, w_wrongdir); + } + + m_default_widths.insert (std::make_pair (ln, std::make_pair (w, w_wrongdir))); + + } + if (wmin > 0.0 || wmin_wrongdir > 0.0) { - if (! is_horizontal) { + if (wmin_wrongdir == 0.0) { + wmin_wrongdir = wmin; + } else if (! is_horizontal) { std::swap (wmin, wmin_wrongdir); } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h index 7bc672639..f52133996 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h @@ -77,7 +77,7 @@ public: * The nondefaultrule name gives the name of the nondefaultrule or an empty string if * none is requested. */ - double layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width = 0.0) const; + std::pair layer_width (const std::string &layer, const std::string &nondefaultrule, const std::pair &def_width = std::make_pair (0.0, 0.0)) const; /** * @brief Get the extension for a layer with the given name @@ -121,8 +121,8 @@ protected: void do_read (db::Layout &layout); private: - std::map > m_nondefault_widths; - std::map m_default_widths; + std::map > > m_nondefault_widths; + std::map > m_default_widths; std::map m_default_ext; std::map > m_min_widths; std::map m_macros_by_name; diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 249bf79ed..fd9b1b896 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -284,3 +284,14 @@ TEST(106_wrongdirection) { run_test (_this, "wrongdirection", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); } + +TEST(107_specialwidths) +{ + run_test (_this, "specialwidths", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); +} + +TEST(108_scanchain) +{ + run_test (_this, "scanchain", "def:test.def", "au.oas.gz", default_options (), false); +} + diff --git a/testdata/lefdef/scanchain/au.oas.gz b/testdata/lefdef/scanchain/au.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..62bd9872536a29580951b0170ce152a8118aac84 GIT binary patch literal 153 zcmV;K0A~LmiwFqBxQJc=17US8Z((x)Qw?_Y_0;uu4E7A>JUCcncx52cp?=sD$cSJUCcncx52cp?=sD$cS4!psa-1E#sz{X;{1JpEjmS%8Ab99{;IYDR_yY&TdIvfX46sbspr z@`d>(%U5QRO6CjvFW4{gzhviS6nwz2Kwj)IBf|t{{x8g5m>C!s$jhiRa4_;Sh`sp5 z2m}k|7s$(seFVz!-(b1H!U$Awz)n_d29Rcu6??IUi3b>dKn_rq$W4|Behdsu4I>#a OFaQ7#X*JMe0ssK6;Epo@ literal 0 HcmV?d00001 diff --git a/testdata/lefdef/specialwidths/test.def b/testdata/lefdef/specialwidths/test.def new file mode 100644 index 000000000..9f53fde84 --- /dev/null +++ b/testdata/lefdef/specialwidths/test.def @@ -0,0 +1,19 @@ +VERSION 5.8 ; +DIVIDERCHAR "/" ; +BUSBITCHARS "[]" ; +DESIGN test ; +UNITS DISTANCE MICRONS 1000 ; +DIEAREA ( 0 0 ) ( 10000 10000 ) ; +NONDEFAULTRULES 1 ; + - ndr + + HARDSPACING + + LAYER M3 WIDTH 500 SPACING 500 +; +END NONDEFAULTRULES +NETS 1 ; + - net_b + + NONDEFAULTRULE ndr + + ROUTED M3 ( 0 2000 ) ( 0 0 ) ( 2000 0 ) via34 ( * 2000 ) ( 4000 * ) ( * 4000 ) + ; +END NETS +END DESIGN diff --git a/testdata/lefdef/specialwidths/test.lef b/testdata/lefdef/specialwidths/test.lef new file mode 100644 index 000000000..2d0b5edc9 --- /dev/null +++ b/testdata/lefdef/specialwidths/test.lef @@ -0,0 +1,43 @@ +VERSION 5.8 ; +BUSBITCHARS "[]" ; +DIVIDERCHAR "/" ; + +UNITS + DATABASE MICRONS 1000 ; +END UNITS + +MANUFACTURINGGRID 0.001 ; + +PROPERTYDEFINITIONS + LAYER LEF58_MINWIDTH STRING ; +END PROPERTYDEFINITIONS + +LAYER M3 + TYPE ROUTING ; + DIRECTION VERTICAL ; + WIDTH 0.4 ; + PROPERTY LEF58_MINWIDTH "MINWIDTH 0.5 ; " ; + PROPERTY LEF58_MINWIDTH "MINWIDTH 0.8 WRONGDIRECTION ; " ; +END M3 + +LAYER VIA3 + TYPE CUT ; +END VIA3 + +LAYER M4 + TYPE ROUTING ; + DIRECTION HORIZONTAL ; + PROPERTY LEF58_WIDTH "WIDTH 0.6 ; " ; + PROPERTY LEF58_WIDTH "WIDTH 1.0 WRONGDIRECTION ; " ; +END M4 + +VIA via34 + LAYER M3 ; + RECT -0.4 -0.3 0.4 0.3 ; + LAYER VIA3 ; + RECT -0.3 -0.25 0.3 0.25 ; + LAYER M4 ; + RECT -1.00 -0.5 1.00 0.5 ; +END via34 + +END LIBRARY From 99af144d98085fb84ec5629ce699cc794efb528f Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 4 Apr 2020 19:01:35 +0200 Subject: [PATCH 14/43] Some refactoring - DEF scanner more modular --- .../lefdef/db_plugin/dbDEFImporter.cc | 312 +++++++++--------- .../lefdef/db_plugin/dbDEFImporter.h | 5 + 2 files changed, 170 insertions(+), 147 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index cdbaf91e9..383f628ca 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -30,6 +30,28 @@ namespace db { +struct DEFImporterGroup +{ + DEFImporterGroup (const std::string &n, const std::string &rn, const std::vector &m) + : name (n), region_name (rn), comp_match (m) + { + // .. nothing yet .. + } + + bool comp_matches (const std::string &name) const + { + for (std::vector::const_iterator m = comp_match.begin (); m != comp_match.end (); ++m) { + if (m->match (name)) { + return true; + } + } + return false; + } + + std::string name, region_name; + std::vector comp_match; +}; + DEFImporter::DEFImporter () : LEFDEFImporter () { @@ -114,28 +136,6 @@ DEFImporter::read_rect (db::Polygon &poly, double scale) poly = db::Polygon (db::Box (pt1, pt2)); } -struct Group -{ - Group (const std::string &n, const std::string &rn, const std::vector &m) - : name (n), region_name (rn), comp_match (m) - { - // .. nothing yet .. - } - - bool comp_matches (const std::string &name) const - { - for (std::vector::const_iterator m = comp_match.begin (); m != comp_match.end (); ++m) { - if (m->match (name)) { - return true; - } - } - return false; - } - - std::string name, region_name; - std::vector comp_match; -}; - std::pair DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu) { @@ -204,10 +204,6 @@ DEFImporter::read_diearea (db::Layout &layout, db::Cell &design, double scale) void DEFImporter::read_nondefaultrules (double scale) { - // read NONDEFAULTRULES sections - get_long (); - expect (";"); - while (test ("-")) { std::string n = get (); @@ -236,9 +232,131 @@ DEFImporter::read_nondefaultrules (double scale) test (";"); } +} - test ("END"); - test ("NONDEFAULTRULES"); +void +DEFImporter::read_regions (std::map > ®ions, double scale) +{ + while (test ("-")) { + + std::string n = get (); + std::vector &polygons = regions [n]; + + while (! peek (";")) { + + if (test ("+")) { + + // ignore other options for now + while (! peek (";")) { + take (); + } + break; + + } else { + + db::Polygon box; + read_rect (box, scale); + polygons.push_back (box); + + } + + } + + test (";"); + + } +} +void +DEFImporter::read_groups (std::list &groups, double /*scale*/) +{ + while (test ("-")) { + + std::string n = get (); + std::string rn; + std::vector match; + + while (! peek (";")) { + + if (test ("+")) { + + // gets the region name if there is one + if (test ("REGION")) { + rn = get (); + } + + // ignore the reset for now + while (! peek (";")) { + take (); + } + break; + + } else { + + match.push_back (tl::GlobPattern (get ())); + + } + + } + + groups.push_back (DEFImporterGroup (n, rn, match)); + + test (";"); + + } +} + +void +DEFImporter::read_blockages (db::Layout &layout, db::Cell &design, double scale) +{ + while (test ("-")) { + + std::string layer; + + while (! test (";")) { + + if (test ("PLACEMENT")) { + + // indicates a placement blockage + layer = std::string (); + + } else if (test ("LAYER")) { + + layer = get (); + + } else if (test ("+")) { + + // ignore options for now + while (! peek ("RECT") && ! peek ("POLYGON") && ! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + + } else if (test ("POLYGON")) { + + db::Polygon p; + read_polygon (p, scale); + + std::pair dl = open_layer (layout, layer, layer.empty () ? PlacementBlockage : Blockage); + if (dl.first) { + design.shapes (dl.second).insert (p); + } + + } else if (test ("RECT")) { + + db::Polygon p; + read_rect (p, scale); + + std::pair dl = open_layer (layout, layer, layer.empty () ? PlacementBlockage : Blockage); + if (dl.first) { + design.shapes (dl.second).insert (p); + } + + } else { + expect (";"); + } + + } + + } } void @@ -249,7 +367,7 @@ DEFImporter::do_read (db::Layout &layout) std::map styles; std::map via_desc = m_lef_importer.vias (); std::map > regions; - std::list groups; + std::list groups; std::list > instances; db::Cell &design = layout.cell (layout.add_cell ("TOP")); @@ -300,45 +418,25 @@ DEFImporter::do_read (db::Layout &layout) } else if (test ("NONDEFAULTRULES")) { + // read NONDEFAULTRULES sections + get_long (); + expect (";"); + read_nondefaultrules (scale); + expect ("END"); + expect ("NONDEFAULTRULES"); + } else if (test ("REGIONS")) { // Read REGION statements get_long (); expect (";"); - while (test ("-")) { + read_regions (regions, scale); - std::string n = get (); - std::vector &polygons = regions [n]; - - while (! peek (";")) { - - if (test ("+")) { - - // ignore other options for now - while (! peek (";")) { - take (); - } - break; - - } else { - - db::Polygon box; - read_rect (box, scale); - polygons.push_back (box); - - } - - } - - test (";"); - - } - - test ("END"); - test ("REGIONS"); + expect ("END"); + expect ("REGIONS"); } else if (test ("PINPROPERTIES")) { // read over PINPROPERTIES statements @@ -366,45 +464,13 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { + read_groups (groups, scale); - std::string n = get (); - std::string rn; - std::vector match; - - while (! peek (";")) { - - if (test ("+")) { - - // gets the region name if there is one - if (test ("REGION")) { - rn = get (); - } - - // ignore the reset for now - while (! peek (";")) { - take (); - } - break; - - } else { - - match.push_back (tl::GlobPattern (get ())); - - } - - } - - groups.push_back (Group (n, rn, match)); - - test (";"); - - } - - test ("END"); - test ("GROUPS"); + expect ("END"); + expect ("GROUPS"); } else if (test ("BEGINEXT")) { + // read over BEGINEXT sections while (! test ("ENDEXT")) { take (); @@ -415,58 +481,10 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { + read_blockages (layout, design, scale); - std::string layer; - - while (! test (";")) { - - if (test ("PLACEMENT")) { - - // indicates a placement blockage - layer = std::string (); - - } else if (test ("LAYER")) { - - layer = get (); - - } else if (test ("+")) { - - // ignore options for now - while (! peek ("RECT") && ! peek ("POLYGON") && ! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } - - } else if (test ("POLYGON")) { - - db::Polygon p; - read_polygon (p, scale); - - std::pair dl = open_layer (layout, layer, layer.empty () ? PlacementBlockage : Blockage); - if (dl.first) { - design.shapes (dl.second).insert (p); - } - - } else if (test ("RECT")) { - - db::Polygon p; - read_rect (p, scale); - - std::pair dl = open_layer (layout, layer, layer.empty () ? PlacementBlockage : Blockage); - if (dl.first) { - design.shapes (dl.second).insert (p); - } - - } else { - expect (";"); - } - - } - - } - - test ("END"); - test ("BLOCKAGES"); + expect ("END"); + expect ("BLOCKAGES"); } else if ((specialnets = test ("SPECIALNETS")) == true || test ("NETS")) { @@ -1325,7 +1343,7 @@ DEFImporter::do_read (db::Layout &layout) // Walk through the groups, create a group container cell and put all instances // that match the group match string there. Then delete these cells (spec says "do not assign any component to more than one group"). - for (std::list::const_iterator g = groups.begin (); g != groups.end (); ++g) { + for (std::list::const_iterator g = groups.begin (); g != groups.end (); ++g) { db::Cell *group_cell = &layout.cell (layout.add_cell (("GROUP_" + g->name).c_str ())); design.insert (db::CellInstArray (group_cell->cell_index (), db::Trans ())); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 4fa08fbc3..0ac133de8 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -36,6 +36,8 @@ namespace db { +struct DEFImporterGroup; + /** * @brief The DEF importer object */ @@ -70,6 +72,9 @@ private: std::pair get_def_ext (const std::string &ln, const std::pair &wxy, double dbu); void read_diearea (db::Layout &layout, db::Cell &design, double scale); void read_nondefaultrules (double scale); + void read_regions (std::map > ®ions, double scale); + void read_groups (std::list &groups, double scale); + void read_blockages (db::Layout &layout, db::Cell &design, double scale); }; } From 9df6d29761a5d28d79d3d5fd3d93bb9dd5cbbc7d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 4 Apr 2020 19:14:56 +0200 Subject: [PATCH 15/43] Some refactoring - DEF scanner more modular (2) --- .../lefdef/db_plugin/dbDEFImporter.cc | 1620 +++++++++-------- .../lefdef/db_plugin/dbDEFImporter.h | 7 + 2 files changed, 833 insertions(+), 794 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 383f628ca..54c97fbb2 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -359,17 +359,831 @@ DEFImporter::read_blockages (db::Layout &layout, db::Cell &design, double scale) } } +void +DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets) +{ + while (test ("-")) { + + std::string net = get (); + std::string nondefaultrule; + std::string stored_netname, stored_nondefaultrule; + std::string taperrule; + bool in_subnet = false; + + db::properties_id_type prop_id = 0; + if (produce_net_props ()) { + db::PropertiesRepository::properties_set props; + props.insert (std::make_pair (net_prop_name_id (), tl::Variant (net))); + prop_id = layout.properties_repository ().properties_id (props); + } + + while (test ("(")) { + while (! test (")")) { + take (); + } + } + + while (test ("+")) { + + bool was_shield = false; + + if (! specialnets && test ("SUBNET")) { + + while (test ("(")) { + while (! test (")")) { + take (); + } + } + + if (! in_subnet) { + stored_netname = net; + stored_nondefaultrule = nondefaultrule; + in_subnet = true; + } + + } else if (! specialnets && test ("NONDEFAULTRULE")) { + + nondefaultrule = get (); + + } else if ((was_shield = test ("SHIELD")) == true || test ("NOSHIELD") || test ("ROUTED") || test ("FIXED") || test ("COVER")) { + + if (was_shield) { + take (); + } + + do { + + std::string ln = get (); + + taperrule.clear (); + const std::string *rulename = 0; + + std::pair w (0, 0); + if (specialnets) { + db::Coord n = db::coord_traits::rounded (get_double () * scale); + w = std::make_pair (n, n); + } + + const db::Polygon *style = 0; + + int sn = std::numeric_limits::max (); + + if (specialnets) { + + while (test ("+")) { + + if (test ("STYLE")) { + sn = get_long (); + } else if (test ("SHAPE")) { + take (); + } + + } + + } else { + + while (true) { + if (test ("TAPER")) { + taperrule.clear (); + rulename = &taperrule; + } else if (test ("TAPERRULE")) { + taperrule = get (); + rulename = &taperrule; + } else if (test ("STYLE")) { + sn = get_long (); + } else { + break; + } + } + + } + + if (! rulename) { + rulename = &nondefaultrule; + } + + std::pair def_ext (0, 0); + + if (! specialnets) { + w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); + def_ext = get_def_ext (ln, w, layout.dbu ()); + } + + std::map::const_iterator s = m_styles.find (sn); + if (s != m_styles.end ()) { + style = &s->second; + } + + std::vector > ext; + std::vector pts; + + double x = 0.0, y = 0.0; + + while (true) { + + if (test ("MASK")) { + // ignore mask spec + get_long (); + } + + if (test ("RECT")) { + + if (! test ("(")) { + error (tl::to_string (tr ("RECT routing specification not followed by coordinate list"))); + } + + // breaks wiring + pts.clear (); + + // rect spec + + double x1 = get_double (); + double y1 = get_double (); + double x2 = get_double (); + double y2 = get_double (); + + test (")"); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + + db::Box rect (db::Point (db::DPoint ((x + x1) * scale, (y + y1) * scale)), + db::Point (db::DPoint ((x + x2) * scale, (y + y2) * scale))); + + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (rect, prop_id)); + } else { + design.shapes (dl.second).insert (rect); + } + + } + + } else if (test ("VIRTUAL")) { + + // virtual specs simply create a new segment + pts.clear (); + + } else if (peek ("(")) { + + ext.clear (); + + while (peek ("(") || peek ("MASK")) { + + if (test ("MASK")) { + // ignore MASK spec + get_long (); + } + + if (! test ("(")) { + // We could have a via here: in that case we have swallowed MASK already, but + // since we don't do anything with that, this does not hurt for now. + break; + } + + if (! test ("*")) { + x = get_double (); + } + if (! test ("*")) { + y = get_double (); + } + pts.push_back (db::Point (db::DPoint (x * scale, y * scale))); + std::pair ee = def_ext; + if (! peek (")")) { + db::Coord e = db::coord_traits::rounded (get_double () * scale); + ee.first = ee.second = e; + } + ext.push_back (ee); + + test (")"); + + } + + if (pts.size () > 1) { + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + + if (! style) { + + // Use the default style (octagon "pen" for non-manhattan segments, paths for + // horizontal/vertical segments). + // Manhattan paths are stitched together from two-point paths if they + + std::pair e = std::max (ext.front (), ext.back ()); + bool is_isotropic = (e.first == e.second && w.first == w.second); + bool was_path = false; + + std::vector::const_iterator pt = pts.begin (); + while (pt != pts.end ()) { + + std::vector::const_iterator pt0 = pt; + do { + ++pt; + } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); + + if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { + + if (pt - pt0 == 1) { + ++pt; + } + + db::Coord wxy, wxy_perp, exy; + + if (pt0->x () == pt0 [1].x ()) { + wxy = w.second; + wxy_perp = w.first; + exy = e.second; + } else { + wxy = w.first; + wxy_perp = w.second; + exy = e.first; + } + + db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + + if (pt == pts.end ()) { + break; + } + + --pt; + + was_path = true; + + } else { + + if (! is_isotropic) { + warn("Anisotropic wire widths not supported for diagonal wires"); + } + + db::Coord s = (w.first + 1) / 2; + db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); + + db::Point octagon[8] = { + db::Point (-s, t), + db::Point (-t, s), + db::Point (t, s), + db::Point (s, t), + db::Point (s, -t), + db::Point (t, -s), + db::Point (-t, -s), + db::Point (-s, -t) + }; + + db::Polygon k; + k.assign_hull (octagon, octagon + sizeof (octagon) / sizeof (octagon[0])); + + db::Polygon p = db::minkowsky_sum (k, db::Edge (*pt0, *pt)); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + + was_path = false; + + } + + } + + } else { + + for (size_t i = 0; i < pts.size () - 1; ++i) { + db::Polygon p = db::minkowsky_sum (*style, db::Edge (pts [i], pts [i + 1])); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + } + + } + + } + + } else if (! peek ("NEW") && ! peek ("+") && ! peek ("-") && ! peek (";")) { + + // indicates a via + std::string vn = get (); + db::FTrans ft = get_orient (true /*optional*/); + + db::Coord dx = 0, dy = 0; + long nx = 1, ny = 1; + + if (specialnets && test ("DO")) { + + nx = std::max (0l, get_long ()); + test ("BY"); + ny = std::max (0l, get_long ()); + test ("STEP"); + dx = db::coord_traits::rounded (get_double () * scale); + dy = db::coord_traits::rounded (get_double () * scale); + + if (nx < 0) { + dx = -dx; + nx = -nx; + } + if (ny < 0) { + dy = -dy; + ny = -ny; + } + + } + + std::map::const_iterator vd = m_via_desc.find (vn); + if (vd != m_via_desc.end () && ! pts.empty ()) { + if (nx <= 1 && ny <= 1) { + design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); + } else { + design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())), db::Vector (dx, 0), db::Vector (0, dy), (unsigned long) nx, (unsigned long) ny)); + } + if (ln == vd->second.m1) { + ln = vd->second.m2; + } else if (ln == vd->second.m2) { + ln = vd->second.m1; + } + } + + if (! specialnets) { + w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); + def_ext = get_def_ext (ln, w, layout.dbu ()); + } + + // continue a segment with the current point and the new layer + if (pts.size () > 1) { + pts.erase (pts.begin (), pts.end () - 1); + } + + } else { + break; + } + + } + + } while (test ("NEW")); + + if (in_subnet) { + in_subnet = false; + net = stored_netname; + stored_netname.clear (); + nondefaultrule = stored_nondefaultrule; + stored_nondefaultrule.clear (); + } + + } else if (test ("POLYGON")) { + + std::string ln = get (); + + db::Polygon p; + read_polygon (p, scale); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + } else if (test ("RECT")) { + + std::string ln = get (); + + db::Polygon p; + read_rect (p, scale); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + } else { + while (! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + } + + } + + expect (";"); + + } +} + +void +DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) +{ + while (test ("-")) { + + std::string n = get (); + ViaDesc &vd = m_via_desc.insert (std::make_pair (n, ViaDesc ())).first->second; + + // produce a cell for vias + std::string cellname = "VIA_" + n; + db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ())); + vd.cell = &cell; + + bool has_via_rule = false; + + db::Vector cutsize, cutspacing; + db::Vector be, te; + db::Vector bo, to; + db::Point offset; + int rows = 1, columns = 1; + std::string pattern; + + std::map > geometry; + std::vector *top = 0, *cut = 0, *bottom = 0; + + while (test ("+")) { + + double x, y; + + if (test ("VIARULE")) { + + has_via_rule = true; + take (); + + } else if (test ("CUTSIZE")) { + + x = get_double (); + y = get_double (); + cutsize = db::Vector (db::DVector (x * scale, y * scale)); + + } else if (test ("CUTSPACING")) { + + x = get_double (); + y = get_double (); + cutspacing = db::Vector (db::DVector (x * scale, y * scale)); + + } else if (test ("ORIGIN")) { + + x = get_double (); + y = get_double (); + offset = db::Point (db::DPoint (x * scale, y * scale)); + + } else if (test ("ENCLOSURE")) { + + x = get_double (); + y = get_double (); + be = db::Vector (db::DVector (x * scale, y * scale)); + + x = get_double (); + y = get_double (); + te = db::Vector (db::DVector (x * scale, y * scale)); + + } else if (test ("OFFSET")) { + + x = get_double (); + y = get_double (); + bo = db::Vector (db::DVector (x * scale, y * scale)); + + x = get_double (); + y = get_double (); + to = db::Vector (db::DVector (x * scale, y * scale)); + + } else if (test ("ROWCOL")) { + + rows = get_long (); + columns = get_long (); + + } else if (test ("PATTERN")) { + + pattern = get (); + + } else if (test ("LAYERS")) { + + std::string bn = get (); + std::string cn = get (); + std::string tn = get (); + + bottom = &geometry.insert (std::make_pair (bn, std::vector ())).first->second; + cut = &geometry.insert (std::make_pair (cn, std::vector ())).first->second; + top = &geometry.insert (std::make_pair (tn, std::vector ())).first->second; + + vd.m1 = bn; + vd.m2 = tn; + + } else if (test ("POLYGON")) { + + std::string ln = get (); + + if (test ("+")) { + expect ("MASK"); + get_long (); + } + + std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; + polygons.push_back (db::Polygon ()); + read_polygon (polygons.back (), scale); + + } else if (test ("RECT")) { + + std::string ln = get (); + + if (test ("+")) { + expect ("MASK"); + get_long (); + } + + std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; + polygons.push_back (db::Polygon ()); + read_rect (polygons.back (), scale); + + } + + } + + if (vd.m1.empty () && vd.m2.empty ()) { + + // analyze the layers to find the metals + std::vector routing_layers; + for (std::map >::const_iterator b = geometry.begin (); b != geometry.end (); ++b) { + if (m_lef_importer.is_routing_layer (b->first)) { + routing_layers.push_back (b->first); + } + } + + if (routing_layers.size () == 2) { + vd.m1 = routing_layers[0]; + vd.m2 = routing_layers[1]; + } else { + warn ("Can't determine routing layers for via: " + n); + } + + } + + test (";"); + + if (has_via_rule && top && cut && bottom) { + create_generated_via (*bottom, *cut, *top, + cutsize, cutspacing, be, te, bo, to, offset, rows, columns, pattern); + } + + for (std::map >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { + std::pair dl = open_layer (layout, g->first, ViaGeometry); + if (dl.first) { + for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { + cell.shapes (dl.second).insert (*p); + } + } + } + + } +} + +void +DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale) +{ + while (test ("-")) { + + take (); // pin name + + std::string net; + std::string dir; + std::map > geometry; + db::Trans trans; + + while (test ("+")) { + + bool flush = false; + + if (test ("DIRECTION")) { + dir = get (); + } else if (test ("NET")) { + net = get (); + } else if (test ("LAYER")) { + + std::string ln = get (); + + while (test ("DESIGNRULEWIDTH") || test ("SPACING")) { + take (); + } + + double x, y; + + test ("("); + x = get_double (); + y = get_double (); + db::Point pt1 = db::Point (db::DPoint (x * scale, y * scale)); + test (")"); + + test ("("); + x = get_double (); + y = get_double (); + db::Point pt2 = db::Point (db::DPoint (x * scale, y * scale)); + test (")"); + + geometry.insert (std::make_pair (ln, std::vector ())).first->second.push_back (db::Polygon (db::Box (pt1, pt2))); + + } else if (test ("POLYGON")) { + + std::string ln = get (); + + while (test ("DESIGNRULEWIDTH") || test ("SPACING")) { + take (); + } + + std::vector points; + + double x = 0.0, y = 0.0; + + while (! test ("+") && ! test (";")) { + + test ("("); + if (! test ("*")) { + x = get_double (); + } + if (! test ("*")) { + y = get_double (); + } + points.push_back (db::Point (db::DPoint (x * scale, y * scale))); + test (")"); + + } + + std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; + polygons.push_back (db::Polygon ()); + polygons.back ().assign_hull (points.begin (), points.end ()); + + } else if (test ("PLACED") || test ("FIXED") || test ("COVER")) { + + test ("("); + double x = get_double (); + double y = get_double (); + db::Vector d = db::Vector (db::DVector (x * scale, y * scale)); + test (")"); + + db::FTrans ft = get_orient (false /*mandatory*/); + trans = db::Trans (ft.rot (), d); + + } else if (test ("PORT")) { + + flush = true; + + } else { + while (! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + } + + if (flush || ! peek ("+")) { + + // TODO: put a label on every single object? + std::string label = net; + /* don't add the direction currently, a name is sufficient + if (! dir.empty ()) { + label += ":"; + label += dir; + } + */ + + // Produce geometry collected so far + for (std::map >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { + + std::pair dl = open_layer (layout, g->first, Pins); + if (dl.first) { + + db::properties_id_type prop_id = 0; + if (produce_pin_props ()) { + db::PropertiesRepository::properties_set props; + props.insert (std::make_pair (pin_prop_name_id (), tl::Variant (label))); + prop_id = layout.properties_repository ().properties_id (props); + } + + for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { + db::Polygon pt = p->transformed (trans); + if (prop_id == 0) { + design.shapes (dl.second).insert (pt); + } else { + design.shapes (dl.second).insert (db::PolygonWithProperties (pt, prop_id)); + } + } + + } + + dl = open_layer (layout, g->first, Label); + if (dl.first) { + db::Box bbox; + if (! g->second.empty ()) { + bbox = g->second.back ().box ().transformed (trans); + } + design.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (db::Vector (bbox.center ())))); + } + + } + + geometry.clear (); + trans = db::Trans (); + + } + + } + + expect (";"); + + } +} + +void +DEFImporter::read_styles (double scale) +{ + while (test ("-")) { + + test ("STYLE"); + + int sn = get_long (); + + std::vector points; + + double x = 0.0, y = 0.0; + + while (! test (";")) { + + test ("("); + if (! test ("*")) { + x = get_double (); + } + if (! test ("*")) { + y = get_double (); + } + points.push_back (db::Point (db::DPoint (x * scale, y * scale))); + test (")"); + + } + + m_styles.insert (std::make_pair (sn, db::Polygon ())).first->second.assign_hull (points.begin (), points.end ()); + + } +} + +void +DEFImporter::read_components (std::list > &instances, double scale) +{ + while (test ("-")) { + + std::string inst_name = get (); + std::string model = get (); + + db::Cell *cell = m_lef_importer.macro_by_name (model); + + while (test ("+")) { + + if (test ("PLACED") || test ("FIXED") || test ("COVER")) { + + test ("("); + double x = get_double (); + double y = get_double (); + db::Point pt = db::Point (db::DPoint (x * scale, y * scale)); + test (")"); + + db::FTrans ft = get_orient (false /*mandatory*/); + db::Vector d = pt - m_lef_importer.macro_bbox_by_name (model).transformed (ft).lower_left (); + + if (cell) { + db::CellInstArray inst (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), d)); + instances.push_back (std::make_pair (inst_name, inst)); + } else { + warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model); + } + + } else { + while (! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + } + + } + + expect (";"); + + } +} + void DEFImporter::do_read (db::Layout &layout) { double dbu_mic = 1000.0; double scale = 1.0 / (dbu_mic * layout.dbu ()); - std::map styles; - std::map via_desc = m_lef_importer.vias (); + std::map > regions; std::list groups; std::list > instances; + m_via_desc = m_lef_importer.vias (); + m_styles.clear (); + db::Cell &design = layout.cell (layout.add_cell ("TOP")); while (! at_end ()) { @@ -491,429 +1305,13 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { + read_nets (layout, design, scale, specialnets); - std::string net = get (); - std::string nondefaultrule; - std::string stored_netname, stored_nondefaultrule; - std::string taperrule; - bool in_subnet = false; - - db::properties_id_type prop_id = 0; - if (produce_net_props ()) { - db::PropertiesRepository::properties_set props; - props.insert (std::make_pair (net_prop_name_id (), tl::Variant (net))); - prop_id = layout.properties_repository ().properties_id (props); - } - - while (test ("(")) { - while (! test (")")) { - take (); - } - } - - while (test ("+")) { - - bool was_shield = false; - - if (! specialnets && test ("SUBNET")) { - - while (test ("(")) { - while (! test (")")) { - take (); - } - } - - if (! in_subnet) { - stored_netname = net; - stored_nondefaultrule = nondefaultrule; - in_subnet = true; - } - - } else if (! specialnets && test ("NONDEFAULTRULE")) { - - nondefaultrule = get (); - - } else if ((was_shield = test ("SHIELD")) == true || test ("NOSHIELD") || test ("ROUTED") || test ("FIXED") || test ("COVER")) { - - if (was_shield) { - take (); - } - - do { - - std::string ln = get (); - - taperrule.clear (); - const std::string *rulename = 0; - - std::pair w (0, 0); - if (specialnets) { - db::Coord n = db::coord_traits::rounded (get_double () * scale); - w = std::make_pair (n, n); - } - - const db::Polygon *style = 0; - - int sn = std::numeric_limits::max (); - - if (specialnets) { - - while (test ("+")) { - - if (test ("STYLE")) { - sn = get_long (); - } else if (test ("SHAPE")) { - take (); - } - - } - - } else { - - while (true) { - if (test ("TAPER")) { - taperrule.clear (); - rulename = &taperrule; - } else if (test ("TAPERRULE")) { - taperrule = get (); - rulename = &taperrule; - } else if (test ("STYLE")) { - sn = get_long (); - } else { - break; - } - } - - } - - if (! rulename) { - rulename = &nondefaultrule; - } - - std::pair def_ext (0, 0); - - if (! specialnets) { - w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = get_def_ext (ln, w, layout.dbu ()); - } - - std::map::const_iterator s = styles.find (sn); - if (s != styles.end ()) { - style = &s->second; - } - - std::vector > ext; - std::vector pts; - - double x = 0.0, y = 0.0; - - while (true) { - - if (test ("MASK")) { - // ignore mask spec - get_long (); - } - - if (test ("RECT")) { - - if (! test ("(")) { - error (tl::to_string (tr ("RECT routing specification not followed by coordinate list"))); - } - - // breaks wiring - pts.clear (); - - // rect spec - - double x1 = get_double (); - double y1 = get_double (); - double x2 = get_double (); - double y2 = get_double (); - - test (")"); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - - db::Box rect (db::Point (db::DPoint ((x + x1) * scale, (y + y1) * scale)), - db::Point (db::DPoint ((x + x2) * scale, (y + y2) * scale))); - - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (rect, prop_id)); - } else { - design.shapes (dl.second).insert (rect); - } - - } - - } else if (test ("VIRTUAL")) { - - // virtual specs simply create a new segment - pts.clear (); - - } else if (peek ("(")) { - - ext.clear (); - - while (peek ("(") || peek ("MASK")) { - - if (test ("MASK")) { - // ignore MASK spec - get_long (); - } - - if (! test ("(")) { - // We could have a via here: in that case we have swallowed MASK already, but - // since we don't do anything with that, this does not hurt for now. - break; - } - - if (! test ("*")) { - x = get_double (); - } - if (! test ("*")) { - y = get_double (); - } - pts.push_back (db::Point (db::DPoint (x * scale, y * scale))); - std::pair ee = def_ext; - if (! peek (")")) { - db::Coord e = db::coord_traits::rounded (get_double () * scale); - ee.first = ee.second = e; - } - ext.push_back (ee); - - test (")"); - - } - - if (pts.size () > 1) { - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - - if (! style) { - - // Use the default style (octagon "pen" for non-manhattan segments, paths for - // horizontal/vertical segments). - // Manhattan paths are stitched together from two-point paths if they - - std::pair e = std::max (ext.front (), ext.back ()); - bool is_isotropic = (e.first == e.second && w.first == w.second); - bool was_path = false; - - std::vector::const_iterator pt = pts.begin (); - while (pt != pts.end ()) { - - std::vector::const_iterator pt0 = pt; - do { - ++pt; - } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); - - if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { - - if (pt - pt0 == 1) { - ++pt; - } - - db::Coord wxy, wxy_perp, exy; - - if (pt0->x () == pt0 [1].x ()) { - wxy = w.second; - wxy_perp = w.first; - exy = e.second; - } else { - wxy = w.first; - wxy_perp = w.second; - exy = e.first; - } - - db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - - if (pt == pts.end ()) { - break; - } - - --pt; - - was_path = true; - - } else { - - if (! is_isotropic) { - warn("Anisotropic wire widths not supported for diagonal wires"); - } - - db::Coord s = (w.first + 1) / 2; - db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); - - db::Point octagon[8] = { - db::Point (-s, t), - db::Point (-t, s), - db::Point (t, s), - db::Point (s, t), - db::Point (s, -t), - db::Point (t, -s), - db::Point (-t, -s), - db::Point (-s, -t) - }; - - db::Polygon k; - k.assign_hull (octagon, octagon + sizeof (octagon) / sizeof (octagon[0])); - - db::Polygon p = db::minkowsky_sum (k, db::Edge (*pt0, *pt)); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - - was_path = false; - - } - - } - - } else { - - for (size_t i = 0; i < pts.size () - 1; ++i) { - db::Polygon p = db::minkowsky_sum (*style, db::Edge (pts [i], pts [i + 1])); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } - - } - - } - - } else if (! peek ("NEW") && ! peek ("+") && ! peek ("-") && ! peek (";")) { - - // indicates a via - std::string vn = get (); - db::FTrans ft = get_orient (true /*optional*/); - - db::Coord dx = 0, dy = 0; - long nx = 1, ny = 1; - - if (specialnets && test ("DO")) { - - nx = std::max (0l, get_long ()); - test ("BY"); - ny = std::max (0l, get_long ()); - test ("STEP"); - dx = db::coord_traits::rounded (get_double () * scale); - dy = db::coord_traits::rounded (get_double () * scale); - - if (nx < 0) { - dx = -dx; - nx = -nx; - } - if (ny < 0) { - dy = -dy; - ny = -ny; - } - - } - - std::map::const_iterator vd = via_desc.find (vn); - if (vd != via_desc.end () && ! pts.empty ()) { - if (nx <= 1 && ny <= 1) { - design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); - } else { - design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())), db::Vector (dx, 0), db::Vector (0, dy), (unsigned long) nx, (unsigned long) ny)); - } - if (ln == vd->second.m1) { - ln = vd->second.m2; - } else if (ln == vd->second.m2) { - ln = vd->second.m1; - } - } - - if (! specialnets) { - w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = get_def_ext (ln, w, layout.dbu ()); - } - - // continue a segment with the current point and the new layer - if (pts.size () > 1) { - pts.erase (pts.begin (), pts.end () - 1); - } - - } else { - break; - } - - } - - } while (test ("NEW")); - - if (in_subnet) { - in_subnet = false; - net = stored_netname; - stored_netname.clear (); - nondefaultrule = stored_nondefaultrule; - stored_nondefaultrule.clear (); - } - - } else if (test ("POLYGON")) { - - std::string ln = get (); - - db::Polygon p; - read_polygon (p, scale); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } else if (test ("RECT")) { - - std::string ln = get (); - - db::Polygon p; - read_rect (p, scale); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } else { - while (! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } - } - - } - - expect (";"); - - } - - test ("END"); + expect ("END"); if (specialnets) { - test ("SPECIALNETS"); + expect ("SPECIALNETS"); } else { - test ("NETS"); + expect ("NETS"); } } else if (test ("VIAS")) { @@ -921,163 +1319,7 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { - - std::string n = get (); - ViaDesc &vd = via_desc.insert (std::make_pair (n, ViaDesc ())).first->second; - - // produce a cell for vias - std::string cellname = "VIA_" + n; - db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ())); - vd.cell = &cell; - - bool has_via_rule = false; - - db::Vector cutsize, cutspacing; - db::Vector be, te; - db::Vector bo, to; - db::Point offset; - int rows = 1, columns = 1; - std::string pattern; - - std::map > geometry; - std::vector *top = 0, *cut = 0, *bottom = 0; - - while (test ("+")) { - - double x, y; - - if (test ("VIARULE")) { - - has_via_rule = true; - take (); - - } else if (test ("CUTSIZE")) { - - x = get_double (); - y = get_double (); - cutsize = db::Vector (db::DVector (x * scale, y * scale)); - - } else if (test ("CUTSPACING")) { - - x = get_double (); - y = get_double (); - cutspacing = db::Vector (db::DVector (x * scale, y * scale)); - - } else if (test ("ORIGIN")) { - - x = get_double (); - y = get_double (); - offset = db::Point (db::DPoint (x * scale, y * scale)); - - } else if (test ("ENCLOSURE")) { - - x = get_double (); - y = get_double (); - be = db::Vector (db::DVector (x * scale, y * scale)); - - x = get_double (); - y = get_double (); - te = db::Vector (db::DVector (x * scale, y * scale)); - - } else if (test ("OFFSET")) { - - x = get_double (); - y = get_double (); - bo = db::Vector (db::DVector (x * scale, y * scale)); - - x = get_double (); - y = get_double (); - to = db::Vector (db::DVector (x * scale, y * scale)); - - } else if (test ("ROWCOL")) { - - rows = get_long (); - columns = get_long (); - - } else if (test ("PATTERN")) { - - pattern = get (); - - } else if (test ("LAYERS")) { - - std::string bn = get (); - std::string cn = get (); - std::string tn = get (); - - bottom = &geometry.insert (std::make_pair (bn, std::vector ())).first->second; - cut = &geometry.insert (std::make_pair (cn, std::vector ())).first->second; - top = &geometry.insert (std::make_pair (tn, std::vector ())).first->second; - - vd.m1 = bn; - vd.m2 = tn; - - } else if (test ("POLYGON")) { - - std::string ln = get (); - - if (test ("+")) { - expect ("MASK"); - get_long (); - } - - std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; - polygons.push_back (db::Polygon ()); - read_polygon (polygons.back (), scale); - - } else if (test ("RECT")) { - - std::string ln = get (); - - if (test ("+")) { - expect ("MASK"); - get_long (); - } - - std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; - polygons.push_back (db::Polygon ()); - read_rect (polygons.back (), scale); - - } - - } - - if (vd.m1.empty () && vd.m2.empty ()) { - - // analyze the layers to find the metals - std::vector routing_layers; - for (std::map >::const_iterator b = geometry.begin (); b != geometry.end (); ++b) { - if (m_lef_importer.is_routing_layer (b->first)) { - routing_layers.push_back (b->first); - } - } - - if (routing_layers.size () == 2) { - vd.m1 = routing_layers[0]; - vd.m2 = routing_layers[1]; - } else { - warn ("Can't determine routing layers for via: " + n); - } - - } - - test (";"); - - if (has_via_rule && top && cut && bottom) { - create_generated_via (*bottom, *cut, *top, - cutsize, cutspacing, be, te, bo, to, offset, rows, columns, pattern); - } - - for (std::map >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { - std::pair dl = open_layer (layout, g->first, ViaGeometry); - if (dl.first) { - for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { - cell.shapes (dl.second).insert (*p); - } - } - } - - } + read_vias (layout, design, scale); expect ("END"); expect ("VIAS"); @@ -1087,80 +1329,17 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { + read_styles (scale); - test ("STYLE"); - - int sn = get_long (); - - std::vector points; - - double x = 0.0, y = 0.0; - - while (! test (";")) { - - test ("("); - if (! test ("*")) { - x = get_double (); - } - if (! test ("*")) { - y = get_double (); - } - points.push_back (db::Point (db::DPoint (x * scale, y * scale))); - test (")"); - - } - - styles.insert (std::make_pair (sn, db::Polygon ())).first->second.assign_hull (points.begin (), points.end ()); - - } - - test ("END"); - test ("STYLES"); + expect ("END"); + expect ("STYLES"); } else if (test ("COMPONENTS")) { get_long (); expect (";"); - while (test ("-")) { - - std::string inst_name = get (); - std::string model = get (); - - db::Cell *cell = m_lef_importer.macro_by_name (model); - - while (test ("+")) { - - if (test ("PLACED") || test ("FIXED") || test ("COVER")) { - - test ("("); - double x = get_double (); - double y = get_double (); - db::Point pt = db::Point (db::DPoint (x * scale, y * scale)); - test (")"); - - db::FTrans ft = get_orient (false /*mandatory*/); - db::Vector d = pt - m_lef_importer.macro_bbox_by_name (model).transformed (ft).lower_left (); - - if (cell) { - db::CellInstArray inst (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), d)); - instances.push_back (std::make_pair (inst_name, inst)); - } else { - warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model); - } - - } else { - while (! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } - } - - } - - expect (";"); - - } + read_components (instances, scale); expect ("END"); expect ("COMPONENTS"); @@ -1170,154 +1349,7 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { - - take (); // pin name - - std::string net; - std::string dir; - std::map > geometry; - db::Trans trans; - - while (test ("+")) { - - bool flush = false; - - if (test ("DIRECTION")) { - dir = get (); - } else if (test ("NET")) { - net = get (); - } else if (test ("LAYER")) { - - std::string ln = get (); - - while (test ("DESIGNRULEWIDTH") || test ("SPACING")) { - take (); - } - - double x, y; - - test ("("); - x = get_double (); - y = get_double (); - db::Point pt1 = db::Point (db::DPoint (x * scale, y * scale)); - test (")"); - - test ("("); - x = get_double (); - y = get_double (); - db::Point pt2 = db::Point (db::DPoint (x * scale, y * scale)); - test (")"); - - geometry.insert (std::make_pair (ln, std::vector ())).first->second.push_back (db::Polygon (db::Box (pt1, pt2))); - - } else if (test ("POLYGON")) { - - std::string ln = get (); - - while (test ("DESIGNRULEWIDTH") || test ("SPACING")) { - take (); - } - - std::vector points; - - double x = 0.0, y = 0.0; - - while (! test ("+") && ! test (";")) { - - test ("("); - if (! test ("*")) { - x = get_double (); - } - if (! test ("*")) { - y = get_double (); - } - points.push_back (db::Point (db::DPoint (x * scale, y * scale))); - test (")"); - - } - - std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; - polygons.push_back (db::Polygon ()); - polygons.back ().assign_hull (points.begin (), points.end ()); - - } else if (test ("PLACED") || test ("FIXED") || test ("COVER")) { - - test ("("); - double x = get_double (); - double y = get_double (); - db::Vector d = db::Vector (db::DVector (x * scale, y * scale)); - test (")"); - - db::FTrans ft = get_orient (false /*mandatory*/); - trans = db::Trans (ft.rot (), d); - - } else if (test ("PORT")) { - - flush = true; - - } else { - while (! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } - } - - if (flush || ! peek ("+")) { - - // TODO: put a label on every single object? - std::string label = net; - /* don't add the direction currently, a name is sufficient - if (! dir.empty ()) { - label += ":"; - label += dir; - } - */ - - // Produce geometry collected so far - for (std::map >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { - - std::pair dl = open_layer (layout, g->first, Pins); - if (dl.first) { - - db::properties_id_type prop_id = 0; - if (produce_pin_props ()) { - db::PropertiesRepository::properties_set props; - props.insert (std::make_pair (pin_prop_name_id (), tl::Variant (label))); - prop_id = layout.properties_repository ().properties_id (props); - } - - for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { - db::Polygon pt = p->transformed (trans); - if (prop_id == 0) { - design.shapes (dl.second).insert (pt); - } else { - design.shapes (dl.second).insert (db::PolygonWithProperties (pt, prop_id)); - } - } - - } - - dl = open_layer (layout, g->first, Label); - if (dl.first) { - db::Box bbox; - if (! g->second.empty ()) { - bbox = g->second.back ().box ().transformed (trans); - } - design.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (db::Vector (bbox.center ())))); - } - - } - - geometry.clear (); - trans = db::Trans (); - - } - - } - - expect (";"); - - } + read_pins (layout, design, scale); expect ("END"); expect ("PINS"); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 0ac133de8..13a8f90cb 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -64,6 +64,8 @@ protected: private: LEFImporter m_lef_importer; std::map > m_nondefault_widths; + std::map m_via_desc; + std::map m_styles; db::FTrans get_orient (bool optional); void read_polygon (db::Polygon &poly, double scale); @@ -75,6 +77,11 @@ private: void read_regions (std::map > ®ions, double scale); void read_groups (std::list &groups, double scale); void read_blockages (db::Layout &layout, db::Cell &design, double scale); + void read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets); + void read_vias (db::Layout &layout, db::Cell &design, double scale); + void read_pins (db::Layout &layout, db::Cell &design, double scale); + void read_styles (double scale); + void read_components (std::list > &instances, double scale); }; } From dea3743d5930bb97794c30186ea3f897022b6d58 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 4 Apr 2020 19:31:01 +0200 Subject: [PATCH 16/43] Some refactoring - DEF scanner more modular (3) --- .../lefdef/db_plugin/dbDEFImporter.cc | 663 +++++++++--------- .../lefdef/db_plugin/dbDEFImporter.h | 1 + 2 files changed, 346 insertions(+), 318 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 54c97fbb2..9486ab3ff 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -359,6 +359,329 @@ DEFImporter::read_blockages (db::Layout &layout, db::Cell &design, double scale) } } +void +DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::Cell &design, double scale, db::properties_id_type prop_id, bool specialnets) +{ + std::string taperrule; + + do { + + std::string ln = get (); + + taperrule.clear (); + const std::string *rulename = 0; + + std::pair w (0, 0); + if (specialnets) { + db::Coord n = db::coord_traits::rounded (get_double () * scale); + w = std::make_pair (n, n); + } + + const db::Polygon *style = 0; + + int sn = std::numeric_limits::max (); + + if (specialnets) { + + while (test ("+")) { + + if (test ("STYLE")) { + sn = get_long (); + } else if (test ("SHAPE")) { + take (); + } + + } + + } else { + + while (true) { + if (test ("TAPER")) { + taperrule.clear (); + rulename = &taperrule; + } else if (test ("TAPERRULE")) { + taperrule = get (); + rulename = &taperrule; + } else if (test ("STYLE")) { + sn = get_long (); + } else { + break; + } + } + + } + + if (! rulename) { + rulename = &nondefaultrule; + } + + std::pair def_ext (0, 0); + + if (! specialnets) { + w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); + def_ext = get_def_ext (ln, w, layout.dbu ()); + } + + std::map::const_iterator s = m_styles.find (sn); + if (s != m_styles.end ()) { + style = &s->second; + } + + std::vector > ext; + std::vector pts; + + double x = 0.0, y = 0.0; + + while (true) { + + if (test ("MASK")) { + // ignore mask spec + get_long (); + } + + if (test ("RECT")) { + + if (! test ("(")) { + error (tl::to_string (tr ("RECT routing specification not followed by coordinate list"))); + } + + // breaks wiring + pts.clear (); + + // rect spec + + double x1 = get_double (); + double y1 = get_double (); + double x2 = get_double (); + double y2 = get_double (); + + test (")"); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + + db::Box rect (db::Point (db::DPoint ((x + x1) * scale, (y + y1) * scale)), + db::Point (db::DPoint ((x + x2) * scale, (y + y2) * scale))); + + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (rect, prop_id)); + } else { + design.shapes (dl.second).insert (rect); + } + + } + + } else if (test ("VIRTUAL")) { + + // virtual specs simply create a new segment + pts.clear (); + + } else if (peek ("(")) { + + ext.clear (); + + while (peek ("(") || peek ("MASK")) { + + if (test ("MASK")) { + // ignore MASK spec + get_long (); + } + + if (! test ("(")) { + // We could have a via here: in that case we have swallowed MASK already, but + // since we don't do anything with that, this does not hurt for now. + break; + } + + if (! test ("*")) { + x = get_double (); + } + if (! test ("*")) { + y = get_double (); + } + pts.push_back (db::Point (db::DPoint (x * scale, y * scale))); + std::pair ee = def_ext; + if (! peek (")")) { + db::Coord e = db::coord_traits::rounded (get_double () * scale); + ee.first = ee.second = e; + } + ext.push_back (ee); + + test (")"); + + } + + if (pts.size () > 1) { + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + + if (! style) { + + // Use the default style (octagon "pen" for non-manhattan segments, paths for + // horizontal/vertical segments). + // Manhattan paths are stitched together from two-point paths if they + + std::pair e = std::max (ext.front (), ext.back ()); + bool is_isotropic = (e.first == e.second && w.first == w.second); + bool was_path = false; + + std::vector::const_iterator pt = pts.begin (); + while (pt != pts.end ()) { + + std::vector::const_iterator pt0 = pt; + do { + ++pt; + } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); + + if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { + + if (pt - pt0 == 1) { + ++pt; + } + + db::Coord wxy, wxy_perp, exy; + + if (pt0->x () == pt0 [1].x ()) { + wxy = w.second; + wxy_perp = w.first; + exy = e.second; + } else { + wxy = w.first; + wxy_perp = w.second; + exy = e.first; + } + + db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + + if (pt == pts.end ()) { + break; + } + + --pt; + + was_path = true; + + } else { + + if (! is_isotropic) { + warn("Anisotropic wire widths not supported for diagonal wires"); + } + + db::Coord s = (w.first + 1) / 2; + db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); + + db::Point octagon[8] = { + db::Point (-s, t), + db::Point (-t, s), + db::Point (t, s), + db::Point (s, t), + db::Point (s, -t), + db::Point (t, -s), + db::Point (-t, -s), + db::Point (-s, -t) + }; + + db::Polygon k; + k.assign_hull (octagon, octagon + sizeof (octagon) / sizeof (octagon[0])); + + db::Polygon p = db::minkowsky_sum (k, db::Edge (*pt0, *pt)); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + + was_path = false; + + } + + } + + } else { + + for (size_t i = 0; i < pts.size () - 1; ++i) { + db::Polygon p = db::minkowsky_sum (*style, db::Edge (pts [i], pts [i + 1])); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + } + + } + + } + + } else if (! peek ("NEW") && ! peek ("+") && ! peek ("-") && ! peek (";")) { + + // indicates a via + std::string vn = get (); + db::FTrans ft = get_orient (true /*optional*/); + + db::Coord dx = 0, dy = 0; + long nx = 1, ny = 1; + + if (specialnets && test ("DO")) { + + nx = std::max (0l, get_long ()); + test ("BY"); + ny = std::max (0l, get_long ()); + test ("STEP"); + dx = db::coord_traits::rounded (get_double () * scale); + dy = db::coord_traits::rounded (get_double () * scale); + + if (nx < 0) { + dx = -dx; + nx = -nx; + } + if (ny < 0) { + dy = -dy; + ny = -ny; + } + + } + + std::map::const_iterator vd = m_via_desc.find (vn); + if (vd != m_via_desc.end () && ! pts.empty ()) { + if (nx <= 1 && ny <= 1) { + design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); + } else { + design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())), db::Vector (dx, 0), db::Vector (0, dy), (unsigned long) nx, (unsigned long) ny)); + } + if (ln == vd->second.m1) { + ln = vd->second.m2; + } else if (ln == vd->second.m2) { + ln = vd->second.m1; + } + } + + if (! specialnets) { + w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); + def_ext = get_def_ext (ln, w, layout.dbu ()); + } + + // continue a segment with the current point and the new layer + if (pts.size () > 1) { + pts.erase (pts.begin (), pts.end () - 1); + } + + } else { + break; + } + + } + + } while (test ("NEW")); +} + void DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets) { @@ -367,7 +690,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool std::string net = get (); std::string nondefaultrule; std::string stored_netname, stored_nondefaultrule; - std::string taperrule; + db::properties_id_type stored_prop_id; bool in_subnet = false; db::properties_id_type prop_id = 0; @@ -389,6 +712,8 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool if (! specialnets && test ("SUBNET")) { + std::string subnetname = get (); + while (test ("(")) { while (! test (")")) { take (); @@ -398,7 +723,18 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool if (! in_subnet) { stored_netname = net; stored_nondefaultrule = nondefaultrule; + stored_prop_id = prop_id; in_subnet = true; + } else { + warn ("Nested subnets"); + } + + net = stored_netname + "/" + subnetname; + + if (produce_net_props ()) { + db::PropertiesRepository::properties_set props; + props.insert (std::make_pair (net_prop_name_id (), tl::Variant (net))); + prop_id = layout.properties_repository ().properties_id (props); } } else if (! specialnets && test ("NONDEFAULTRULE")) { @@ -411,329 +747,20 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool take (); } - do { - - std::string ln = get (); - - taperrule.clear (); - const std::string *rulename = 0; - - std::pair w (0, 0); - if (specialnets) { - db::Coord n = db::coord_traits::rounded (get_double () * scale); - w = std::make_pair (n, n); - } - - const db::Polygon *style = 0; - - int sn = std::numeric_limits::max (); - - if (specialnets) { - - while (test ("+")) { - - if (test ("STYLE")) { - sn = get_long (); - } else if (test ("SHAPE")) { - take (); - } - - } - - } else { - - while (true) { - if (test ("TAPER")) { - taperrule.clear (); - rulename = &taperrule; - } else if (test ("TAPERRULE")) { - taperrule = get (); - rulename = &taperrule; - } else if (test ("STYLE")) { - sn = get_long (); - } else { - break; - } - } - - } - - if (! rulename) { - rulename = &nondefaultrule; - } - - std::pair def_ext (0, 0); - - if (! specialnets) { - w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = get_def_ext (ln, w, layout.dbu ()); - } - - std::map::const_iterator s = m_styles.find (sn); - if (s != m_styles.end ()) { - style = &s->second; - } - - std::vector > ext; - std::vector pts; - - double x = 0.0, y = 0.0; - - while (true) { - - if (test ("MASK")) { - // ignore mask spec - get_long (); - } - - if (test ("RECT")) { - - if (! test ("(")) { - error (tl::to_string (tr ("RECT routing specification not followed by coordinate list"))); - } - - // breaks wiring - pts.clear (); - - // rect spec - - double x1 = get_double (); - double y1 = get_double (); - double x2 = get_double (); - double y2 = get_double (); - - test (")"); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - - db::Box rect (db::Point (db::DPoint ((x + x1) * scale, (y + y1) * scale)), - db::Point (db::DPoint ((x + x2) * scale, (y + y2) * scale))); - - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (rect, prop_id)); - } else { - design.shapes (dl.second).insert (rect); - } - - } - - } else if (test ("VIRTUAL")) { - - // virtual specs simply create a new segment - pts.clear (); - - } else if (peek ("(")) { - - ext.clear (); - - while (peek ("(") || peek ("MASK")) { - - if (test ("MASK")) { - // ignore MASK spec - get_long (); - } - - if (! test ("(")) { - // We could have a via here: in that case we have swallowed MASK already, but - // since we don't do anything with that, this does not hurt for now. - break; - } - - if (! test ("*")) { - x = get_double (); - } - if (! test ("*")) { - y = get_double (); - } - pts.push_back (db::Point (db::DPoint (x * scale, y * scale))); - std::pair ee = def_ext; - if (! peek (")")) { - db::Coord e = db::coord_traits::rounded (get_double () * scale); - ee.first = ee.second = e; - } - ext.push_back (ee); - - test (")"); - - } - - if (pts.size () > 1) { - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - - if (! style) { - - // Use the default style (octagon "pen" for non-manhattan segments, paths for - // horizontal/vertical segments). - // Manhattan paths are stitched together from two-point paths if they - - std::pair e = std::max (ext.front (), ext.back ()); - bool is_isotropic = (e.first == e.second && w.first == w.second); - bool was_path = false; - - std::vector::const_iterator pt = pts.begin (); - while (pt != pts.end ()) { - - std::vector::const_iterator pt0 = pt; - do { - ++pt; - } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); - - if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { - - if (pt - pt0 == 1) { - ++pt; - } - - db::Coord wxy, wxy_perp, exy; - - if (pt0->x () == pt0 [1].x ()) { - wxy = w.second; - wxy_perp = w.first; - exy = e.second; - } else { - wxy = w.first; - wxy_perp = w.second; - exy = e.first; - } - - db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - - if (pt == pts.end ()) { - break; - } - - --pt; - - was_path = true; - - } else { - - if (! is_isotropic) { - warn("Anisotropic wire widths not supported for diagonal wires"); - } - - db::Coord s = (w.first + 1) / 2; - db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); - - db::Point octagon[8] = { - db::Point (-s, t), - db::Point (-t, s), - db::Point (t, s), - db::Point (s, t), - db::Point (s, -t), - db::Point (t, -s), - db::Point (-t, -s), - db::Point (-s, -t) - }; - - db::Polygon k; - k.assign_hull (octagon, octagon + sizeof (octagon) / sizeof (octagon[0])); - - db::Polygon p = db::minkowsky_sum (k, db::Edge (*pt0, *pt)); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - - was_path = false; - - } - - } - - } else { - - for (size_t i = 0; i < pts.size () - 1; ++i) { - db::Polygon p = db::minkowsky_sum (*style, db::Edge (pts [i], pts [i + 1])); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } - - } - - } - - } else if (! peek ("NEW") && ! peek ("+") && ! peek ("-") && ! peek (";")) { - - // indicates a via - std::string vn = get (); - db::FTrans ft = get_orient (true /*optional*/); - - db::Coord dx = 0, dy = 0; - long nx = 1, ny = 1; - - if (specialnets && test ("DO")) { - - nx = std::max (0l, get_long ()); - test ("BY"); - ny = std::max (0l, get_long ()); - test ("STEP"); - dx = db::coord_traits::rounded (get_double () * scale); - dy = db::coord_traits::rounded (get_double () * scale); - - if (nx < 0) { - dx = -dx; - nx = -nx; - } - if (ny < 0) { - dy = -dy; - ny = -ny; - } - - } - - std::map::const_iterator vd = m_via_desc.find (vn); - if (vd != m_via_desc.end () && ! pts.empty ()) { - if (nx <= 1 && ny <= 1) { - design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); - } else { - design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())), db::Vector (dx, 0), db::Vector (0, dy), (unsigned long) nx, (unsigned long) ny)); - } - if (ln == vd->second.m1) { - ln = vd->second.m2; - } else if (ln == vd->second.m2) { - ln = vd->second.m1; - } - } - - if (! specialnets) { - w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = get_def_ext (ln, w, layout.dbu ()); - } - - // continue a segment with the current point and the new layer - if (pts.size () > 1) { - pts.erase (pts.begin (), pts.end () - 1); - } - - } else { - break; - } - - } - - } while (test ("NEW")); + read_single_net (nondefaultrule, layout, design, scale, prop_id, specialnets); if (in_subnet) { + in_subnet = false; + net = stored_netname; - stored_netname.clear (); nondefaultrule = stored_nondefaultrule; + prop_id = stored_prop_id; + + stored_netname.clear (); stored_nondefaultrule.clear (); + stored_prop_id = 0; + } } else if (test ("POLYGON")) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 13a8f90cb..6158da2cf 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -82,6 +82,7 @@ private: void read_pins (db::Layout &layout, db::Cell &design, double scale); void read_styles (double scale); void read_components (std::list > &instances, double scale); + void read_single_net (std::string &nondefaultrule, db::Layout &layout, db::Cell &design, double scale, properties_id_type prop_id, bool specialnets); }; } From 4757ad50449fce73d1341f030a4f8c9609fea84b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 4 Apr 2020 19:42:01 +0200 Subject: [PATCH 17/43] Some refactoring - DEF scanner more modular (4) --- .../lefdef/db_plugin/dbDEFImporter.cc | 209 +++++++++--------- .../lefdef/db_plugin/dbDEFImporter.h | 1 + 2 files changed, 106 insertions(+), 104 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 9486ab3ff..4d7da4147 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -359,6 +359,110 @@ DEFImporter::read_blockages (db::Layout &layout, db::Cell &design, double scale) } } +void +DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, unsigned int layer, properties_id_type prop_id, const std::vector &pts, const std::vector > &ext, std::pair w) +{ + if (! style) { + + // Use the default style (octagon "pen" for non-manhattan segments, paths for + // horizontal/vertical segments). + // Manhattan paths are stitched together from two-point paths if they + + std::pair e = std::max (ext.front (), ext.back ()); + bool is_isotropic = (e.first == e.second && w.first == w.second); + bool was_path = false; + + std::vector::const_iterator pt = pts.begin (); + while (pt != pts.end ()) { + + std::vector::const_iterator pt0 = pt; + do { + ++pt; + } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); + + if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { + + if (pt - pt0 == 1) { + ++pt; + } + + db::Coord wxy, wxy_perp, exy; + + if (pt0->x () == pt0 [1].x ()) { + wxy = w.second; + wxy_perp = w.first; + exy = e.second; + } else { + wxy = w.first; + wxy_perp = w.second; + exy = e.first; + } + + db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); + if (prop_id != 0) { + design.shapes (layer).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (layer).insert (p); + } + + if (pt == pts.end ()) { + break; + } + + --pt; + + was_path = true; + + } else { + + if (! is_isotropic) { + warn("Anisotropic wire widths not supported for diagonal wires"); + } + + db::Coord s = (w.first + 1) / 2; + db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); + + db::Point octagon[8] = { + db::Point (-s, t), + db::Point (-t, s), + db::Point (t, s), + db::Point (s, t), + db::Point (s, -t), + db::Point (t, -s), + db::Point (-t, -s), + db::Point (-s, -t) + }; + + db::Polygon k; + k.assign_hull (octagon, octagon + sizeof (octagon) / sizeof (octagon[0])); + + db::Polygon p = db::minkowsky_sum (k, db::Edge (*pt0, *pt)); + if (prop_id != 0) { + design.shapes (layer).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (layer).insert (p); + } + + was_path = false; + + } + + } + + } else { + + for (size_t i = 0; i < pts.size () - 1; ++i) { + db::Polygon p = db::minkowsky_sum (*style, db::Edge (pts [i], pts [i + 1])); + if (prop_id != 0) { + design.shapes (layer).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (layer).insert (p); + } + } + + } +} + void DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::Cell &design, double scale, db::properties_id_type prop_id, bool specialnets) { @@ -512,112 +616,10 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C } if (pts.size () > 1) { - std::pair dl = open_layer (layout, ln, Routing); if (dl.first) { - - if (! style) { - - // Use the default style (octagon "pen" for non-manhattan segments, paths for - // horizontal/vertical segments). - // Manhattan paths are stitched together from two-point paths if they - - std::pair e = std::max (ext.front (), ext.back ()); - bool is_isotropic = (e.first == e.second && w.first == w.second); - bool was_path = false; - - std::vector::const_iterator pt = pts.begin (); - while (pt != pts.end ()) { - - std::vector::const_iterator pt0 = pt; - do { - ++pt; - } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); - - if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { - - if (pt - pt0 == 1) { - ++pt; - } - - db::Coord wxy, wxy_perp, exy; - - if (pt0->x () == pt0 [1].x ()) { - wxy = w.second; - wxy_perp = w.first; - exy = e.second; - } else { - wxy = w.first; - wxy_perp = w.second; - exy = e.first; - } - - db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - - if (pt == pts.end ()) { - break; - } - - --pt; - - was_path = true; - - } else { - - if (! is_isotropic) { - warn("Anisotropic wire widths not supported for diagonal wires"); - } - - db::Coord s = (w.first + 1) / 2; - db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); - - db::Point octagon[8] = { - db::Point (-s, t), - db::Point (-t, s), - db::Point (t, s), - db::Point (s, t), - db::Point (s, -t), - db::Point (t, -s), - db::Point (-t, -s), - db::Point (-s, -t) - }; - - db::Polygon k; - k.assign_hull (octagon, octagon + sizeof (octagon) / sizeof (octagon[0])); - - db::Polygon p = db::minkowsky_sum (k, db::Edge (*pt0, *pt)); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - - was_path = false; - - } - - } - - } else { - - for (size_t i = 0; i < pts.size () - 1; ++i) { - db::Polygon p = db::minkowsky_sum (*style, db::Edge (pts [i], pts [i + 1])); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } - + produce_routing_geometry (design, style, dl.second, prop_id, pts, ext, w); } - } } else if (! peek ("NEW") && ! peek ("+") && ! peek ("-") && ! peek (";")) { @@ -1467,4 +1469,3 @@ DEFImporter::do_read (db::Layout &layout) } } - diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 6158da2cf..8e4a29b78 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -83,6 +83,7 @@ private: void read_styles (double scale); void read_components (std::list > &instances, double scale); void read_single_net (std::string &nondefaultrule, db::Layout &layout, db::Cell &design, double scale, properties_id_type prop_id, bool specialnets); + void produce_routing_geometry (db::Cell &design, const db::Polygon *style, unsigned int layer, properties_id_type prop_id, const std::vector &pts, const std::vector > &ext, std::pair w); }; } From cd801206bc17882795e83e51cd623a4182fdacc3 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 4 Apr 2020 20:28:15 +0200 Subject: [PATCH 18/43] Some refactoring - DEF scanner more modular (5) --- .../lefdef/db_plugin/dbDEFImporter.cc | 89 ++++++++----------- .../lefdef/db_plugin/dbDEFImporter.h | 2 + 2 files changed, 37 insertions(+), 54 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 4d7da4147..9414c9aeb 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -92,6 +92,22 @@ DEFImporter::get_orient (bool optional) } } +db::Point +DEFImporter::get_point (double scale) +{ + double x = get_double (); + double y = get_double (); + return db::Point (db::DPoint (x * scale, y * scale)); +} + +db::Vector +DEFImporter::get_vector (double scale) +{ + double x = get_double (); + double y = get_double (); + return db::Vector (db::DVector (x * scale, y * scale)); +} + void DEFImporter::read_polygon (db::Polygon &poly, double scale) { @@ -119,18 +135,12 @@ DEFImporter::read_polygon (db::Polygon &poly, double scale) void DEFImporter::read_rect (db::Polygon &poly, double scale) { - double x = 0.0, y = 0.0; - test ("("); - x = get_double (); - y = get_double (); - db::Point pt1 = db::Point (db::DPoint (x * scale, y * scale)); + db::Point pt1 = get_point (scale); test (")"); test ("("); - x = get_double (); - y = get_double (); - db::Point pt2 = db::Point (db::DPoint (x * scale, y * scale)); + db::Point pt2 = get_point (scale); test (")"); poly = db::Polygon (db::Box (pt1, pt2)); @@ -174,13 +184,11 @@ DEFImporter::get_def_ext (const std::string &ln, const std::pair points; + std::vector points; while (! test (";")) { test ("("); - double x = get_double (); - double y = get_double (); - points.push_back (db::DPoint (x * scale, y * scale)); + points.push_back (get_point (scale)); test (")"); } @@ -190,11 +198,11 @@ DEFImporter::read_diearea (db::Layout &layout, db::Cell &design, double scale) std::pair dl = open_layer (layout, std::string (), Outline); if (dl.first) { if (points.size () == 2) { - design.shapes (dl.second).insert (db::Box (db::DBox (points [0], points [1]))); + design.shapes (dl.second).insert (db::Box (points [0], points [1])); } else { - db::DPolygon p; + db::Polygon p; p.assign_hull (points.begin (), points.end ()); - design.shapes (dl.second).insert (db::Polygon (p)); + design.shapes (dl.second).insert (p); } } @@ -564,6 +572,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C std::pair dl = open_layer (layout, ln, Routing); if (dl.first) { + db::Point p (x, y); db::Box rect (db::Point (db::DPoint ((x + x1) * scale, (y + y1) * scale)), db::Point (db::DPoint ((x + x2) * scale, (y + y2) * scale))); @@ -837,8 +846,6 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) while (test ("+")) { - double x, y; - if (test ("VIARULE")) { has_via_rule = true; @@ -846,41 +853,25 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) } else if (test ("CUTSIZE")) { - x = get_double (); - y = get_double (); - cutsize = db::Vector (db::DVector (x * scale, y * scale)); + cutsize = get_vector (scale); } else if (test ("CUTSPACING")) { - x = get_double (); - y = get_double (); - cutspacing = db::Vector (db::DVector (x * scale, y * scale)); + cutspacing = get_vector (scale); } else if (test ("ORIGIN")) { - x = get_double (); - y = get_double (); - offset = db::Point (db::DPoint (x * scale, y * scale)); + offset = get_point (scale); } else if (test ("ENCLOSURE")) { - x = get_double (); - y = get_double (); - be = db::Vector (db::DVector (x * scale, y * scale)); - - x = get_double (); - y = get_double (); - te = db::Vector (db::DVector (x * scale, y * scale)); + be = get_vector (scale); + te = get_vector (scale); } else if (test ("OFFSET")) { - x = get_double (); - y = get_double (); - bo = db::Vector (db::DVector (x * scale, y * scale)); - - x = get_double (); - y = get_double (); - to = db::Vector (db::DVector (x * scale, y * scale)); + bo = get_vector (scale); + to = get_vector (scale); } else if (test ("ROWCOL")) { @@ -1000,18 +991,12 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale) take (); } - double x, y; - test ("("); - x = get_double (); - y = get_double (); - db::Point pt1 = db::Point (db::DPoint (x * scale, y * scale)); + db::Point pt1 = get_point (scale); test (")"); test ("("); - x = get_double (); - y = get_double (); - db::Point pt2 = db::Point (db::DPoint (x * scale, y * scale)); + db::Point pt2 = get_point (scale); test (")"); geometry.insert (std::make_pair (ln, std::vector ())).first->second.push_back (db::Polygon (db::Box (pt1, pt2))); @@ -1049,9 +1034,7 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale) } else if (test ("PLACED") || test ("FIXED") || test ("COVER")) { test ("("); - double x = get_double (); - double y = get_double (); - db::Vector d = db::Vector (db::DVector (x * scale, y * scale)); + db::Vector d = get_vector (scale); test (")"); db::FTrans ft = get_orient (false /*mandatory*/); @@ -1172,9 +1155,7 @@ DEFImporter::read_components (std::list > if (test ("PLACED") || test ("FIXED") || test ("COVER")) { test ("("); - double x = get_double (); - double y = get_double (); - db::Point pt = db::Point (db::DPoint (x * scale, y * scale)); + db::Point pt = get_point (scale); test (")"); db::FTrans ft = get_orient (false /*mandatory*/); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 8e4a29b78..0a0b5b0ba 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -84,6 +84,8 @@ private: void read_components (std::list > &instances, double scale); void read_single_net (std::string &nondefaultrule, db::Layout &layout, db::Cell &design, double scale, properties_id_type prop_id, bool specialnets); void produce_routing_geometry (db::Cell &design, const db::Polygon *style, unsigned int layer, properties_id_type prop_id, const std::vector &pts, const std::vector > &ext, std::pair w); + db::Point get_point (double scale); + db::Vector get_vector (double scale); }; } From df7c530013bdde6226c981c3f8742995e5606199 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 5 Apr 2020 22:56:04 +0200 Subject: [PATCH 19/43] Bugfix for the net reader of DEF - wasn't properly reading diagonal parts. --- .../lefdef/db_plugin/dbDEFImporter.cc | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 9414c9aeb..657f7e581 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -374,7 +374,8 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u // Use the default style (octagon "pen" for non-manhattan segments, paths for // horizontal/vertical segments). - // Manhattan paths are stitched together from two-point paths if they + // Manhattan paths are stitched together from two-point paths if the + // horizontal and vertical width is different. std::pair e = std::max (ext.front (), ext.back ()); bool is_isotropic = (e.first == e.second && w.first == w.second); @@ -384,15 +385,25 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u while (pt != pts.end ()) { std::vector::const_iterator pt0 = pt; - do { - ++pt; - } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); + ++pt; + if (pt == pts.end ()) { + break; + } - if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { - - if (pt - pt0 == 1) { + bool multipart = false; + if (is_isotropic) { + while (pt != pts.end () && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())) { ++pt; + multipart = true; } + if (multipart) { + --pt; + } + } + + // The next part is the interval [pt0..pt] (pt inclusive) + + if (multipart || (pt0->x () == pt0[1].x () || pt0->y () == pt0[1].y())) { db::Coord wxy, wxy_perp, exy; @@ -406,19 +417,13 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u exy = e.first; } - db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); + db::Path p (pt0, pt + 1, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt + 1 == pts.end () ? exy : 0, false); if (prop_id != 0) { design.shapes (layer).insert (db::object_with_properties (p, prop_id)); } else { design.shapes (layer).insert (p); } - if (pt == pts.end ()) { - break; - } - - --pt; - was_path = true; } else { From 3ada29d6067b671682218b77a07ece5dda9a0220 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 5 Apr 2020 23:49:19 +0200 Subject: [PATCH 20/43] Some bugfixes for LEF/DEF reader for special nets (extension handling) --- .../lefdef/db_plugin/dbDEFImporter.cc | 35 ++++++++++++------ .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 6 +++ testdata/lefdef/specialnets_geo/au.oas.gz | Bin 337 -> 337 bytes 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 657f7e581..4b65f2ade 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -377,9 +377,8 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u // Manhattan paths are stitched together from two-point paths if the // horizontal and vertical width is different. - std::pair e = std::max (ext.front (), ext.back ()); - bool is_isotropic = (e.first == e.second && w.first == w.second); - bool was_path = false; + bool is_isotropic = (w.first == w.second); + bool was_path_before = false; std::vector::const_iterator pt = pts.begin (); while (pt != pts.end ()) { @@ -405,26 +404,39 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u if (multipart || (pt0->x () == pt0[1].x () || pt0->y () == pt0[1].y())) { - db::Coord wxy, wxy_perp, exy; + db::Coord wxy, wxy_perp; if (pt0->x () == pt0 [1].x ()) { wxy = w.second; wxy_perp = w.first; - exy = e.second; } else { wxy = w.first; wxy_perp = w.second; - exy = e.first; } - db::Path p (pt0, pt + 1, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt + 1 == pts.end () ? exy : 0, false); + // compute begin extension + db::Coord be = 0; + if (pt0 == pts.begin ()) { + be = ext.front ().first; + } else if (was_path_before) { + // provides the overlap to the previous segment + be = wxy_perp / 2; + } + + // compute end extension + db::Coord ee = 0; + if (pt + 1 == pts.end ()) { + ee = ext.back ().first; + } + + db::Path p (pt0, pt + 1, wxy, be, ee, false); if (prop_id != 0) { design.shapes (layer).insert (db::object_with_properties (p, prop_id)); } else { design.shapes (layer).insert (p); } - was_path = true; + was_path_before = true; } else { @@ -456,7 +468,7 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u design.shapes (layer).insert (p); } - was_path = false; + was_path_before = false; } @@ -596,8 +608,6 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C } else if (peek ("(")) { - ext.clear (); - while (peek ("(") || peek ("MASK")) { if (test ("MASK")) { @@ -689,6 +699,9 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C pts.erase (pts.begin (), pts.end () - 1); } + ext.clear (); + ext.push_back (def_ext); + } else { break; } diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index fd9b1b896..5ff589fb1 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -112,6 +112,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file tl::OutputStream stream (tmp_file); db::SaveLayoutOptions options; options.set_format ("OASIS"); + options.set_option_by_name ("oasis_permissive", tl::Variant (true)); db::Writer writer (options); writer.write (layout, stream); } @@ -244,6 +245,11 @@ TEST(20) run_test (_this, "def11", "lef:test.lef+def:test.def", "au.oas.gz", default_options ()); } +TEST(21) +{ + run_test (_this, "def12", "lef:test.lef+def:test.def", "au.oas.gz", default_options ()); +} + TEST(100) { run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false); diff --git a/testdata/lefdef/specialnets_geo/au.oas.gz b/testdata/lefdef/specialnets_geo/au.oas.gz index 994644702511b980169ee5e6379707783cf41b93..9a20c2234753451d7489d7dc87b5c1710ecb9b94 100644 GIT binary patch delta 73 zcmV-P0Ji_p0?`5uABzYGUQdc%00VSwaFGn%0m+f-B_XqmFap(qq%2t2Pca>0I>FSy fe~#%G(;22Mj8~XI!bm!kF##9|rE;c>lL7z$3ymB< delta 73 zcmV-P0Ji_p0?`5tABzYG+OUIO00UulkqzAe#gXeJBJ+!gFai~V0I>FSy fe~#%G(;22Mj8~XI!bn<^F##9|7~`e>lmY+%J98aZ From 9c62bb015f481c62d55e3b6a4bc65aa70a41ad5b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 5 Apr 2020 23:56:43 +0200 Subject: [PATCH 21/43] Include BLOCKAGE in map file LEF/DEF, becoming case insensitive for purpose --- src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index bd79bb5af..8ffdc60df 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -101,6 +101,7 @@ read_map_file (const std::string &path, db::LEFDEFLayerDelegate &layers) purpose_translation ["SPNET"] = "NET"; purpose_translation ["NET"] = "NET"; purpose_translation ["VIA"] = "VIA"; + purpose_translation ["BLOCKAGE"] = "BLK"; while (! ts.at_end ()) { @@ -156,7 +157,7 @@ read_map_file (const std::string &path, db::LEFDEFLayerDelegate &layers) std::vector translated_purposes; std::vector purposes = tl::split (w2, ","); for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { - std::map::const_iterator i = purpose_translation.find (*p); + std::map::const_iterator i = purpose_translation.find (tl::to_upper_case (*p)); if (i != purpose_translation.end ()) { translated_purposes.push_back (i->second); } From 61714090e3e6f85c143ddde107a818d80c5ef2fd Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 14 Apr 2020 22:48:18 +0200 Subject: [PATCH 22/43] Maybe fixed performance issue: usually it's not a good idea to iterate the layout's hierarchy while deleting something from it. --- src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 4b65f2ade..fb3902d48 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -1397,6 +1397,8 @@ DEFImporter::do_read (db::Layout &layout) if (! groups.empty ()) { + db::LayoutLocker locker (&layout); + others_cell = &layout.cell (layout.add_cell ("NOGROUP")); design.insert (db::CellInstArray (others_cell->cell_index (), db::Trans ())); From 921af5264327fcfb013ff7ce3d2831793b2d44dc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 14 Apr 2020 23:15:08 +0200 Subject: [PATCH 23/43] DEF reader bugfix: wasn't reading SPECIALNETS + ROUTED + RECT --- .../lefdef/db_plugin/dbDEFImporter.cc | 101 +++++++++++------- testdata/lefdef/specialnets_geo/test.def | 3 +- 2 files changed, 62 insertions(+), 42 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index fb3902d48..08edc10cc 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -770,15 +770,70 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool nondefaultrule = get (); - } else if ((was_shield = test ("SHIELD")) == true || test ("NOSHIELD") || test ("ROUTED") || test ("FIXED") || test ("COVER")) { + } else { - if (was_shield) { - take (); + bool prefixed = false; + + if ((was_shield = test ("SHIELD")) == true || test ("NOSHIELD") || test ("ROUTED") || test ("FIXED") || test ("COVER")) { + if (was_shield) { + take (); + } + prefixed = true; } - read_single_net (nondefaultrule, layout, design, scale, prop_id, specialnets); + bool any = false; - if (in_subnet) { + if (test ("POLYGON")) { + + std::string ln = get (); + + db::Polygon p; + read_polygon (p, scale); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + any = true; + + } else if (test ("RECT")) { + + std::string ln = get (); + + db::Polygon p; + read_rect (p, scale); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + any = true; + + } else if (prefixed) { + + read_single_net (nondefaultrule, layout, design, scale, prop_id, specialnets); + any = true; + + } else { + + // lazily skip everything else + while (! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + + } + + if (any && in_subnet) { in_subnet = false; @@ -792,42 +847,6 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool } - } else if (test ("POLYGON")) { - - std::string ln = get (); - - db::Polygon p; - read_polygon (p, scale); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } else if (test ("RECT")) { - - std::string ln = get (); - - db::Polygon p; - read_rect (p, scale); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } else { - while (! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } } } diff --git a/testdata/lefdef/specialnets_geo/test.def b/testdata/lefdef/specialnets_geo/test.def index 2874f0491..0686c4fec 100644 --- a/testdata/lefdef/specialnets_geo/test.def +++ b/testdata/lefdef/specialnets_geo/test.def @@ -16,8 +16,9 @@ VIAS 1 ; END VIAS SPECIALNETS 1 ; - dummy + + ROUTED RECT M2 ( 350 0 ) ( 200 100 ) + POLYGON M1 ( 300 0 ) ( 300 50 ) ( 350 50 ) ( 400 100 ) ( 400 0 ) - + POLYGON M2 ( 300 150 ) ( 300 200 ) ( 350 200 ) ( 400 250 ) ( 400 150 ) + + ROUTED POLYGON M2 ( 300 150 ) ( 300 200 ) ( 350 200 ) ( 400 250 ) ( 400 150 ) + RECT M1 ( 0 0 ) ( 100 200 ) + ROUTED M1 30 ( 0 0 15 ) ( 100 0 0 ) VIA1_dummy ( 100 100 10 ) + ROUTED M2 50 + SHAPE RING + STYLE 1 ( 0 100 ) ( 100 200 ) ( 200 200 ) From d4a333966b4d108530d37c2496d3aeb62d422551 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 14 Apr 2020 23:16:43 +0200 Subject: [PATCH 24/43] Updated testdata for last patch. --- testdata/lefdef/specialnets_geo/au.oas.gz | Bin 337 -> 346 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/testdata/lefdef/specialnets_geo/au.oas.gz b/testdata/lefdef/specialnets_geo/au.oas.gz index 9a20c2234753451d7489d7dc87b5c1710ecb9b94..cffe301036e98a0a255fff963ec96a3908949e8a 100644 GIT binary patch delta 62 zcmV-E0Kxy!0@?xxABzYG7bupo2POe6;KCjJ2be&@J^Z3QAjOPKCm7cN4P^kSKr(X; UlPpuiNCpfH08r9-!k+>F0HVbd-v9sr delta 53 zcmV-50LuT`0?`5oABzYGUQdd#2POd|K*C5m)-b`lL7z$9d;D2 From 54cf57c7728f46bbfcdabecbba32b32e6106ffc4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 18 Apr 2020 17:58:50 +0200 Subject: [PATCH 25/43] LEF/DEF enhancements (via cellname suffix configurable, group separation disabled by default) Two new reader options: 1.) via cell name prefix (default is "VIA_"). This name is put in front of the via name to form the cell cell name 2.) group separation disabled by default. Groups are not put into individual parent cells by default. --- .../lefdef/db_plugin/dbDEFImporter.cc | 35 +++++++++-- .../lefdef/db_plugin/dbDEFImporter.h | 2 +- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 52 ++++++++++----- .../lefdef/db_plugin/dbLEFDEFImporter.h | 63 ++++++++++++++++--- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 24 +++---- .../lefdef/db_plugin/dbLEFImporter.cc | 17 +++-- .../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 26 ++++++++ .../LEFDEFTechnologyComponentEditor.ui | 53 ++++++++++++---- .../lefdef/lay_plugin/layLEFDEFImport.cc | 2 +- .../lay_plugin/layLEFDEFImportDialogs.cc | 4 ++ .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 8 ++- testdata/ruby/dbReaders.rb | 8 +++ 12 files changed, 230 insertions(+), 64 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 4b65f2ade..806259f55 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -59,9 +59,9 @@ DEFImporter::DEFImporter () } void -DEFImporter::read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDelegate &ld) +DEFImporter::read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state) { - m_lef_importer.read (stream, layout, ld); + m_lef_importer.read (stream, layout, state); } @@ -846,8 +846,9 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) ViaDesc &vd = m_via_desc.insert (std::make_pair (n, ViaDesc ())).first->second; // produce a cell for vias - std::string cellname = "VIA_" + n; + std::string cellname = options ().via_cellname_prefix () + n; db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ())); + reader_state ()->register_via_cell (n, &cell); vd.cell = &cell; bool has_via_rule = false; @@ -1395,7 +1396,7 @@ DEFImporter::do_read (db::Layout &layout) db::Cell *others_cell = &design; - if (! groups.empty ()) { + if (! groups.empty () && options ().separate_groups ()) { others_cell = &layout.cell (layout.add_cell ("NOGROUP")); design.insert (db::CellInstArray (others_cell->cell_index (), db::Trans ())); @@ -1410,16 +1411,21 @@ DEFImporter::do_read (db::Layout &layout) if (! g->region_name.empty ()) { - std::map >::const_iterator r = regions.find (g->region_name); + std::map >::iterator r = regions.find (g->region_name); if (r == regions.end ()) { - warn (tl::sprintf (tl::to_string (tr ("Not a valid region name: %s in group %s")), g->region_name, g->name)); + + warn (tl::sprintf (tl::to_string (tr ("Not a valid region name or region is already used: %s in group %s")), g->region_name, g->name)); + } else { + std::pair dl = open_layer (layout, std::string (), Region); if (dl.first) { for (std::vector::const_iterator p = r->second.begin (); p != r->second.end (); ++p) { group_cell->shapes (dl.second).insert (*p); } } + regions.erase (r); + } } @@ -1451,6 +1457,23 @@ DEFImporter::do_read (db::Layout &layout) } + // put all remaining regions into the "others_cell" which is the top cell if there are no groups. + + if (! regions.empty ()) { + + std::pair dl = open_layer (layout, std::string (), Region); + if (dl.first) { + + for (std::map >::const_iterator r = regions.begin (); r != regions.end (); ++r) { + for (std::vector::const_iterator p = r->second.begin (); p != r->second.end (); ++p) { + others_cell->shapes (dl.second).insert (*p); + } + } + + } + + } + // treat all remaining cells and put them into the "others_cell" which is the top cell // if there are no groups. diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 0a0b5b0ba..b0f421ad8 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -56,7 +56,7 @@ public: * 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, LEFDEFLayerDelegate &ld); + void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state); protected: void do_read (db::Layout &layout); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index eb895007b..a574da6a7 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -52,6 +52,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_produce_via_geometry (true), m_via_geometry_suffix (""), m_via_geometry_datatype (0), + m_via_cellname_prefix ("VIA_"), m_produce_pins (true), m_pins_suffix (".PIN"), m_pins_datatype (2), @@ -66,7 +67,8 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_labels_datatype (1), m_produce_routing (true), m_routing_suffix (""), - m_routing_datatype (0) + m_routing_datatype (0), + m_separate_groups (false) { // .. nothing yet .. } @@ -90,6 +92,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_produce_via_geometry (d.m_produce_via_geometry), m_via_geometry_suffix (d.m_via_geometry_suffix), m_via_geometry_datatype (d.m_via_geometry_datatype), + m_via_cellname_prefix (d.m_via_cellname_prefix), m_produce_pins (d.m_produce_pins), m_pins_suffix (d.m_pins_suffix), m_pins_datatype (d.m_pins_datatype), @@ -105,6 +108,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_produce_routing (d.m_produce_routing), m_routing_suffix (d.m_routing_suffix), m_routing_datatype (d.m_routing_datatype), + m_separate_groups (d.m_separate_groups), m_lef_files (d.m_lef_files) { // .. nothing yet .. @@ -126,7 +130,7 @@ LEFDEFReaderOptions::format_name () const // ----------------------------------------------------------------------------------- // LEFDEFLayerDelegate implementation -LEFDEFLayerDelegate::LEFDEFLayerDelegate (const LEFDEFReaderOptions *tc) +LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc) : m_create_layers (true), m_laynum (1), mp_tech_comp (tc) { if (tc) { @@ -136,14 +140,14 @@ LEFDEFLayerDelegate::LEFDEFLayerDelegate (const LEFDEFReaderOptions *tc) } void -LEFDEFLayerDelegate::register_layer (const std::string &ln) +LEFDEFReaderState::register_layer (const std::string &ln) { m_default_number.insert (std::make_pair (ln, m_laynum)); ++m_laynum; } std::pair -LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose) +LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose) { if (purpose == Outline || purpose == PlacementBlockage || purpose == Region) { @@ -327,13 +331,13 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer } void -LEFDEFLayerDelegate::prepare (db::Layout &layout) +LEFDEFReaderState::prepare (db::Layout &layout) { m_layer_map.prepare (layout); } void -LEFDEFLayerDelegate::finish (db::Layout &layout) +LEFDEFReaderState::finish (db::Layout &layout) { int lnum = 0; @@ -393,11 +397,24 @@ LEFDEFLayerDelegate::finish (db::Layout &layout) } } +void +LEFDEFReaderState::register_via_cell (const std::string &vn, db::Cell *cell) +{ + m_via_cells [vn] = cell; +} + +db::Cell * +LEFDEFReaderState::via_cell (const std::string &vn) +{ + std::map::const_iterator i = m_via_cells.find (vn); + return i != m_via_cells.end () ? i->second : 0; +} + // ----------------------------------------------------------------------------------- // LEFDEFImporter implementation LEFDEFImporter::LEFDEFImporter () - : mp_progress (0), mp_stream (0), mp_layer_delegate (0), + : mp_progress (0), mp_stream (0), mp_reader_state (0), m_produce_net_props (false), m_net_prop_name_id (0), m_produce_inst_props (false), m_inst_prop_name_id (0), m_produce_pin_props (false), m_pin_prop_name_id (0) @@ -411,7 +428,7 @@ LEFDEFImporter::~LEFDEFImporter () } void -LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDelegate &ld) +LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state) { m_fn = stream.filename (); @@ -420,34 +437,39 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDe progress.set_format_unit (1000.0); progress.set_unit (10000.0); + mp_reader_state = &state; + + if (state.tech_comp ()) { + m_options = *state.tech_comp (); + } + m_produce_net_props = false; m_net_prop_name_id = 0; - if (ld.tech_comp () && ld.tech_comp ()->produce_net_names ()) { + if (m_options.produce_net_names ()) { m_produce_net_props = true; - m_net_prop_name_id = layout.properties_repository ().prop_name_id (ld.tech_comp ()->net_property_name ()); + m_net_prop_name_id = layout.properties_repository ().prop_name_id (m_options.net_property_name ()); } m_produce_inst_props = false; m_inst_prop_name_id = 0; - if (ld.tech_comp () && ld.tech_comp ()->produce_inst_names ()) { + if (m_options.produce_inst_names ()) { m_produce_inst_props = true; - m_inst_prop_name_id = layout.properties_repository ().prop_name_id (ld.tech_comp ()->inst_property_name ()); + m_inst_prop_name_id = layout.properties_repository ().prop_name_id (m_options.inst_property_name ()); } m_produce_pin_props = false; m_pin_prop_name_id = 0; - if (ld.tech_comp () && ld.tech_comp ()->produce_pin_names ()) { + if (m_options.produce_pin_names ()) { m_produce_pin_props = true; - m_pin_prop_name_id = layout.properties_repository ().prop_name_id (ld.tech_comp ()->pin_property_name ()); + m_pin_prop_name_id = layout.properties_repository ().prop_name_id (m_options.pin_property_name ()); } try { mp_progress = &progress; - mp_layer_delegate = &ld; mp_stream = new tl::TextInputStream (stream); do_read (layout); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index fe4e40b6b..c6ca07a68 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -255,6 +255,16 @@ public: m_via_geometry_datatype = s; } + const std::string &via_cellname_prefix () const + { + return m_via_cellname_prefix; + } + + void set_via_cellname_prefix (const std::string &s) + { + m_via_cellname_prefix = s; + } + bool produce_pins () const { return m_produce_pins; @@ -435,6 +445,16 @@ public: m_lef_files = lf; } + bool separate_groups () const + { + return m_separate_groups; + } + + void set_separate_groups (bool f) + { + m_separate_groups = f; + } + private: bool m_read_all_layers; db::LayerMap m_layer_map; @@ -454,6 +474,7 @@ private: bool m_produce_via_geometry; std::string m_via_geometry_suffix; int m_via_geometry_datatype; + std::string m_via_cellname_prefix; bool m_produce_pins; std::string m_pins_suffix; int m_pins_datatype; @@ -469,6 +490,7 @@ private: bool m_produce_routing; std::string m_routing_suffix; int m_routing_datatype; + bool m_separate_groups; std::vector m_lef_files; }; @@ -493,13 +515,13 @@ enum LayerPurpose * * This class will handle the creation and management of layers in the LEF/DEF reader context */ -class DB_PLUGIN_PUBLIC LEFDEFLayerDelegate +class DB_PLUGIN_PUBLIC LEFDEFReaderState { public: /** * @brief Constructor */ - LEFDEFLayerDelegate (const LEFDEFReaderOptions *tc); + LEFDEFReaderState (const LEFDEFReaderOptions *tc); /** * @brief Set the layer map @@ -546,6 +568,16 @@ public: */ void finish (db::Layout &layout); + /** + * @brief Registers a via cell for the via with the given name + */ + void register_via_cell (const std::string &vn, db::Cell *cell); + + /** + * @brief Gets the via cell for the given via name or 0 if no such via is registered + */ + db::Cell *via_cell (const std::string &vn); + /** * @brief Get the technology component pointer */ @@ -560,6 +592,7 @@ private: bool m_create_layers; int m_laynum; std::map m_default_number; + std::map m_via_cells; const LEFDEFReaderOptions *mp_tech_comp; }; @@ -602,7 +635,7 @@ public: * * This method reads the layout specified into the given layout */ - void read (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDelegate &layer_delegate); + void read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state); protected: /** @@ -677,7 +710,7 @@ protected: */ std::pair open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose) { - return mp_layer_delegate->open_layer (layout, name, purpose); + return mp_reader_state->open_layer (layout, name, purpose); } /** @@ -685,7 +718,7 @@ protected: */ void register_layer (const std::string &l) { - mp_layer_delegate->register_layer (l); + mp_reader_state->register_layer (l); } /** @@ -752,7 +785,22 @@ protected: return m_pin_prop_name_id; } -protected: + /** + * @brief Gets the reader options + */ + const db::LEFDEFReaderOptions &options () const + { + return m_options; + } + + /** + * @brief Gets the reader state object + */ + db::LEFDEFReaderState *reader_state () + { + return mp_reader_state; + } + void create_generated_via (std::vector &bottom, std::vector &cut, std::vector &top, @@ -767,7 +815,7 @@ protected: private: tl::AbsoluteProgress *mp_progress; tl::TextInputStream *mp_stream; - LEFDEFLayerDelegate *mp_layer_delegate; + LEFDEFReaderState *mp_reader_state; std::string m_cellname; std::string m_fn; std::string m_last_token; @@ -777,6 +825,7 @@ private: db::property_names_id_type m_inst_prop_name_id; bool m_produce_pin_props; db::property_names_id_type m_pin_prop_name_id; + db::LEFDEFReaderOptions m_options; const std::string &next (); }; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 8ffdc60df..e7e7f168c 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -84,7 +84,7 @@ static bool is_def_format (const std::string &fn) * the map file. */ static void -read_map_file (const std::string &path, db::LEFDEFLayerDelegate &layers) +read_map_file (const std::string &path, db::LEFDEFReaderState &layers) { tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path; @@ -186,7 +186,7 @@ read_map_file (const std::string &path, db::LEFDEFLayerDelegate &layers) * @brief Imports a .map file present next to the input files */ static void -import_map_file_heuristics (const std::string &main_path, db::LEFDEFLayerDelegate &layers) +import_map_file_heuristics (const std::string &main_path, db::LEFDEFReaderState &layers) { std::string input_dir = tl::absolute_path (main_path); if (! tl::file_exists (input_dir)) { @@ -273,11 +273,11 @@ private: } // Take the layer map and the "read all layers" flag from the reader options - hence we override the - db::LEFDEFLayerDelegate layers (lefdef_options); + db::LEFDEFReaderState state (lefdef_options); - import_map_file_heuristics (m_stream.absolute_path (), layers); + import_map_file_heuristics (m_stream.absolute_path (), state); - layers.prepare (layout); + state.prepare (layout); layout.dbu (lefdef_options->dbu ()); if (import_lef) { @@ -292,12 +292,12 @@ private: tl::InputStream lef_stream (lp); tl::log << tl::to_string (tr ("Reading")) << " " << lp; - importer.read (lef_stream, layout, layers); + importer.read (lef_stream, layout, state); } tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source (); - importer.read (m_stream, layout, layers); + importer.read (m_stream, layout, state); } else { @@ -311,7 +311,7 @@ private: tl::InputStream lef_stream (lp); tl::log << tl::to_string (tr ("Reading")) << " " << lp; - importer.read_lef (lef_stream, layout, layers); + importer.read_lef (lef_stream, layout, state); } @@ -330,7 +330,7 @@ private: std::string lp = tl::combine_path (input_dir, *e); tl::InputStream lef_stream (lp); tl::log << tl::to_string (tr ("Reading")) << " " << lp; - importer.read_lef (lef_stream, layout, layers); + importer.read_lef (lef_stream, layout, state); } @@ -339,13 +339,13 @@ private: } tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source (); - importer.read (m_stream, layout, layers); + importer.read (m_stream, layout, state); } - layers.finish (layout); + state.finish (layout); - m_layer_map = layers.layer_map (); + m_layer_map = state.layer_map (); return m_layer_map; } }; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index cb5995b1d..72f6140da 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -345,20 +345,18 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p points.push_back (db::Vector (db::DVector (x / dbu, y / dbu))); std::string vn = get (); - std::pair cn = layout.cell_by_name (("VIA_" + vn).c_str ()); - if (! cn.first) { + db::Cell *vc = reader_state ()->via_cell (vn); + if (! vc) { warn ("Unknown via: " + vn); } if (iterate) { std::vector ti = get_iteration (layout); - if (cn.first) { - for (std::vector::const_iterator t = ti.begin (); t != ti.end (); ++t) { - cell.insert (db::CellInstArray (db::CellInst (cn.second), *t * db::Trans (points [0]))); - } + for (std::vector::const_iterator t = ti.begin (); t != ti.end (); ++t) { + cell.insert (db::CellInstArray (db::CellInst (vc->cell_index ()), *t * db::Trans (points [0]))); } - } else if (cn.first) { - cell.insert (db::CellInstArray (db::CellInst (cn.second), db::Trans (points [0]))); + } else { + cell.insert (db::CellInstArray (db::CellInst (vc->cell_index ()), db::Trans (points [0]))); } expect (";"); @@ -565,8 +563,9 @@ LEFImporter::read_viadef (Layout &layout) std::string n = get (); // produce a cell for vias - std::string cellname = "VIA_" + n; + std::string cellname = options ().via_cellname_prefix () + n; db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ())); + reader_state ()->register_via_cell (n, &cell); ViaDesc &via_desc = m_vias[n]; via_desc.cell = &cell; diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index f0640f3e4..55191416e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -260,6 +260,18 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "@brief Sets the via geometry layer datatype value.\n" "See \\produce_via_geometry for details about this property.\n" ) + + gsi::method ("via_cellname_prefix", &db::LEFDEFReaderOptions::via_cellname_prefix, + "@brief Gets the via cellname prefix.\n" + "Vias are represented by cells. The cell name is formed by combining the via cell name prefix and the via name.\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + + gsi::method ("via_cellname_prefix=", &db::LEFDEFReaderOptions::set_via_cellname_prefix, gsi::arg ("prefix"), + "@brief Sets the via cellname prefix.\n" + "See \\via_cellname_prefix for details about this property.\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + gsi::method ("produce_pins", &db::LEFDEFReaderOptions::produce_pins, "@brief Gets a value indicating whether pin geometries shall be produced.\n" "See \\produce_via_geometry for details about the layer production rules." @@ -380,6 +392,20 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "@brief Sets the routing layer datatype value.\n" "See \\produce_via_geometry for details about the layer production rules." ) + + gsi::method ("separate_groups", &db::LEFDEFReaderOptions::separate_groups, + "@brief Gets a value indicating whether to create separate parent cells for individual groups.\n" + "If this property is set to true, instances belonging to different groups are separated by putting them into " + "individual parent cells. These parent cells are named after the groups and are put into the master top cell.\n" + "If this property is set to false (the default), no such group parents will be formed." + "\n" + "This property has been added in version 0.26.5.\n" + ) + + gsi::method ("separate_groups=", &db::LEFDEFReaderOptions::set_separate_groups, gsi::arg ("flag"), + "@brief Gets a value indicating whether to create separate parent cells for individual groups.\n" + "See \\seperate_groups for details about this property.\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files, "@brief Gets the list technology LEF files to additionally import\n" "Returns a list of path names for technology LEF files to read in addition to the primary file. " diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui index 2b2dcf365..3833de8a3 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui +++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui @@ -7,7 +7,7 @@ 0 0 775 - 766 + 855 @@ -200,31 +200,28 @@ true - + 4 4 - + Layout database unit - - - - - 0 - 0 - + + + + Via cell name prefix - + @@ -237,6 +234,40 @@ + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + Produce a parent cell for each group + + + + + + + Separate groups + + + diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc index 3c8f051c2..14d8c7463 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc @@ -140,7 +140,7 @@ public: } } - db::LEFDEFLayerDelegate layers (&options); + db::LEFDEFReaderState layers (&options); layers.prepare (*layout); layout->dbu (options.dbu ()); diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc index 14474fa23..8aeef44bd 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc @@ -425,6 +425,7 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_produce_via_geometry (produce_via_geometry->isChecked ()); data->set_via_geometry_suffix (tl::to_string (suffix_via_geometry->text ())); data->set_via_geometry_datatype (datatype_via_geometry->text ().toInt ()); + data->set_via_cellname_prefix (tl::to_string (prefix_via_cellname->text ())); data->set_produce_pins (produce_pins->isChecked ()); data->set_pins_suffix (tl::to_string (suffix_pins->text ())); data->set_pins_datatype (datatype_pins->text ().toInt ()); @@ -440,6 +441,7 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_produce_labels (produce_labels->isChecked ()); data->set_labels_suffix (tl::to_string (suffix_labels->text ())); data->set_labels_datatype (datatype_labels->text ().toInt ()); + data->set_separate_groups (separate_groups->isChecked ()); data->clear_lef_files (); for (int i = 0; i < lef_files->count (); ++i) { @@ -477,6 +479,7 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options produce_via_geometry->setChecked (data->produce_via_geometry ()); suffix_via_geometry->setText (tl::to_qstring (data->via_geometry_suffix ())); datatype_via_geometry->setText (QString::number (data->via_geometry_datatype ())); + prefix_via_cellname->setText (tl::to_qstring (data->via_cellname_prefix ())); produce_pins->setChecked (data->produce_pins ()); suffix_pins->setText (tl::to_qstring (data->pins_suffix ())); datatype_pins->setText (QString::number (data->pins_datatype ())); @@ -492,6 +495,7 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options produce_labels->setChecked (data->produce_labels ()); suffix_labels->setText (tl::to_qstring (data->labels_suffix ())); datatype_labels->setText (QString::number (data->labels_datatype ())); + separate_groups->setChecked (data->separate_groups ()); checkbox_changed (); diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 5ff589fb1..0908b18e9 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -51,7 +51,7 @@ static db::LEFDEFReaderOptions default_options () static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &tc, bool priv = true) { - db::LEFDEFLayerDelegate ld (&tc); + db::LEFDEFReaderState ld (&tc); db::Manager m (false); db::Layout layout (&m), layout2 (&m), layout_au (&m); @@ -232,7 +232,11 @@ TEST(17) TEST(18) { - run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au.oas.gz", default_options ()); + db::LEFDEFReaderOptions options = default_options (); + options.set_separate_groups (true); + run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au.oas.gz", options); + + run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au_nogroups.oas.gz", default_options ()); } TEST(19) diff --git a/testdata/ruby/dbReaders.rb b/testdata/ruby/dbReaders.rb index 4c89cc871..9cc558f75 100644 --- a/testdata/ruby/dbReaders.rb +++ b/testdata/ruby/dbReaders.rb @@ -249,6 +249,10 @@ class DBReaders_TestClass < TestBase conf.via_geometry_suffix = "XVIA" assert_equal(conf.via_geometry_suffix, "XVIA") + assert_equal(conf.via_cellname_prefix, "VIA_") + conf.via_cellname_prefix = "ABC" + assert_equal(conf.via_cellname_prefix, "ABC") + assert_equal(conf.via_geometry_datatype, 0) conf.via_geometry_datatype = 17 assert_equal(conf.via_geometry_datatype, 17) @@ -313,6 +317,10 @@ class DBReaders_TestClass < TestBase conf.routing_datatype = 22 assert_equal(conf.routing_datatype, 22) + assert_equal(conf.separate_groups, false) + conf.separate_groups = true + assert_equal(conf.separate_groups, true) + assert_equal(conf.lef_files.join(","), "") conf.lef_files = [ "u.lef", "v.lef" ] assert_equal(conf.lef_files.join(","), "u.lef,v.lef") From 9a7f0a9c2a80308f0777b2a55e3793ca19acdadc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 18 Apr 2020 18:48:25 +0200 Subject: [PATCH 26/43] Fixed a LEF/DEF reader bug (was '+ RECT' or '+ POLYGON' in SPECIALNETS) --- src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc | 6 ++++-- testdata/lefdef/specialnets_geo/test.def | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 6ef63978f..ea5de1c3f 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -773,17 +773,19 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool } else { bool prefixed = false; + bool can_have_rect_or_polygon = true; if ((was_shield = test ("SHIELD")) == true || test ("NOSHIELD") || test ("ROUTED") || test ("FIXED") || test ("COVER")) { if (was_shield) { take (); } prefixed = true; + can_have_rect_or_polygon = test ("+"); } bool any = false; - if (test ("POLYGON")) { + if (can_have_rect_or_polygon && test ("POLYGON")) { std::string ln = get (); @@ -801,7 +803,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool any = true; - } else if (test ("RECT")) { + } else if (can_have_rect_or_polygon && test ("RECT")) { std::string ln = get (); diff --git a/testdata/lefdef/specialnets_geo/test.def b/testdata/lefdef/specialnets_geo/test.def index 0686c4fec..b9b3e39c8 100644 --- a/testdata/lefdef/specialnets_geo/test.def +++ b/testdata/lefdef/specialnets_geo/test.def @@ -16,9 +16,9 @@ VIAS 1 ; END VIAS SPECIALNETS 1 ; - dummy - + ROUTED RECT M2 ( 350 0 ) ( 200 100 ) + + ROUTED + RECT M2 ( 350 0 ) ( 200 100 ) + POLYGON M1 ( 300 0 ) ( 300 50 ) ( 350 50 ) ( 400 100 ) ( 400 0 ) - + ROUTED POLYGON M2 ( 300 150 ) ( 300 200 ) ( 350 200 ) ( 400 250 ) ( 400 150 ) + + ROUTED + POLYGON M2 ( 300 150 ) ( 300 200 ) ( 350 200 ) ( 400 250 ) ( 400 150 ) + RECT M1 ( 0 0 ) ( 100 200 ) + ROUTED M1 30 ( 0 0 15 ) ( 100 0 0 ) VIA1_dummy ( 100 100 10 ) + ROUTED M2 50 + SHAPE RING + STYLE 1 ( 0 100 ) ( 100 200 ) ( 200 200 ) From d93ef3ff974dc84ff55c4fa4be1a55b36324d0b7 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 19 Apr 2020 10:39:27 +0200 Subject: [PATCH 27/43] Timing reports for stream writers too, reporting file names for reader and writer timing. --- src/db/db/dbReader.cc | 18 ++++++++++++++++++ src/db/db/dbReader.h | 10 ++-------- src/db/db/dbWriter.cc | 4 ++++ .../streamers/cif/db_plugin/dbCIFReader.cc | 2 -- .../streamers/dxf/db_plugin/dbDXFReader.cc | 2 -- .../gds2/db_plugin/dbGDS2ReaderBase.cc | 2 -- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 5 ++--- .../streamers/magic/db_plugin/dbMAGReader.cc | 2 +- .../streamers/oasis/db_plugin/dbOASISReader.cc | 2 -- 9 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/db/db/dbReader.cc b/src/db/db/dbReader.cc index 4e1455bc1..fc6f13adb 100644 --- a/src/db/db/dbReader.cc +++ b/src/db/db/dbReader.cc @@ -24,6 +24,8 @@ #include "dbReader.h" #include "dbStream.h" #include "tlClassRegistry.h" +#include "tlTimer.h" +#include "tlLog.h" namespace db { @@ -74,5 +76,21 @@ Reader::~Reader () } } +const db::LayerMap & +Reader::read (db::Layout &layout, const db::LoadLayoutOptions &options) +{ + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading file: ")) + m_stream.source ()); + + return mp_actual_reader->read (layout, options); +} + +const db::LayerMap & +Reader::read (db::Layout &layout) +{ + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading file: ")) + m_stream.source ()); + + return mp_actual_reader->read (layout); +} + } diff --git a/src/db/db/dbReader.h b/src/db/db/dbReader.h index 6429ea71b..bab39df87 100644 --- a/src/db/db/dbReader.h +++ b/src/db/db/dbReader.h @@ -125,10 +125,7 @@ public: * @param layout The layout object to write to * @param options The LayerMap object */ - const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options) - { - return mp_actual_reader->read (layout, options); - } + const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options); /** * @brief The basic read method (without mapping) @@ -143,10 +140,7 @@ public: * @param layout The layout object to write to * @return The LayerMap object */ - const db::LayerMap &read (db::Layout &layout) - { - return mp_actual_reader->read (layout); - } + const db::LayerMap &read (db::Layout &layout); /** * @brief Returns a format describing the file format found diff --git a/src/db/db/dbWriter.cc b/src/db/db/dbWriter.cc index 5dfdcefa0..917790212 100644 --- a/src/db/db/dbWriter.cc +++ b/src/db/db/dbWriter.cc @@ -26,6 +26,8 @@ #include "tlClassRegistry.h" #include "tlAssert.h" #include "tlStream.h" +#include "tlTimer.h" +#include "tlLog.h" namespace db { @@ -54,6 +56,8 @@ Writer::~Writer () void Writer::write (db::Layout &layout, tl::OutputStream &stream) { + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Writing file: ")) + stream.path ()); + tl_assert (mp_writer != 0); mp_writer->write (layout, stream, m_options); } diff --git a/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc b/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc index f63d9ffb5..df544ffe2 100644 --- a/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc +++ b/src/plugins/streamers/cif/db_plugin/dbCIFReader.cc @@ -818,8 +818,6 @@ CIFReader::read_cell (db::Layout &layout, db::Cell &cell, double sf, int level) void CIFReader::do_read (db::Layout &layout) { - tl::SelfTimer timer (tl::verbosity () >= 21, "File read"); - try { double sf = 0.01 / m_dbu; diff --git a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc index 85fe87027..2a7f8327b 100644 --- a/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc +++ b/src/plugins/streamers/dxf/db_plugin/dbDXFReader.cc @@ -379,8 +379,6 @@ DXFReader::open_layer (db::Layout &layout, const std::string &n) void DXFReader::do_read (db::Layout &layout, db::cell_index_type top) { - tl::SelfTimer timer (tl::verbosity () >= 21, "File read"); - // create the zero layer - this is not mapped to GDS but can be specified in the layer mapping as // a layer named "0". std::pair ll = layer_map ().logical (zero_layer_name, layout); diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc index 4d6695891..1541960e0 100644 --- a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc @@ -233,8 +233,6 @@ eq_y (const GDS2XY &a, const GDS2XY &b) void GDS2ReaderBase::do_read (db::Layout &layout) { - tl::SelfTimer timer (tl::verbosity () >= 21, "File read"); - m_cellname = ""; m_libname = ""; m_mapped_cellnames.clear (); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index e7e7f168c..5c196d026 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -272,7 +272,6 @@ private: lefdef_options = &default_options; } - // Take the layer map and the "read all layers" flag from the reader options - hence we override the db::LEFDEFReaderState state (lefdef_options); import_map_file_heuristics (m_stream.absolute_path (), state); @@ -282,7 +281,7 @@ private: if (import_lef) { - tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Reading LEF file"))); + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file"))); db::LEFImporter importer; @@ -301,7 +300,7 @@ private: } else { - tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Reading DEF file"))); + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading DEF file"))); DEFImporter importer; diff --git a/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc b/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc index f44a71330..b9fa4bb06 100644 --- a/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc +++ b/src/plugins/streamers/magic/db_plugin/dbMAGReader.cc @@ -111,7 +111,7 @@ MAGReader::read (db::Layout &layout, const db::LoadLayoutOptions &options) m_tech.clear (); { - tl::SelfTimer timer (tl::verbosity () >= 21, "Reading MAGIC file tree"); + tl::SelfTimer timer (tl::verbosity () >= 11, "Reading MAGIC file tree"); // This is the seed do_read (layout, top_cell, m_stream); diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc index 2d084c313..6311ff2cf 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc @@ -689,8 +689,6 @@ static const char magic_bytes[] = { "%SEMI-OASIS\015\012" }; void OASISReader::do_read (db::Layout &layout) { - tl::SelfTimer timer (tl::verbosity () >= 21, "File read"); - unsigned char r; char *mb; From 9825245e0cb99f0973cb08ce45026ad51a4f4806 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 19 Apr 2020 12:16:55 +0200 Subject: [PATCH 28/43] Implemented LEF MACRO FOREIGN --- .../lefdef/db_plugin/dbDEFImporter.cc | 43 ---------------- .../lefdef/db_plugin/dbDEFImporter.h | 3 -- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 43 ++++++++++++++++ .../lefdef/db_plugin/dbLEFDEFImporter.h | 18 +++++++ .../lefdef/db_plugin/dbLEFImporter.cc | 38 ++++++++++++-- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 31 +++++++---- testdata/lefdef/foreigncell/au.oas.gz | Bin 0 -> 859 bytes testdata/lefdef/foreigncell/foreign.gds | Bin 0 -> 3484 bytes testdata/lefdef/foreigncell/in.lef | 48 ++++++++++++++++++ testdata/lefdef/foreigncell/in_tech.lef | 36 +++++++++++++ testdata/lefdef/issue-489b/in.lef | 1 - 11 files changed, 201 insertions(+), 60 deletions(-) create mode 100644 testdata/lefdef/foreigncell/au.oas.gz create mode 100644 testdata/lefdef/foreigncell/foreign.gds create mode 100644 testdata/lefdef/foreigncell/in.lef create mode 100644 testdata/lefdef/foreigncell/in_tech.lef diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index ea5de1c3f..3c047f817 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -65,49 +65,6 @@ DEFImporter::read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReader } -db::FTrans -DEFImporter::get_orient (bool optional) -{ - if (test ("N")) { - return db::FTrans (db::FTrans::r0); - } else if (test ("S")) { - return db::FTrans (db::FTrans::r180); - } else if (test ("W")) { - return db::FTrans (db::FTrans::r90); - } else if (test ("E")) { - return db::FTrans (db::FTrans::r270); - } else if (test ("FN")) { - return db::FTrans (db::FTrans::m90); - } else if (test ("FS")) { - return db::FTrans (db::FTrans::m0); - } else if (test ("FW")) { - return db::FTrans (db::FTrans::m45); - } else if (test ("FE")) { - return db::FTrans (db::FTrans::m135); - } else if (optional) { - return db::FTrans (db::FTrans::r0); - } else { - error (tl::to_string (tr ("Invalid orientation specification: ")) + get ()); - return db::FTrans (db::FTrans::r0); - } -} - -db::Point -DEFImporter::get_point (double scale) -{ - double x = get_double (); - double y = get_double (); - return db::Point (db::DPoint (x * scale, y * scale)); -} - -db::Vector -DEFImporter::get_vector (double scale) -{ - double x = get_double (); - double y = get_double (); - return db::Vector (db::DVector (x * scale, y * scale)); -} - void DEFImporter::read_polygon (db::Polygon &poly, double scale) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index b0f421ad8..dc9e36488 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -67,7 +67,6 @@ private: std::map m_via_desc; std::map m_styles; - db::FTrans get_orient (bool optional); void read_polygon (db::Polygon &poly, double scale); void read_rect (db::Polygon &poly, double scale); std::pair get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu); @@ -84,8 +83,6 @@ private: void read_components (std::list > &instances, double scale); void read_single_net (std::string &nondefaultrule, db::Layout &layout, db::Cell &design, double scale, properties_id_type prop_id, bool specialnets); void produce_routing_geometry (db::Cell &design, const db::Polygon *style, unsigned int layer, properties_id_type prop_id, const std::vector &pts, const std::vector > &ext, std::pair w); - db::Point get_point (double scale); - db::Vector get_vector (double scale); }; } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index a574da6a7..d045b7534 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -830,5 +830,48 @@ LEFDEFImporter::create_generated_via (std::vector &bottom, } +db::FTrans +LEFDEFImporter::get_orient (bool optional) +{ + if (test ("N")) { + return db::FTrans (db::FTrans::r0); + } else if (test ("S")) { + return db::FTrans (db::FTrans::r180); + } else if (test ("W")) { + return db::FTrans (db::FTrans::r90); + } else if (test ("E")) { + return db::FTrans (db::FTrans::r270); + } else if (test ("FN")) { + return db::FTrans (db::FTrans::m90); + } else if (test ("FS")) { + return db::FTrans (db::FTrans::m0); + } else if (test ("FW")) { + return db::FTrans (db::FTrans::m45); + } else if (test ("FE")) { + return db::FTrans (db::FTrans::m135); + } else if (optional) { + return db::FTrans (db::FTrans::r0); + } else { + error (tl::to_string (tr ("Invalid orientation specification: ")) + get ()); + return db::FTrans (db::FTrans::r0); + } +} + +db::Point +LEFDEFImporter::get_point (double scale) +{ + double x = get_double (); + double y = get_double (); + return db::Point (db::DPoint (x * scale, y * scale)); +} + +db::Vector +LEFDEFImporter::get_vector (double scale) +{ + double x = get_double (); + double y = get_double (); + return db::Vector (db::DVector (x * scale, y * scale)); +} + } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index c6ca07a68..83e84ecb0 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -705,6 +705,24 @@ protected: */ long get_long (); + /** + * @brief Gets an orientation code + * The orientation code is read employing the LEF/DEF convention ("N" for r0 etc.) + */ + db::FTrans get_orient (bool optional); + + /** + * @brief Reads a point + * A point is given by two coordinates, x and y + */ + db::Point get_point (double scale); + + /** + * @brief Reads a vector + * A vector is given by two coordinates, x and y + */ + db::Vector get_vector (double scale); + /** * @brief Create a new layer or return the index of the given layer */ diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 72f6140da..fccdd779b 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -742,10 +742,8 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("ORIGIN")) { - double x = get_double (); - double y = get_double (); + origin = get_point (1.0 / layout.dbu ()); expect (";"); - origin = db::Point (db::DPoint (x / layout.dbu (), y / layout.dbu ())); } else if (test ("SIZE")) { @@ -761,11 +759,16 @@ LEFImporter::read_macro (Layout &layout) std::string dir; while (! at_end ()) { + if (test ("END")) { + break; + } else if (test ("DIRECTION")) { + dir = get (); test (";"); + } else if (test ("PORT")) { // produce pin labels @@ -806,6 +809,35 @@ LEFImporter::read_macro (Layout &layout) expect (pn); + } else if (test ("FOREIGN")) { + + std::string cn = get (); + + if (cn == mn) { + // rename out macro placeholder cell so we don't create a recursive hierarchy + layout.rename_cell (cell.cell_index (), ("LEF_" + mn).c_str ()); + } + + db::cell_index_type ci; + std::pair c = layout.cell_by_name (cn.c_str ()); + if (c.first) { + ci = c.second; + } else { + ci = layout.add_cell (cn.c_str ()); + layout.cell (ci).set_ghost_cell (true); + } + + db::Point origin; + db::FTrans ft; + if (! peek (";")) { + origin = get_point (1.0 / layout.dbu ()); + ft = get_orient (true); + } + + expect (";"); + + cell.insert (db::CellInstArray (db::CellInst (ci), (db::Trans (origin - db::Point ()) * db::Trans (ft)).inverted ())); + } else if (test ("OBS")) { read_geometries (layout, cell, Obstructions); diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 0908b18e9..7dbd7772c 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -51,6 +51,11 @@ static db::LEFDEFReaderOptions default_options () static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &tc, bool priv = true) { + std::string fn_path (priv ? tl::testsrc_private () : tl::testsrc ()); + fn_path += "/testdata/lefdef/"; + fn_path += lef_dir; + fn_path += "/"; + db::LEFDEFReaderState ld (&tc); db::Manager m (false); @@ -66,11 +71,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file if (ex.test ("def:")) { - std::string fn (priv ? tl::testsrc_private () : tl::testsrc ()); - fn += "/testdata/lefdef/"; - fn += lef_dir; - fn += "/"; - std::string f; + std::string fn = fn_path, f; ex.read_word_or_quoted (f); fn += f; @@ -79,17 +80,23 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file } else if (ex.test ("lef:")) { - std::string fn (priv ? tl::testsrc_private () : tl::testsrc ()); - fn += "/testdata/lefdef/"; - fn += lef_dir; - fn += "/"; - std::string f; + std::string fn = fn_path, f; ex.read_word_or_quoted (f); fn += f; tl::InputStream stream (fn); imp.read_lef (stream, layout, ld); + } else if (ex.test ("gds:")) { + + std::string fn = fn_path, f; + ex.read_word_or_quoted (f); + fn += f; + + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (layout, db::LoadLayoutOptions ()); + } else { break; @@ -305,3 +312,7 @@ TEST(108_scanchain) run_test (_this, "scanchain", "def:test.def", "au.oas.gz", default_options (), false); } +TEST(109_foreigncell) +{ + run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef", "au.oas.gz", default_options (), false); +} diff --git a/testdata/lefdef/foreigncell/au.oas.gz b/testdata/lefdef/foreigncell/au.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..a46321b03e36bc56c9ec2e5bd21b35ef0920623e GIT binary patch literal 859 zcmV-h1El;PiwFo#B%EFV19WY0E^lFT0Oe6lXj54fzUSWeoA=Yi<{?N{c80zv(|Kt+ z!ysmn)~7xuKX1&dww-YvZ_=a&+H_2+R=R0H#DxoW;lf1;rHGVF7cOL$LmA3Y2G@cc zDN?cw(g`j^=Ds$~v_pmNy_@r$@0|19^WFPp&P-chWs^B8rv!k+`V7?I(f$+BPUPHl za>UJ97c%BK*UC8N1@n@7#X9F)6qtw-*)0!e4r_>Lft>4PZFk5_rQ|@$Jnv3<`O0)W z5|X(c)ZaldzU%u`ax^>axICqW64u_>yCqnO^a@ ztrw@uGj7?ND$qi8X597jUQx64N$+-{5>5QL6VD9ve;vOn%C>w}&L0 zjuD~SSf6cWD8}+WED02+l7nW7W*{HPB%XeJ%F3AJG!@#PC=h9(E)}VuVwI?j z%Bq~otAZ-30aa3ERZ&$feu^;NE3m{pgEwRq9+PEQ!()HqpYF0h|A9x=aE)?xxDT4a z$eTh97K#0c)L=_khDYQHah`I2ahd_beHhn%i0WDt(N1Xv*7zE-Yf~S%R@9tm8UdUWFDc!xC)ZW!NGO+6vrkG(4_F?=ji{1Um9j`xPUh zvq1&5-E~oS!B4uwM{)O-)doK0u7M@ggrIN#IkSP^K@Fb5M|e+nr3T?|{DPTh|F>Zi zB-Fq`%CV+^qni7Xe`lFgSf$A_ILMtq$mgLRJ3A)JJ8I_x`q=s1wi z0wSeK5rk-{D4=nHgoF?cE~wlfkrdR>P*6k^sVGuWVE+Hv9rD1B7?2PRYmI)pGqW@M z_G4^IBw;uqok7_Ax1{AOX~oZ~cwaJMG&Z_dq$Aa|YtO~OgZFPd`*#1`Epyj?DoAJ3 z+vlx`qMn|fedGB;ZlX{e&5w*@DCriFmemn;J=>(UJtfwnjiIzj+otG;eYvr*VR{I4 zD^%B4IbEM!KioZ_x>i{OzrJ#%QkpG#^9W=u zJ!Z@2v2(qJBe{Ix$MJm5TZQ|IlO5h$YE&mh(yJgios2u3&u8-iXS3}+&PH#rKbw*9 z!-opFT)tOxCZ0^Q{O@aPiR?|KGdTSfp=^+-EtF8k^o@1+XGVVS`^FKBvk)WoT@WL> z;^ylec_aRB8sB1(j1!lY7$1a?haq1>ihev5Bj?m1Ms(GWTD;G&{O}eM#$g`*S7Tu0e*S~85$`20$?NqjB}esrA=ayg_34{1Vtw3uz2_v>r*GMa^{L&6p>Ip~ zB_(>lxCh$evDv4dGUdtoMLmgorFtXok=8TXSr2VK^^9S4l51vtBpH`_l5s39X?Aq| z`jXbK=c@ILeyoR_XLXTvj=4$Zxd5U4n&%uyJxRZtG16}i!p8YYbtonCiS_U?yczE) zg!`}%BhTp(gruL*xr03vo0i0@Fl5#OovjTSfgoLv5CX2(2|d0EGd%*#4x zWZpk8HZm{mM&`9TNTO-nvOT_DOga7~l literal 0 HcmV?d00001 diff --git a/testdata/lefdef/foreigncell/in.lef b/testdata/lefdef/foreigncell/in.lef new file mode 100644 index 000000000..d796cba46 --- /dev/null +++ b/testdata/lefdef/foreigncell/in.lef @@ -0,0 +1,48 @@ +MACRO macro1 + CLASS CORE ; + FOREIGN foreign1 0.5 -0.2 W ; + ORIGIN 0.000 0.000 ; + SIZE 0.384 BY 0.480 ; + PIN Z + PORT + LAYER M1 ; + RECT 0.306 0.357 0.318 0.403 ; + RECT 0.318 0.115 0.352 0.403 ; + VIA 0.336 0.167 square ; + VIA 0.336 0.351 square ; + END + END Z +END macro1 + +MACRO macro2 + CLASS CORE ; + FOREIGN foreign2 -0.15 0.25 ; + ORIGIN 0.000 0.000 ; + SIZE 0.384 BY 0.480 ; + PIN Z + PORT + LAYER M1 ; + RECT 0.306 0.357 0.318 0.403 ; + RECT 0.318 0.115 0.352 0.403 ; + VIA 0.336 0.167 square ; + VIA 0.336 0.351 square ; + END + END Z +END macro2 + +MACRO macro3 + CLASS CORE ; + FOREIGN macro3 ; + ORIGIN 0.000 0.000 ; + SIZE 0.384 BY 0.480 ; + PIN Z + PORT + LAYER M1 ; + RECT 0.306 0.357 0.318 0.403 ; + RECT 0.318 0.115 0.352 0.403 ; + VIA 0.336 0.167 square ; + VIA 0.336 0.351 square ; + END + END Z +END macro3 + diff --git a/testdata/lefdef/foreigncell/in_tech.lef b/testdata/lefdef/foreigncell/in_tech.lef new file mode 100644 index 000000000..eb0e75b0b --- /dev/null +++ b/testdata/lefdef/foreigncell/in_tech.lef @@ -0,0 +1,36 @@ +LAYER OD + TYPE IMPLANT ; +END OD +LAYER VTS_N + TYPE IMPLANT ; +END VTS_N +LAYER VTS_P + TYPE IMPLANT ; +END VTS_P +LAYER M0OD + TYPE IMPLANT ; +END M0OD +LAYER M0PO + TYPE MASTERSLICE ; +END M0PO +LAYER VIA0 + TYPE CUT ; +END VIA0 +LAYER M1 + TYPE MASTERSLICE ; +END M1 +LAYER VIA1 + TYPE CUT ; +END VIA1 +LAYER M2 + TYPE MASTERSLICE ; +END M2 + +VIA square + LAYER M0PO ; + RECT -0.006 -0.006 0.006 0.006 ; + LAYER VIA0 ; + RECT -0.006 -0.006 0.006 0.006 ; + LAYER M1 ; + RECT -0.006 -0.006 0.006 0.006 ; +END square diff --git a/testdata/lefdef/issue-489b/in.lef b/testdata/lefdef/issue-489b/in.lef index 857ae0d04..05832b7bd 100644 --- a/testdata/lefdef/issue-489b/in.lef +++ b/testdata/lefdef/issue-489b/in.lef @@ -1,6 +1,5 @@ MACRO dummy CLASS CORE ; - FOREIGN dummy 0.000 0.000 ; ORIGIN 0.000 0.000 ; SIZE 0.384 BY 0.480 ; SYMMETRY X Y ; From e51f15b1167dc2a0c53cdedce917cf3eba9ecb7d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 19 Apr 2020 14:38:14 +0200 Subject: [PATCH 29/43] New layer flavors: special nets, LEF pins. --- .../lefdef/db_plugin/dbDEFImporter.cc | 8 +- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 34 ++++ .../lefdef/db_plugin/dbLEFDEFImporter.h | 86 ++++++++- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 11 +- .../lefdef/db_plugin/dbLEFImporter.cc | 2 +- .../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 60 ++++++ .../LEFDEFTechnologyComponentEditor.ui | 176 ++++++++++++------ .../lay_plugin/layLEFDEFImportDialogs.cc | 18 ++ .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 23 +++ .../foreigncell/au_lefpins_mapped.oas.gz | Bin 0 -> 859 bytes .../lefdef/foreigncell/au_no_lefpins.oas.gz | Bin 0 -> 796 bytes .../lefdef/specialnets_geo/au_no_spnet.oas.gz | Bin 0 -> 224 bytes .../specialnets_geo/au_spnet_mapped.oas.gz | Bin 0 -> 378 bytes testdata/ruby/dbReaders.rb | 24 +++ 14 files changed, 367 insertions(+), 75 deletions(-) create mode 100644 testdata/lefdef/foreigncell/au_lefpins_mapped.oas.gz create mode 100644 testdata/lefdef/foreigncell/au_no_lefpins.oas.gz create mode 100644 testdata/lefdef/specialnets_geo/au_no_spnet.oas.gz create mode 100644 testdata/lefdef/specialnets_geo/au_spnet_mapped.oas.gz diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 3c047f817..708e29b12 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -543,7 +543,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C test (")"); - std::pair dl = open_layer (layout, ln, Routing); + std::pair dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing); if (dl.first) { db::Point p (x, y); @@ -597,7 +597,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C } if (pts.size () > 1) { - std::pair dl = open_layer (layout, ln, Routing); + std::pair dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing); if (dl.first) { produce_routing_geometry (design, style, dl.second, prop_id, pts, ext, w); } @@ -749,7 +749,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool db::Polygon p; read_polygon (p, scale); - std::pair dl = open_layer (layout, ln, Routing); + std::pair dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing); if (dl.first) { if (prop_id != 0) { design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); @@ -767,7 +767,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool db::Polygon p; read_rect (p, scale); - std::pair dl = open_layer (layout, ln, Routing); + std::pair dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing); if (dl.first) { if (prop_id != 0) { design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index d045b7534..07122526d 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -56,6 +56,9 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_produce_pins (true), m_pins_suffix (".PIN"), m_pins_datatype (2), + m_produce_lef_pins (true), + m_lef_pins_suffix (".PIN"), + m_lef_pins_datatype (2), m_produce_obstructions (true), m_obstructions_suffix (".OBS"), m_obstructions_datatype (3), @@ -68,6 +71,9 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_produce_routing (true), m_routing_suffix (""), m_routing_datatype (0), + m_produce_special_routing (true), + m_special_routing_suffix (""), + m_special_routing_datatype (0), m_separate_groups (false) { // .. nothing yet .. @@ -96,6 +102,9 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_produce_pins (d.m_produce_pins), m_pins_suffix (d.m_pins_suffix), m_pins_datatype (d.m_pins_datatype), + m_produce_lef_pins (d.m_produce_lef_pins), + m_lef_pins_suffix (d.m_lef_pins_suffix), + m_lef_pins_datatype (d.m_lef_pins_datatype), m_produce_obstructions (d.m_produce_obstructions), m_obstructions_suffix (d.m_obstructions_suffix), m_obstructions_datatype (d.m_obstructions_datatype), @@ -108,6 +117,9 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_produce_routing (d.m_produce_routing), m_routing_suffix (d.m_routing_suffix), m_routing_datatype (d.m_routing_datatype), + m_produce_special_routing (d.m_produce_special_routing), + m_special_routing_suffix (d.m_special_routing_suffix), + m_special_routing_datatype (d.m_special_routing_datatype), m_separate_groups (d.m_separate_groups), m_lef_files (d.m_lef_files) { @@ -216,6 +228,9 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu default: produce = mp_tech_comp->produce_routing (); break; + case SpecialRouting: + produce = mp_tech_comp->produce_special_routing (); + break; case ViaGeometry: produce = mp_tech_comp->produce_via_geometry (); break; @@ -225,6 +240,9 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu case Pins: produce = mp_tech_comp->produce_pins (); break; + case LEFPins: + produce = mp_tech_comp->produce_lef_pins (); + break; case Obstructions: produce = mp_tech_comp->produce_obstructions (); break; @@ -255,6 +273,11 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu canonical_purpose = "NET"; dt += mp_tech_comp->routing_datatype (); break; + case SpecialRouting: + name += mp_tech_comp->special_routing_suffix (); + canonical_purpose = "SPNET"; + dt += mp_tech_comp->special_routing_datatype (); + break; case ViaGeometry: name += mp_tech_comp->via_geometry_suffix (); dt += mp_tech_comp->via_geometry_datatype (); @@ -270,6 +293,11 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu dt += mp_tech_comp->pins_datatype (); canonical_purpose = "PIN"; break; + case LEFPins: + name += mp_tech_comp->lef_pins_suffix (); + dt += mp_tech_comp->lef_pins_datatype (); + canonical_purpose = "LEFPIN"; + break; case Obstructions: name += mp_tech_comp->obstructions_suffix (); dt += mp_tech_comp->obstructions_datatype (); @@ -360,6 +388,9 @@ LEFDEFReaderState::finish (db::Layout &layout) default: dt = mp_tech_comp->routing_datatype (); break; + case SpecialRouting: + dt = mp_tech_comp->special_routing_datatype (); + break; case ViaGeometry: dt = mp_tech_comp->via_geometry_datatype (); break; @@ -369,6 +400,9 @@ LEFDEFReaderState::finish (db::Layout &layout) case Pins: dt = mp_tech_comp->pins_datatype (); break; + case LEFPins: + dt = mp_tech_comp->lef_pins_datatype (); + break; case Obstructions: dt = mp_tech_comp->obstructions_datatype (); break; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 83e84ecb0..6c9adf325 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -295,6 +295,36 @@ public: m_pins_datatype = s; } + bool produce_lef_pins () const + { + return m_produce_lef_pins; + } + + void set_produce_lef_pins (bool f) + { + m_produce_lef_pins = f; + } + + const std::string &lef_pins_suffix () const + { + return m_lef_pins_suffix; + } + + void set_lef_pins_suffix (const std::string &s) + { + m_lef_pins_suffix = s; + } + + int lef_pins_datatype () const + { + return m_lef_pins_datatype; + } + + void set_lef_pins_datatype (int s) + { + m_lef_pins_datatype = s; + } + bool produce_obstructions () const { return m_produce_obstructions; @@ -415,6 +445,36 @@ public: m_routing_datatype = s; } + bool produce_special_routing () const + { + return m_produce_special_routing; + } + + void set_produce_special_routing (bool f) + { + m_produce_special_routing = f; + } + + const std::string &special_routing_suffix () const + { + return m_special_routing_suffix; + } + + void set_special_routing_suffix (const std::string &s) + { + m_special_routing_suffix = s; + } + + int special_routing_datatype () const + { + return m_special_routing_datatype; + } + + void set_special_routing_datatype (int s) + { + m_special_routing_datatype = s; + } + void clear_lef_files () { m_lef_files.clear (); @@ -478,6 +538,9 @@ private: bool m_produce_pins; std::string m_pins_suffix; int m_pins_datatype; + bool m_produce_lef_pins; + std::string m_lef_pins_suffix; + int m_lef_pins_datatype; bool m_produce_obstructions; std::string m_obstructions_suffix; int m_obstructions_datatype; @@ -490,6 +553,9 @@ private: bool m_produce_routing; std::string m_routing_suffix; int m_routing_datatype; + bool m_produce_special_routing; + std::string m_special_routing_suffix; + int m_special_routing_datatype; bool m_separate_groups; std::vector m_lef_files; }; @@ -499,15 +565,17 @@ private: */ enum LayerPurpose { - Routing = 0, - ViaGeometry = 1, - Label = 2, - Pins = 3, - Obstructions = 4, - Outline = 5, - Blockage = 6, - PlacementBlockage = 7, - Region = 8 + Routing = 0, // from DEF only + SpecialRouting, // from DEF only + ViaGeometry, // from LEF+DEF + Label, // from LEF+DEF + Pins, // from DEF + LEFPins, // from LEF + Obstructions, // from LEF only + Outline, // from LEF+DEF + Blockage, // from DEF only + PlacementBlockage, // from DEF only + Region, // from DEF only }; /** diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 5c196d026..699518e7a 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -96,9 +96,10 @@ read_map_file (const std::string &path, db::LEFDEFReaderState &layers) tl::TextInputStream ts (file_stream); std::map purpose_translation; - purpose_translation ["LEFPIN"] = "PIN"; + purpose_translation ["LEFPIN"] = "LEFPIN"; + purpose_translation ["PIN"] = "PIN"; purpose_translation ["LEFOBS"] = "OBS"; - purpose_translation ["SPNET"] = "NET"; + purpose_translation ["SPNET"] = "SPNET"; purpose_translation ["NET"] = "NET"; purpose_translation ["VIA"] = "VIA"; purpose_translation ["BLOCKAGE"] = "BLK"; @@ -406,6 +407,9 @@ class LEFDEFFormatDeclaration tl::make_member (&LEFDEFReaderOptions::produce_pins, &LEFDEFReaderOptions::set_produce_pins, "produce-pins") + tl::make_member (&LEFDEFReaderOptions::pins_suffix, &LEFDEFReaderOptions::set_pins_suffix, "pins-suffix") + tl::make_member (&LEFDEFReaderOptions::pins_datatype, &LEFDEFReaderOptions::set_pins_datatype, "pins-datatype") + + tl::make_member (&LEFDEFReaderOptions::produce_lef_pins, &LEFDEFReaderOptions::set_produce_lef_pins, "produce-lef-pins") + + tl::make_member (&LEFDEFReaderOptions::lef_pins_suffix, &LEFDEFReaderOptions::set_lef_pins_suffix, "lef-pins-suffix") + + tl::make_member (&LEFDEFReaderOptions::lef_pins_datatype, &LEFDEFReaderOptions::set_lef_pins_datatype, "lef-pins-datatype") + tl::make_member (&LEFDEFReaderOptions::produce_obstructions, &LEFDEFReaderOptions::set_produce_obstructions, "produce-obstructions") + tl::make_member (&LEFDEFReaderOptions::obstructions_suffix, &LEFDEFReaderOptions::set_obstructions_suffix, "obstructions-suffix") + tl::make_member (&LEFDEFReaderOptions::obstructions_datatype, &LEFDEFReaderOptions::set_obstructions_datatype, "obstructions-datatype") + @@ -418,6 +422,9 @@ class LEFDEFFormatDeclaration tl::make_member (&LEFDEFReaderOptions::produce_routing, &LEFDEFReaderOptions::set_produce_routing, "produce-routing") + tl::make_member (&LEFDEFReaderOptions::routing_suffix, &LEFDEFReaderOptions::set_routing_suffix, "routing-suffix") + tl::make_member (&LEFDEFReaderOptions::routing_datatype, &LEFDEFReaderOptions::set_routing_datatype, "routing-datatype") + + tl::make_member (&LEFDEFReaderOptions::produce_special_routing, &LEFDEFReaderOptions::set_produce_special_routing, "produce-special-routing") + + tl::make_member (&LEFDEFReaderOptions::special_routing_suffix, &LEFDEFReaderOptions::set_special_routing_suffix, "special-routing-suffix") + + tl::make_member (&LEFDEFReaderOptions::special_routing_datatype, &LEFDEFReaderOptions::set_special_routing_datatype, "special-routing-datatype") + tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files") ); } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index fccdd779b..090fdfae8 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -789,7 +789,7 @@ LEFImporter::read_macro (Layout &layout) } std::map bboxes; - read_geometries (layout, cell, Pins, &bboxes, prop_id); + read_geometries (layout, cell, LEFPins, &bboxes, prop_id); for (std::map ::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) { std::pair dl = open_layer (layout, b->first, Label); diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index 55191416e..6d31e64cc 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -296,6 +296,30 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "@brief Sets the pin geometry layer datatype value.\n" "See \\produce_via_geometry for details about the layer production rules." ) + + gsi::method ("produce_lef_pins", &db::LEFDEFReaderOptions::produce_lef_pins, + "@brief Gets a value indicating whether LEF pin geometries shall be produced.\n" + "See \\produce_via_geometry for details about the layer production rules." + ) + + gsi::method ("produce_lef_pins=", &db::LEFDEFReaderOptions::set_produce_lef_pins, gsi::arg ("produce"), + "@brief Sets a value indicating whether LEF pin geometries shall be produced.\n" + "See \\produce_via_geometry for details about the layer production rules." + ) + + gsi::method ("lef_pins_suffix", &db::LEFDEFReaderOptions::lef_pins_suffix, + "@brief Gets the LEF pin geometry layer name suffix.\n" + "See \\produce_via_geometry for details about the layer production rules." + ) + + gsi::method ("lef_pins_suffix=", &db::LEFDEFReaderOptions::set_lef_pins_suffix, gsi::arg ("suffix"), + "@brief Sets the LEF pin geometry layer name suffix.\n" + "See \\produce_via_geometry for details about the layer production rules." + ) + + gsi::method ("lef_pins_datatype", &db::LEFDEFReaderOptions::lef_pins_datatype, + "@brief Gets the LEF pin geometry layer datatype value.\n" + "See \\produce_via_geometry for details about the layer production rules." + ) + + gsi::method ("lef_pins_datatype=", &db::LEFDEFReaderOptions::set_lef_pins_datatype, gsi::arg ("datatype"), + "@brief Sets the LEF pin geometry layer datatype value.\n" + "See \\produce_via_geometry for details about the layer production rules." + ) + gsi::method ("produce_obstructions", &db::LEFDEFReaderOptions::produce_obstructions, "@brief Gets a value indicating whether obstruction markers shall be produced.\n" "See \\produce_via_geometry for details about the layer production rules." @@ -392,6 +416,42 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "@brief Sets the routing layer datatype value.\n" "See \\produce_via_geometry for details about the layer production rules." ) + + gsi::method ("produce_special_routing", &db::LEFDEFReaderOptions::produce_special_routing, + "@brief Gets a value indicating whether special routing geometry shall be produced.\n" + "See \\produce_via_geometry for details about the layer production rules.\n" + "\n" + "The differentiation between special and normal routing has been introduced in version 0.26.5." + ) + + gsi::method ("produce_special_routing=", &db::LEFDEFReaderOptions::set_produce_special_routing, gsi::arg ("produce"), + "@brief Sets a value indicating whether special routing geometry shall be produced.\n" + "See \\produce_via_geometry for details about the layer production rules." + "\n" + "The differentiation between special and normal routing has been introduced in version 0.26.5." + ) + + gsi::method ("special_routing_suffix", &db::LEFDEFReaderOptions::special_routing_suffix, + "@brief Gets the special routing layer name suffix.\n" + "See \\produce_via_geometry for details about the layer production rules." + "\n" + "The differentiation between special and normal routing has been introduced in version 0.26.5." + ) + + gsi::method ("special_routing_suffix=", &db::LEFDEFReaderOptions::set_special_routing_suffix, gsi::arg ("suffix"), + "@brief Sets the special routing layer name suffix.\n" + "See \\produce_via_geometry for details about the layer production rules." + "\n" + "The differentiation between special and normal routing has been introduced in version 0.26.5." + ) + + gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype, + "@brief Gets the special routing layer datatype value.\n" + "See \\produce_via_geometry for details about the layer production rules." + "\n" + "The differentiation between special and normal routing has been introduced in version 0.26.5." + ) + + gsi::method ("special_routing_datatype=", &db::LEFDEFReaderOptions::set_special_routing_datatype, gsi::arg ("datatype"), + "@brief Sets the special routing layer datatype value.\n" + "See \\produce_via_geometry for details about the layer production rules." + "\n" + "The differentiation between special and normal routing has been introduced in version 0.26.5." + ) + gsi::method ("separate_groups", &db::LEFDEFReaderOptions::separate_groups, "@brief Gets a value indicating whether to create separate parent cells for individual groups.\n" "If this property is set to true, instances belonging to different groups are separated by putting them into " diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui index 3833de8a3..845452c8e 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui +++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui @@ -590,13 +590,6 @@ - - - - Obstructions - - - @@ -613,19 +606,6 @@ - - - - - - - - - - Routing - - - @@ -642,43 +622,14 @@ - - - - - - - - - - Pin labels - - - - + Blockages - - - - - 0 - 0 - - - - - - - :/right.png - - - - + @@ -694,18 +645,125 @@ - - - - - - - + - + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + Pin labels + + + + + + + + + + + + + Special routing + + + + + + + + + + + + + Routing + + + + + + + + + + + + + Obstructions + + + + + + + + + + + + + + + + + + + LEF Pins + + + diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc index 8aeef44bd..16b70262d 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc @@ -353,9 +353,11 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent) connect (produce_regions, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_via_geometry, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_pins, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); + connect (produce_lef_pins, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_obstructions, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_blockages, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_routing, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); + connect (produce_special_routing, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_labels, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (add_lef_file, SIGNAL (clicked ()), this, SLOT (add_lef_file_clicked ())); connect (del_lef_files, SIGNAL (clicked ()), this, SLOT (del_lef_files_clicked ())); @@ -429,6 +431,9 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_produce_pins (produce_pins->isChecked ()); data->set_pins_suffix (tl::to_string (suffix_pins->text ())); data->set_pins_datatype (datatype_pins->text ().toInt ()); + data->set_produce_lef_pins (produce_lef_pins->isChecked ()); + data->set_lef_pins_suffix (tl::to_string (suffix_lef_pins->text ())); + data->set_lef_pins_datatype (datatype_lef_pins->text ().toInt ()); data->set_produce_obstructions (produce_obstructions->isChecked ()); data->set_obstructions_suffix (tl::to_string (suffix_obstructions->text ())); data->set_obstructions_datatype (datatype_obstructions->text ().toInt ()); @@ -438,6 +443,9 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_produce_routing (produce_routing->isChecked ()); data->set_routing_suffix (tl::to_string (suffix_routing->text ())); data->set_routing_datatype (datatype_routing->text ().toInt ()); + data->set_produce_special_routing (produce_special_routing->isChecked ()); + data->set_special_routing_suffix (tl::to_string (suffix_special_routing->text ())); + data->set_special_routing_datatype (datatype_special_routing->text ().toInt ()); data->set_produce_labels (produce_labels->isChecked ()); data->set_labels_suffix (tl::to_string (suffix_labels->text ())); data->set_labels_datatype (datatype_labels->text ().toInt ()); @@ -483,6 +491,9 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options produce_pins->setChecked (data->produce_pins ()); suffix_pins->setText (tl::to_qstring (data->pins_suffix ())); datatype_pins->setText (QString::number (data->pins_datatype ())); + produce_lef_pins->setChecked (data->produce_lef_pins ()); + suffix_lef_pins->setText (tl::to_qstring (data->lef_pins_suffix ())); + datatype_lef_pins->setText (QString::number (data->lef_pins_datatype ())); produce_obstructions->setChecked (data->produce_obstructions ()); suffix_obstructions->setText (tl::to_qstring (data->obstructions_suffix ())); datatype_obstructions->setText (QString::number (data->obstructions_datatype ())); @@ -492,6 +503,9 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options produce_routing->setChecked (data->produce_routing ()); suffix_routing->setText (tl::to_qstring (data->routing_suffix ())); datatype_routing->setText (QString::number (data->routing_datatype ())); + produce_special_routing->setChecked (data->produce_special_routing ()); + suffix_special_routing->setText (tl::to_qstring (data->special_routing_suffix ())); + datatype_special_routing->setText (QString::number (data->special_routing_datatype ())); produce_labels->setChecked (data->produce_labels ()); suffix_labels->setText (tl::to_qstring (data->labels_suffix ())); datatype_labels->setText (QString::number (data->labels_datatype ())); @@ -523,15 +537,19 @@ LEFDEFReaderOptionsEditor::checkbox_changed () placement_blockage_layer->setEnabled (produce_placement_blockages->isChecked ()); suffix_via_geometry->setEnabled (produce_via_geometry->isChecked ()); suffix_pins->setEnabled (produce_pins->isChecked ()); + suffix_lef_pins->setEnabled (produce_lef_pins->isChecked ()); suffix_obstructions->setEnabled (produce_obstructions->isChecked ()); suffix_blockages->setEnabled (produce_blockages->isChecked ()); suffix_routing->setEnabled (produce_routing->isChecked ()); + suffix_special_routing->setEnabled (produce_special_routing->isChecked ()); suffix_labels->setEnabled (produce_labels->isChecked ()); datatype_via_geometry->setEnabled (produce_via_geometry->isChecked ()); datatype_pins->setEnabled (produce_pins->isChecked ()); + datatype_lef_pins->setEnabled (produce_lef_pins->isChecked ()); datatype_obstructions->setEnabled (produce_obstructions->isChecked ()); datatype_blockages->setEnabled (produce_blockages->isChecked ()); datatype_routing->setEnabled (produce_routing->isChecked ()); + datatype_special_routing->setEnabled (produce_special_routing->isChecked ()); datatype_labels->setEnabled (produce_labels->isChecked ()); } diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 7dbd7772c..45b21683b 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -295,6 +295,19 @@ TEST(104_doxy_vias) TEST(105_specialnets_geo) { run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); + + db::LEFDEFReaderOptions options = default_options (); + options.set_produce_special_routing (false); + run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au_no_spnet.oas.gz", options, false); + + options.set_produce_special_routing (true); + options.set_special_routing_datatype (10); + options.set_special_routing_suffix (".SPNET"); + + options.set_via_geometry_datatype (11); + options.set_via_geometry_suffix (".VIA"); + + run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au_spnet_mapped.oas.gz", options, false); } TEST(106_wrongdirection) @@ -315,4 +328,14 @@ TEST(108_scanchain) TEST(109_foreigncell) { run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef", "au.oas.gz", default_options (), false); + + db::LEFDEFReaderOptions options = default_options (); + options.set_produce_lef_pins (false); + run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef", "au_no_lefpins.oas.gz", options, false); + + options.set_produce_lef_pins (true); + options.set_lef_pins_datatype (10); + options.set_lef_pins_suffix (".LEFPIN"); + + run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef", "au_lefpins_mapped.oas.gz", options, false); } diff --git a/testdata/lefdef/foreigncell/au_lefpins_mapped.oas.gz b/testdata/lefdef/foreigncell/au_lefpins_mapped.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..7416d50b67a50f24160c04775a45aca30886ad1c GIT binary patch literal 859 zcmV-h1El;PiwFo?H=JGo19WY0E^lFT0Oe6jXd71)efPcj|18-W3PGzT#iNEgBg-wN zR0}zoBt!I>MB`7~IKxDiT!AgOlG`|V<3I>mWYJ`iMHWFA6M|8_=%RF4OfbQOt_$6S z5R8^0q#}z_`o@+OE5zV^-{#(P?!D*T^WG&^Rx>OvwK zR=C}4xSPfKz6hrJC?6E2uIkswSEiBMXo z7R$4hcsCm+(zu=SYTy6hSBs?c;+;rq?|!DkC0Lk}nT+Y=2uqOC&18nkn1lSNiL#i94^c(O&Qd5Ty-*ecm>RXx6oJx%WS)M1+Rj?!B$Yb|REV}wpN2HhutqdS zV>M3WH9-?KNs~22Q#DObd`g&sby($|zzebg56Bv9;;E-mK*Z?PZm>uB_tV08qR3`ElixgFj+~guRd6k4)=x6+fs5sn$ zCV!8peE2O>XaAu4{09BumVi)XnU_AUWi7h`r53mQSJ;@`50w la=nA3f&V5)9A$e(+w{+x{Lx17%K!Nw^dGl~vHvIr0059ru(ALE literal 0 HcmV?d00001 diff --git a/testdata/lefdef/foreigncell/au_no_lefpins.oas.gz b/testdata/lefdef/foreigncell/au_no_lefpins.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..f0e21a2099c706a17290cee957a3e57c28b1237f GIT binary patch literal 796 zcmV+%1LOQ3iwFowH=JGo19WY0E^lFT0OgTQXcIvc$LG!LXEwV{G>ag)Rp~}iH%%20 zbEvwl!8BQ$txf$})-k**DI(%o@FGP@j-k}x zNt|tyXvKne=knhC{%_vQ|INXa(HA?C>`ui}vIj``sE(>U`h5k}{VBVzJ8h?8y$R!- z9ZOh7uhDN0#?D#i1tus5x8;Gv-wJ}NCuLhn(>`m&<6ckP=&{F~OmRFC^n1Cjth1Gc z`L+x3?xEy>WuHybCTU9)yGPN6dr?gcdwwYR{bj!))3nMKsx&zP#*<8-f+}rM`pJNZ(Z5ZG ziw&Y57d_iPD9~x{jw-rke{ajPHE1NPp=84NySL73gmX_Eh!Dn&M97U7v-y!ixRrGh z&!t$mUAle8DP~Dy;*ChPUq91e5sB&3%_Lz7^0qRGp*?iMxvZH_iM0ek%oPOsoHWfgb?s?K=VgfcuQ<}4}0x-bv3;1TBs~Y0Yp{wdaA_IpFb{L^9?!!%snSy5 zCPRT?HS~~CyTH?GA2L5N5<2aZQNvvub?4jF9sU=0Us<(lH+NMmp&IyH`!AXIcmv9? z06*Y6eJeExAMh(?iv8n-HIPsh`zURA(3(AD_mVniF2XXH?qJr1O;~~oOv+5)GmE^k z9GK<;)4WXlHS_{+5*hnzQ01QxnfHHZ%Irt_p4YI)UlR}tWDcV#@`cFUPKi|TH_{T> a9b%o%y~;O5JoP^>gnk0f#ioIg1poj>IfOO< literal 0 HcmV?d00001 diff --git a/testdata/lefdef/specialnets_geo/au_no_spnet.oas.gz b/testdata/lefdef/specialnets_geo/au_no_spnet.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..4bf45b0312df6e018c5d1584253c6957ddcc26cf GIT binary patch literal 224 zcmV<603ZJ!iwFojGn`%k19WY0E^lFT08Z@2gEzO`uOm0 zBxht6#Fyk3Fe6xeVV;ihKx`PFQkt7v$<6K`8sg*W=gQ2&%)o=p;b!tRWM%{kLTMo1 zh?yD82h-dvAXAu`fFf`fFQce6BLgFoO@OAns3kKaQ%Z`lv8W{zBa?=Ps37yzyJVUeg2RN0ssIj8)hf~ literal 0 HcmV?d00001 diff --git a/testdata/lefdef/specialnets_geo/au_spnet_mapped.oas.gz b/testdata/lefdef/specialnets_geo/au_spnet_mapped.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..7decf1260d997e1cf39da23007c07dbec4fafd37 GIT binary patch literal 378 zcmV-=0fqh_iwFpyHJn}m19WY0E^lFT0OgE5Pr^_XhVMDI(n1T3375f?=wie{LS>QY zLZrbaP#SLWW4eP3IuIFjaAR~}@Fy522Syh+qX}t@adL2UboUQ8`b^+~w&MP`g+nA1aBD#TK||R`&&W>z-2+t`|6Ur!Dr}TCk%jR@(ZmJKkS{ z#Zp`ZEnjRqjfSBe9v%0^=}BMBa8a*u;kR49(+&=jbKSFE@0?Brn%Q-$LOxqWjjpyj zLBsVNs!(FYK~FU8q7*4m-H7cnUypVg<LRO9z;3r(W)%c16c|gB`F98*`>2o+=00i4RI?z15UdrVfl1hgqCVjR zhBz=^aE#A*3$K{}jW5i5oWw(u4MC=WA&l^nl8K>QC$17ViLvpfj4+?OgCvoMiR_j@ YI-&efic5JM{O2L$3*NHe>hb~r0R5=4a{vGU literal 0 HcmV?d00001 diff --git a/testdata/ruby/dbReaders.rb b/testdata/ruby/dbReaders.rb index 9cc558f75..c874c782f 100644 --- a/testdata/ruby/dbReaders.rb +++ b/testdata/ruby/dbReaders.rb @@ -269,6 +269,18 @@ class DBReaders_TestClass < TestBase conf.pins_datatype = 18 assert_equal(conf.pins_datatype, 18) + assert_equal(conf.produce_lef_pins, true) + conf.produce_lef_pins = false + assert_equal(conf.produce_lef_pins, false) + + assert_equal(conf.lef_pins_suffix, ".PIN") + conf.lef_pins_suffix = "LEFPIN" + assert_equal(conf.lef_pins_suffix, "LEFPIN") + + assert_equal(conf.lef_pins_datatype, 2) + conf.lef_pins_datatype = 181 + assert_equal(conf.lef_pins_datatype, 181) + assert_equal(conf.produce_obstructions, true) conf.produce_obstructions = false assert_equal(conf.produce_obstructions, false) @@ -317,6 +329,18 @@ class DBReaders_TestClass < TestBase conf.routing_datatype = 22 assert_equal(conf.routing_datatype, 22) + assert_equal(conf.produce_special_routing, true) + conf.produce_special_routing = false + assert_equal(conf.produce_special_routing, false) + + assert_equal(conf.special_routing_suffix, "") + conf.special_routing_suffix = "SPROUT" + assert_equal(conf.special_routing_suffix, "SPROUT") + + assert_equal(conf.special_routing_datatype, 0) + conf.special_routing_datatype = 23 + assert_equal(conf.special_routing_datatype, 23) + assert_equal(conf.separate_groups, false) conf.separate_groups = true assert_equal(conf.separate_groups, true) From 040af426dcfa8dd3cd11b2643fd19bde2c5d6981 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 19 Apr 2020 16:54:41 +0200 Subject: [PATCH 30/43] WIP: refactoring of map file reading. --- src/db/db/dbLayoutUtils.h | 2 +- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 268 +++++++++++++++--- .../lefdef/db_plugin/dbLEFDEFImporter.h | 48 +++- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 155 +--------- .../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 16 +- .../LEFDEFTechnologyComponentEditor.ui | 178 ++++++++---- .../lay_plugin/layLEFDEFImportDialogs.cc | 10 + .../lay_plugin/layLEFDEFImportDialogs.h | 1 + .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 11 +- testdata/ruby/dbReaders.rb | 4 + 10 files changed, 444 insertions(+), 249 deletions(-) diff --git a/src/db/db/dbLayoutUtils.h b/src/db/db/dbLayoutUtils.h index 07ba86332..badbf8ae6 100644 --- a/src/db/db/dbLayoutUtils.h +++ b/src/db/db/dbLayoutUtils.h @@ -42,7 +42,7 @@ namespace db * * This implementation will create new layers if required. */ -class DirectLayerMapping +class DB_PUBLIC DirectLayerMapping : public ImportLayerMapping { public: diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 07122526d..431ff911f 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 "dbLayoutUtils.h" #include "tlStream.h" #include "tlProgress.h" +#include "tlFileUtils.h" #include @@ -74,7 +76,8 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_produce_special_routing (true), m_special_routing_suffix (""), m_special_routing_datatype (0), - m_separate_groups (false) + m_separate_groups (false), + m_consider_map_file (true) { // .. nothing yet .. } @@ -121,6 +124,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_special_routing_suffix (d.m_special_routing_suffix), m_special_routing_datatype (d.m_special_routing_datatype), m_separate_groups (d.m_separate_groups), + m_consider_map_file (d.m_consider_map_file), m_lef_files (d.m_lef_files) { // .. nothing yet .. @@ -142,8 +146,20 @@ LEFDEFReaderOptions::format_name () const // ----------------------------------------------------------------------------------- // LEFDEFLayerDelegate implementation +static db::LayerProperties lp_from_string (const std::string &ld) +{ + db::LayerProperties lp; + tl::Extractor ex (ld.c_str ()); + try { + ex.read (lp); + return lp; + } catch (...) { + return db::LayerProperties (0, 0); + } +} + LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc) - : m_create_layers (true), m_laynum (1), mp_tech_comp (tc) + : m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc) { if (tc) { m_layer_map = tc->layer_map (); @@ -158,8 +174,208 @@ LEFDEFReaderState::register_layer (const std::string &ln) ++m_laynum; } -std::pair +void +LEFDEFReaderState::set_explicit_layer_mapping (bool f) +{ + m_has_explicit_layer_mapping = f; + if (! f) { + m_layers.clear (); + } +} + +void +LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpose, unsigned int layer) +{ + m_layers [std::make_pair (n, purpose)] = std::make_pair (true, layer); +} + +void +LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) +{ + tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path; + + tl::InputFile file (path); + tl::InputStream file_stream (file); + tl::TextInputStream ts (file_stream); + + std::map purpose_translation; + purpose_translation ["LEFPIN"] = LEFPins; + purpose_translation ["PIN"] = Pins; + purpose_translation ["LEFOBS"] = Obstructions; + purpose_translation ["SPNET"] = SpecialRouting; + purpose_translation ["NET"] = Routing; + purpose_translation ["VIA"] = ViaGeometry; + purpose_translation ["BLOCKAGE"] = Blockage; + + std::map, db::LayerProperties> layer_map; + + if (tech_comp ()) { + + const db::LEFDEFReaderOptions &options = *tech_comp (); + + if (options.produce_placement_blockages ()) { + layer_map [std::make_pair (std::string (), Blockage)] = lp_from_string (options.placement_blockage_layer ()); + } + if (options.produce_cell_outlines ()) { + layer_map [std::make_pair (std::string (), Outline)] = lp_from_string (options.cell_outline_layer ()); + } + if (options.produce_regions ()) { + layer_map [std::make_pair (std::string (), Region)] = lp_from_string (options.region_layer ()); + } + + } + + while (! ts.at_end ()) { + + const std::string &l = ts.get_line (); + + tl::Extractor ex (l.c_str ()); + if (ex.at_end () || ex.test ("#")) { + + // ignore empty of comment lines + + } else { + + std::string w1, w2; + int layer = 0, datatype = 0; + + if (ex.try_read_word (w1) && ex.try_read_word (w2, "._$,/:") && ex.try_read (layer) && ex.try_read (datatype)) { + + if (w1 == "DIEAREA") { + + layer_map [std::make_pair (std::string (), Outline)] = db::LayerProperties (layer, datatype, "OUTLINE"); + + } else if (w1 == "NAME") { + + // converts a line like + // "NAME M1/PINS,M2/PINS ..." + // into a canonical name mapping like + // "(M1/LABELS): M1.LABEL" + // "(M2/LABELS): M2.LABEL" + + std::vector layers; + std::vector purposes = tl::split (w2, ","); + for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { + layers.push_back (tl::split (*p, "/").front ()); + } + + std::string final_name = tl::join (layers, "/") + ".LABEL"; + for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { + layer_map [std::make_pair (*l, Label)] = db::LayerProperties (layer, datatype, final_name); + } + + } else { + + // converts a line like + // "M1 SPNET,NET,PINS,LEFPINS ..." + // into a canonical name mapping like + // "(M1,NET): M1.NET/PINS" + // "(M1,PINS): M1.NET/PINS" + // (separating, translating and recombing the purposes) + + std::set translated_purposes; + std::string purpose_str; + std::vector purposes = tl::split (w2, ","); + for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { + + std::map::const_iterator i = purpose_translation.find (tl::to_upper_case (*p)); + if (i != purpose_translation.end ()) { + + translated_purposes.insert (i->second); + + if (! purpose_str.empty ()) { + purpose_str += "/"; + } + purpose_str += i->first; + + } + } + + std::string final_name = w1 + "." + purpose_str; + + for (std::set::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) { + layer_map [std::make_pair (w1, *p)] = db::LayerProperties (layer, datatype, final_name); + } + + } + + } + + } + + } + + set_explicit_layer_mapping (true); + + db::DirectLayerMapping lm (&layout); + for (std::map, db::LayerProperties>::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) { + map_layer_explicit (i->first.first, i->first.second, lm.map_layer (i->second).second); + } + + // @@@ TODO: need to assign layer/datatype for all layers present. +} + +void +LEFDEFReaderState::import_map_file_heuristics (const std::string &main_path, db::Layout &layout) +{ + std::string input_dir = tl::absolute_path (main_path); + if (! tl::file_exists (input_dir)) { + return; + } + + std::string bn = tl::basename (tl::filename (main_path)); + std::vector map_files; + std::string map_file_exact; + + std::vector entries = tl::dir_entries (input_dir); + for (std::vector::const_iterator e = entries.begin (); e != entries.end (); ++e) { + + if (tl::to_lower_case (tl::extension (*e)) == "map") { + + if (tl::basename (*e) == bn) { + map_file_exact = *e; + } else { + map_files.push_back (*e); + } + + } + + } + + try { + if (! map_file_exact.empty ()) { + read_map_file (tl::combine_path (input_dir, map_file_exact), layout); + } else if (map_files.size () == 1) { + read_map_file (tl::combine_path (input_dir, map_files.front ()), layout); + } + } catch (tl::Exception &ex) { + // ignore read errors on map file (this is a heuristics!) + tl::error << ex.msg (); + } +} + +std::pair LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose) +{ + std::map , std::pair >::const_iterator nl = m_layers.find (std::make_pair (n, purpose)); + if (nl == m_layers.end ()) { + + std::pair ll (false, 0); + + if (! m_has_explicit_layer_mapping) { + ll = open_layer_uncached (layout, n, purpose); + } + + m_layers.insert (std::make_pair (std::make_pair (n, purpose), ll)); + return ll; + + } else { + return nl->second; + } +} + +std::pair +LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n, LayerPurpose purpose) { if (purpose == Outline || purpose == PlacementBlockage || purpose == Region) { @@ -167,21 +383,17 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu // as is "(name)". It's used for implementing the automatic map file import // feature. std::string ld; - std::string canonical_name; bool produce; if (purpose == Outline) { produce = mp_tech_comp->produce_cell_outlines (); ld = mp_tech_comp->cell_outline_layer (); - canonical_name = "(OUTLINE)"; } else if (purpose == Region) { produce = mp_tech_comp->produce_regions (); ld = mp_tech_comp->region_layer (); - canonical_name = "(REGION)"; } else { produce = mp_tech_comp->produce_placement_blockages (); ld = mp_tech_comp->placement_blockage_layer (); - canonical_name = "(BLK)"; } if (! produce) { @@ -203,10 +415,6 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu return ll; - } else if ((ll = m_layer_map.logical (db::LayerProperties (canonical_name), layout)).first) { - - return ll; - } else if (! m_create_layers) { return std::pair (false, 0); @@ -256,74 +464,54 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu } // Note: "name" is the decorated name as provided by the tech component's - // x_suffix specifications. As this is a variable entity, we also provide - // a canonical name of the form "(layer,purpose)" where purpose is a - // predefined suffix. The canonical name is the last fallback. Hence this - // allows importing layer mapping files as canonical name mapping. + // x_suffix specifications. std::string name (n); int dt = 0; - std::string canonical_purpose; - if (mp_tech_comp) { switch (purpose) { case Routing: default: name += mp_tech_comp->routing_suffix (); - canonical_purpose = "NET"; dt += mp_tech_comp->routing_datatype (); break; case SpecialRouting: name += mp_tech_comp->special_routing_suffix (); - canonical_purpose = "SPNET"; dt += mp_tech_comp->special_routing_datatype (); break; case ViaGeometry: name += mp_tech_comp->via_geometry_suffix (); dt += mp_tech_comp->via_geometry_datatype (); - canonical_purpose = "VIA"; break; case Label: name += mp_tech_comp->labels_suffix (); dt += mp_tech_comp->labels_datatype (); - canonical_purpose = "LABEL"; break; case Pins: name += mp_tech_comp->pins_suffix (); dt += mp_tech_comp->pins_datatype (); - canonical_purpose = "PIN"; break; case LEFPins: name += mp_tech_comp->lef_pins_suffix (); dt += mp_tech_comp->lef_pins_datatype (); - canonical_purpose = "LEFPIN"; break; case Obstructions: name += mp_tech_comp->obstructions_suffix (); dt += mp_tech_comp->obstructions_datatype (); - canonical_purpose = "OBS"; break; case Blockage: name += mp_tech_comp->blockages_suffix (); dt += mp_tech_comp->blockages_datatype (); - canonical_purpose = "BLK"; break; } } - std::string canonical_name = std::string ("(") + n + "," + canonical_purpose + ")"; - std::pair ll = m_layer_map.logical (name, layout); if (ll.first) { return ll; - } else if ((ll = m_layer_map.logical (db::LayerProperties (canonical_name), layout)).first) { - - // final fallback: try canonical name - return ll; - } else { ll = m_layer_map.logical (n, layout); @@ -341,14 +529,14 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu } else { - std::map , unsigned int>::const_iterator nl = m_layers.find (std::make_pair (n, purpose)); - if (nl == m_layers.end ()) { - unsigned int li = layout.insert_layer (db::LayerProperties (name)); - m_layer_map.map (db::LayerProperties (name), li); - m_layers.insert (std::make_pair (std::make_pair (n, purpose), li)); - return std::pair (true, li); + std::map , unsigned int>::const_iterator l = m_unassigned_layers.find (std::make_pair (n, purpose)); + if (l != m_unassigned_layers.end ()) { + return std::pair (true, l->second); } else { - return std::pair (true, nl->second); + unsigned int li = layout.insert_layer (db::LayerProperties (name)); + m_unassigned_layers.insert (std::make_pair (std::make_pair (n, purpose), li)); + m_layer_map.map (db::LayerProperties (name), li); + return std::pair (true, li); } } @@ -380,7 +568,7 @@ LEFDEFReaderState::finish (db::Layout &layout) used_numbers.insert (ln->second); } - for (std::map, unsigned int>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { + for (std::map, unsigned int>::const_iterator l = m_unassigned_layers.begin (); l != m_unassigned_layers.end (); ++l) { int dt = 0; switch (l->first.second) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 6c9adf325..df61cf62e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -515,6 +515,16 @@ public: m_separate_groups = f; } + bool consider_map_file () const + { + return m_consider_map_file; + } + + void set_consider_map_file (bool f) + { + m_consider_map_file = f; + } + private: bool m_read_all_layers; db::LayerMap m_layer_map; @@ -557,6 +567,7 @@ private: std::string m_special_routing_suffix; int m_special_routing_datatype; bool m_separate_groups; + bool m_consider_map_file; std::vector m_lef_files; }; @@ -592,7 +603,32 @@ public: LEFDEFReaderState (const LEFDEFReaderOptions *tc); /** - * @brief Set the layer map + * @brief Provides an explicit layer mapping + * This method is used when reading the layer map file. + */ + void map_layer_explicit (const std::string &n, LayerPurpose purpose, unsigned int layer); + + /** + * @brief Provides an explicit layer mapping + * If this flag is set, the layer mapping specified in the reader options are ignored. + */ + void set_explicit_layer_mapping (bool f); + + /** + * @brief Reads a map file + */ + void read_map_file (const std::string &path, db::Layout &layout); + + /** + * @brief Imports a .map file present next to the input files + * "main_path" path of an input file (DEF). If a suitable .map file is found at this path, + * it is loaded into the reader state object. This will eventually disable any other layer + * mapping except for the global layers (region, outline, placement blockage). + */ + void import_map_file_heuristics (const std::string &main_path, db::Layout &layout); + + /** + * @brief Sets the layer map */ virtual void set_layer_map (const db::LayerMap &lm, bool create_layers) { @@ -601,7 +637,7 @@ public: } /** - * @brief Get the layer map + * @brief Gets the layer map */ const db::LayerMap &layer_map () const { @@ -609,7 +645,7 @@ public: } /** - * @brief Get the layer map (non-const version) + * @brief Gets the layer map (non-const version) */ db::LayerMap &layer_map () { @@ -655,13 +691,17 @@ public: } private: - std::map , unsigned int> m_layers; + std::map , std::pair > m_layers; + std::map , unsigned int> m_unassigned_layers; db::LayerMap m_layer_map; bool m_create_layers; + bool m_has_explicit_layer_mapping; int m_laynum; std::map m_default_number; std::map m_via_cells; const LEFDEFReaderOptions *mp_tech_comp; + + std::pair open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose); }; /** diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 699518e7a..f42a438e2 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -30,6 +30,7 @@ #include "dbLEFImporter.h" #include "dbDEFImporter.h" #include "dbLEFDEFImporter.h" +#include "dbLayoutUtils.h" namespace db { @@ -77,156 +78,6 @@ static bool is_def_format (const std::string &fn) return false; } -/** - * @brief Reads a map file - * - * NOTE: this is rather experimental ... no idea what is the specification of - * the map file. - */ -static void -read_map_file (const std::string &path, db::LEFDEFReaderState &layers) -{ - tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path; - - db::LayerMap &lm = layers.layer_map (); - unsigned int n = lm.next_index (); - - tl::InputFile file (path); - tl::InputStream file_stream (file); - tl::TextInputStream ts (file_stream); - - std::map purpose_translation; - purpose_translation ["LEFPIN"] = "LEFPIN"; - purpose_translation ["PIN"] = "PIN"; - purpose_translation ["LEFOBS"] = "OBS"; - purpose_translation ["SPNET"] = "SPNET"; - purpose_translation ["NET"] = "NET"; - purpose_translation ["VIA"] = "VIA"; - purpose_translation ["BLOCKAGE"] = "BLK"; - - while (! ts.at_end ()) { - - const std::string &l = ts.get_line (); - - tl::Extractor ex (l.c_str ()); - if (ex.at_end () || ex.test ("#")) { - - // ignore empty of comment lines - - } else { - - std::string w1, w2; - int layer = 0, datatype = 0; - - if (ex.try_read_word (w1) && ex.try_read_word (w2, "._$,/:") && ex.try_read (layer) && ex.try_read (datatype)) { - - if (w1 == "DIEAREA") { - - std::string canonical_name = "OUTLINE"; - lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype)); - - } else if (w1 == "NAME") { - - // converts a line like - // "NAME M1/PINS,M2/PINS ..." - // into a canonical name mapping like - // "(M1/LABELS): M1.LABEL" - // "(M2/LABELS): M2.LABEL" - - std::vector layers; - std::vector purposes = tl::split (w2, ","); - for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { - layers.push_back (tl::split (*p, "/").front ()); - } - - std::string final_name = tl::join (layers, "/") + ".LABEL"; - for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { - std::string canonical_name = std::string ("(") + *l + ",LABEL)"; - lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name)); - } - ++n; - - } else { - - // converts a line like - // "M1 SPNET,NET,PINS,LEFPINS ..." - // into a canonical name mapping like - // "(M1,NET): M1.NET/PINS" - // "(M1,PINS): M1.NET/PINS" - // (separating, translating and recombing the purposes) - - std::vector translated_purposes; - std::vector purposes = tl::split (w2, ","); - for (std::vector::const_iterator p = purposes.begin (); p != purposes.end (); ++p) { - std::map::const_iterator i = purpose_translation.find (tl::to_upper_case (*p)); - if (i != purpose_translation.end ()) { - translated_purposes.push_back (i->second); - } - } - - std::sort (translated_purposes.begin (), translated_purposes.end ()); - translated_purposes.erase (std::unique (translated_purposes.begin (), translated_purposes.end ()), translated_purposes.end ()); - std::string final_name = w1 + "." + tl::join (translated_purposes, "/"); - - for (std::vector::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) { - std::string canonical_name = std::string ("(") + w1 + "," + *p + ")"; - lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name)); - } - ++n; - - } - - } - - } - - } -} - -/** - * @brief Imports a .map file present next to the input files - */ -static void -import_map_file_heuristics (const std::string &main_path, db::LEFDEFReaderState &layers) -{ - std::string input_dir = tl::absolute_path (main_path); - if (! tl::file_exists (input_dir)) { - return; - } - - std::string bn = tl::basename (tl::filename (main_path)); - std::vector map_files; - std::string map_file_exact; - - std::vector entries = tl::dir_entries (input_dir); - for (std::vector::const_iterator e = entries.begin (); e != entries.end (); ++e) { - - if (tl::to_lower_case (tl::extension (*e)) == "map") { - - if (tl::basename (*e) == bn) { - map_file_exact = *e; - } else { - map_files.push_back (*e); - } - - } - - } - - try { - if (! map_file_exact.empty ()) { - read_map_file (tl::combine_path (input_dir, map_file_exact), layers); - tl::log << layers.layer_map ().to_string_file_format (); // @@@ - } else if (map_files.size () == 1) { - read_map_file (tl::combine_path (input_dir, map_files.front ()), layers); - tl::log << layers.layer_map ().to_string_file_format (); // @@@ - } - } catch (tl::Exception &ex) { - // ignore read errors on map file (this is a heuristics!) - tl::error << ex.msg (); - } -} - class LEFDEFReader : public db::ReaderBase { @@ -275,7 +126,9 @@ private: db::LEFDEFReaderState state (lefdef_options); - import_map_file_heuristics (m_stream.absolute_path (), state); + if (lefdef_options->consider_map_file ()) { + state.import_map_file_heuristics (m_stream.absolute_path (), layout); + } state.prepare (layout); layout.dbu (lefdef_options->dbu ()); diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index 6d31e64cc..14336a90b 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -461,11 +461,25 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "This property has been added in version 0.26.5.\n" ) + gsi::method ("separate_groups=", &db::LEFDEFReaderOptions::set_separate_groups, gsi::arg ("flag"), - "@brief Gets a value indicating whether to create separate parent cells for individual groups.\n" + "@brief Sets a value indicating whether to create separate parent cells for individual groups.\n" "See \\seperate_groups for details about this property.\n" "\n" "This property has been added in version 0.26.5.\n" ) + + gsi::method ("consider_map_file", &db::LEFDEFReaderOptions::consider_map_file, + "@brief Gets a value indicating whether to consider reading .map files next to DEF files.\n" + "If this property is set to true (the default), the DEF reader will look for .map files next to the " + "DEF file. If such a file is found, it will be used to map DEF layers to layout layers. The layer mapping " + "settings specified in the reader options are ignored in this case.\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + + gsi::method ("consider_map_file=", &db::LEFDEFReaderOptions::set_consider_map_file, gsi::arg ("flag"), + "@brief Sets a value indicating whether to consider reading .map files next to DEF files.\n" + "See \\consider_map_file for details about this property.\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files, "@brief Gets the list technology LEF files to additionally import\n" "Returns a list of path names for technology LEF files to read in addition to the primary file. " diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui index 845452c8e..1ae4b3c64 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui +++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui @@ -207,17 +207,13 @@ 4 - - - - Layout database unit - - - - - - - Via cell name prefix + + + + + 0 + 0 + @@ -234,6 +230,34 @@ + + + + Produce a parent cell for each group + + + + + + + Via cell name prefix + + + + + + + Layout database unit + + + + + + + Separate groups + + + @@ -244,27 +268,20 @@ - - - - - 0 - 0 - + + + + Consider map files - - + + - Produce a parent cell for each group + Look for .map files next to DEF files and use them to map layers - - - - - - Separate groups + + true @@ -517,13 +534,6 @@ - - - - Produce ... - - - @@ -764,6 +774,56 @@ + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Layer assignment is not used if a .map file is present for DEF layer mapping + + + + + + :/warn_16.png + + + + + + + + 1 + 0 + + + + Produce ... + + + + + + @@ -781,10 +841,7 @@ true - - - 6 - + 9 @@ -797,21 +854,14 @@ 4 - + Read all layers (additionally to the ones in the mapping table) - - - - Qt::Horizontal - - - - + @@ -833,6 +883,32 @@ + + + + + 0 + 0 + + + + This table is not used if a .map file is present for DEF layer mapping + + + + + + :/warn_16.png + + + + + + + Qt::Horizontal + + + @@ -881,12 +957,12 @@ setChecked(bool) - 186 - 598 + 229 + 838 - 155 - 553 + 198 + 701 diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc index 16b70262d..fec570018 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc @@ -363,6 +363,7 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent) connect (del_lef_files, SIGNAL (clicked ()), this, SLOT (del_lef_files_clicked ())); connect (move_lef_files_up, SIGNAL (clicked ()), this, SLOT (move_lef_files_up_clicked ())); connect (move_lef_files_down, SIGNAL (clicked ()), this, SLOT (move_lef_files_down_clicked ())); + connect (consider_map_file, SIGNAL (stateChanged (int)), this, SLOT (consider_map_file_state_changed ())); lay::activate_help_links (help_label); } @@ -450,6 +451,7 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_labels_suffix (tl::to_string (suffix_labels->text ())); data->set_labels_datatype (datatype_labels->text ().toInt ()); data->set_separate_groups (separate_groups->isChecked ()); + data->set_consider_map_file (consider_map_file->isChecked ()); data->clear_lef_files (); for (int i = 0; i < lef_files->count (); ++i) { @@ -510,6 +512,7 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options suffix_labels->setText (tl::to_qstring (data->labels_suffix ())); datatype_labels->setText (QString::number (data->labels_datatype ())); separate_groups->setChecked (data->separate_groups ()); + consider_map_file->setChecked (data->consider_map_file ()); checkbox_changed (); @@ -526,6 +529,13 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options } } +void +LEFDEFReaderOptionsEditor::consider_map_file_state_changed () +{ + warn1->setVisible (consider_map_file->isChecked ()); + warn2->setVisible (consider_map_file->isChecked ()); +} + void LEFDEFReaderOptionsEditor::checkbox_changed () { diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h index 7234c76aa..1da4f81b2 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h @@ -98,6 +98,7 @@ private slots: void del_lef_files_clicked (); void move_lef_files_up_clicked (); void move_lef_files_down_clicked (); + void consider_map_file_state_changed (); private: tl::weak_ptr mp_tech; diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 45b21683b..97e36f7d9 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -69,7 +69,15 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file while (! ex.at_end ()) { - if (ex.test ("def:")) { + if (ex.test ("map:")) { + + std::string fn = fn_path, f; + ex.read_word_or_quoted (f); + fn += f; + + ld.read_map_file (fn, layout); + + } else if (ex.test ("def:")) { std::string fn = fn_path, f; ex.read_word_or_quoted (f); @@ -230,6 +238,7 @@ TEST(15) TEST(16) { run_test (_this, "def7", "lef:cells.lef+lef:tech.lef+def:in.def.gz", "au.oas.gz", default_options ()); + run_test (_this, "def7", "map:in.map+lef:cells.lef+lef:tech.lef+def:in.def.gz", "au_with_map_file.oas.gz", default_options ()); } TEST(17) diff --git a/testdata/ruby/dbReaders.rb b/testdata/ruby/dbReaders.rb index c874c782f..b17092355 100644 --- a/testdata/ruby/dbReaders.rb +++ b/testdata/ruby/dbReaders.rb @@ -345,6 +345,10 @@ class DBReaders_TestClass < TestBase conf.separate_groups = true assert_equal(conf.separate_groups, true) + assert_equal(conf.consider_map_file, true) + conf.consider_map_file = false + assert_equal(conf.consider_map_file, false) + assert_equal(conf.lef_files.join(","), "") conf.lef_files = [ "u.lef", "v.lef" ] assert_equal(conf.lef_files.join(","), "u.lef,v.lef") From 71906a5681f1feede10997dbd5809d2dcb435c8a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 19 Apr 2020 19:12:03 +0200 Subject: [PATCH 31/43] WIP: some further refactoring of the layer mapping scheme. --- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 431ff911f..78e8e26cc 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -209,22 +209,6 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) std::map, db::LayerProperties> layer_map; - if (tech_comp ()) { - - const db::LEFDEFReaderOptions &options = *tech_comp (); - - if (options.produce_placement_blockages ()) { - layer_map [std::make_pair (std::string (), Blockage)] = lp_from_string (options.placement_blockage_layer ()); - } - if (options.produce_cell_outlines ()) { - layer_map [std::make_pair (std::string (), Outline)] = lp_from_string (options.cell_outline_layer ()); - } - if (options.produce_regions ()) { - layer_map [std::make_pair (std::string (), Region)] = lp_from_string (options.region_layer ()); - } - - } - while (! ts.at_end ()) { const std::string &l = ts.get_line (); @@ -311,8 +295,6 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) for (std::map, db::LayerProperties>::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) { map_layer_explicit (i->first.first, i->first.second, lm.map_layer (i->second).second); } - - // @@@ TODO: need to assign layer/datatype for all layers present. } void @@ -362,7 +344,7 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu std::pair ll (false, 0); - if (! m_has_explicit_layer_mapping) { + if (n.empty () || ! m_has_explicit_layer_mapping) { ll = open_layer_uncached (layout, n, purpose); } @@ -377,13 +359,13 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu std::pair LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n, LayerPurpose purpose) { - if (purpose == Outline || purpose == PlacementBlockage || purpose == Region) { + if (n.empty ()) { // NOTE: the canonical name is independent from the tech component's settings // as is "(name)". It's used for implementing the automatic map file import // feature. std::string ld; - bool produce; + bool produce = false; if (purpose == Outline) { produce = mp_tech_comp->produce_cell_outlines (); From c7de5420702f7f889b1890392a1ca69cdca63be9 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 19 Apr 2020 20:14:12 +0200 Subject: [PATCH 32/43] Some more refactoring of DEF layer mapping --- .../lefdef/db_plugin/dbDEFImporter.cc | 4 +- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 39 ++++++++----------- .../lefdef/db_plugin/dbLEFDEFImporter.h | 11 ++---- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 3 +- .../lefdef/lay_plugin/layLEFDEFImport.cc | 15 ++++--- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 4 +- 6 files changed, 30 insertions(+), 46 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 708e29b12..3c6e00563 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -1398,7 +1398,7 @@ DEFImporter::do_read (db::Layout &layout) } else { - std::pair dl = open_layer (layout, std::string (), Region); + std::pair dl = open_layer (layout, std::string (), Regions); if (dl.first) { for (std::vector::const_iterator p = r->second.begin (); p != r->second.end (); ++p) { group_cell->shapes (dl.second).insert (*p); @@ -1441,7 +1441,7 @@ DEFImporter::do_read (db::Layout &layout) if (! regions.empty ()) { - std::pair dl = open_layer (layout, std::string (), Region); + std::pair dl = open_layer (layout, std::string (), Regions); if (dl.first) { for (std::map >::const_iterator r = regions.begin (); r != regions.end (); ++r) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 78e8e26cc..11105b085 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -146,25 +146,15 @@ LEFDEFReaderOptions::format_name () const // ----------------------------------------------------------------------------------- // LEFDEFLayerDelegate implementation -static db::LayerProperties lp_from_string (const std::string &ld) -{ - db::LayerProperties lp; - tl::Extractor ex (ld.c_str ()); - try { - ex.read (lp); - return lp; - } catch (...) { - return db::LayerProperties (0, 0); - } -} - -LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc) +LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout) : m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc) { if (tc) { m_layer_map = tc->layer_map (); m_create_layers = tc->read_all_layers (); } + + m_layer_map.prepare (layout); } void @@ -184,9 +174,10 @@ LEFDEFReaderState::set_explicit_layer_mapping (bool f) } void -LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpose, unsigned int layer) +LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpose, const db::LayerProperties &lp, unsigned int layer) { m_layers [std::make_pair (n, purpose)] = std::make_pair (true, layer); + m_layer_map.map (lp, layer); } void @@ -229,6 +220,14 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) layer_map [std::make_pair (std::string (), Outline)] = db::LayerProperties (layer, datatype, "OUTLINE"); + } else if (w1 == "REGIONS") { + + layer_map [std::make_pair (std::string (), Regions)] = db::LayerProperties (layer, datatype, "REGIONS"); + + } else if (w1 == "BLOCKAGE") { + + layer_map [std::make_pair (std::string (), PlacementBlockage)] = db::LayerProperties (layer, datatype, "PLACEMENT_BLK"); + } else if (w1 == "NAME") { // converts a line like @@ -293,7 +292,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) db::DirectLayerMapping lm (&layout); for (std::map, db::LayerProperties>::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) { - map_layer_explicit (i->first.first, i->first.second, lm.map_layer (i->second).second); + map_layer_explicit (i->first.first, i->first.second, i->second, lm.map_layer (i->second).second); } } @@ -370,10 +369,10 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n if (purpose == Outline) { produce = mp_tech_comp->produce_cell_outlines (); ld = mp_tech_comp->cell_outline_layer (); - } else if (purpose == Region) { + } else if (purpose == Regions) { produce = mp_tech_comp->produce_regions (); ld = mp_tech_comp->region_layer (); - } else { + } else if (purpose == PlacementBlockage) { produce = mp_tech_comp->produce_placement_blockages (); ld = mp_tech_comp->placement_blockage_layer (); } @@ -528,12 +527,6 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n } } -void -LEFDEFReaderState::prepare (db::Layout &layout) -{ - m_layer_map.prepare (layout); -} - void LEFDEFReaderState::finish (db::Layout &layout) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index df61cf62e..40838f89d 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -586,7 +586,7 @@ enum LayerPurpose Outline, // from LEF+DEF Blockage, // from DEF only PlacementBlockage, // from DEF only - Region, // from DEF only + Regions, // from DEF only }; /** @@ -600,13 +600,13 @@ public: /** * @brief Constructor */ - LEFDEFReaderState (const LEFDEFReaderOptions *tc); + LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout); /** * @brief Provides an explicit layer mapping * This method is used when reading the layer map file. */ - void map_layer_explicit (const std::string &n, LayerPurpose purpose, unsigned int layer); + void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer); /** * @brief Provides an explicit layer mapping @@ -662,11 +662,6 @@ public: */ void register_layer (const std::string &l); - /** - * @brief Prepare, i.e. create layers required by the layer map - */ - void prepare (db::Layout &layout); - /** * @brief Finish, i.e. assign GDS layer numbers to the layers */ diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index f42a438e2..4caffcf97 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -124,13 +124,12 @@ private: lefdef_options = &default_options; } - db::LEFDEFReaderState state (lefdef_options); + db::LEFDEFReaderState state (lefdef_options, layout); if (lefdef_options->consider_map_file ()) { state.import_map_file_heuristics (m_stream.absolute_path (), layout); } - state.prepare (layout); layout.dbu (lefdef_options->dbu ()); if (import_lef) { diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc index 14d8c7463..f16b275ef 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImport.cc @@ -140,8 +140,7 @@ public: } } - db::LEFDEFReaderState layers (&options); - layers.prepare (*layout); + db::LEFDEFReaderState state (&options, *layout); layout->dbu (options.dbu ()); if (import_lef) { @@ -153,11 +152,11 @@ public: for (std::vector::const_iterator l = options.begin_lef_files (); l != options.end_lef_files (); ++l) { tl::InputStream lef_stream (*l); tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l; - importer.read (lef_stream, *layout, layers); + importer.read (lef_stream, *layout, state); } tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file; - importer.read (stream, *layout, layers); + importer.read (stream, *layout, state); } else { @@ -177,23 +176,23 @@ public: if (fi.isAbsolute ()) { tl::InputStream lef_stream (*l); tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l; - importer.read_lef (lef_stream, *layout, layers); + importer.read_lef (lef_stream, *layout, state); } else { std::string ex_l = tl::to_string (def_fi.absoluteDir ().absoluteFilePath (tl::to_qstring (*l))); tl::InputStream lef_stream (ex_l); tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l; - importer.read_lef (lef_stream, *layout, layers); + importer.read_lef (lef_stream, *layout, state); } } tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file; - importer.read (stream, *layout, layers); + importer.read (stream, *layout, state); } - layers.finish (*layout); + state.finish (*layout); lay::LayoutView *view = lay::LayoutView::current (); if (! view || data.mode == 1) { diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 97e36f7d9..cdd6bf28c 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -56,14 +56,12 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file fn_path += lef_dir; fn_path += "/"; - db::LEFDEFReaderState ld (&tc); - db::Manager m (false); db::Layout layout (&m), layout2 (&m), layout_au (&m); tl::Extractor ex (filename); - ld.prepare (layout); + db::LEFDEFReaderState ld (&tc, layout); db::DEFImporter imp; From f6140055d653944bb5fa36da95524672578b54a9 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 24 Apr 2020 23:21:27 +0200 Subject: [PATCH 33/43] Modified reader scheme for FOREIGNCELL --- src/laybasic/laybasic/layLayerProperties.cc | 13 +++-- .../lefdef/db_plugin/dbDEFImporter.cc | 6 +-- .../lefdef/db_plugin/dbLEFImporter.cc | 47 ++++++++++++------ .../lefdef/db_plugin/dbLEFImporter.h | 4 +- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 9 ++-- testdata/lefdef/foreigncell/au.oas.gz | Bin 859 -> 811 bytes .../foreigncell/au_lefpins_mapped.oas.gz | Bin 859 -> 0 bytes .../lefdef/foreigncell/au_no_lefpins.oas.gz | Bin 796 -> 0 bytes testdata/lefdef/foreigncell/foreign.gds | Bin 3484 -> 3722 bytes testdata/lefdef/foreigncell/in.def | 17 +++++++ .../lefdef/lefpins/au_lefpins_mapped.oas.gz | Bin 0 -> 335 bytes testdata/lefdef/lefpins/au_no_lefpins.oas.gz | Bin 0 -> 269 bytes testdata/lefdef/lefpins/in.def | 15 ++++++ testdata/lefdef/lefpins/in.lef | 15 ++++++ testdata/lefdef/lefpins/in_tech.lef | 36 ++++++++++++++ 15 files changed, 135 insertions(+), 27 deletions(-) delete mode 100644 testdata/lefdef/foreigncell/au_lefpins_mapped.oas.gz delete mode 100644 testdata/lefdef/foreigncell/au_no_lefpins.oas.gz create mode 100644 testdata/lefdef/foreigncell/in.def create mode 100644 testdata/lefdef/lefpins/au_lefpins_mapped.oas.gz create mode 100644 testdata/lefdef/lefpins/au_no_lefpins.oas.gz create mode 100644 testdata/lefdef/lefpins/in.def create mode 100644 testdata/lefdef/lefpins/in.lef create mode 100644 testdata/lefdef/lefpins/in_tech.lef diff --git a/src/laybasic/laybasic/layLayerProperties.cc b/src/laybasic/laybasic/layLayerProperties.cc index 53a4e88be..e150fa401 100644 --- a/src/laybasic/laybasic/layLayerProperties.cc +++ b/src/laybasic/laybasic/layLayerProperties.cc @@ -1839,10 +1839,15 @@ LayerPropertiesList::load (tl::XMLSource &stream, std::vector > std::string inst_name = get (); std::string model = get (); - db::Cell *cell = m_lef_importer.macro_by_name (model); + std::pair ct = m_lef_importer.macro_by_name (model); while (test ("+")) { @@ -1158,8 +1158,8 @@ DEFImporter::read_components (std::list > db::FTrans ft = get_orient (false /*mandatory*/); db::Vector d = pt - m_lef_importer.macro_bbox_by_name (model).transformed (ft).lower_left (); - if (cell) { - db::CellInstArray inst (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), d)); + 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)); } else { warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 090fdfae8..1f8d4b942 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -105,14 +105,14 @@ LEFImporter::layer_width (const std::string &layer, const std::string &nondefaul } } -db::Cell * +std::pair LEFImporter::macro_by_name (const std::string &name) const { - std::map::const_iterator m = m_macros_by_name.find (name); + std::map >::const_iterator m = m_macros_by_name.find (name); if (m != m_macros_by_name.end ()) { return m->second; } else { - return 0; + return std::make_pair ((db::Cell *) 0, db::Trans ()); } } @@ -726,9 +726,9 @@ LEFImporter::read_macro (Layout &layout) std::string mn = get (); set_cellname (mn); - db::Cell &cell = layout.cell (layout.add_cell (mn.c_str ())); - - m_macros_by_name.insert (std::make_pair (mn, &cell)); + db::Cell &cell = layout.cell (layout.add_cell ()); + db::Cell *foreign_cell = 0; + db::Trans foreign_trans; db::Point origin; db::Vector size; @@ -811,13 +811,12 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("FOREIGN")) { - std::string cn = get (); - - if (cn == mn) { - // rename out macro placeholder cell so we don't create a recursive hierarchy - layout.rename_cell (cell.cell_index (), ("LEF_" + mn).c_str ()); + if (foreign_cell) { + error ("Duplicate FOREIGN definition"); } + std::string cn = get (); + db::cell_index_type ci; std::pair c = layout.cell_by_name (cn.c_str ()); if (c.first) { @@ -836,7 +835,8 @@ LEFImporter::read_macro (Layout &layout) expect (";"); - cell.insert (db::CellInstArray (db::CellInst (ci), (db::Trans (origin - db::Point ()) * db::Trans (ft)).inverted ())); + foreign_cell = &layout.cell (ci); + foreign_trans = (db::Trans (origin - db::Point ()) * db::Trans (ft)).inverted (); } else if (test ("OBS")) { @@ -851,9 +851,26 @@ LEFImporter::read_macro (Layout &layout) } - std::pair dl = open_layer (layout, std::string (), Outline); - if (dl.first) { - cell.shapes (dl.second).insert (db::Box (-origin, -origin + size)); + if (! foreign_cell) { + + // actually implement the real cell + + layout.rename_cell (cell.cell_index (), mn.c_str ()); + + std::pair dl = open_layer (layout, std::string (), Outline); + if (dl.first) { + cell.shapes (dl.second).insert (db::Box (-origin, -origin + size)); + } + + m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ()))); + + } else { + + // use FOREIGN cell instead of new one + + layout.delete_cell (cell.cell_index ()); + m_macros_by_name.insert (std::make_pair (mn, std::make_pair (foreign_cell, foreign_trans))); + } m_macro_bboxes_by_name.insert (std::make_pair (mn, db::Box (-origin, -origin + size))); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h index f52133996..859ceef54 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h @@ -63,7 +63,7 @@ public: * Returns 0 if the name is not a valid macro name. Otherwise it returns the pointer * to the corresponding db::Cell object. */ - db::Cell *macro_by_name (const std::string ¯o_name) const; + std::pair macro_by_name (const std::string ¯o_name) const; /** * @brief Get the cell bbox for the given macro name @@ -125,7 +125,7 @@ private: std::map > m_default_widths; std::map m_default_ext; std::map > m_min_widths; - std::map m_macros_by_name; + std::map > m_macros_by_name; std::map m_macro_bboxes_by_name; std::map m_vias; std::set m_routing_layers, m_cut_layers; diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index cdd6bf28c..30090da2b 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -334,15 +334,18 @@ TEST(108_scanchain) TEST(109_foreigncell) { - run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef", "au.oas.gz", default_options (), false); + run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef+def:in.def", "au.oas.gz", default_options (), false); +} +TEST(110_lefpins) +{ db::LEFDEFReaderOptions options = default_options (); options.set_produce_lef_pins (false); - run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef", "au_no_lefpins.oas.gz", options, false); + run_test (_this, "lefpins", "lef:in_tech.lef+lef:in.lef+def:in.def", "au_no_lefpins.oas.gz", options, false); options.set_produce_lef_pins (true); options.set_lef_pins_datatype (10); options.set_lef_pins_suffix (".LEFPIN"); - run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef", "au_lefpins_mapped.oas.gz", options, false); + run_test (_this, "lefpins", "lef:in_tech.lef+lef:in.lef+def:in.def", "au_lefpins_mapped.oas.gz", options, false); } diff --git a/testdata/lefdef/foreigncell/au.oas.gz b/testdata/lefdef/foreigncell/au.oas.gz index a46321b03e36bc56c9ec2e5bd21b35ef0920623e..fec13c35bc49f6cff4b3e934555e6673cff62a79 100644 GIT binary patch literal 811 zcmV+`1JwK zIqQt4$Af0IEDyWJQuy;yGClH5p=h&qtP%OFYg88NOMX3A2-!t*Y0mHEBeL!qwcwYq zkxbt{h*!T#T^gH}Ro7Su=9B63=gm<|9&(Lp{Xy7hGHoTOHA7i(jUTE(^PoVEx<mXMx+BSJ5HZUK?{&yhj{Xkl{fQ3&ZTSt2K%PF6_HbPJfroH{@XVL}rN zJ?;o8C}&}jG5x3rIcwB)@(d&O7*-^Pvzc)_%Q8?;WQxeXf~=Fb@dajdJkcPr4^fIK zp*$6+NF^%M2vw*`HA-oe4$+uC_9Z523%1ZB-fM%`f*rI5+u|15fE__M$(i4vCA@++ zcoUxEb$E?#{ekZM%74FwreCwl=eP||fYqsQr8Rho-Br8>d(t|r;uqN45O#Up1nCLP z>E9*|J;|}k_*-e2--O5fHd?{cEx6T%ZPbRTP1uKZXu+Ro9rkdSnL=bBOu8M^BjS-c zC2r_S82JY?Fa2Y88%$jM*xcXno_Vd{J=WkmqH+CI46{|7`PWq-qOamtOvU6qtEpZ; zN5i+_8NRat%lv<9GdR|Tj`$R7DAwhENAIyF$9ARNXkvtuAc|u9cm;RF#5tC5u`X(} pih~5=UJ97c%BK*UC8N1@n@7#X9F)6qtw-*)0!e4r_>Lft>4PZFk5_rQ|@$Jnv3<`O0)W z5|X(c)ZaldzU%u`ax^>axICqW64u_>yCqnO^a@ ztrw@uGj7?ND$qi8X597jUQx64N$+-{5>5QL6VD9ve;vOn%C>w}&L0 zjuD~SSf6cWD8}+WED02+l7nW7W*{HPB%XeJ%F3AJG!@#PC=h9(E)}VuVwI?j z%Bq~otAZ-30aa3ERZ&$feu^;NE3m{pgEwRq9+PEQ!()HqpYF0h|A9x=aE)?xxDT4a z$eTh97K#0c)L=_khDYQHah`I2ahd_beHhn%i0WDt(N1Xv*7zE-Yf~S%R@9tm8UdUWFDc!xC)ZW!NGO+6vrkG(4_F?=ji{1Um9j`xPUh zvq1&5-E~oS!B4uwM{)O-)doK0u7M@ggrIN#IkSP^K@Fb5M|e+nr3T?|{DPTh|F>Zi zB-Fq`%CMB`7~IKxDiT!AgOlG`|V<3I>mWYJ`iMHWFA6M|8_=%RF4OfbQOt_$6S z5R8^0q#}z_`o@+OE5zV^-{#(P?!D*T^WG&^Rx>OvwK zR=C}4xSPfKz6hrJC?6E2uIkswSEiBMXo z7R$4hcsCm+(zu=SYTy6hSBs?c;+;rq?|!DkC0Lk}nT+Y=2uqOC&18nkn1lSNiL#i94^c(O&Qd5Ty-*ecm>RXx6oJx%WS)M1+Rj?!B$Yb|REV}wpN2HhutqdS zV>M3WH9-?KNs~22Q#DObd`g&sby($|zzebg56Bv9;;E-mK*Z?PZm>uB_tV08qR3`ElixgFj+~guRd6k4)=x6+fs5sn$ zCV!8peE2O>XaAu4{09BumVi)XnU_AUWi7h`r53mQSJ;@`50w la=nA3f&V5)9A$e(+w{+x{Lx17%K!Nw^dGl~vHvIr0059ru(ALE diff --git a/testdata/lefdef/foreigncell/au_no_lefpins.oas.gz b/testdata/lefdef/foreigncell/au_no_lefpins.oas.gz deleted file mode 100644 index f0e21a2099c706a17290cee957a3e57c28b1237f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 796 zcmV+%1LOQ3iwFowH=JGo19WY0E^lFT0OgTQXcIvc$LG!LXEwV{G>ag)Rp~}iH%%20 zbEvwl!8BQ$txf$})-k**DI(%o@FGP@j-k}x zNt|tyXvKne=knhC{%_vQ|INXa(HA?C>`ui}vIj``sE(>U`h5k}{VBVzJ8h?8y$R!- z9ZOh7uhDN0#?D#i1tus5x8;Gv-wJ}NCuLhn(>`m&<6ckP=&{F~OmRFC^n1Cjth1Gc z`L+x3?xEy>WuHybCTU9)yGPN6dr?gcdwwYR{bj!))3nMKsx&zP#*<8-f+}rM`pJNZ(Z5ZG ziw&Y57d_iPD9~x{jw-rke{ajPHE1NPp=84NySL73gmX_Eh!Dn&M97U7v-y!ixRrGh z&!t$mUAle8DP~Dy;*ChPUq91e5sB&3%_Lz7^0qRGp*?iMxvZH_iM0ek%oPOsoHWfgb?s?K=VgfcuQ<}4}0x-bv3;1TBs~Y0Yp{wdaA_IpFb{L^9?!!%snSy5 zCPRT?HS~~CyTH?GA2L5N5<2aZQNvvub?4jF9sU=0Us<(lH+NMmp&IyH`!AXIcmv9? z06*Y6eJeExAMh(?iv8n-HIPsh`zURA(3(AD_mVniF2XXH?qJr1O;~~oOv+5)GmE^k z9GK<;)4WXlHS_{+5*hnzQ01QxnfHHZ%Irt_p4YI)UlR}tWDcV#@`cFUPKi|TH_{T> a9b%o%y~;O5JoP^>gnk0f#ioIg1poj>IfOO< diff --git a/testdata/lefdef/foreigncell/foreign.gds b/testdata/lefdef/foreigncell/foreign.gds index d8558194ee5591e8bad6602b2b1263b2351e5532..dce50b5e8bc9622937007a8af423587446394e30 100644 GIT binary patch literal 3722 zcmeH~yH8V59LIn6-g2oG@I`!uxX=Vt6sQWmYNA*Skx*k8h_9wXi#4?x+W1)Aj1JDS zbTBa*<01otad6PZ$-%$CI6FAG;P-pZ`RNrAqb8!plN>(h{@&-Ddw--7itmp}o98#a zk(jKPbm5?8s%Bg*K0J1&zkXbPP5x+mPIt`(`Phst0`A6<;P2v zN#kYnG+NF0*P2jPvVyavd^KXYXNHc9q&iGa z;i=+Q(}(ia(zr-$6((*bVQ(hc`~Pl!;%;{Q+THXnayN~#=(iRR?H3h` zOv;u0Sm!XQKk7(d%E=X&l(RP4k@Tlr<7iw`^;jBz_s-9&f5y~*l|~pObJZOmfUM_w zggmEdOtOx-&5?CdPJ8tu)sE*`$J~HPIqN1l>gKOy0_$6tv}ax=mZrXi_fauf)>CT`d0`jW9^~d9etYmvSZQ^VZ;53Axu|^@jAP zUWujgUpW60?%(U95!i)4^dlLUa^@LzJmcgfz6~Q+;vT)M)9-VnKjkFu&7++0X-6_H z=Se#ymL|S?PrlPf6Sj}y|KFFLH2BS(G?2f$lLqo{bkabUwv%f9 zrRt=C{9BzgkUyi7Y8}x|%8oVbIv2@~$PP!|2iZ|+ucVxI?2ykQ)Xt}b>IXVtQy3O6 sP8CX%mDK#-YIAdQ=Mn6K{k8C&PWm|xdMQeo_shb2k7&C;MT*7bBdwc(4gdfE literal 3484 zcmeH~J#17*5Xa}eJ3n6>V+^qni7Xe`lFgSf$A_ILMtq$mgLRJ3A)JJ8I_x`q=s1wi z0wSeK5rk-{D4=nHgoF?cE~wlfkrdR>P*6k^sVGuWVE+Hv9rD1B7?2PRYmI)pGqW@M z_G4^IBw;uqok7_Ax1{AOX~oZ~cwaJMG&Z_dq$Aa|YtO~OgZFPd`*#1`Epyj?DoAJ3 z+vlx`qMn|fedGB;ZlX{e&5w*@DCriFmemn;J=>(UJtfwnjiIzj+otG;eYvr*VR{I4 zD^%B4IbEM!KioZ_x>i{OzrJ#%QkpG#^9W=u zJ!Z@2v2(qJBe{Ix$MJm5TZQ|IlO5h$YE&mh(yJgios2u3&u8-iXS3}+&PH#rKbw*9 z!-opFT)tOxCZ0^Q{O@aPiR?|KGdTSfp=^+-EtF8k^o@1+XGVVS`^FKBvk)WoT@WL> z;^ylec_aRB8sB1(j1!lY7$1a?haq1>ihev5Bj?m1Ms(GWTD;G&{O}eM#$g`*S7Tu0e*S~85$`20$?NqjB}esrA=ayg_34{1Vtw3uz2_v>r*GMa^{L&6p>Ip~ zB_(>lxCh$evDv4dGUdtoMLmgorFtXok=8TXSr2VK^^9S4l51vtBpH`_l5s39X?Aq| z`jXbK=c@ILeyoR_XLXTvj=4$Zxd5U4n&%uyJxRZtG16}i!p8YYbtonCiS_U?yczE) zg!`}%BhTp(gruL*xr03vo0i0@Fl5#OovjTSfgoLv5CX2(2|d0EGd%*#4x zWZpk8HZm{mM&`9TNTO-nvOT_DOga7~l diff --git a/testdata/lefdef/foreigncell/in.def b/testdata/lefdef/foreigncell/in.def new file mode 100644 index 000000000..04045ef5f --- /dev/null +++ b/testdata/lefdef/foreigncell/in.def @@ -0,0 +1,17 @@ + +VERSION 5.8 ; +DIVIDERCHAR "/" ; +BUSBITCHARS "[]" ; +DESIGN foreigncells ; +UNITS DISTANCE MICRONS 1000 ; + +DIEAREA ( 0 0 ) ( 1000 2000 ) ; + +COMPONENTS 3 ; + - macro1 macro1 + PLACED ( 0 0 ) N ; + - macro2 macro2 + PLACED ( 0 500 ) N ; + - macro3 macro3 + PLACED ( 0 1000 ) N ; +END COMPONENTS + +END DESIGN + diff --git a/testdata/lefdef/lefpins/au_lefpins_mapped.oas.gz b/testdata/lefdef/lefpins/au_lefpins_mapped.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..80c578b58c1ab2d050ebe49837ecad8425204e8f GIT binary patch literal 335 zcmV-V0kHlbiwFq7R-;}319WY0E^lFT08Z@2gEzO`uOnh zq~#Z-W~S#Qr{?4ov-1VVySoI(2L$;CxCVtpar|lmL?XZGQ-4B zbh0u=akKau1o$(vGBfbNS==l@jRwqYATbz=o5|OZnH?wsrMWqM4fT9n-2y!QfLtyf zR4z9Mi0kO&>I394@}Tgz+5JO9d_4VJnK^*QA#->cL~gS(@bL1AG_r{_vhy+u{$N!p hj5-4cBR_*kG6ygYF7PuojAX#T004gq;E|gG001U{oqqrT literal 0 HcmV?d00001 diff --git a/testdata/lefdef/lefpins/au_no_lefpins.oas.gz b/testdata/lefdef/lefpins/au_no_lefpins.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..099aeed882a461a3d5e5ce06c40c89cda1901a4f GIT binary patch literal 269 zcmV+o0rLJIiwFoaSEF7419WY0E^lFT08Z@2gEzO`uOnh zq~#Z-W~S#Qr{?4ov-1VVySoI(2L$;CxCVtpar|lmL?XZGQ-4B zbaJ!!8U*+=vobUAz**cZKwSpRY#=chi<`;UkeMAQ0;Rdx{X;{1JpEjmIe>!599{;I z+pG*cyu2cfY$A>9yo`cB7#6UeW8!Am!6+n>%)!vW{D7I4N$>!pj5-4cBR>O3>;?M; Tex`X*yvPFKbKmq^&5KMfG literal 0 HcmV?d00001 diff --git a/testdata/lefdef/lefpins/in.def b/testdata/lefdef/lefpins/in.def new file mode 100644 index 000000000..58d6e328b --- /dev/null +++ b/testdata/lefdef/lefpins/in.def @@ -0,0 +1,15 @@ + +VERSION 5.8 ; +DIVIDERCHAR "/" ; +BUSBITCHARS "[]" ; +DESIGN foreigncells ; +UNITS DISTANCE MICRONS 1000 ; + +DIEAREA ( 0 0 ) ( 1000 2000 ) ; + +COMPONENTS 3 ; + - macro1 macro1 + PLACED ( 0 0 ) N ; +END COMPONENTS + +END DESIGN + diff --git a/testdata/lefdef/lefpins/in.lef b/testdata/lefdef/lefpins/in.lef new file mode 100644 index 000000000..e2751e688 --- /dev/null +++ b/testdata/lefdef/lefpins/in.lef @@ -0,0 +1,15 @@ +MACRO macro1 + CLASS CORE ; + ORIGIN 0.000 0.000 ; + SIZE 0.384 BY 0.480 ; + PIN Z + PORT + LAYER M1 ; + RECT 0.306 0.357 0.318 0.403 ; + RECT 0.318 0.115 0.352 0.403 ; + VIA 0.336 0.167 square ; + VIA 0.336 0.351 square ; + END + END Z +END macro1 + diff --git a/testdata/lefdef/lefpins/in_tech.lef b/testdata/lefdef/lefpins/in_tech.lef new file mode 100644 index 000000000..eb0e75b0b --- /dev/null +++ b/testdata/lefdef/lefpins/in_tech.lef @@ -0,0 +1,36 @@ +LAYER OD + TYPE IMPLANT ; +END OD +LAYER VTS_N + TYPE IMPLANT ; +END VTS_N +LAYER VTS_P + TYPE IMPLANT ; +END VTS_P +LAYER M0OD + TYPE IMPLANT ; +END M0OD +LAYER M0PO + TYPE MASTERSLICE ; +END M0PO +LAYER VIA0 + TYPE CUT ; +END VIA0 +LAYER M1 + TYPE MASTERSLICE ; +END M1 +LAYER VIA1 + TYPE CUT ; +END VIA1 +LAYER M2 + TYPE MASTERSLICE ; +END M2 + +VIA square + LAYER M0PO ; + RECT -0.006 -0.006 0.006 0.006 ; + LAYER VIA0 ; + RECT -0.006 -0.006 0.006 0.006 ; + LAYER M1 ; + RECT -0.006 -0.006 0.006 0.006 ; +END square From 4c6f1475b1ae35af111e104b36f8454e9b78bf26 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 25 Apr 2020 19:45:02 +0200 Subject: [PATCH 34/43] Made rba:layLayoutView test functional without qtbindings enabled. --- src/laybasic/laybasic/gsiDeclLayLayoutView.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc index 3c57c6f45..76ab0d461 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc @@ -412,11 +412,19 @@ static lay::LayoutView *new_view (QWidget *parent, bool editable, db::Manager *m } return lv; } +#else +static lay::LayoutView *new_view (tl::Variant /*dummy*/, bool editable, db::Manager *manager, unsigned int options) +{ + return new lay::LayoutView (manager, editable, 0 /*plugin parent*/, 0 /*parent*/, "view", options); +} #endif Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "LayoutView", #if defined(HAVE_QTBINDINGS) gsi::constructor ("new", &new_view, gsi::arg ("parent", (QWidget *) 0, "nil"), gsi::arg ("editable", false), gsi::arg ("manager", (db::Manager *) 0, "nil"), gsi::arg ("options", (unsigned int) 0), +#else + gsi::constructor ("new", &new_view, gsi::arg ("parent", tl::Variant (), "nil"), gsi::arg ("editable", false), gsi::arg ("manager", (db::Manager *) 0, "nil"), gsi::arg ("options", (unsigned int) 0), +#endif "@brief Creates a standalone view\n" "\n" "This constructor is for special purposes only. To create a view in the context of a main window, " @@ -430,7 +438,6 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou "This constructor has been introduced in version 0.25.\n" "It has been enhanced with the arguments in version 0.27.\n" ) + -#endif gsi::constant ("LV_NoLayers", (unsigned int) lay::LayoutView::LV_NoLayers, "@brief With this option, no layers view will be provided (see \\layer_control_frame)\n" "Use this value with the constructor's 'options' argument.\n" From c602871e0e88d3d03d229f964d847817441f8843 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 25 Apr 2020 21:08:11 +0200 Subject: [PATCH 35/43] Implemented Stefan's solution #3 for FOREIGN != MACRO in LEF --- .../lefdef/db_plugin/dbLEFImporter.cc | 22 ++++++++++++++++++ testdata/lefdef/foreigncell/au.oas.gz | Bin 811 -> 828 bytes 2 files changed, 22 insertions(+) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 1f8d4b942..2d20ff902 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -729,6 +729,7 @@ LEFImporter::read_macro (Layout &layout) db::Cell &cell = layout.cell (layout.add_cell ()); db::Cell *foreign_cell = 0; db::Trans foreign_trans; + std::string foreign_name; db::Point origin; db::Vector size; @@ -837,6 +838,7 @@ LEFImporter::read_macro (Layout &layout) foreign_cell = &layout.cell (ci); foreign_trans = (db::Trans (origin - db::Point ()) * db::Trans (ft)).inverted (); + foreign_name = cn; } else if (test ("OBS")) { @@ -864,6 +866,26 @@ LEFImporter::read_macro (Layout &layout) m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ()))); + } else if (foreign_name != mn) { + + warn ("FOREIGN name differs from MACRO name in macro: " + mn); + + layout.rename_cell (cell.cell_index (), mn.c_str ()); + + // clear imported LEF geometry with a foreign cell, but provide a level of indirection so we have + // both the MACRO and the FOREIGN name + + for (unsigned int l = 0; l < layout.layers (); ++l) { + if (layout.is_valid_layer (l)) { + cell.clear (l); + } + } + + cell.clear_insts (); + + cell.insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), foreign_trans)); + m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ()))); + } else { // use FOREIGN cell instead of new one diff --git a/testdata/lefdef/foreigncell/au.oas.gz b/testdata/lefdef/foreigncell/au.oas.gz index fec13c35bc49f6cff4b3e934555e6673cff62a79..9c3843f9ba7da312a8f14dd2c5098f34cded1bbf 100644 GIT binary patch literal 828 zcmV-C1H=3uiwFqXiKJct19WY0E^lFT0OeFoYa3S-o%`OKFU`zTCeaWm+LW|-)DU+@ zZbJxYA;(j9s6M9B#BtK3!&Dx*0$ENZ_iN{b&{Y<$DOq$;j4&n?)xW`nVnSBhcT=)3 zT67^w>Sf52JyvX*{( zt*ePSHy?EFd=s`KkyeA*nQGuw%AQm4uZzjg3i<2htA22$%mn9sSy&2d?PWWT**H$g za>1R>O^2OEO+M|JE7A8WncT!D<%+|`u_xrSo>^aRtpu%bDPk9$m4#rGPsoO6Hp3sH zb|&}5LA?A?_QR=Lvg(;j;bJCt?wmDg%cnfE(fT%OcUW&dY<419@yxFpVdtPgPI_jo zb33dxT8m?%d4ga9QN142zB^R3E{>V6W9HHk(>$uNW&My@Xvd88v79*EgAo?PBRg{k zw)|)3?CV#{-Xdhwz!6~--m`&7@pEL+7}}T|dlW)q)A<-=g&0gpv92KExPkL^NVWb|zio|dsKkXD)2I`4S5!rW9a7zw8&xDRA z8l?9jNiijqrveqJL}i+w3RS5_DNWK-R5zwRz(noB4!XztJ@C8m1Z}{sxP!LfiC|dd z%x};Y9>HID8y@0Kc#LlRfo}fDf4PI^AG6AbxCak_)v3><4fqv%>v#k9q)k}IzhHk$ z=<|jJ(gRp9KF^p&hGUhfXVNOa4fpw7w1(%qaAOF&s0VY~un(Kig{No}_VAF2LSo#Q z@dju_q!J5C$~2TH@d7g~G~gW>%c}Un>wX*6}0O z#o9+wbEA2VmhZvO_~sU@@^6+iSRcYb{0VDFA9BB==U5Z;A?l%jvBvBBcnuFkP1gHT zKbfB3BuFB?&vWT_8RGQ5Fc1$Qq-y8czp|gyNa|0XQ#CDhS4iCz(dyfLIPN7N2(30! G1^@uZ=%4QZ literal 811 zcmV+`1JwK zIqQt4$Af0IEDyWJQuy;yGClH5p=h&qtP%OFYg88NOMX3A2-!t*Y0mHEBeL!qwcwYq zkxbt{h*!T#T^gH}Ro7Su=9B63=gm<|9&(Lp{Xy7hGHoTOHA7i(jUTE(^PoVEx<mXMx+BSJ5HZUK?{&yhj{Xkl{fQ3&ZTSt2K%PF6_HbPJfroH{@XVL}rN zJ?;o8C}&}jG5x3rIcwB)@(d&O7*-^Pvzc)_%Q8?;WQxeXf~=Fb@dajdJkcPr4^fIK zp*$6+NF^%M2vw*`HA-oe4$+uC_9Z523%1ZB-fM%`f*rI5+u|15fE__M$(i4vCA@++ zcoUxEb$E?#{ekZM%74FwreCwl=eP||fYqsQr8Rho-Br8>d(t|r;uqN45O#Up1nCLP z>E9*|J;|}k_*-e2--O5fHd?{cEx6T%ZPbRTP1uKZXu+Ro9rkdSnL=bBOu8M^BjS-c zC2r_S82JY?Fa2Y88%$jM*xcXno_Vd{J=WkmqH+CI46{|7`PWq-qOamtOvU6qtEpZ; zN5i+_8NRat%lv<9GdR|Tj`$R7DAwhENAIyF$9ARNXkvtuAc|u9cm;RF#5tC5u`X(} pih~5= Date: Sat, 25 Apr 2020 22:05:01 +0200 Subject: [PATCH 36/43] Added LEF reading timer (LEF next to DEF) --- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 4 +- .../lefdef/db_plugin/dbLEFDEFImporter.h | 18 +++++++ .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 3 ++ .../lefdef/db_plugin/dbLEFImporter.cc | 18 ++++++- .../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 19 +++++++ .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 12 +++++ .../foreigncell/au_ignore_foreign.oas.gz | Bin 0 -> 872 bytes testdata/lefdef/foreigncell/in2.lef | 47 ++++++++++++++++++ 8 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 testdata/lefdef/foreigncell/au_ignore_foreign.oas.gz create mode 100644 testdata/lefdef/foreigncell/in2.lef diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 11105b085..2e18707ee 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -77,7 +77,8 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_special_routing_suffix (""), m_special_routing_datatype (0), m_separate_groups (false), - m_consider_map_file (true) + m_consider_map_file (true), + m_macro_resolution_mode (0) { // .. nothing yet .. } @@ -125,6 +126,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_special_routing_datatype (d.m_special_routing_datatype), m_separate_groups (d.m_separate_groups), m_consider_map_file (d.m_consider_map_file), + m_macro_resolution_mode (d.m_macro_resolution_mode), m_lef_files (d.m_lef_files) { // .. nothing yet .. diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 40838f89d..bb41ade22 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -525,6 +525,23 @@ public: m_consider_map_file = f; } + /** + * @brief Specify the LEF macro resolution strategy + * Values are: + * 0: propduce LEF geometry unless a FOREIGN cell is specified (default) + * 1: produce LEF geometry always and ignore FOREIGN + * 2: produce a placeholder cell always (even if FOREIGN isn't given) + */ + unsigned int macro_resolution_mode () const + { + return m_macro_resolution_mode; + } + + void set_macro_resolution_mode (unsigned int m) + { + m_macro_resolution_mode = m; + } + private: bool m_read_all_layers; db::LayerMap m_layer_map; @@ -568,6 +585,7 @@ private: int m_special_routing_datatype; bool m_separate_groups; bool m_consider_map_file; + unsigned int m_macro_resolution_mode; std::vector m_lef_files; }; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 4caffcf97..b919fb0c7 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -180,6 +180,9 @@ private: if (is_lef_format (*e)) { std::string lp = tl::combine_path (input_dir, *e); + + tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp); + tl::InputStream lef_stream (lp); tl::log << tl::to_string (tr ("Reading")) << " " << lp; importer.read_lef (lef_stream, layout, state); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 2d20ff902..0cb8fc40d 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -853,7 +853,7 @@ LEFImporter::read_macro (Layout &layout) } - if (! foreign_cell) { + if (options ().macro_resolution_mode () == 1 || (! foreign_cell && options ().macro_resolution_mode () != 2)) { // actually implement the real cell @@ -866,6 +866,22 @@ LEFImporter::read_macro (Layout &layout) m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ()))); + } else if (! foreign_cell) { + + // macro resolution mode #2 (always create a MACRO reference, no LEF geometry) + + db::cell_index_type ci; + std::pair c = layout.cell_by_name (mn.c_str ()); + if (c.first) { + ci = c.second; + } else { + ci = layout.add_cell (mn.c_str ()); + layout.cell (ci).set_ghost_cell (true); + } + + layout.delete_cell (cell.cell_index ()); + m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&layout.cell (ci), db::Trans ()))); + } else if (foreign_name != mn) { warn ("FOREIGN name differs from MACRO name in macro: " + mn); diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index 14336a90b..b41e96977 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -480,6 +480,25 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n" "This property has been added in version 0.26.5.\n" ) + + gsi::method ("macro_resolution_mode", &db::LEFDEFReaderOptions::macro_resolution_mode, + "@brief Gets the macro resolution mode.\n" + "This property describes the way LEF macros are turned into GDS cells. There " + "are three modes available:\n" + "\n" + "@ul\n" + " @li 0: propduce LEF geometry unless a FOREIGN cell is specified (default) @/li\n" + " @li 1: produce LEF geometry always and ignore FOREIGN @/li\n" + " @li 2: produce a placeholder cell always (even if FOREIGN isn't given) @/li\n" + "@/ul\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + + gsi::method ("macro_resolution_mode=", &db::LEFDEFReaderOptions::set_macro_resolution_mode, gsi::arg ("mode"), + "@brief Sets the macro resolution mode.\n" + "See \\macro_resolution_mode for details about this property.\n" + "\n" + "This property has been added in version 0.26.5.\n" + ) + gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files, "@brief Gets the list technology LEF files to additionally import\n" "Returns a list of path names for technology LEF files to read in addition to the primary file. " diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 30090da2b..f6f70c009 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -335,6 +335,18 @@ TEST(108_scanchain) TEST(109_foreigncell) { run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef+def:in.def", "au.oas.gz", default_options (), false); + + db::LEFDEFReaderOptions options = default_options (); + + run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in2.lef+def:in.def", "au_default.oas.gz", options, false); + + options.set_macro_resolution_mode (1); + + run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in2.lef+def:in.def", "au_ignore_foreign.oas.gz", options, false); + + options.set_macro_resolution_mode (2); + + run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef+def:in.def", "au_always_foreign.oas.gz", options, false); } TEST(110_lefpins) diff --git a/testdata/lefdef/foreigncell/au_ignore_foreign.oas.gz b/testdata/lefdef/foreigncell/au_ignore_foreign.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..44831e8e56939afe244ce6ca4d300d6263bd7106 GIT binary patch literal 872 zcmV-u1DE_CiwFp7kEC7z19WY0E^lFT0OeFoY};fQ{@(BNZ~T+FwS|Oofr08!QS1Z| zLdqdsO|i(2NxZHr8M0Hv;)eW%QT^? z2M*OVO&k#7OXFs(7?&Nv2fxqzeDCx4eP3ICwdxez*UR~;TU8Q3>?sQ!@aW`~GG43( z#r%9wb!SV?OyHJ$XV$3%7u*^DeSt|Ssp0YY(z6OuMxq+{WiL4A6biCjUuj2;rB*F! zHajUz=9a@+dnHSe5TDp5aE4c_!R$;m@G51`srVQ9np9*pcO7h^q{l47!2|W(eTV> z_;u7y=RP`$@4lINBYRntJ##r+O6Sg=wWe(GjAu4lUq+uVNpC- zaqeg>|Cl-R?9nop2{RB7Zg79aCZpAlkWCVEZa(OI{zcf1NWAYjX5yF~#Zxbsg$0Qz zT3(s31j!>LG1Sl^+<-eq5-!?=r%W6ru4qqrZi!+npTLqpaUnnL6lezWsZ8SOmr-y_ z4w3hhe=_@^Uy-MNWA3x#Ylw$i z>@`MTn?&p60YOONokm#(oN@8bD8wDKm|hU-A< zYgiy$hehMVv}vRft<)b1>+BAE%kJSDWWEOrhp>mY zVQvSWz$WzIKHh|Va!5@fF%qV|13Vz~#G<5|h7=|KBGk)x+T9ivSDrTa2p&_f8)Tn0 z_&cMZcok!G732T93d|TA Date: Sat, 25 Apr 2020 22:13:46 +0200 Subject: [PATCH 37/43] Added missing test files --- .../lefdef/foreigncell/au_always_foreign.oas.gz | Bin 0 -> 828 bytes testdata/lefdef/foreigncell/au_default.oas.gz | Bin 0 -> 870 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 testdata/lefdef/foreigncell/au_always_foreign.oas.gz create mode 100644 testdata/lefdef/foreigncell/au_default.oas.gz diff --git a/testdata/lefdef/foreigncell/au_always_foreign.oas.gz b/testdata/lefdef/foreigncell/au_always_foreign.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..587178ba318161f20d69712878d7b9c40c69b051 GIT binary patch literal 828 zcmV-C1H=3uiwFn+k)&P#19WY0E^lFT0OeFoYa3S-o%`OKFU`zTCeaWm+LW|-)DU+@ zZbJxYA;(j9s6M9B#BtK3!&Dx*0$ENZ_iN{b&{Y<$DOq$;j4&n?)xW`nVnSBhcT=)3 zT67^w>Sf52JyvX*{( zt*ePSHy?EFd=s`KkyeA*nQGuw%AQm4uZzjg3i<2htA22$%mn9sSy&2d?PWWT**H$g za>1R>O^2OEO+M|JE7A8WncT!D<%+|`u_xrSo>^aRtpu%bDPk9$m4#rGPsoO6Hp3sH zb|&}5LA?A?_QR=Lvg(;j;bJCt?wmDg%cnfE(fT%OcUW&dY<419@yxFpVdtPgPI_jo zb33dxT8m?%d4ga9QN142zB^R3E{>V6W9HHk(>$uNW&My@Xvd88v79*EgAo?PBRg{k zw)|)3?CV#{-Xdhwz!6~--m`&7@pEL+7}}T|dlW)q)A<-=g&0gpv92KExPkL^NVWb|zio|dsKkXD)2I`4S5!rW9a7zw8&xDRA z8l?9jNiijqrveqJL}i+w3RS5_DNWK-R5zwRz(noB4!XztJ@C8m1Z}{sxP!LfiC|dd z%x};Y9>HID8y@0Kc#LlRfo}fDf4PI^AG6AbxCak_)v3><4fqv%>v#k9q)k}IzhHk$ z=<|jJ(gRp9KF^p&hGUhfXVNOa4fpw7w1(%qaAOF&s0VY~un(Kig{No}_VAF2LSo#Q z@dju_q!J5C$~2TH@d7g~G~gW>%c}Un>wX*6}0O z#o9+wbEA2VmhZvO_~sU@@^6+iSRcYb{0VDFA9BB==U5Z;A?l%jvBvBBcnuFkP1gHT zKbfB3BuFB?&vWT_8RGQ5Fc1$Qq-y8czp|gyNa|0XQ#CDhS4iCz(dyfLIPN7N2(30! G1^@sf(w`jw literal 0 HcmV?d00001 diff --git a/testdata/lefdef/foreigncell/au_default.oas.gz b/testdata/lefdef/foreigncell/au_default.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..bc6f4204d0326bdac5f8eb5d6fd22b044126d043 GIT binary patch literal 870 zcmV-s1DX6EiwFoxkfdG!19WY0E^lFT0OeFoZyQwy&X=oV@&Nx_d9IyivWs@S*RTm{fELc>Q6-5;aS+k5P6jfay@7Yup zin3r~Ri$Eq5YNuoO+@(v@HY3{^X@&m_q@@(SaAyO%cWe!ttbh=_Kd|G^UUd!GM=pj zh1^n5aTkiteBc&+XTd24@455-+X6``sgvuA#itddj6@~yOI~on$>(Lcw%&^BtIcZE zXtYzBEX29ZtCe73z7lxllIN8DOMLR3eC|@|q90r+QMn~wA%Bf7eg&Q85mDm!$T%#`?yXV%u68$mN%i|9prVq-R#!ABWX? zb9GEK&Ja`}s?~z(=O>ER>tp7ln0aHwG)6VHsGTq?t(dW16B8$UP{N{kU}kn`%RhFu zpT64c6+#9L4B-ah1sll7{0tgH8XbQLSoa|7-YB@%nIbpQ;IAsOQc|V zCCp+*9wUiRH4AeCZiFOMurW`WI7(c>p7Gow#YjGdC4u66ZqCWm4CFJJ#M4hB?-m_A zO@&S;3X^&aNfoO^WmQh)RY4Wiges}Bs;H`(RL`lJG5ZoC#x}kUH}TR#SpErJUfh8$ z+=lyjAHKzV@D0Aa3tQ|i+~o|5OnwhtZgjZ=chI2YI{U!^TDpTe!-g9`>*NPQ2X0|+ z8+YJH*nw^Q9rky*9&1=2+<+D1-Lz?>8Ct175VqKT_=-J5bc8M}_u&xj!QwtVhQTEF z&<-5oJ{5(;xH0V=qXD5ORwUgtq$u$hrdr06>2_&z`N?n(;StrkiI3=jzY&G#zp#v~ zDEc){zs4&_>oY%~M_A#sKH5XSV};fJARYE+Br!k2gucn6=R4?6as>KSdFEGgkDc6P zc(}!0C;H|zvxVsa&MXe|FlBp?1 wfF#m-ER%YUB1Y?R$NUh2UY(|Y*IrV=S|5)2uQA&CKOctq8@ve(w0;Hv0P$9-dH?_b literal 0 HcmV?d00001 From 751340c963156a61cdc544cbf4c126d2a1e59f31 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 1 May 2020 15:16:08 +0200 Subject: [PATCH 38/43] LEF/DEF: Fixed placement of FOREIGN cell --- .../lefdef/db_plugin/dbLEFImporter.cc | 12 +++-- testdata/lefdef/foreigncell/au.oas.gz | Bin 828 -> 800 bytes .../foreigncell/au_always_foreign.oas.gz | Bin 828 -> 800 bytes testdata/lefdef/foreigncell/au_default.oas.gz | Bin 870 -> 864 bytes .../foreigncell/au_ignore_foreign.oas.gz | Bin 872 -> 906 bytes testdata/lefdef/foreigncell/foreign.gds | Bin 3722 -> 3722 bytes testdata/lefdef/foreigncell/in.def | 2 +- testdata/lefdef/foreigncell/in.lef | 45 ++++-------------- testdata/lefdef/foreigncell/in2.lef | 37 +++++++------- 9 files changed, 34 insertions(+), 62 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 0cb8fc40d..cbe6681f5 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -827,17 +827,19 @@ LEFImporter::read_macro (Layout &layout) layout.cell (ci).set_ghost_cell (true); } - db::Point origin; + db::Point vec; db::FTrans ft; if (! peek (";")) { - origin = get_point (1.0 / layout.dbu ()); + vec = get_point (1.0 / layout.dbu ()); ft = get_orient (true); } expect (";"); foreign_cell = &layout.cell (ci); - foreign_trans = (db::Trans (origin - db::Point ()) * db::Trans (ft)).inverted (); + // What is the definition of the FOREIGN transformation? + // Guessing: this transformation moves the lower-left origin to 0,0 + foreign_trans = db::Trans (db::Point () - vec) * db::Trans (ft); foreign_name = cn; } else if (test ("OBS")) { @@ -899,7 +901,7 @@ LEFImporter::read_macro (Layout &layout) cell.clear_insts (); - cell.insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), foreign_trans)); + cell.insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), db::Trans (db::Point () - origin) * foreign_trans)); m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ()))); } else { @@ -907,7 +909,7 @@ LEFImporter::read_macro (Layout &layout) // use FOREIGN cell instead of new one layout.delete_cell (cell.cell_index ()); - m_macros_by_name.insert (std::make_pair (mn, std::make_pair (foreign_cell, foreign_trans))); + m_macros_by_name.insert (std::make_pair (mn, std::make_pair (foreign_cell, db::Trans (db::Point () - origin) * foreign_trans))); } diff --git a/testdata/lefdef/foreigncell/au.oas.gz b/testdata/lefdef/foreigncell/au.oas.gz index 9c3843f9ba7da312a8f14dd2c5098f34cded1bbf..4aedac249c507b214180efbde321268f6487f6fb 100644 GIT binary patch literal 800 zcmV+*1K<1~iwFo+9jsme19WY0E^lFT0OeFoYZE~j-gjnpvzy(WxHgL*xk#066m^rT zh>%0IX$_{$nyj^cE^E4}fi%^me%)FTPd(Hk9y~}1rHI!40YOWVQuNZ37cb(Wc<>O4 zcoZk;HdfR>pmTYjdFFi{-Vc~Pxny5zf2J#!%BexXu>&UeIlyf_5q)RQ>FXMFa;e__ zWVe&*x0AietaCQiZJ!iLM2&1bpXvWoLPQVd96Mtpg)Adqz2@eN z<>3}l`h{QyUZLRRZ*4f5M_SBPpElD5GNReZ)gECo0EV1&tVW1NZRSbpm{ z_UG0*FAblwMX!3Uip`DK}sO!`bKgL%v;EhH0W zWn!VhZ6X=<#c+Tzev|`j$LUmm67OT=){6>}ZxEuG63SD72B=6S8l*B+s7fgf(QQ=I zJNF`@PvfUBg$LK+{2O#}U>0id6h7hwc!cNSA-*^VJtwU4x(VVW4C$w%h92cuX84mh&M&|{ zei^Y6YH+>|%V-`37T_B+DtU`$VGY-rDFj=>sP!2&h;VR74ja1c1;1nFrT?sMj)}8B zi(7}U%xem-u>!vkmGdXFolU0guam(c}WAfFI eO2Qv_PEpnHgbSf52JyvX*{( zt*ePSHy?EFd=s`KkyeA*nQGuw%AQm4uZzjg3i<2htA22$%mn9sSy&2d?PWWT**H$g za>1R>O^2OEO+M|JE7A8WncT!D<%+|`u_xrSo>^aRtpu%bDPk9$m4#rGPsoO6Hp3sH zb|&}5LA?A?_QR=Lvg(;j;bJCt?wmDg%cnfE(fT%OcUW&dY<419@yxFpVdtPgPI_jo zb33dxT8m?%d4ga9QN142zB^R3E{>V6W9HHk(>$uNW&My@Xvd88v79*EgAo?PBRg{k zw)|)3?CV#{-Xdhwz!6~--m`&7@pEL+7}}T|dlW)q)A<-=g&0gpv92KExPkL^NVWb|zio|dsKkXD)2I`4S5!rW9a7zw8&xDRA z8l?9jNiijqrveqJL}i+w3RS5_DNWK-R5zwRz(noB4!XztJ@C8m1Z}{sxP!LfiC|dd z%x};Y9>HID8y@0Kc#LlRfo}fDf4PI^AG6AbxCak_)v3><4fqv%>v#k9q)k}IzhHk$ z=<|jJ(gRp9KF^p&hGUhfXVNOa4fpw7w1(%qaAOF&s0VY~un(Kig{No}_VAF2LSo#Q z@dju_q!J5C$~2TH@d7g~G~gW>%c}Un>wX*6}0O z#o9+wbEA2VmhZvO_~sU@@^6+iSRcYb{0VDFA9BB==U5Z;A?l%jvBvBBcnuFkP1gHT zKbfB3BuFB?&vWT_8RGQ5Fc1$Qq-y8czp|gyNa|0XQ#CDhS4iCz(dyfLIPN7N2(30! G1^@uZ=%4QZ diff --git a/testdata/lefdef/foreigncell/au_always_foreign.oas.gz b/testdata/lefdef/foreigncell/au_always_foreign.oas.gz index 587178ba318161f20d69712878d7b9c40c69b051..4aedac249c507b214180efbde321268f6487f6fb 100644 GIT binary patch literal 800 zcmV+*1K<1~iwFo+9jsme19WY0E^lFT0OeFoYZE~j-gjnpvzy(WxHgL*xk#066m^rT zh>%0IX$_{$nyj^cE^E4}fi%^me%)FTPd(Hk9y~}1rHI!40YOWVQuNZ37cb(Wc<>O4 zcoZk;HdfR>pmTYjdFFi{-Vc~Pxny5zf2J#!%BexXu>&UeIlyf_5q)RQ>FXMFa;e__ zWVe&*x0AietaCQiZJ!iLM2&1bpXvWoLPQVd96Mtpg)Adqz2@eN z<>3}l`h{QyUZLRRZ*4f5M_SBPpElD5GNReZ)gECo0EV1&tVW1NZRSbpm{ z_UG0*FAblwMX!3Uip`DK}sO!`bKgL%v;EhH0W zWn!VhZ6X=<#c+Tzev|`j$LUmm67OT=){6>}ZxEuG63SD72B=6S8l*B+s7fgf(QQ=I zJNF`@PvfUBg$LK+{2O#}U>0id6h7hwc!cNSA-*^VJtwU4x(VVW4C$w%h92cuX84mh&M&|{ zei^Y6YH+>|%V-`37T_B+DtU`$VGY-rDFj=>sP!2&h;VR74ja1c1;1nFrT?sMj)}8B zi(7}U%xem-u>!vkmGdXFolU0guam(c}WAfFI eO2Qv_PEpnHgbSf52JyvX*{( zt*ePSHy?EFd=s`KkyeA*nQGuw%AQm4uZzjg3i<2htA22$%mn9sSy&2d?PWWT**H$g za>1R>O^2OEO+M|JE7A8WncT!D<%+|`u_xrSo>^aRtpu%bDPk9$m4#rGPsoO6Hp3sH zb|&}5LA?A?_QR=Lvg(;j;bJCt?wmDg%cnfE(fT%OcUW&dY<419@yxFpVdtPgPI_jo zb33dxT8m?%d4ga9QN142zB^R3E{>V6W9HHk(>$uNW&My@Xvd88v79*EgAo?PBRg{k zw)|)3?CV#{-Xdhwz!6~--m`&7@pEL+7}}T|dlW)q)A<-=g&0gpv92KExPkL^NVWb|zio|dsKkXD)2I`4S5!rW9a7zw8&xDRA z8l?9jNiijqrveqJL}i+w3RS5_DNWK-R5zwRz(noB4!XztJ@C8m1Z}{sxP!LfiC|dd z%x};Y9>HID8y@0Kc#LlRfo}fDf4PI^AG6AbxCak_)v3><4fqv%>v#k9q)k}IzhHk$ z=<|jJ(gRp9KF^p&hGUhfXVNOa4fpw7w1(%qaAOF&s0VY~un(Kig{No}_VAF2LSo#Q z@dju_q!J5C$~2TH@d7g~G~gW>%c}Un>wX*6}0O z#o9+wbEA2VmhZvO_~sU@@^6+iSRcYb{0VDFA9BB==U5Z;A?l%jvBvBBcnuFkP1gHT zKbfB3BuFB?&vWT_8RGQ5Fc1$Qq-y8czp|gyNa|0XQ#CDhS4iCz(dyfLIPN7N2(30! G1^@sf(w`jw diff --git a/testdata/lefdef/foreigncell/au_default.oas.gz b/testdata/lefdef/foreigncell/au_default.oas.gz index bc6f4204d0326bdac5f8eb5d6fd22b044126d043..6362bf9f124053c57de0cc3eb048932b3ae22b2b 100644 GIT binary patch literal 864 zcmV-m1E2gKiwFq0AFN&g19WY0E^lFT0OeFmZyQw`dCsL!LQ((&qEk zu$Z3@tKMwMoe8~C;Lf_0@Lg{vcuOE@HGO=2rSzj z!}#WF*;ljIMa8$4qQy+^!UcQM5zqNnv;Aq@>C)at)au5f>{}l+qwcUkO!-!=`%zSD zwiic4>kL5!;zlE^eRiy9zcFGyOqh!&OzWh^5%puH-bonybx}IrgAz8y12c0&TmG@L z^X%28t`lz1@S?*IG5|nE=A#kJVj|6X`LO%(Cs8LRBr%;$K$c6ult9irrO3j9Op3N& z#w=!(5t0d2voSZ|PLPa>4(2J7M42l(lfGA?7%8W)EKpp?PrC)0fpR93dHQJ-ypoG2 zsL<&|h4d3hX;>o~t8p5y37V)$nye|Bs%ctEJE!U9)XRvN8~8Td!t;+{;TLpmZVP&F z8}8#>_!jTLH~88%tg+j0z?n7~`vH2~$>kQ@MT3s7+4uL*{9Uv;Y`6)uPI(|~!uQzU zz?*O+Y{3Tp4hP%ZA#2(o+=ROMPR24b46QUC2y5&ve8uh~IzkT?`mm37U~U(lz+jSJ z(H0!xJ{1LN)R^%fq5)w@b=j~?IhOvyRLgui-8OBmJRR;4Jf>Q=@DUyG526y|ca~99 z)wsbKH+U86eYk@jW0lkU_(%AOsI2}cG1jrnNW5>X^2n;^*0FK%05Z(jD#L?$2N|mq z%;kG{_BX6DiP7h&(PRH=G$u+9_RyDXumeF44ya%I{2uymIVOoDm>}^gc@+ qO20rcqu=9xmWL3G+64Wx9;Q@UK*2gjYyaoNFny&X=oV@&Nx_d9IyivWs@S*RTm{fELc>Q6-5;aS+k5P6jfay@7Yup zin3r~Ri$Eq5YNuoO+@(v@HY3{^X@&m_q@@(SaAyO%cWe!ttbh=_Kd|G^UUd!GM=pj zh1^n5aTkiteBc&+XTd24@455-+X6``sgvuA#itddj6@~yOI~on$>(Lcw%&^BtIcZE zXtYzBEX29ZtCe73z7lxllIN8DOMLR3eC|@|q90r+QMn~wA%Bf7eg&Q85mDm!$T%#`?yXV%u68$mN%i|9prVq-R#!ABWX? zb9GEK&Ja`}s?~z(=O>ER>tp7ln0aHwG)6VHsGTq?t(dW16B8$UP{N{kU}kn`%RhFu zpT64c6+#9L4B-ah1sll7{0tgH8XbQLSoa|7-YB@%nIbpQ;IAsOQc|V zCCp+*9wUiRH4AeCZiFOMurW`WI7(c>p7Gow#YjGdC4u66ZqCWm4CFJJ#M4hB?-m_A zO@&S;3X^&aNfoO^WmQh)RY4Wiges}Bs;H`(RL`lJG5ZoC#x}kUH}TR#SpErJUfh8$ z+=lyjAHKzV@D0Aa3tQ|i+~o|5OnwhtZgjZ=chI2YI{U!^TDpTe!-g9`>*NPQ2X0|+ z8+YJH*nw^Q9rky*9&1=2+<+D1-Lz?>8Ct175VqKT_=-J5bc8M}_u&xj!QwtVhQTEF z&<-5oJ{5(;xH0V=qXD5ORwUgtq$u$hrdr06>2_&z`N?n(;StrkiI3=jzY&G#zp#v~ zDEc){zs4&_>oY%~M_A#sKH5XSV};fJARYE+Br!k2gucn6=R4?6as>KSdFEGgkDc6P zc(}!0C;H|zvxVsa&MXe|FlBp?1 wfF#m-ER%YUB1Y?R$NUh2UY(|Y*IrV=S|5)2uQA&CKOctq8@ve(w0;Hv0P$9-dH?_b diff --git a/testdata/lefdef/foreigncell/au_ignore_foreign.oas.gz b/testdata/lefdef/foreigncell/au_ignore_foreign.oas.gz index 44831e8e56939afe244ce6ca4d300d6263bd7106..c9dd21723297b02c121d520c30bd1668a62c76a4 100644 GIT binary patch literal 906 zcmV;519ki#iwFo$Ago>h19WY0E^lFT0Oe9kZyQw&52@B6_f5TP4%JmdWR3xw+hRT8o{! z({A@7VVPg5)w|0{iUNKnaSq1?wPI&yE4EoKnVGV6LkPW_Pv0nAx9n>r`jM(7jvB=M znDAp#6!W>6)J(0{s*9IRW5xM$C7PO?E0r^J#Kffdf@w6DJ1cglw&c)6Z>3?o_eoJV zjdtxTryEUu;KjG!NW7l7CCa9;R9lRuu3U*t$Hhyg(dvBebbGY6S!?$kQ8JB>TD6`h z5JRR>?|o9Mw>pbsqJ4p&4V-4vu75G=7<+5XeC#t<&zSa^CN73YOrz^Fu{Xuw=pB@Z zQS4fr@@)CXo8!-aTJje1Zo$iOWZj5k>&Ga8!TDU;?tS`Mt?Qugw;vOJOpfD)AI!mm z#1>*^2{~lsF_Ku?FowL#ogs-7;wVtYj}l*qPn)?S#Y8@br2xhG^h_pCZy;Z|Ndn!B ze6E$r{+tBe4r_zR~!n(|g(;ls!521-ou zCm^2C7(z;`4q*eMo_auZZFPz{#JPuI)COu-hY)2vwSJGd>bXPA zK12l~Pa&kD%Bq~otAZL(MK!2Os;nxis)p1{YFJOcN?3gp@4`A(pTNQca&vwg`fwM1 z$6fdy2k;%<+<`T22Zp>JV<&!wK7W?nhWo^=_?G){k5uoIEwA7XP@ViZumwM&xrtkF z6xfDM`~j^U{(#eC5V!*k{k^E6M;WTr9tYOAUHFFErxsQFuy6wVWB~KK@D$uhek0p( zgeSBq1jmI@^O(4V7HmkGp-WEiFQmQnXVdM_;_|cMp1>*XwT?%0z&}`p@twI$otgMo zXONZqut&b;tN~bk7}5vs3wz|hWrY|%5Dr3-NhSax59ze*kit?sVt gK}f;y3EU&6s8A(kHju3SpAWM0Hv;)eW%QT^? z2M*OVO&k#7OXFs(7?&Nv2fxqzeDCx4eP3ICwdxez*UR~;TU8Q3>?sQ!@aW`~GG43( z#r%9wb!SV?OyHJ$XV$3%7u*^DeSt|Ssp0YY(z6OuMxq+{WiL4A6biCjUuj2;rB*F! zHajUz=9a@+dnHSe5TDp5aE4c_!R$;m@G51`srVQ9np9*pcO7h^q{l47!2|W(eTV> z_;u7y=RP`$@4lINBYRntJ##r+O6Sg=wWe(GjAu4lUq+uVNpC- zaqeg>|Cl-R?9nop2{RB7Zg79aCZpAlkWCVEZa(OI{zcf1NWAYjX5yF~#Zxbsg$0Qz zT3(s31j!>LG1Sl^+<-eq5-!?=r%W6ru4qqrZi!+npTLqpaUnnL6lezWsZ8SOmr-y_ z4w3hhe=_@^Uy-MNWA3x#Ylw$i z>@`MTn?&p60YOONokm#(oN@8bD8wDKm|hU-A< zYgiy$hehMVv}vRft<)b1>+BAE%kJSDWWEOrhp>mY zVQvSWz$WzIKHh|Va!5@fF%qV|13Vz~#G<5|h7=|KBGk)x+T9ivSDrTa2p&_f8)Tn0 z_&cMZcok!G732T93d|TA Date: Sat, 2 May 2020 00:14:06 +0200 Subject: [PATCH 39/43] Layer mapping scheme enhancements, UI enhancements * A map file can now be specified and should be read relative to the technology * Giving a map file will disable the pattern-based mapping * UI enhanced accordingly * Added UI option to configure macro resolution mode * Bugfix: LEF files have not been read relative to the tech * Bugfix: Some options where not persistent --- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 43 +- .../lefdef/db_plugin/dbLEFDEFImporter.h | 18 +- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 70 +- .../lefdef/db_plugin/dbLEFImporter.cc | 89 +- .../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 34 +- .../LEFDEFTechnologyComponentEditor.ui | 1125 +++++++++-------- .../lay_plugin/layLEFDEFImportDialogs.cc | 32 +- .../lay_plugin/layLEFDEFImportDialogs.h | 2 +- 8 files changed, 781 insertions(+), 632 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 2e18707ee..8195cfbd0 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -77,7 +77,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_special_routing_suffix (""), m_special_routing_datatype (0), m_separate_groups (false), - m_consider_map_file (true), + m_map_file (), m_macro_resolution_mode (0) { // .. nothing yet .. @@ -125,7 +125,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_special_routing_suffix (d.m_special_routing_suffix), m_special_routing_datatype (d.m_special_routing_datatype), m_separate_groups (d.m_separate_groups), - m_consider_map_file (d.m_consider_map_file), + m_map_file (d.m_map_file), m_macro_resolution_mode (d.m_macro_resolution_mode), m_lef_files (d.m_lef_files) { @@ -298,45 +298,6 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) } } -void -LEFDEFReaderState::import_map_file_heuristics (const std::string &main_path, db::Layout &layout) -{ - std::string input_dir = tl::absolute_path (main_path); - if (! tl::file_exists (input_dir)) { - return; - } - - std::string bn = tl::basename (tl::filename (main_path)); - std::vector map_files; - std::string map_file_exact; - - std::vector entries = tl::dir_entries (input_dir); - for (std::vector::const_iterator e = entries.begin (); e != entries.end (); ++e) { - - if (tl::to_lower_case (tl::extension (*e)) == "map") { - - if (tl::basename (*e) == bn) { - map_file_exact = *e; - } else { - map_files.push_back (*e); - } - - } - - } - - try { - if (! map_file_exact.empty ()) { - read_map_file (tl::combine_path (input_dir, map_file_exact), layout); - } else if (map_files.size () == 1) { - read_map_file (tl::combine_path (input_dir, map_files.front ()), layout); - } - } catch (tl::Exception &ex) { - // ignore read errors on map file (this is a heuristics!) - tl::error << ex.msg (); - } -} - std::pair LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index bb41ade22..3d7a05412 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -515,14 +515,14 @@ public: m_separate_groups = f; } - bool consider_map_file () const + const std::string &map_file () const { - return m_consider_map_file; + return m_map_file; } - void set_consider_map_file (bool f) + void set_map_file (const std::string &f) { - m_consider_map_file = f; + m_map_file = f; } /** @@ -584,7 +584,7 @@ private: std::string m_special_routing_suffix; int m_special_routing_datatype; bool m_separate_groups; - bool m_consider_map_file; + std::string m_map_file; unsigned int m_macro_resolution_mode; std::vector m_lef_files; }; @@ -637,14 +637,6 @@ public: */ void read_map_file (const std::string &path, db::Layout &layout); - /** - * @brief Imports a .map file present next to the input files - * "main_path" path of an input file (DEF). If a suitable .map file is found at this path, - * it is loaded into the reader state object. This will eventually disable any other layer - * mapping except for the global layers (region, outline, placement blockage). - */ - void import_map_file_heuristics (const std::string &main_path, db::Layout &layout); - /** * @brief Sets the layer map */ diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index b919fb0c7..983a68596 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -31,6 +31,7 @@ #include "dbDEFImporter.h" #include "dbLEFDEFImporter.h" #include "dbLayoutUtils.h" +#include "dbTechnology.h" namespace db { @@ -103,14 +104,32 @@ public: { return "LEFDEF"; } + private: tl::InputStream &m_stream; db::LayerMap m_layer_map; - std::string correct_path (const std::string &fn) + std::string correct_path (const std::string &fn, const db::Layout &layout) { if (! tl::is_absolute (fn)) { + + // if a technology is given and the file can be found in the technology's base path, take it + // from there. + std::string tn = layout.meta_info_value ("technology"); + const db::Technology *tech = 0; + if (! tn.empty ()) { + tech = db::Technologies::instance ()->technology_by_name (tn); + } + + if (tech && ! tech->base_path ().empty ()) { + std::string new_fn = tl::combine_path (tech->base_path (), fn); + if (tl::file_exists (new_fn)) { + return new_fn; + } + } + return tl::combine_path (m_stream.absolute_path (), fn); + } else { return fn; } @@ -126,8 +145,8 @@ private: db::LEFDEFReaderState state (lefdef_options, layout); - if (lefdef_options->consider_map_file ()) { - state.import_map_file_heuristics (m_stream.absolute_path (), layout); + if (! lefdef_options->map_file ().empty ()) { + state.read_map_file (correct_path (lefdef_options->map_file (), layout), layout); } layout.dbu (lefdef_options->dbu ()); @@ -140,7 +159,7 @@ private: for (std::vector::const_iterator l = lefdef_options->begin_lef_files (); l != lefdef_options->end_lef_files (); ++l) { - std::string lp = correct_path (*l); + std::string lp = correct_path (*l, layout); tl::InputStream lef_stream (lp); tl::log << tl::to_string (tr ("Reading")) << " " << lp; @@ -159,7 +178,7 @@ private: for (std::vector::const_iterator l = lefdef_options->begin_lef_files (); l != lefdef_options->end_lef_files (); ++l) { - std::string lp = correct_path (*l); + std::string lp = correct_path (*l, layout); tl::InputStream lef_stream (lp); tl::log << tl::to_string (tr ("Reading")) << " " << lp; @@ -167,8 +186,7 @@ private: } - // Additionally read all LEF files next to the DEF file and if there is a single .map file - // or one with the same name than the input file with ".map" suffix, try to read this one too. + // Additionally read all LEF files next to the DEF file std::string input_dir = tl::absolute_path (m_stream.absolute_path ()); @@ -205,6 +223,39 @@ private: } }; +namespace { + + struct MacroResolutionModeConverter + { + public: + MacroResolutionModeConverter () + { + m_values.push_back ("default"); + m_values.push_back ("always-lef"); + m_values.push_back ("always-cellref"); + } + + std::string to_string (unsigned int v) const + { + return v < m_values.size () ? m_values[v] : std::string (); + } + + void from_string (const std::string &s, unsigned int &v) const + { + v = 0; + for (unsigned int i = 0; i < (unsigned int) m_values.size (); ++i) { + if (m_values [i] == s) { + v = i; + } + } + } + + private: + std::vector m_values; + }; + +} + class LEFDEFFormatDeclaration : public db::StreamFormatDeclaration { @@ -280,7 +331,10 @@ class LEFDEFFormatDeclaration tl::make_member (&LEFDEFReaderOptions::produce_special_routing, &LEFDEFReaderOptions::set_produce_special_routing, "produce-special-routing") + tl::make_member (&LEFDEFReaderOptions::special_routing_suffix, &LEFDEFReaderOptions::set_special_routing_suffix, "special-routing-suffix") + tl::make_member (&LEFDEFReaderOptions::special_routing_datatype, &LEFDEFReaderOptions::set_special_routing_datatype, "special-routing-datatype") + - tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files") + tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files") + + tl::make_member (&LEFDEFReaderOptions::macro_resolution_mode, &LEFDEFReaderOptions::set_macro_resolution_mode, "macro-resolution-mode", MacroResolutionModeConverter ()) + + tl::make_member (&LEFDEFReaderOptions::separate_groups, &LEFDEFReaderOptions::set_separate_groups, "separate-groups") + + tl::make_member (&LEFDEFReaderOptions::map_file, &LEFDEFReaderOptions::set_map_file, "map-file") ); } }; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index cbe6681f5..b537b532e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -347,7 +347,7 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p std::string vn = get (); db::Cell *vc = reader_state ()->via_cell (vn); if (! vc) { - warn ("Unknown via: " + vn); + warn (tl::to_string (tr ("Unknown via: ")) + vn); } if (iterate) { @@ -549,7 +549,7 @@ LEFImporter::read_viadef_by_geometry (Layout &layout, db::Cell &cell, ViaDesc &v via_desc.m1 = routing_layers[0]; via_desc.m2 = routing_layers[1]; } else { - warn ("Can't determine routing layers for via: " + n); + warn (tl::to_string (tr ("Can't determine routing layers for via: ")) + n); } reset_cellname (); @@ -724,6 +724,11 @@ void LEFImporter::read_macro (Layout &layout) { std::string mn = get (); + + if (m_macros_by_name.find (mn) != m_macros_by_name.end ()) { + error (tl::to_string (tr ("Duplicate MACRO name: ")) + mn); + } + set_cellname (mn); db::Cell &cell = layout.cell (layout.add_cell ()); @@ -813,20 +818,11 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("FOREIGN")) { if (foreign_cell) { - error ("Duplicate FOREIGN definition"); + error (tl::to_string (tr ("Duplicate FOREIGN definition"))); } std::string cn = get (); - db::cell_index_type ci; - std::pair c = layout.cell_by_name (cn.c_str ()); - if (c.first) { - ci = c.second; - } else { - ci = layout.add_cell (cn.c_str ()); - layout.cell (ci).set_ghost_cell (true); - } - db::Point vec; db::FTrans ft; if (! peek (";")) { @@ -836,11 +832,24 @@ LEFImporter::read_macro (Layout &layout) expect (";"); - foreign_cell = &layout.cell (ci); - // What is the definition of the FOREIGN transformation? - // Guessing: this transformation moves the lower-left origin to 0,0 - foreign_trans = db::Trans (db::Point () - vec) * db::Trans (ft); - foreign_name = cn; + if (options ().macro_resolution_mode () != 1) { + + db::cell_index_type ci; + std::pair c = layout.cell_by_name (cn.c_str ()); + if (c.first) { + ci = c.second; + } else { + ci = layout.add_cell (cn.c_str ()); + layout.cell (ci).set_ghost_cell (true); + } + + foreign_cell = &layout.cell (ci); + // What is the definition of the FOREIGN transformation? + // Guessing: this transformation moves the lower-left origin to 0,0 + foreign_trans = db::Trans (db::Point () - vec) * db::Trans (ft); + foreign_name = cn; + + } } else if (test ("OBS")) { @@ -855,38 +864,42 @@ LEFImporter::read_macro (Layout &layout) } - if (options ().macro_resolution_mode () == 1 || (! foreign_cell && options ().macro_resolution_mode () != 2)) { + if (! foreign_cell) { - // actually implement the real cell + if (options ().macro_resolution_mode () != 2) { - layout.rename_cell (cell.cell_index (), mn.c_str ()); + // actually implement the real cell - std::pair dl = open_layer (layout, std::string (), Outline); - if (dl.first) { - cell.shapes (dl.second).insert (db::Box (-origin, -origin + size)); - } + layout.rename_cell (cell.cell_index (), mn.c_str ()); - m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ()))); + std::pair dl = open_layer (layout, std::string (), Outline); + if (dl.first) { + cell.shapes (dl.second).insert (db::Box (-origin, -origin + size)); + } - } else if (! foreign_cell) { + m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ()))); - // macro resolution mode #2 (always create a MACRO reference, no LEF geometry) - - db::cell_index_type ci; - std::pair c = layout.cell_by_name (mn.c_str ()); - if (c.first) { - ci = c.second; } else { - ci = layout.add_cell (mn.c_str ()); - layout.cell (ci).set_ghost_cell (true); - } - layout.delete_cell (cell.cell_index ()); - m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&layout.cell (ci), db::Trans ()))); + // macro resolution mode #2 (always create a MACRO reference, no LEF geometry) + + db::cell_index_type ci; + std::pair c = layout.cell_by_name (mn.c_str ()); + if (c.first) { + ci = c.second; + } else { + ci = layout.add_cell (mn.c_str ()); + layout.cell (ci).set_ghost_cell (true); + } + + layout.delete_cell (cell.cell_index ()); + m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&layout.cell (ci), db::Trans ()))); + + } } else if (foreign_name != mn) { - warn ("FOREIGN name differs from MACRO name in macro: " + mn); + warn (tl::to_string (tr ("FOREIGN name differs from MACRO name in macro: ")) + mn); layout.rename_cell (cell.cell_index (), mn.c_str ()); diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index b41e96977..30fd2a0b1 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -466,17 +466,20 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "\n" "This property has been added in version 0.26.5.\n" ) + - gsi::method ("consider_map_file", &db::LEFDEFReaderOptions::consider_map_file, - "@brief Gets a value indicating whether to consider reading .map files next to DEF files.\n" - "If this property is set to true (the default), the DEF reader will look for .map files next to the " - "DEF file. If such a file is found, it will be used to map DEF layers to layout layers. The layer mapping " - "settings specified in the reader options are ignored in this case.\n" + gsi::method ("map_file", &db::LEFDEFReaderOptions::map_file, + "@brief Gets the layer map file to use.\n" + "If a layer map file is given, the reader will pull the layer mapping from this file. The layer mapping rules " + "specified in the reader options are ignored in this case. These are the name suffix rules for vias, blockages, routing, " + "special routing, pins etc. and the corresponding datatype rules. The \\layer_map attribute will also be ignored. " + "\n" + "The layer map file path will be resolved relative to the technology base path if the LEF/DEF reader options are " + "used in the context of a technology.\n" "\n" "This property has been added in version 0.26.5.\n" ) + - gsi::method ("consider_map_file=", &db::LEFDEFReaderOptions::set_consider_map_file, gsi::arg ("flag"), - "@brief Sets a value indicating whether to consider reading .map files next to DEF files.\n" - "See \\consider_map_file for details about this property.\n" + gsi::method ("map_file=", &db::LEFDEFReaderOptions::set_map_file, gsi::arg ("file"), + "@brief Sets the layer map file to use.\n" + "See \\map_file for details about this property.\n" "\n" "This property has been added in version 0.26.5.\n" ) + @@ -513,6 +516,21 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "@brief Detailed LEF/DEF reader options\n" "This class is a aggregate belonging to the \\LoadLayoutOptions class. It provides options for the LEF/DEF reader. " "These options have been placed into a separate class to account for their complexity." + "\n" + "This class specifically handles layer mapping. This is the process of generating layer names or GDS layer/datatypes " + "from LEF/DEF layers and purpose combinations. There are basically two ways: to use a map file or to use pattern-based production rules.\n" + "\n" + "To use a layer map file, set the \\map_file attribute to the name of the layer map file. The layer map " + "file lists the GDS layer and datatype numbers to generate for the geometry.\n" + "\n" + "The pattern-based approach will use the layer name and attach a purpose-dependent suffix to it. " + "Use the ..._suffix attributes to specify this suffix. For routing, the corresponding attribute is \\routing_suffix for example. " + "A purpose can also be mapped to a specific GDS datatype using the corresponding ..._datatype attributes.\n" + "The decorated or undecorated names are looked up in a layer mapping table in the next step. The layer mapping table " + "is specified using the \\layer_map attribute. This table can be used to map layer names to specific GDS layers " + "by using entries of the form 'NAME: layer-number'.\n" + "\n" + "If a layer map file is present, the pattern-based attributes are ignored.\n" ); } diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui index 1ae4b3c64..3b849c53f 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui +++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFTechnologyComponentEditor.ui @@ -6,8 +6,8 @@ 0 0 - 775 - 855 + 859 + 868 @@ -207,7 +207,84 @@ 4 + + + + FOREIGN macros + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + Via cell name prefix + + + + + + + Layout DBU + + + + + + + + Link to external cells for FOREIGN, LEF macros otherwise + + + + + Ignore FOREIGN, Produce LEF macros always + + + + + Always link to external cells + + + + + + + + Produce a parent cell for each group + + + + + + + Groups + + + + + + + + 0 + 0 + + + + + @@ -230,60 +307,21 @@ - - - - Produce a parent cell for each group + + + + Qt::Horizontal - - - - - - Via cell name prefix + + QSizePolicy::Fixed - - - - - - Layout database unit + + + 5 + 20 + - - - - - - Separate groups - - - - - - - - 0 - 0 - - - - - - - - Consider map files - - - - - - - Look for .map files next to DEF files and use them to map layers - - - true - - + @@ -291,7 +329,7 @@ - Production (specify what objects to produce and on what layers) + Global Production Rules (specify what objects to produce and on what layers) true @@ -312,32 +350,6 @@ 6 - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - As properties with name ... - - - - - - @@ -368,18 +380,77 @@ - - + + - Produce ... - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + As properties with name ... - - + + + + + + + Qt::Vertical + + + + + + + + + + + + + :/right.png + + + + + + + + + + <html><body>(<a href="int:/about/variant_notation.xml">See here for the name notation</a>)</body></html> + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + + + + + + + + + :/right.png + + + + + + + + + + + + + :/right.png + + + + + 0 @@ -387,11 +458,11 @@ - Cell outlines + Blockages - + @@ -422,9 +493,6 @@ - - - @@ -432,63 +500,7 @@ - - - - - 0 - 0 - - - - Blockages - - - - - - - <html><body>(<a href="int:/about/variant_notation.xml">See here for the name notation</a>)</body></html> - - - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing - - - - - - - - - - GDS datatype ... - - - - - - Layer name suffix ... - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - On layer with spec ... @@ -498,282 +510,6 @@ - - - - - - - - - - - - - - - - Via geometry - - - - - - - - - - :/right.png - - - - - - - Qt::Vertical - - - - - - - Pins - - - - - - - Regions - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - - - - :/right.png - - - - - - - - - - - - - Pin names - - - - - - - - - - :/right.png - - - - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - Blockages - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - Pin labels - - - - - - - - - - - - - Special routing - - - - - - - - - - - - - Routing - - - - - - - - - - - - - Obstructions - - - - - - - - - - - - - - - - - - - LEF Pins - - - @@ -795,24 +531,11 @@ 0 - - - - Layer assignment is not used if a .map file is present for DEF layer mapping - - - - - - :/warn_16.png - - - - 1 + 0 0 @@ -824,94 +547,480 @@ - - - - - - - - 0 - 1 - - - - Layer Mapping (filter/modify layers, assign GDS layer/datatypes) - - - true - - - - 9 - - - 4 - - - 9 - - - 4 - - - - - Read all layers (additionally to the ones in the mapping table) - - + + - - + + - + 0 - 1 + 0 - - - 16 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised + + Regions - - + + + + Pin names + + + + + + + + 0 + 0 + + + + Cell outlines + + + + + 0 0 - - This table is not used if a .map file is present for DEF layer mapping - - :/warn_16.png - - - - - - - Qt::Horizontal + :/right.png + + + + 0 + + + + Layer Map File + + + + + + Qt::Vertical + + + + 20 + 278 + + + + + + + + Layer map file + + + + + + + ... + + + false + + + + + + + + + + If a layer map file is given, pattern based rules are ignored. +If used inside a technology, the file will be looked up relative to the technology's base path. + + + + + + + + Pattern Based Layer Production Rules + + + + + + + 0 + 150 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + + + + + + Special routing + + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + Routing + + + + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + Via geometry + + + + + + + Pin labels + + + + + + + LEF Pins + + + + + + + Layer name suffix ... + + + + + + + Pins + + + + + + + + + + + + + GDS datatype ... + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + + + + + + + + + Blockages + + + + + + + Obstructions + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + + + Layer name suffix ... + + + + + + + GDS datatype ... + + + + + + + Qt::Vertical + + + + + + + + + + + 0 + 1 + + + + Layer Mapping (filter/modify layers, assign GDS layer/datatypes) + + + true + + + + 9 + + + 4 + + + 9 + + + 4 + + + + + Read all layers (additionally to the ones in the mapping table) + + + + + + + + 0 + 1 + + + + + 16 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + Qt::Horizontal + + + + + + + + + + @@ -934,16 +1043,6 @@ dbu produce_net_names net_prop_name - produce_outlines - outline_layer - produce_placement_blockages - placement_blockage_layer - produce_via_geometry - suffix_via_geometry - datatype_via_geometry - produce_pins - suffix_pins - datatype_pins read_all_cbx diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc index fec570018..89f4754d3 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc @@ -363,7 +363,7 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent) connect (del_lef_files, SIGNAL (clicked ()), this, SLOT (del_lef_files_clicked ())); connect (move_lef_files_up, SIGNAL (clicked ()), this, SLOT (move_lef_files_up_clicked ())); connect (move_lef_files_down, SIGNAL (clicked ()), this, SLOT (move_lef_files_down_clicked ())); - connect (consider_map_file, SIGNAL (stateChanged (int)), this, SLOT (consider_map_file_state_changed ())); + connect (browse_mapfile, SIGNAL (clicked ()), this, SLOT (browse_mapfile_clicked ())); lay::activate_help_links (help_label); } @@ -451,7 +451,8 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_labels_suffix (tl::to_string (suffix_labels->text ())); data->set_labels_datatype (datatype_labels->text ().toInt ()); data->set_separate_groups (separate_groups->isChecked ()); - data->set_consider_map_file (consider_map_file->isChecked ()); + data->set_map_file (tl::to_string (mapfile_path->text ())); + data->set_macro_resolution_mode (foreign_mode->currentIndex ()); data->clear_lef_files (); for (int i = 0; i < lef_files->count (); ++i) { @@ -512,7 +513,9 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options suffix_labels->setText (tl::to_qstring (data->labels_suffix ())); datatype_labels->setText (QString::number (data->labels_datatype ())); separate_groups->setChecked (data->separate_groups ()); - consider_map_file->setChecked (data->consider_map_file ()); + mapfile_path->setText (tl::to_qstring (data->map_file ())); + layer_map_mode->setCurrentIndex (data->map_file ().empty () ? 1 : 0); + foreign_mode->setCurrentIndex (data->macro_resolution_mode ()); checkbox_changed (); @@ -529,13 +532,6 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options } } -void -LEFDEFReaderOptionsEditor::consider_map_file_state_changed () -{ - warn1->setVisible (consider_map_file->isChecked ()); - warn2->setVisible (consider_map_file->isChecked ()); -} - void LEFDEFReaderOptionsEditor::checkbox_changed () { @@ -563,6 +559,22 @@ LEFDEFReaderOptionsEditor::checkbox_changed () datatype_labels->setEnabled (produce_labels->isChecked ()); } +void +LEFDEFReaderOptionsEditor::browse_mapfile_clicked () +{ + std::string title, filters; + title = tl::to_string (QObject::tr ("Select Layer Map File")); + filters = tl::to_string (QObject::tr ("LEF/DEF layer map files (*.map);;All files (*)")); + QString file = QFileDialog::getOpenFileName (this, tl::to_qstring (title), QString (), tl::to_qstring (filters)); + if (! file.isNull ()) { + if (mp_tech) { + mapfile_path->setText (tl::to_qstring (mp_tech->correct_path (tl::to_string (file)))); + } else { + mapfile_path->setText (file); + } + } +} + void LEFDEFReaderOptionsEditor::add_lef_file_clicked () { diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h index 1da4f81b2..695285e0b 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.h @@ -98,7 +98,7 @@ private slots: void del_lef_files_clicked (); void move_lef_files_up_clicked (); void move_lef_files_down_clicked (); - void consider_map_file_state_changed (); + void browse_mapfile_clicked (); private: tl::weak_ptr mp_tech; From fd63d1017fd7a517f67d8b8a028795301903df97 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 2 May 2020 09:30:17 +0200 Subject: [PATCH 40/43] Added tests for LEF/DEF mapfile, fixed a few bugs. --- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 2 +- .../lefdef/db_plugin/dbLEFImporter.cc | 8 ++--- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 24 +++++++++++-- testdata/lefdef/mapfile/au.oas.gz | Bin 0 -> 508 bytes testdata/lefdef/mapfile/in.def | 32 ++++++++++++++++++ testdata/lefdef/mapfile/in.lef | 19 +++++++++++ testdata/lefdef/mapfile/in_tech.lef | 27 +++++++++++++++ testdata/lefdef/mapfile/test.map | 18 ++++++++++ 8 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 testdata/lefdef/mapfile/au.oas.gz create mode 100644 testdata/lefdef/mapfile/in.def create mode 100644 testdata/lefdef/mapfile/in.lef create mode 100644 testdata/lefdef/mapfile/in_tech.lef create mode 100644 testdata/lefdef/mapfile/test.map diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 983a68596..2bd4466ae 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -128,7 +128,7 @@ private: } } - return tl::combine_path (m_stream.absolute_path (), fn); + return tl::combine_path (tl::dirname (m_stream.absolute_path ()), fn); } else { return fn; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index b537b532e..7bf3c307a 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -604,12 +604,12 @@ LEFImporter::read_layer (Layout & /*layout*/) } else if (test ("TYPE")) { - if (test ("ROUTING")) { + std::string type = get (); + + if (type == "ROUTING" || type == "MASTERSLICE") { m_routing_layers.insert (ln); - } else if (test ("CUT")) { + } else if (type == "CUT") { m_cut_layers.insert (ln); - } else { - get (); } expect (";"); diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index f6f70c009..827377a2a 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -49,7 +49,7 @@ static db::LEFDEFReaderOptions default_options () return tc; } -static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &tc, bool priv = true) +static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true) { std::string fn_path (priv ? tl::testsrc_private () : tl::testsrc ()); fn_path += "/testdata/lefdef/"; @@ -61,7 +61,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file tl::Extractor ex (filename); - db::LEFDEFReaderState ld (&tc, layout); + db::LEFDEFReaderState ld (&options, layout); db::DEFImporter imp; @@ -103,6 +103,18 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file db::Reader reader (stream); reader.read (layout, db::LoadLayoutOptions ()); + } else if (ex.test("read:")) { + + std::string fn = fn_path, f; + ex.read_word_or_quoted (f); + fn += f; + + tl::InputStream stream (fn); + db::Reader reader (stream); + db::LoadLayoutOptions lo; + lo.set_options (options); + reader.read (layout, lo); + } else { break; @@ -361,3 +373,11 @@ TEST(110_lefpins) run_test (_this, "lefpins", "lef:in_tech.lef+lef:in.lef+def:in.def", "au_lefpins_mapped.oas.gz", options, false); } + +TEST(111_mapfile) +{ + db::LEFDEFReaderOptions options = default_options (); + options.set_map_file ("test.map"); + + run_test (_this, "mapfile", "read:in.def", "au.oas.gz", options, false); +} diff --git a/testdata/lefdef/mapfile/au.oas.gz b/testdata/lefdef/mapfile/au.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..629c7144bc827d1420891ebf3db05ad7bec45729 GIT binary patch literal 508 zcmVaT?9SNY0W+&HBN7@9_DkNq23#Ns*^) z*R|4DFJI3O_vuBKUdC1OSj|bUg*%Do29jnJMA`67e;9>*PfjB@7~n0O#DiQ0G8x2C ze#QBeVQgiR*Zol+Jr$ISlI9K61&OXEDz3=nc|lcC(nZFzCelO4M8y>u+yJ#AN}4xw zs@M}Ph^oEp;`(Tbs9Mg^PP}mYzU4?Pd?4bl3cv1;uY3<{_}~>ezKLS^2Z^OBO?mze zRwav>qbo`MV&+Pu4#qbILf4HWp&CaVbkaTthos?^;fn*RVypzXTPn yUJuB}`UyE_MOEqktZmc@$uU@R>kA^-c-k2&M0rm#P~QE|2jDl8kqyDK1ONa$2?68) literal 0 HcmV?d00001 diff --git a/testdata/lefdef/mapfile/in.def b/testdata/lefdef/mapfile/in.def new file mode 100644 index 000000000..f24be607b --- /dev/null +++ b/testdata/lefdef/mapfile/in.def @@ -0,0 +1,32 @@ + +VERSION 5.8 ; +DIVIDERCHAR "/" ; +BUSBITCHARS "[]" ; +DESIGN mapfile ; +UNITS DISTANCE MICRONS 1000 ; + +DIEAREA ( 0 0 ) ( 1000 2000 ) ; + +COMPONENTS 3 ; + - macro1 macro1 + PLACED ( 0 0 ) N ; +END COMPONENTS + +SPECIALNETS 1 ; +- VDD ( * VDD ) ++ ROUTED M1 50 + SHAPE STRIPE ( 500 0 ) ( 500 500 25 ) square ( 0 500 ) ++ USE POWER ; +END SPECIALNETS + +PINS 1 ; +- VDD + NET VDD + SPECIAL + DIRECTION INOUT + USE POWER + + LAYER M1 ( 0 0 ) ( 50 70 ) + ; +END PINS + +NETS 1 ; +- TOP ++ ROUTED M1 ( 100 700 ) ( 500 * ) ; +END NETS + +END DESIGN + diff --git a/testdata/lefdef/mapfile/in.lef b/testdata/lefdef/mapfile/in.lef new file mode 100644 index 000000000..38d550efa --- /dev/null +++ b/testdata/lefdef/mapfile/in.lef @@ -0,0 +1,19 @@ +MACRO macro1 + CLASS CORE ; + ORIGIN 0.035 0.235 ; + SIZE 0.07 BY 0.47 ; + PIN Z + PORT + LAYER M1 ; + RECT -0.02 0 0.02 0.2 ; + RECT -0.03 -0.2 0.01 -0.1 ; + VIA 0.0 0.2 square ; + VIA 0.01 -0.2 square ; + END + END Z + OBS + LAYER M1 ; + RECT -0.035 -0.235 0.035 0.235 ; + END +END macro1 + diff --git a/testdata/lefdef/mapfile/in_tech.lef b/testdata/lefdef/mapfile/in_tech.lef new file mode 100644 index 000000000..83f711256 --- /dev/null +++ b/testdata/lefdef/mapfile/in_tech.lef @@ -0,0 +1,27 @@ +LAYER M0PO + TYPE MASTERSLICE ; + WIDTH 0.02 ; +END M0PO +LAYER VIA0 + TYPE CUT ; +END VIA0 +LAYER M1 + TYPE MASTERSLICE ; + WIDTH 0.025 ; +END M1 +LAYER VIA1 + TYPE CUT ; +END VIA1 +LAYER M2 + TYPE MASTERSLICE ; + WIDTH 0.03 ; +END M2 + +VIA square + LAYER M0PO ; + RECT -0.006 -0.006 0.006 0.006 ; + LAYER VIA0 ; + RECT -0.006 -0.006 0.006 0.006 ; + LAYER M1 ; + RECT -0.006 -0.006 0.006 0.006 ; +END square diff --git a/testdata/lefdef/mapfile/test.map b/testdata/lefdef/mapfile/test.map new file mode 100644 index 000000000..7a8609dad --- /dev/null +++ b/testdata/lefdef/mapfile/test.map @@ -0,0 +1,18 @@ +DIEAREA ALL 100 0 +M0PO LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 10 0 +VIA0 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 11 0 +M1 LEFPIN 12 0 +M1 LEFOBS 12 1 +M1 PIN 12 2 +M1 NET 12 3 +M1 SPNET 12 4 +M1 VIA 12 5 +M1 FILLOPC 12 100 +M1 FILLOPC:MASK:1 12 101 +M1 FILLOPC:MASK:2 12 102 +M1 BLOCKAGEFILL 12 150 +M1 BLOCKAGE 12 151 +M1 FILL 12 152 +NAME M1/PIN 12 10 +VIA1 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 13 0 +M2 LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 14 0 From b5faa7f6be2ffe46cbb9455858dbc1e0c06d17ae Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 2 May 2020 09:32:00 +0200 Subject: [PATCH 41/43] Fixed RBA tests. --- testdata/ruby/dbReaders.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testdata/ruby/dbReaders.rb b/testdata/ruby/dbReaders.rb index b17092355..eb33d4c61 100644 --- a/testdata/ruby/dbReaders.rb +++ b/testdata/ruby/dbReaders.rb @@ -345,9 +345,9 @@ class DBReaders_TestClass < TestBase conf.separate_groups = true assert_equal(conf.separate_groups, true) - assert_equal(conf.consider_map_file, true) - conf.consider_map_file = false - assert_equal(conf.consider_map_file, false) + assert_equal(conf.map_file, "") + conf.map_file = "xyz.map" + assert_equal(conf.map_file, "xyz.map") assert_equal(conf.lef_files.join(","), "") conf.lef_files = [ "u.lef", "v.lef" ] From 99ec635e5a7afe1a815fbc2eb630e9ec56d9e272 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 2 May 2020 13:19:26 +0200 Subject: [PATCH 42/43] Start LEF browser in tech base dir in the context of a technology --- .../streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc index 89f4754d3..2ca27a3d8 100644 --- a/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc +++ b/src/plugins/streamers/lefdef/lay_plugin/layLEFDEFImportDialogs.cc @@ -581,7 +581,13 @@ LEFDEFReaderOptionsEditor::add_lef_file_clicked () std::string title, filters; title = tl::to_string (QObject::tr ("Add LEF Files")); filters = tl::to_string (QObject::tr ("LEF files (*.lef *.LEF *.lef.gz *.LEF.gz);;All files (*)")); - QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), QString (), tl::to_qstring (filters)); + + std::string dir; + if (mp_tech) { + dir = mp_tech->base_path (); + } + + QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filters)); for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) { if (mp_tech) { lef_files->addItem (tl::to_qstring (mp_tech->correct_path (tl::to_string (*f)))); From 5fd60e0d49870cb5ecb4f6e8ddcc8172829d8696 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 2 May 2020 13:22:04 +0200 Subject: [PATCH 43/43] Planning LEF/DEF enhancements for 0.27 now as this is a too big change. --- .../lefdef/db_plugin/gsiDeclDbLEFDEF.cc | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc index 30fd2a0b1..8c4fc324b 100644 --- a/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc +++ b/src/plugins/streamers/lefdef/db_plugin/gsiDeclDbLEFDEF.cc @@ -264,13 +264,13 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "@brief Gets the via cellname prefix.\n" "Vias are represented by cells. The cell name is formed by combining the via cell name prefix and the via name.\n" "\n" - "This property has been added in version 0.26.5.\n" + "This property has been added in version 0.27.\n" ) + gsi::method ("via_cellname_prefix=", &db::LEFDEFReaderOptions::set_via_cellname_prefix, gsi::arg ("prefix"), "@brief Sets the via cellname prefix.\n" "See \\via_cellname_prefix for details about this property.\n" "\n" - "This property has been added in version 0.26.5.\n" + "This property has been added in version 0.27.\n" ) + gsi::method ("produce_pins", &db::LEFDEFReaderOptions::produce_pins, "@brief Gets a value indicating whether pin geometries shall be produced.\n" @@ -420,37 +420,37 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "@brief Gets a value indicating whether special routing geometry shall be produced.\n" "See \\produce_via_geometry for details about the layer production rules.\n" "\n" - "The differentiation between special and normal routing has been introduced in version 0.26.5." + "The differentiation between special and normal routing has been introduced in version 0.27." ) + gsi::method ("produce_special_routing=", &db::LEFDEFReaderOptions::set_produce_special_routing, gsi::arg ("produce"), "@brief Sets a value indicating whether special routing geometry shall be produced.\n" "See \\produce_via_geometry for details about the layer production rules." "\n" - "The differentiation between special and normal routing has been introduced in version 0.26.5." + "The differentiation between special and normal routing has been introduced in version 0.27." ) + gsi::method ("special_routing_suffix", &db::LEFDEFReaderOptions::special_routing_suffix, "@brief Gets the special routing layer name suffix.\n" "See \\produce_via_geometry for details about the layer production rules." "\n" - "The differentiation between special and normal routing has been introduced in version 0.26.5." + "The differentiation between special and normal routing has been introduced in version 0.27." ) + gsi::method ("special_routing_suffix=", &db::LEFDEFReaderOptions::set_special_routing_suffix, gsi::arg ("suffix"), "@brief Sets the special routing layer name suffix.\n" "See \\produce_via_geometry for details about the layer production rules." "\n" - "The differentiation between special and normal routing has been introduced in version 0.26.5." + "The differentiation between special and normal routing has been introduced in version 0.27." ) + gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype, "@brief Gets the special routing layer datatype value.\n" "See \\produce_via_geometry for details about the layer production rules." "\n" - "The differentiation between special and normal routing has been introduced in version 0.26.5." + "The differentiation between special and normal routing has been introduced in version 0.27." ) + gsi::method ("special_routing_datatype=", &db::LEFDEFReaderOptions::set_special_routing_datatype, gsi::arg ("datatype"), "@brief Sets the special routing layer datatype value.\n" "See \\produce_via_geometry for details about the layer production rules." "\n" - "The differentiation between special and normal routing has been introduced in version 0.26.5." + "The differentiation between special and normal routing has been introduced in version 0.27." ) + gsi::method ("separate_groups", &db::LEFDEFReaderOptions::separate_groups, "@brief Gets a value indicating whether to create separate parent cells for individual groups.\n" @@ -458,13 +458,13 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "individual parent cells. These parent cells are named after the groups and are put into the master top cell.\n" "If this property is set to false (the default), no such group parents will be formed." "\n" - "This property has been added in version 0.26.5.\n" + "This property has been added in version 0.27.\n" ) + gsi::method ("separate_groups=", &db::LEFDEFReaderOptions::set_separate_groups, gsi::arg ("flag"), "@brief Sets a value indicating whether to create separate parent cells for individual groups.\n" "See \\seperate_groups for details about this property.\n" "\n" - "This property has been added in version 0.26.5.\n" + "This property has been added in version 0.27.\n" ) + gsi::method ("map_file", &db::LEFDEFReaderOptions::map_file, "@brief Gets the layer map file to use.\n" @@ -475,13 +475,13 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi "The layer map file path will be resolved relative to the technology base path if the LEF/DEF reader options are " "used in the context of a technology.\n" "\n" - "This property has been added in version 0.26.5.\n" + "This property has been added in version 0.27.\n" ) + gsi::method ("map_file=", &db::LEFDEFReaderOptions::set_map_file, gsi::arg ("file"), "@brief Sets the layer map file to use.\n" "See \\map_file for details about this property.\n" "\n" - "This property has been added in version 0.26.5.\n" + "This property has been added in version 0.27.\n" ) + gsi::method ("macro_resolution_mode", &db::LEFDEFReaderOptions::macro_resolution_mode, "@brief Gets the macro resolution mode.\n" @@ -494,13 +494,13 @@ gsi::Class decl_lefdef_config ("db", "LEFDEFReaderConfi " @li 2: produce a placeholder cell always (even if FOREIGN isn't given) @/li\n" "@/ul\n" "\n" - "This property has been added in version 0.26.5.\n" + "This property has been added in version 0.27.\n" ) + gsi::method ("macro_resolution_mode=", &db::LEFDEFReaderOptions::set_macro_resolution_mode, gsi::arg ("mode"), "@brief Sets the macro resolution mode.\n" "See \\macro_resolution_mode for details about this property.\n" "\n" - "This property has been added in version 0.26.5.\n" + "This property has been added in version 0.27.\n" ) + gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files, "@brief Gets the list technology LEF files to additionally import\n"