From 9cb77d6222eade1c042c90275345da1b248e1a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Sat, 23 Apr 2022 22:26:37 +0200 Subject: [PATCH] Lefdef enhancements (#1053) * Implementated patch as suggested by issue-1047 * Implementing blend-mode for LEF/DEF for a first solution for issue-1048 * Added testcase, fixed other tests * Issue-1050 fixed - now REGION, BLOCKAGE and DIEAREA are relevant from mapping file, nothing else * Bug fixes * Experimental: DEF multipart paths * Experimental: ignore LEF wire extension, ignore PATTERNNAME * Implemented PATTERNNAME in DEF instead of LEF .. * Implemented nondefaultrule vias * LEF/DEF: non-defaultrule vias need a name suffix. * Refined solution for NDR via names, updated test data * Updated test data * Multiple map files and 'REGIONS FENCE' + 'REGIONS GUIDE' layer mapping entries. * Added test data, updated doc. * Some enhancements and feedback REGIONS in map files -> REGION REGION NONE for map files (maps REGIONs which are neither GUIDE or FENCE) Bugfix: VIA with ORIGIN No via cell name prefix by default for buddy tools * Simplified buddy tool options for LEF/DEF property names Dropped --lefdef-dont-produce-instance-names, --lefdef-dont-produce-pin-names and --lefdef-dont-produce-net-names options. Instead, these options have to be enabled by giving the respective property names. Writing the property names takes some space and these options are simply confusing and redundant. * Issue a warning about missing cut geometry for a DEF via with PATTERNNAME (which is ignored) * Fixed issue-1065 --- src/buddies/src/bd/bdReaderOptions.cc | 50 ++-- src/buddies/src/bd/bdReaderOptions.h | 3 - src/db/db/dbCommonReader.cc | 127 +++++----- src/db/db/dbCommonReader.h | 93 ++++++-- .../gds2/db_plugin/dbGDS2ReaderBase.cc | 8 +- .../lefdef/db_plugin/dbDEFImporter.cc | 133 ++++++++--- .../lefdef/db_plugin/dbDEFImporter.h | 2 +- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 219 +++++++++++++----- .../lefdef/db_plugin/dbLEFDEFImporter.h | 56 ++++- .../lefdef/db_plugin/dbLEFDEFPlugin.cc | 3 + .../lefdef/db_plugin/dbLEFImporter.cc | 16 +- .../lefdef/db_plugin/dbLEFImporter.h | 2 +- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 124 +++++++++- .../oasis/db_plugin/dbOASISReader.cc | 5 +- testdata/lefdef/blend_mode/au1.oas.gz | Bin 0 -> 630 bytes testdata/lefdef/blend_mode/au2.oas.gz | Bin 0 -> 610 bytes testdata/lefdef/blend_mode/au3.oas.gz | Bin 0 -> 607 bytes testdata/lefdef/blend_mode/layers.map | 4 + testdata/lefdef/blend_mode/sub.def | 3 + testdata/lefdef/blend_mode/sub.lef | 4 + testdata/lefdef/blend_mode/top.def | 6 + testdata/lefdef/map_regions/au.oas.gz | Bin 0 -> 292 bytes testdata/lefdef/map_regions/test.add.map | 5 + testdata/lefdef/map_regions/test.def | 12 + testdata/lefdef/map_regions/test.lef | 4 + testdata/lefdef/map_regions/test.map | 1 + testdata/lefdef/mapfile/au.oas.gz | Bin 1213 -> 537 bytes testdata/lefdef/patternname/Makefile | 6 + testdata/lefdef/patternname/au.oas.gz | Bin 0 -> 249 bytes testdata/lefdef/patternname/v.def | 15 ++ testdata/lefdef/patternname/v.lef | 26 +++ testdata/lefdef/patternname/v.map | 3 + testdata/lefdef/viasize2/au.oas.gz | Bin 0 -> 424 bytes testdata/lefdef/viasize2/test.def | 37 +++ testdata/lefdef/viasize2/test.lef | 24 ++ testdata/lefdef/viasize2/test_fail.map | 9 + testdata/lefdef/viasize2/test_ok.map | 9 + 37 files changed, 778 insertions(+), 231 deletions(-) create mode 100644 testdata/lefdef/blend_mode/au1.oas.gz create mode 100644 testdata/lefdef/blend_mode/au2.oas.gz create mode 100644 testdata/lefdef/blend_mode/au3.oas.gz create mode 100644 testdata/lefdef/blend_mode/layers.map create mode 100644 testdata/lefdef/blend_mode/sub.def create mode 100644 testdata/lefdef/blend_mode/sub.lef create mode 100644 testdata/lefdef/blend_mode/top.def create mode 100644 testdata/lefdef/map_regions/au.oas.gz create mode 100644 testdata/lefdef/map_regions/test.add.map create mode 100644 testdata/lefdef/map_regions/test.def create mode 100644 testdata/lefdef/map_regions/test.lef create mode 100644 testdata/lefdef/map_regions/test.map create mode 100644 testdata/lefdef/patternname/Makefile create mode 100644 testdata/lefdef/patternname/au.oas.gz create mode 100644 testdata/lefdef/patternname/v.def create mode 100644 testdata/lefdef/patternname/v.lef create mode 100644 testdata/lefdef/patternname/v.map create mode 100644 testdata/lefdef/viasize2/au.oas.gz create mode 100755 testdata/lefdef/viasize2/test.def create mode 100755 testdata/lefdef/viasize2/test.lef create mode 100755 testdata/lefdef/viasize2/test_fail.map create mode 100755 testdata/lefdef/viasize2/test_ok.map diff --git a/src/buddies/src/bd/bdReaderOptions.cc b/src/buddies/src/bd/bdReaderOptions.cc index 2cc09cd22..55b296ad0 100644 --- a/src/buddies/src/bd/bdReaderOptions.cc +++ b/src/buddies/src/bd/bdReaderOptions.cc @@ -68,19 +68,11 @@ GenericReaderOptions::GenericReaderOptions () m_magic_lib_path.push_back (i->to_string ()); } - tl::Variant v; + m_lefdef_net_property_name = std::string (); + m_lefdef_inst_property_name = std::string (); + m_lefdef_pin_property_name = std::string (); - v = load_options.get_option_by_name ("lefdef_config.net_property_name"); - m_lefdef_produce_net_names = ! v.is_nil (); - m_lefdef_net_property_name = v .to_parsable_string (); - - v = load_options.get_option_by_name ("lefdef_config.instance_property_name"); - m_lefdef_produce_inst_names = ! v.is_nil (); - m_lefdef_inst_property_name = v .to_parsable_string (); - - v = load_options.get_option_by_name ("lefdef_config.pin_property_name"); - m_lefdef_produce_pin_names = ! v.is_nil (); - m_lefdef_pin_property_name = v .to_parsable_string (); + m_lefdef_via_cellname_prefix = std::string (); m_lefdef_produce_cell_outlines = load_options.get_option_by_name ("lefdef_config.produce_cell_outlines").to_bool (); m_lefdef_cell_outline_layer = load_options.get_option_by_name ("lefdef_config.cell_outline_layer").to_string (); @@ -91,7 +83,6 @@ GenericReaderOptions::GenericReaderOptions () m_lefdef_produce_via_geometry = load_options.get_option_by_name ("lefdef_config.produce_via_geometry").to_bool (); m_lefdef_via_geometry_suffix = load_options.get_option_by_name ("lefdef_config.via_geometry_suffix_str").to_string (); m_lefdef_via_geometry_datatype = load_options.get_option_by_name ("lefdef_config.via_geometry_datatype_str").to_string (); - m_lefdef_via_cellname_prefix = load_options.get_option_by_name ("lefdef_config.via_cellname_prefix").to_string (); m_lefdef_produce_pins = load_options.get_option_by_name ("lefdef_config.produce_pins").to_bool (); m_lefdef_pins_suffix = load_options.get_option_by_name ("lefdef_config.pins_suffix_str").to_string (); m_lefdef_pins_datatype = load_options.get_option_by_name ("lefdef_config.pins_datatype_str").to_string (); @@ -383,39 +374,27 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd) std::string group ("[" + m_group_prefix + " options - LEF/DEF specific]"); cmd << tl::arg (group + - "#!--" + m_long_prefix + "lefdef-dont-produce-net-names", &m_lefdef_produce_net_names, "Disables producing net names as shape properties", - "If this option is present, net names will not be emitted as shape properties." - ) - << tl::arg (group + "#--" + m_long_prefix + "lefdef-net-property-name=spec", &m_lefdef_net_property_name, "Specifies which property name to use for net names", "This option gives the name of the shape property used to annotate net names. For 'spec' use:\n" "\n" "* \"#n\" for property number \"n\" (compatible with GDS2)\n" "* A plain word for a named property (not compatible with GDS2)\n" "\n" - "Producing net name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-net-names'." - ) - << tl::arg (group + - "#!--" + m_long_prefix + "lefdef-dont-produce-instance-names", &m_lefdef_produce_inst_names, "Disables producing DEF macro instance names as instance properties", - "If this option is present, DEF macro instance names will not be emitted as instance properties." + "By default, net names are not produced." ) << tl::arg (group + "#--" + m_long_prefix + "lefdef-instance-property-name=spec", &m_lefdef_inst_property_name, "Specifies which property name to use for DEF macro instance names", "This option gives the name of the instance property used to annotate DEF macro instance names. " "For the 'spec' format see '--" + m_long_prefix + "lefdef-net-property-name'." "\n" - "Producing instance name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-instance-names'." - ) - << tl::arg (group + - "#!--" + m_long_prefix + "lefdef-dont-produce-pin-names", &m_lefdef_produce_pin_names, "Disables producing pin names as shape or instance properties", - "If this option is present, Pin names will not be emitted as shape or instance properties." + "By default, instance names are not produced." ) << tl::arg (group + "#--" + m_long_prefix + "lefdef-pin-property-name=spec", &m_lefdef_pin_property_name, "Specifies which property name to use for pin names", "This option gives the name of the shape or instance property used to annotate pin names. " "For the 'spec' format see '--" + m_long_prefix + "lefdef-net-property-name'." "\n" - "Producing pin name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-pin-names'." + "By default, pin names are not produced." ) << tl::arg (group + "#!--" + m_long_prefix + "lefdef-dont-produce-cell-outlines", &m_lefdef_produce_cell_outlines, "Disables producing cell outlines", @@ -623,7 +602,10 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd) "layers need to specified individually for different layer/purpose combinations.\n" "\n" "The mapping file is one layer mapping entry per line. Each line is a layer name, followed by a list of purposes (VIA, PIN ...) " - "and a layer and datatype number. In addition, 'DIEAREA' can be used to map the design outline to a layer. 'NAME' in place of the " + "and a layer and datatype number. In addition, 'DIEAREA', 'REGION' and 'BLOCKAGE' can be used to map the design outline, regions and blockages to a layer. " + "'REGION' can have a detailed specifier which is 'FENCE', 'GUIDE' or 'NONE' for fence, guide or other type regions (e.g. 'REGION FENCE 99/0').\n" + "\n" + "'NAME' in place of the " "layer name and using layer/purpose in the purpose column allows mapping labels to specific layers.\n" "\n" "This is an example for a layer map file:\n" @@ -639,7 +621,9 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd) "VIA1 LEFPIN,VIA,PIN,NET,SPNET 13 0\n" "M2 LEFPIN,PIN,NET,SPNET,VIA 14 0\n" "\n" - "If a map file is used, only the layers present in the map file are generated. No other layers are produced." + "If a map file is used, only the layers present in the map file are generated. No other layers are produced.\n" + "\n" + "Multiple map files can be given, separated by '+' or ','. In that case, these files are concatenated." ) << tl::arg (group + "!--" + m_long_prefix + "lefdef-macro-resolution-mode", &m_lefdef_macro_resolution_mode, "Specify how to generate layout from LEF macros", @@ -760,9 +744,9 @@ GenericReaderOptions::configure (db::LoadLayoutOptions &load_options) load_options.set_option_by_name ("lefdef_config.layer_map", tl::Variant::make_variant (m_layer_map)); load_options.set_option_by_name ("lefdef_config.create_other_layers", m_create_other_layers); load_options.set_option_by_name ("lefdef_config.dbu", m_dbu); - load_options.set_option_by_name ("lefdef_config.net_property_name", m_lefdef_produce_net_names ? tl::Variant (m_lefdef_net_property_name) : tl::Variant ()); - load_options.set_option_by_name ("lefdef_config.instance_property_name", m_lefdef_produce_inst_names ? tl::Variant (m_lefdef_inst_property_name) : tl::Variant ()); - load_options.set_option_by_name ("lefdef_config.pin_property_name", m_lefdef_produce_pin_names ? tl::Variant (m_lefdef_pin_property_name) : tl::Variant ()); + load_options.set_option_by_name ("lefdef_config.net_property_name", !m_lefdef_net_property_name.empty () ? tl::Variant (m_lefdef_net_property_name) : tl::Variant ()); + load_options.set_option_by_name ("lefdef_config.instance_property_name", !m_lefdef_inst_property_name.empty () ? tl::Variant (m_lefdef_inst_property_name) : tl::Variant ()); + load_options.set_option_by_name ("lefdef_config.pin_property_name", !m_lefdef_pin_property_name.empty () ? tl::Variant (m_lefdef_pin_property_name) : tl::Variant ()); load_options.set_option_by_name ("lefdef_config.produce_cell_outlines", m_lefdef_produce_cell_outlines); load_options.set_option_by_name ("lefdef_config.cell_outline_layer", m_lefdef_cell_outline_layer); load_options.set_option_by_name ("lefdef_config.produce_placement_blockages", m_lefdef_produce_placement_blockages); diff --git a/src/buddies/src/bd/bdReaderOptions.h b/src/buddies/src/bd/bdReaderOptions.h index 3569fe617..37f00249f 100644 --- a/src/buddies/src/bd/bdReaderOptions.h +++ b/src/buddies/src/bd/bdReaderOptions.h @@ -142,11 +142,8 @@ private: void set_read_named_layers (bool f); // LEFDEF - bool m_lefdef_produce_net_names; std::string m_lefdef_net_property_name; - bool m_lefdef_produce_inst_names; std::string m_lefdef_inst_property_name; - bool m_lefdef_produce_pin_names; std::string m_lefdef_pin_property_name; bool m_lefdef_produce_cell_outlines; std::string m_lefdef_cell_outline_layer; diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc index 1e6d49e7d..8f04994b5 100644 --- a/src/db/db/dbCommonReader.cc +++ b/src/db/db/dbCommonReader.cc @@ -30,18 +30,18 @@ namespace db { // --------------------------------------------------------------- -// Common reader implementation +// Common reader basic feature implementation static const size_t null_id = std::numeric_limits::max (); -CommonReader::CommonReader () +CommonReaderBase::CommonReaderBase () : m_cc_resolution (AddToCell), m_create_layers (false) { // .. nothing yet .. } db::cell_index_type -CommonReader::make_cell (db::Layout &layout, const std::string &cn) +CommonReaderBase::make_cell (db::Layout &layout, const std::string &cn) { tl_assert (! cn.empty ()); @@ -69,13 +69,13 @@ CommonReader::make_cell (db::Layout &layout, const std::string &cn) } bool -CommonReader::has_cell (const std::string &cn) const +CommonReaderBase::has_cell (const std::string &cn) const { return m_name_map.find (cn) != m_name_map.end (); } std::pair -CommonReader::cell_by_name (const std::string &cn) const +CommonReaderBase::cell_by_name (const std::string &cn) const { std::map >::const_iterator iname = m_name_map.find (cn); if (iname != m_name_map.end ()) { @@ -86,7 +86,7 @@ CommonReader::cell_by_name (const std::string &cn) const } db::cell_index_type -CommonReader::make_cell (db::Layout &layout, size_t id) +CommonReaderBase::make_cell (db::Layout &layout, size_t id) { tl_assert (id != null_id); @@ -114,13 +114,13 @@ CommonReader::make_cell (db::Layout &layout, size_t id) } bool -CommonReader::has_cell (size_t id) const +CommonReaderBase::has_cell (size_t id) const { return m_id_map.find (id) != m_id_map.end (); } std::pair -CommonReader::cell_by_id (size_t id) const +CommonReaderBase::cell_by_id (size_t id) const { std::map >::const_iterator iid = m_id_map.find (id); if (iid != m_id_map.end ()) { @@ -131,7 +131,7 @@ CommonReader::cell_by_id (size_t id) const } const std::string & -CommonReader::name_for_id (size_t id) const +CommonReaderBase::name_for_id (size_t id) const { std::map::const_iterator n = m_name_for_id.find (id); if (n != m_name_for_id.end ()) { @@ -143,7 +143,7 @@ CommonReader::name_for_id (size_t id) const } void -CommonReader::rename_cell (db::Layout &layout, size_t id, const std::string &cn) +CommonReaderBase::rename_cell (db::Layout &layout, size_t id, const std::string &cn) { m_name_for_id.insert (std::make_pair (id, cn)); @@ -191,7 +191,7 @@ CommonReader::rename_cell (db::Layout &layout, size_t id, const std::string &cn) } db::cell_index_type -CommonReader::cell_for_instance (db::Layout &layout, size_t id) +CommonReaderBase::cell_for_instance (db::Layout &layout, size_t id) { tl_assert (id != null_id); @@ -213,7 +213,7 @@ CommonReader::cell_for_instance (db::Layout &layout, size_t id) } db::cell_index_type -CommonReader::cell_for_instance (db::Layout &layout, const std::string &cn) +CommonReaderBase::cell_for_instance (db::Layout &layout, const std::string &cn) { tl_assert (! cn.empty ()); @@ -235,7 +235,7 @@ CommonReader::cell_for_instance (db::Layout &layout, const std::string &cn) } void -CommonReader::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const +CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const { const db::Cell &src_cell = layout.cell (src_cell_index); db::Cell &target_cell = layout.cell (target_cell_index); @@ -253,7 +253,7 @@ CommonReader::merge_cell (db::Layout &layout, db::cell_index_type target_cell_in } void -CommonReader::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const +CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const { const db::Cell &src_cell = layout.cell (src_cell_index); db::Cell &target_cell = layout.cell (target_cell_index); @@ -281,46 +281,9 @@ CommonReader::merge_cell_without_instances (db::Layout &layout, db::cell_index_t layout.delete_cell (src_cell.cell_index ()); } -const db::LayerMap & -CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options) -{ - init (options); - - tl_assert (!layout.under_construction ()); - - m_common_options.layer_map.prepare (layout); - - layout.start_changes (); - try { - do_read (layout); - finish (layout); - layout.end_changes (); - } catch (...) { - layout.end_changes (); - throw; - } - - // A cleanup may be necessary because of the following scenario: if library proxies contain subcells - // which are proxies itself, the proxy update may make them orphans (the proxies are regenerated). - // The cleanup will removed these. - layout.cleanup (); - - return m_layer_map_out; -} - -const db::LayerMap & -CommonReader::read (db::Layout &layout) -{ - return read (layout, db::LoadLayoutOptions ()); -} - void -CommonReader::init (const LoadLayoutOptions &options) +CommonReaderBase::init () { - m_common_options = options.get_options (); - m_cc_resolution = m_common_options.cell_conflict_resolution; - m_create_layers = m_common_options.create_other_layers; - m_layer_map_out.clear (); m_multi_mapping_placeholders.clear (); m_layer_cache.clear (); @@ -329,7 +292,7 @@ CommonReader::init (const LoadLayoutOptions &options) } void -CommonReader::finish (db::Layout &layout) +CommonReaderBase::finish (db::Layout &layout) { bool any_missing = false; @@ -492,7 +455,7 @@ CommonReader::finish (db::Layout &layout) } std::pair -CommonReader::open_dl (db::Layout &layout, const LDPair &dl) +CommonReaderBase::open_dl (db::Layout &layout, const LDPair &dl) { std::map >::const_iterator lc = m_layer_cache.find (dl); if (lc != m_layer_cache.end ()) { @@ -505,9 +468,9 @@ CommonReader::open_dl (db::Layout &layout, const LDPair &dl) } std::pair -CommonReader::open_dl_uncached (db::Layout &layout, const LDPair &dl) +CommonReaderBase::open_dl_uncached (db::Layout &layout, const LDPair &dl) { - const std::set &li = common_options ().layer_map.logical (dl, layout); + std::set li = m_layer_map.logical (dl, layout); if (li.empty ()) { if (! m_create_layers) { @@ -558,6 +521,58 @@ CommonReader::open_dl_uncached (db::Layout &layout, const LDPair &dl) } } +// --------------------------------------------------------------- +// Common reader implementation + +CommonReader::CommonReader () +{ + // .. nothing yet .. +} + +const db::LayerMap & +CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options) +{ + init (options); + + tl_assert (!layout.under_construction ()); + + layer_map ().prepare (layout); + + layout.start_changes (); + try { + do_read (layout); + finish (layout); + layout.end_changes (); + } catch (...) { + layout.end_changes (); + throw; + } + + // A cleanup may be necessary because of the following scenario: if library proxies contain subcells + // which are proxies itself, the proxy update may make them orphans (the proxies are regenerated). + // The cleanup will removed these. + layout.cleanup (); + + return layer_map_out (); +} + +const db::LayerMap & +CommonReader::read (db::Layout &layout) +{ + return read (layout, db::LoadLayoutOptions ()); +} + +void +CommonReader::init (const LoadLayoutOptions &options) +{ + CommonReaderBase::init (); + + db::CommonReaderOptions common_options = options.get_options (); + set_conflict_resolution_mode (common_options.cell_conflict_resolution); + set_create_layers (common_options.create_other_layers); + set_layer_map (common_options.layer_map); +} + // --------------------------------------------------------------- // Common format declaration diff --git a/src/db/db/dbCommonReader.h b/src/db/db/dbCommonReader.h index 3158bc2b4..9610e1634 100644 --- a/src/db/db/dbCommonReader.h +++ b/src/db/db/dbCommonReader.h @@ -132,8 +132,7 @@ public: /** * @brief A common reader base for GDS2 and OASIS providing common services for both readers */ -class DB_PUBLIC CommonReader - : public ReaderBase +class DB_PUBLIC CommonReaderBase { public: typedef tl::interval_map > layer_name_map; @@ -141,7 +140,7 @@ public: /** * @brief Constructor */ - CommonReader (); + CommonReaderBase (); /** * @brief Make a cell from a name @@ -205,17 +204,40 @@ public: */ void finish (db::Layout &layout); - // Reimplementation of the ReaderBase interace - virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options); - virtual const db::LayerMap &read (db::Layout &layout); + /** + * @brief Re-initialize: clears the tables and caches + */ + void init (); + + /** + * @brief Sets a value indicating whether to create layers + */ + void set_create_layers (bool f) + { + m_create_layers = f; + } + + /** + * @brief Sets the conflict resolution mode + */ + void set_conflict_resolution_mode (CellConflictResolution cc_resolution) + { + m_cc_resolution = cc_resolution; + } + + /** + * @brief Sets the input layer map + */ + void set_layer_map (const db::LayerMap &lm) + { + m_layer_map = lm; + } protected: friend class CommonReaderLayerMapping; virtual void common_reader_error (const std::string &msg) = 0; virtual void common_reader_warn (const std::string &msg) = 0; - virtual void do_read (db::Layout &layout) = 0; - virtual void init (const LoadLayoutOptions &options); /** * @brief Merge (and delete) the src_cell into target_cell @@ -227,14 +249,6 @@ protected: */ void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const; - /** - * @brief Gets the common options - */ - db::CommonReaderOptions &common_options () - { - return m_common_options; - } - /** * @brief Gets the layer name map */ @@ -244,7 +258,23 @@ protected: } /** - * @brief Enters the a layer with a given layer/datatype + * @brief Gets the input layer name + */ + db::LayerMap &layer_map () + { + return m_layer_map; + } + + /** + * @brief Gets the output layer name map + */ + const db::LayerMap &layer_map_out () const + { + return m_layer_map_out; + } + + /** + * @brief Enters the layer with a given layer/datatype */ std::pair open_dl (db::Layout &layout, const LDPair &dl); @@ -255,7 +285,7 @@ private: std::map m_name_for_id; CellConflictResolution m_cc_resolution; bool m_create_layers; - db::CommonReaderOptions m_common_options; + db::LayerMap m_layer_map; db::LayerMap m_layer_map_out; tl::interval_map > m_layer_names; std::map > m_layer_cache; @@ -265,6 +295,33 @@ private: std::pair open_dl_uncached (db::Layout &layout, const LDPair &dl); }; + + +/** + * @brief A common reader base for GDS2 and OASIS providing common services for both readers + */ +class DB_PUBLIC CommonReader + : public ReaderBase, public CommonReaderBase +{ +public: + typedef tl::interval_map > layer_name_map; + + /** + * @brief Constructor + */ + CommonReader (); + + // Reimplementation of the ReaderBase interace + virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options); + virtual const db::LayerMap &read (db::Layout &layout); + +protected: + friend class CommonReaderLayerMapping; + + virtual void init (const LoadLayoutOptions &options); + virtual void do_read (db::Layout &layout) = 0; +}; + /** * @brief A utility class that maps the layers for the proxy cell recovery */ diff --git a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc index f758176eb..7a54340f6 100644 --- a/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc +++ b/src/plugins/streamers/gds2/db_plugin/dbGDS2ReaderBase.cc @@ -59,11 +59,11 @@ GDS2ReaderBase::init (const db::LoadLayoutOptions &options) { CommonReader::init (options); + db::CommonReaderOptions common_options = options.get_options (); + m_read_texts = common_options.enable_text_objects; + m_read_properties = common_options.enable_properties; + db::GDS2ReaderOptions gds2_options = options.get_options (); - - m_read_texts = common_options ().enable_text_objects; - m_read_properties = common_options ().enable_properties; - m_allow_multi_xy_records = gds2_options.allow_multi_xy_records; m_box_mode = gds2_options.box_mode; } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 588f45ff2..3368a0558 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -139,8 +139,15 @@ DEFImporter::get_def_ext (const std::string &ln, const std::pair::rounded (m_lef_importer.layer_ext (ln, std::min (wxy.first, wxy.second) * 0.5 * dbu) / dbu); return std::make_pair (de, de); +#else + // This implementation follows the LEFDEF 5.8 spec saying the "default extension is half the wire width": + db::Coord de = std::min (wxy.first, wxy.second) / 2; + return std::make_pair (de, de); +#endif } void @@ -205,22 +212,39 @@ DEFImporter::read_nondefaultrules (double scale) } void -DEFImporter::read_regions (std::map > ®ions, double scale) +DEFImporter::read_regions (std::map > > > ®ions, double scale) { while (test ("-")) { std::string n = get (); - std::vector &polygons = regions [n]; + + std::vector > > &rg = regions[n]; + rg.push_back (std::pair > (RegionsNone, std::vector ())); + LayerPurpose &p = rg.back ().first; + std::vector &polygons = rg.back ().second; while (! peek (";")) { if (test ("+")) { - // ignore other options for now - while (! peek (";")) { - take (); + if (test ("TYPE")) { + + if (test ("GUIDE")) { + p = RegionsGuide; + } else if (test ("FENCE")) { + p = RegionsFence; + } else { + error (tl::to_string (tr ("REGION type needs to be GUIDE or FENCE"))); + } + + } else { + + // ignore other options for now (i.e. PROPERTY) + while (! peek (";") && ! peek ("+")) { + take (); + } + } - break; } else { @@ -379,7 +403,11 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u // compute begin extension db::Coord be = 0; if (pt0 == pts.begin ()) { - be = ext.front ().first; + if (pt0->x () == pt0 [1].x ()) { + be = ext.front ().second; + } else { + be = ext.front ().first; + } } else if (was_path_before) { // provides the overlap to the previous segment be = wxy_perp / 2; @@ -388,15 +416,32 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u // compute end extension db::Coord ee = 0; if (pt + 1 == pts.end ()) { - ee = ext.back ().first; + if (pt [-1].x () == pt->x ()) { + ee = ext.back ().second; + } else { + ee = ext.back ().first; + } } +#if 0 + // single path 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); } +#else + // multipart paths + for (std::vector::const_iterator i = pt0; i != pt; ++i) { + db::Path p (i, i + 2, wxy, i == pt0 ? be : wxy / 2, i + 1 != pt ? wxy / 2 : ee, false); + if (prop_id != 0) { + design.shapes (layer).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (layer).insert (p); + } + } +#endif was_path_before = true; @@ -667,7 +712,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C unsigned int mask_cut = (mask / 10) % 10; unsigned int mask_bottom = mask % 10; - db::Cell *cell = reader_state ()->via_cell (vn, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); if (cell) { if (nx <= 1 && ny <= 1) { design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); @@ -846,7 +891,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool std::map::const_iterator vd = m_via_desc.find (vn); if (vd != m_via_desc.end ()) { // TODO: no mask specification here? - db::Cell *cell = reader_state ()->via_cell (vn, layout, 0, 0, 0, &m_lef_importer); + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, 0, 0, 0, &m_lef_importer); if (cell) { design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), pt))); } @@ -917,6 +962,9 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) std::set seen_layers; std::vector routing_layers; + bool has_cut_geometry = false; + bool has_patternname = false; + while (test ("+")) { bool is_polygon = false; @@ -980,6 +1028,11 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) rule_based_vg->set_rows (get_long ()); rule_based_vg->set_columns (get_long ()); + } else if (test ("PATTERNNAME")) { + + get (); // ignore + has_patternname = true; + } else if (test ("PATTERN")) { if (! rule_based_vg.get ()) { @@ -1031,6 +1084,7 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) } else if (m_lef_importer.is_cut_layer (ln)) { geo_based_vg->set_maskshift_layer (1, ln); + has_cut_geometry = true; } @@ -1058,6 +1112,10 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) } + if (has_patternname && ! has_cut_geometry) { + warn (tl::sprintf (tl::to_string (tr ("Via %s uses legacy PATTERNAME and no cut geometry - no via shapes are generated")), n)); + } + if (vd.m1.empty () && vd.m2.empty ()) { // analyze the layers to find the metals @@ -1065,7 +1123,7 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) vd.m1 = routing_layers[0]; vd.m2 = routing_layers[1]; } else { - warn ("Can't determine routing layers for via: " + n); + warn (tl::to_string (tr ("Cannot determine routing layers for via: ")) + n); } } @@ -1073,9 +1131,9 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) if (rule_based_vg.get () && geo_based_vg.get ()) { error (tl::to_string (tr ("A via can only be defined through a VIARULE or geometry, not both ways"))); } else if (rule_based_vg.get ()) { - reader_state ()->register_via_cell (n, rule_based_vg.release ()); + reader_state ()->register_via_cell (n, std::string (), rule_based_vg.release ()); } else if (geo_based_vg.get ()) { - reader_state ()->register_via_cell (n, geo_based_vg.release ()); + reader_state ()->register_via_cell (n, std::string (), geo_based_vg.release ()); } else { error (tl::to_string (tr ("Too little information to generate a via"))); } @@ -1442,15 +1500,16 @@ DEFImporter::do_read (db::Layout &layout) double dbu_mic = 1000.0; double scale = 1.0 / (dbu_mic * layout.dbu ()); + size_t top_id = 0; - std::map > regions; + 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")); + db::Cell &design = layout.cell (reader_state ()->make_cell (layout, top_id)); while (! at_end ()) { @@ -1465,7 +1524,7 @@ DEFImporter::do_read (db::Layout &layout) } else if (test ("DESIGN")) { std::string cn = get (); - layout.rename_cell (design.cell_index (), layout.uniquify_cell_name (cn.c_str ()).c_str ()); + reader_state ()->rename_cell (layout, top_id, cn); expect (";"); @@ -1651,7 +1710,7 @@ DEFImporter::do_read (db::Layout &layout) if (! groups.empty () && options ().separate_groups ()) { - others_cell = &layout.cell (layout.add_cell ("NOGROUP")); + others_cell = &layout.cell (reader_state ()->make_cell (layout, "NOGROUP")); design.insert (db::CellInstArray (others_cell->cell_index (), db::Trans ())); // Walk through the groups, create a group container cell and put all instances @@ -1659,24 +1718,35 @@ DEFImporter::do_read (db::Layout &layout) 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 ())); + db::Cell *group_cell = &layout.cell (reader_state ()->make_cell (layout, ("GROUP_" + g->name).c_str ())); design.insert (db::CellInstArray (group_cell->cell_index (), db::Trans ())); if (! g->region_name.empty ()) { - std::map >::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 or region is already used: %s in group %s")), g->region_name, g->name)); } else { - std::set dl = open_layer (layout, std::string (), Regions, 0); - for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) { - for (std::vector::const_iterator p = r->second.begin (); p != r->second.end (); ++p) { - group_cell->shapes (*l).insert (*p); + for (std::vector > >::const_iterator rr = r->second.begin (); rr != r->second.end (); ++rr) { + + std::set dl = open_layer (layout, std::string (), rr->first, 0); + for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) { + group_cell->shapes (*l).insert (rr->second.begin (), rr->second.end ()); } + + if (rr->first != Regions) { + // try the "ALL" slot too for FENCE and GUIDE regions + dl = open_layer (layout, std::string (), Regions, 0); + for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) { + group_cell->shapes (*l).insert (rr->second.begin (), rr->second.end ()); + } + } + } + regions.erase (r); } @@ -1714,12 +1784,19 @@ DEFImporter::do_read (db::Layout &layout) if (! regions.empty ()) { - std::set dl = open_layer (layout, std::string (), Regions, 0); - for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) { + LayerPurpose lps [] = { Regions, RegionsNone, RegionsGuide, RegionsFence }; - 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 (*l).insert (*p); + for (unsigned int i = 0; i < sizeof (lps) / sizeof (lps[0]); ++i) { + + std::set dl = open_layer (layout, std::string (), lps[i], 0); + + for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) { + for (std::map > > >::const_iterator r = regions.begin (); r != regions.end (); ++r) { + for (std::vector > >::const_iterator rr = r->second.begin (); rr != r->second.end (); ++rr) { + if (lps [i] == Regions || rr->first == lps [i]) { + others_cell->shapes (*l).insert (rr->second.begin (), rr->second.end ()); + } + } } } diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 05e9ed06e..432bde8a1 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -79,7 +79,7 @@ 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_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); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 530260821..1eafacd05 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -117,6 +117,12 @@ static std::string purpose_to_name (LayerPurpose purpose) return "OUTLINE"; case Regions: return "REGION"; + case RegionsGuide: + return "REGIONGUIDE"; + case RegionsFence: + return "REGIONFENCE"; + case RegionsNone: + return "REGIONNONE"; case PlacementBlockage: return "BLOCKAGE"; case Routing: @@ -143,9 +149,9 @@ static std::string purpose_to_name (LayerPurpose purpose) return "BLK"; case All: return "ALL"; + default: + return std::string (); } - - return std::string (); } static std::string @@ -213,7 +219,7 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d dl = reader.open_layer (layout, m_top_layer, ViaGeometry, mask_top, via_box.enlarged (m_te)); for (std::set::const_iterator l = dl.begin (); l != dl.end (); ++l) { - cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_te).moved (m_bo))); + cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_te).moved (m_to))); } const char *p = m_pattern.c_str (); @@ -389,7 +395,7 @@ GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &la for (std::list::const_iterator v = m_vias.begin (); v != m_vias.end (); ++v) { - LEFDEFLayoutGenerator *g = reader.via_generator (v->name); + LEFDEFLayoutGenerator *g = reader.via_generator (v->name, v->nondefaultrule); if (! g) { continue; } @@ -401,7 +407,7 @@ GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &la unsigned mshift_cut = get_maskshift (msl [1], ext_msl, masks); unsigned mshift_top = get_maskshift (msl [2], ext_msl, masks); - db::Cell *vc = reader.via_cell (v->name, layout, + db::Cell *vc = reader.via_cell (v->name, v->nondefaultrule, layout, combine_maskshifts (msl [0], v->bottom_mask, mshift_bottom, nm), combine_maskshifts (msl [1], v->cut_mask, mshift_cut, nm), combine_maskshifts (msl [2], v->top_mask, mshift_top, nm), @@ -868,11 +874,11 @@ LEFDEFReaderOptions::special_routing_datatype_str () const // LEFDEFLayerDelegate implementation LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path) - : m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc) + : mp_importer (0), m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc) { if (! tc->map_file ().empty ()) { - read_map_file (correct_path (tc->map_file (), layout, base_path), layout); + read_map_file (tc->map_file (), layout, base_path); } else { @@ -886,7 +892,7 @@ LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout LEFDEFReaderState::~LEFDEFReaderState () { - for (std::map::const_iterator i = m_via_generators.begin (); i != m_via_generators.end (); ++i) { + for (std::map, LEFDEFLayoutGenerator *>::const_iterator i = m_via_generators.begin (); i != m_via_generators.end (); ++i) { delete i->second; } @@ -899,6 +905,22 @@ LEFDEFReaderState::~LEFDEFReaderState () m_macro_generators.clear (); } +void +LEFDEFReaderState::common_reader_error (const std::string &msg) +{ + if (mp_importer) { + mp_importer->error (msg); + } +} + +void +LEFDEFReaderState::common_reader_warn (const std::string &msg) +{ + if (mp_importer) { + mp_importer->warn (msg); + } +} + void LEFDEFReaderState::register_layer (const std::string &ln) { @@ -926,17 +948,71 @@ static bool try_read_layers (tl::Extractor &ex, std::vector &layers) return true; } +static std::string::size_type find_file_sep (const std::string &s, std::string::size_type from) +{ + std::string::size_type p1 = s.find ("+", from); + std::string::size_type p2 = s.find (",", from); + + if (p1 == std::string::npos) { + return p2; + } else if (p2 == std::string::npos) { + return p1; + } else { + return p1 < p2 ? p1 : p2; + } +} + +static std::vector split_file_list (const std::string &infile) +{ + std::vector files; + + size_t p = 0; + for (size_t pp = 0; (pp = find_file_sep (infile, p)) != std::string::npos; p = pp + 1) { + files.push_back (std::string (infile, p, pp - p)); + } + files.push_back (std::string (infile, p)); + + return files; +} + void -LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) +LEFDEFReaderState::read_map_file (const std::string &filename, db::Layout &layout, const std::string &base_path) { m_has_explicit_layer_mapping = true; - tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path; + std::vector paths = split_file_list (filename); + std::map, std::vector > layer_map; + + for (std::vector::const_iterator p = paths.begin (); p != paths.end (); ++p) { + read_single_map_file (correct_path (*p, layout, base_path), layer_map); + } + + // build an explicit layer mapping now. + + tl_assert (m_has_explicit_layer_mapping); + m_layers.clear (); + m_layer_map.clear (); + + db::DirectLayerMapping lm (&layout); + for (std::map, std::vector >::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) { + for (std::vector::const_iterator j = i->second.begin (); j != i->second.end (); ++j) { + unsigned int layer = lm.map_layer (*j).second; + m_layers [i->first].insert (layer); + m_layer_map.mmap (*j, layer); + } + } +} + +void +LEFDEFReaderState::read_single_map_file (const std::string &path, std::map, std::vector > &layer_map) +{ tl::InputFile file (path); tl::InputStream file_stream (file); tl::TextInputStream ts (file_stream); + tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << file_stream.absolute_path (); + std::map purpose_translation; purpose_translation ["LEFPIN"] = LEFPins; purpose_translation ["PIN"] = Pins; @@ -949,8 +1025,6 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) purpose_translation ["BLOCKAGE"] = Blockage; purpose_translation ["ALL"] = All; - std::map, std::vector > layer_map; - while (! ts.at_end ()) { const std::string &l = ts.get_line (); @@ -979,11 +1053,26 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) } } - } else if (w1 == "REGIONS") { + } else if (w1 == "REGION") { + + std::string name = "REGIONS"; + LayerPurpose lp = Regions; + if (w2 == "FENCE") { + name = "REGIONS_FENCE"; + lp = RegionsFence; + } else if (w2 == "GUIDE") { + name = "REGIONS_GUIDE"; + lp = RegionsGuide; + } else if (w2 == "NONE") { + name = "REGIONS_NONE"; + lp = RegionsNone; + } else if (w2 != "ALL") { + tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d - ignoring unknowns REGION purpose %s (use FENCE, GUIDE or ALL)")), path, ts.line_number (), w2); + } for (std::vector::const_iterator l = layers.begin (); l != layers.end (); ++l) { for (std::vector::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) { - layer_map [std::make_pair (std::string (), LayerDetailsKey (Regions))].push_back (db::LayerProperties (*l, *d, "REGIONS")); + layer_map [std::make_pair (std::string (), LayerDetailsKey (lp))].push_back (db::LayerProperties (*l, *d, name)); } } @@ -1124,7 +1213,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) } else if (i->second == All) { for (std::map::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) { - if (p->second != All) { + if (p->second != All && p->second != Blockage) { translated_purposes.insert (LayerDetailsKey (p->second, mask, via_size)); } } @@ -1172,21 +1261,14 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout) } } +} - // build an explicit layer mapping now. - - tl_assert (m_has_explicit_layer_mapping); - m_layers.clear (); - m_layer_map.clear (); - - db::DirectLayerMapping lm (&layout); - for (std::map, std::vector >::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) { - for (std::vector::const_iterator j = i->second.begin (); j != i->second.end (); ++j) { - unsigned int layer = lm.map_layer (*j).second; - m_layers [i->first].insert (layer); - m_layer_map.mmap (*j, layer); - } - } +/** + * @brief Returns true, if the layer purpose has a fallback + */ +static bool has_fallback (LayerPurpose p) +{ + return p == RegionsFence || p == RegionsGuide || p == RegionsNone; } std::set @@ -1201,14 +1283,18 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu std::set ll; - if (n.empty () || ! m_has_explicit_layer_mapping) { + if (! m_has_explicit_layer_mapping) { ll = open_layer_uncached (layout, n, purpose, mask); } m_layers.insert (std::make_pair (std::make_pair (n, LayerDetailsKey (purpose, mask)), ll)); - if (ll.empty ()) { - tl::warn << tl::to_string (tr ("No mapping for layer")) << " '" << n << "', purpose '" << purpose_to_name (purpose) << "'" << tl::noendl; + if (ll.empty () && ! has_fallback (purpose)) { + if (n.empty ()) { + tl::warn << tl::to_string (tr ("No mapping for purpose")) << " '" << purpose_to_name (purpose) << "'" << tl::noendl; + } else { + tl::warn << tl::to_string (tr ("No mapping for layer")) << " '" << n << "', purpose '" << purpose_to_name (purpose) << "'" << tl::noendl; + } if (mask > 0) { tl::warn << tl::to_string (tr (" Mask ")) << mask << tl::noendl; } @@ -1538,6 +1624,8 @@ std::set LEFDEFReaderState::open_layer_uncached(db::Layout &layout void LEFDEFReaderState::finish (db::Layout &layout) { + CommonReaderBase::finish (layout); + int lnum = 0; std::set used_numbers; @@ -1606,18 +1694,22 @@ LEFDEFReaderState::finish (db::Layout &layout) } void -LEFDEFReaderState::register_via_cell (const std::string &vn, LEFDEFLayoutGenerator *generator) +LEFDEFReaderState::register_via_cell (const std::string &vn, const std::string &nondefaultrule, LEFDEFLayoutGenerator *generator) { - if (m_via_generators.find (vn) != m_via_generators.end ()) { - delete m_via_generators [vn]; + if (m_via_generators.find (std::make_pair (vn, nondefaultrule)) != m_via_generators.end ()) { + delete m_via_generators [std::make_pair (vn, nondefaultrule)]; } - m_via_generators [vn] = generator; + m_via_generators [std::make_pair (vn, nondefaultrule)] = generator; } LEFDEFLayoutGenerator * -LEFDEFReaderState::via_generator (const std::string &vn) +LEFDEFReaderState::via_generator (const std::string &vn, const std::string &nondefaultrule) { - std::map::const_iterator g = m_via_generators.find (vn); + std::map, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (std::make_pair (vn, nondefaultrule)); + if (g == m_via_generators.end () && ! nondefaultrule.empty ()) { + // default rule is fallback + g = m_via_generators.find (std::make_pair (vn, std::string ())); + } if (g != m_via_generators.end ()) { return g->second; } else { @@ -1626,31 +1718,45 @@ LEFDEFReaderState::via_generator (const std::string &vn) } db::Cell * -LEFDEFReaderState::via_cell (const std::string &vn, db::Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm) +LEFDEFReaderState::via_cell (const std::string &vn, const std::string &nondefaultrule, db::Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm) { - ViaKey vk (vn, mask_bottom, mask_cut, mask_top); + ViaKey vk (vn, nondefaultrule, mask_bottom, mask_cut, mask_top); + + std::map, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (std::make_pair (vn, nondefaultrule)); + + if (g == m_via_generators.end () && ! vk.nondefaultrule.empty ()) { + // default rule is fallback + g = m_via_generators.find (std::make_pair (vn, std::string ())); + vk.nondefaultrule.clear (); + } + std::map::const_iterator i = m_via_cells.find (vk); if (i == m_via_cells.end ()) { db::Cell *cell = 0; - std::map::const_iterator g = m_via_generators.find (vn); if (g != m_via_generators.end ()) { LEFDEFLayoutGenerator *vg = g->second; - std::string mask_suffix; - if (mask_bottom > 0 || mask_cut > 0 || mask_top > 0) { - mask_suffix += "_"; - mask_suffix += tl::to_string (mask_bottom); - mask_suffix += "_"; - mask_suffix += tl::to_string (mask_cut); - mask_suffix += "_"; - mask_suffix += tl::to_string (mask_top); + std::string n = vn; + + if (! vk.nondefaultrule.empty ()) { + n += "_"; + n += vk.nondefaultrule; } - std::string cn = mp_tech_comp->via_cellname_prefix () + vn + mask_suffix; - cell = &layout.cell (layout.add_cell (cn.c_str ())); + if (mask_bottom > 0 || mask_cut > 0 || mask_top > 0) { + n += "_"; + n += tl::to_string (mask_bottom); + n += "_"; + n += tl::to_string (mask_cut); + n += "_"; + n += tl::to_string (mask_top); + } + + std::string cn = mp_tech_comp->via_cellname_prefix () + n; + cell = &layout.cell (make_cell (layout, cn.c_str ())); std::vector masks; masks.reserve (3); @@ -1705,7 +1811,7 @@ LEFDEFReaderState::foreign_cell (Layout &layout, const std::string &name) if (cc.first) { ci = cc.second; } else { - ci = layout.add_cell (name.c_str ()); + ci = make_cell (layout, name.c_str ()); layout.cell (ci).set_ghost_cell (true); } @@ -1747,7 +1853,7 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std: if (macro_desc.foreign_name != mn) { // create an indirection for renaming the cell - cell = &layout.cell (layout.add_cell (mn.c_str ())); + cell = &layout.cell (make_cell (layout, mn.c_str ())); cell->insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), db::Trans (db::Point () - macro_desc.origin) * macro_desc.foreign_trans)); } else { @@ -1779,7 +1885,7 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std: std::string cn = mn + mask_suffix; - cell = &layout.cell (layout.add_cell (cn.c_str ())); + cell = &layout.cell (make_cell (layout, cn.c_str ())); if (mg->is_fixedmask ()) { mg->create_cell (*this, layout, *cell, 0, std::vector (), nm); @@ -1819,6 +1925,8 @@ LEFDEFImporter::get_mask (long m) void LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state) { + tl::log << tl::to_string (tr ("Reading LEF/DEF file")) << " " << stream.absolute_path (); + m_fn = stream.filename (); tl::AbsoluteProgress progress (tl::to_string (tr ("Reading ")) + m_fn, 1000); @@ -1827,6 +1935,7 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderS progress.set_unit (10000.0); mp_reader_state = &state; + mp_reader_state->attach_reader (this); if (state.tech_comp ()) { m_options = *state.tech_comp (); @@ -1863,11 +1972,13 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderS do_read (layout); + mp_reader_state->attach_reader (0); delete mp_stream; mp_stream = 0; mp_progress = 0; } catch (...) { + mp_reader_state->attach_reader (0); delete mp_stream; mp_stream = 0; mp_progress = 0; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index a76c11be5..ed0af0a49 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -27,6 +27,7 @@ #include "dbPluginCommon.h" #include "dbLayout.h" #include "dbReader.h" +#include "dbCommonReader.h" #include "dbStreamLayers.h" #include "tlStream.h" #include "tlVariant.h" @@ -44,6 +45,7 @@ namespace db { class LEFDEFReaderState; +class LEFDEFImporter; struct MacroDesc; /** @@ -1021,7 +1023,8 @@ private: */ enum LayerPurpose { - Routing = 0, // from DEF only + None = 0, + Routing, // from DEF only Pins, // from DEF Fills, // from DEF FillsOPC, // from DEF @@ -1035,6 +1038,9 @@ enum LayerPurpose Blockage, // from DEF only PlacementBlockage, // from DEF only Regions, // from DEF only + RegionsNone, // from DEF only + RegionsFence, // from DEF only + RegionsGuide, // from DEF only All // from DEF only }; @@ -1049,7 +1055,12 @@ struct LayerDetailsKey LayerDetailsKey (LayerPurpose _purpose, unsigned int _mask = 0, const db::DVector &_via_size = db::DVector ()) : purpose (_purpose), mask (_mask), via_size (_via_size) - { } + { + // normalize the via size such that x is smaller than y size (issue-1065) + if (via_size.y () < via_size.x ()) { + via_size = db::DVector (via_size.y (), via_size.x ()); + } + } bool operator< (const LayerDetailsKey &other) const { @@ -1195,6 +1206,7 @@ private: struct Via { Via () : bottom_mask (0), cut_mask (0), top_mask (0) { } std::string name; + std::string nondefaultrule; unsigned int bottom_mask, cut_mask, top_mask; db::Trans trans; }; @@ -1215,6 +1227,7 @@ private: * This class will handle the creation and management of layers in the LEF/DEF reader context */ class DB_PLUGIN_PUBLIC LEFDEFReaderState + : public db::CommonReaderBase { public: /** @@ -1227,12 +1240,22 @@ public: */ ~LEFDEFReaderState (); + /** + * @brief Attaches to or detaches from an importer + */ + void attach_reader (LEFDEFImporter *importer) + { + mp_importer = importer; + } + /** * @brief Reads the given map file * * Usually this file is read by the constructor. This method is provided for test purposes. + * The filename can be a list of files, separated by "+" or ",". They are loaded together into + * the same map like they were concatenated. */ - void read_map_file (const std::string &path, db::Layout &layout); + void read_map_file (const std::string &filename, db::Layout &layout, const std::string &base_path); /** * @brief Gets the layer map @@ -1272,17 +1295,17 @@ public: * * The generator is capable of creating a via for a specific mask configuration */ - void register_via_cell (const std::string &vn, LEFDEFLayoutGenerator *generator); + void register_via_cell (const std::string &vn, const std::string &nondefaultrule, LEFDEFLayoutGenerator *generator); /** * @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, Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm); + db::Cell *via_cell (const std::string &vn, const std::string &nondefaultrule, Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm); /** * @brief Gets the via generator for a given via name or 0 if there is no such generator */ - LEFDEFLayoutGenerator *via_generator (const std::string &vn); + LEFDEFLayoutGenerator *via_generator (const std::string &vn, const std::string &nondefaultrule); /** * @brief Registers a macro generator for the macro with the given name @@ -1317,19 +1340,23 @@ public: return m_foreign_cells; } +protected: + virtual void common_reader_error (const std::string &msg); + virtual void common_reader_warn (const std::string &msg); + private: /** * @brief A key for the via cache */ struct ViaKey { - ViaKey (const std::string &n, unsigned int mb, unsigned int mc, unsigned int mt) - : name (n), mask_bottom (mb), mask_cut (mc), mask_top (mt) + ViaKey (const std::string &n, const std::string &ndr, unsigned int mb, unsigned int mc, unsigned int mt) + : name (n), nondefaultrule (ndr), mask_bottom (mb), mask_cut (mc), mask_top (mt) { } bool operator== (const ViaKey &other) const { - return name == other.name && mask_bottom == other.mask_bottom && mask_cut == other.mask_cut && mask_top == other.mask_top; + return name == other.name && nondefaultrule == other.nondefaultrule && mask_bottom == other.mask_bottom && mask_cut == other.mask_cut && mask_top == other.mask_top; } bool operator< (const ViaKey &other) const @@ -1337,6 +1364,9 @@ private: if (name != other.name) { return name < other.name; } + if (nondefaultrule != other.nondefaultrule) { + return nondefaultrule < other.nondefaultrule; + } if (mask_bottom != other.mask_bottom) { return mask_bottom < other.mask_bottom; } @@ -1349,7 +1379,7 @@ private: return false; } - std::string name; + std::string name, nondefaultrule; unsigned int mask_bottom, mask_cut, mask_top; }; @@ -1389,6 +1419,7 @@ private: LEFDEFReaderState (const LEFDEFReaderState &); LEFDEFReaderState &operator= (const LEFDEFReaderState &); + LEFDEFImporter *mp_importer; std::map , std::set > m_layers; db::LayerMap m_layer_map; bool m_create_layers; @@ -1397,13 +1428,14 @@ private: std::map m_default_number; const LEFDEFReaderOptions *mp_tech_comp; std::map m_via_cells; - std::map m_via_generators; + std::map, LEFDEFLayoutGenerator *> m_via_generators; std::map > m_macro_cells; std::map m_macro_generators; std::map m_foreign_cells; std::set open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask); db::cell_index_type foreign_cell(Layout &layout, const std::string &name); + void read_single_map_file (const std::string &path, std::map, std::vector > &layer_map); }; /** @@ -1453,6 +1485,8 @@ struct DB_PLUGIN_PUBLIC MacroDesc class DB_PLUGIN_PUBLIC LEFDEFImporter { public: + friend class LEFDEFReaderState; + /** * @brief Default constructor */ diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc index 1cce6e831..bf4d35314 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFPlugin.cc @@ -123,6 +123,9 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti db::LEFDEFReaderState state (&effective_options, layout, base_path); + db::CommonReaderOptions common_options = options.get_options (); + state.set_conflict_resolution_mode (common_options.cell_conflict_resolution); + layout.dbu (effective_options.dbu ()); if (import_lef) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 8de6300b8..5d6625ad4 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -380,7 +380,7 @@ LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, Laye } void -LEFImporter::read_nondefaultrule (db::Layout & /*layout*/) +LEFImporter::read_nondefaultrule (db::Layout &layout) { // read NONDEFAULTRULE sections std::string n = get (); @@ -408,11 +408,7 @@ LEFImporter::read_nondefaultrule (db::Layout & /*layout*/) } else if (test ("VIA")) { - // ignore VIA statements - std::string v = get (); - while (! test ("END") || ! test (v)) { - take (); - } + read_viadef (layout, n); } else { while (! at_end () && ! test (";")) { @@ -640,7 +636,7 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc } void -LEFImporter::read_viadef (Layout &layout) +LEFImporter::read_viadef (Layout &layout, const std::string &nondefaultrule) { std::string n = get (); @@ -653,11 +649,11 @@ LEFImporter::read_viadef (Layout &layout) if (test ("VIARULE")) { std::unique_ptr vg (new RuleBasedViaGenerator ()); read_viadef_by_rule (vg.get (), via_desc, n, layout.dbu ()); - reader_state ()->register_via_cell (n, vg.release ()); + reader_state ()->register_via_cell (n, nondefaultrule, vg.release ()); } else { std::unique_ptr vg (new GeometryBasedLayoutGenerator ()); read_viadef_by_geometry (vg.get (), via_desc, n, layout.dbu ()); - reader_state ()->register_via_cell (n, vg.release ()); + reader_state ()->register_via_cell (n, nondefaultrule, vg.release ()); } test ("VIA"); @@ -1064,7 +1060,7 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("VIA")) { - read_viadef (layout); + read_viadef (layout, std::string ()); } else if (test ("BEGINEXT")) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h index 0ed26e12a..b638d775c 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h @@ -147,7 +147,7 @@ private: std::vector get_iteration (double dbu); void read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, 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 (Layout &layout, const std::string &nondefaultrule); void read_viadef_by_rule (RuleBasedViaGenerator *vg, ViaDesc &desc, const std::string &n, double dbu); void read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc &desc, const std::string &n, double dbu); void read_layer (Layout &layout); diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index ad415cdc4..fd49e97d2 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -50,7 +50,7 @@ static db::LEFDEFReaderOptions default_options () return tc; } -static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *filename, const db::LEFDEFReaderOptions &options, bool priv = true) +static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *filename, const db::LEFDEFReaderOptions &options, bool priv = true, db::CellConflictResolution cc_mode = db::RenameCell) { std::string fn_path (priv ? tl::testdata_private () : tl::testdata ()); fn_path += "/lefdef/"; @@ -60,6 +60,7 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f tl::Extractor ex (filename); db::LEFDEFReaderState ld (&options, layout, fn_path); + ld.set_conflict_resolution_mode (cc_mode); db::DEFImporter imp; bool any_def = false; @@ -69,11 +70,10 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f if (ex.test ("map:")) { - std::string fn = fn_path, f; + std::string f; ex.read_word_or_quoted (f); - fn += f; - ld.read_map_file (fn, layout); + ld.read_map_file (f, layout, fn_path); } else if (ex.test ("def:")) { @@ -142,12 +142,12 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f return ld.layer_map (); } -static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true) +static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true, db::CellConflictResolution cc_mode = db::RenameCell) { db::Manager m (false); db::Layout layout (&m), layout2 (&m), layout_au (&m); - db::LayerMap lm = read (layout, lef_dir, filename, options, priv); + db::LayerMap lm = read (layout, lef_dir, filename, options, priv, cc_mode); // normalize the layout by writing to OASIS and reading from .. @@ -210,6 +210,73 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch return lm; } +static void run_test2 (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *filename2, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true, db::CellConflictResolution cc_mode = db::RenameCell) +{ + db::Manager m (false); + db::Layout layout (&m), layout2 (&m), layout_au (&m); + + read (layout, lef_dir, filename, options, priv, cc_mode); + read (layout, lef_dir, filename2, options, priv, cc_mode); + + // normalize the layout by writing to OASIS and reading from .. + + // generate a "unique" name ... + unsigned int hash = 0; + if (au) { + for (const char *cp = au; *cp; ++cp) { + hash = (hash << 4) ^ (hash >> 4) ^ ((unsigned int) *cp); + } + } + + std::string tmp_file = _this->tmp_file (tl::sprintf ("tmp_%x.oas", hash)); + + { + 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); + } + + { + tl::InputStream stream (tmp_file); + db::Reader reader (stream); + reader.read (layout2); + } + + if (au) { + + std::string fn (priv ? tl::testdata_private () : tl::testdata ()); + fn += "/lefdef/"; + fn += lef_dir; + fn += "/"; + fn += au; + + try { + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (layout_au); + } catch (...) { + _this->raise (tl::sprintf ("Compare failed - see %s vs %s (not existing or not readable)\n", tmp_file, fn)); + throw; + } + + bool equal = db::compare_layouts (layout2, layout_au, db::layout_diff::f_verbose | db::layout_diff::f_flatten_array_insts, 0); + if (! equal) { + _this->raise (tl::sprintf ("Compare failed - see %s vs %s\n", tmp_file, fn)); + } + + } else { + + bool equal = db::compare_layouts (layout2, layout_au, db::layout_diff::f_verbose | db::layout_diff::f_flatten_array_insts, 0); + if (! equal) { + _this->raise (tl::sprintf ("Compare failed - see %s vs empty file\n", tmp_file)); + } + + } +} + TEST(1) { run_test (_this, "lef1", "lef:in.lef", 0, default_options ()); @@ -252,7 +319,7 @@ TEST(7) TEST(10) { - run_test (_this, "def1", "lef:in.lef+def:in.def", "au.oas.gz", default_options ()); + run_test (_this, "def1", "lef:in.lef+def:in.def", "au2.oas.gz", default_options ()); } TEST(11) @@ -271,7 +338,7 @@ TEST(12) TEST(13) { - run_test (_this, "def4", "lef:in.lef+def:in.def", "au.oas.gz", default_options ()); + run_test (_this, "def4", "lef:in.lef+def:in.def", "au2.oas.gz", default_options ()); } TEST(14) @@ -342,6 +409,13 @@ TEST(23) run_test (_this, "def14", "map:test.map+lef:tech.lef+lef:stdlib.lef+def:test.def", "au.oas.gz", opt); } +TEST(24) +{ + db::LEFDEFReaderOptions opt = default_options (); + opt.set_macro_resolution_mode (1); + run_test (_this, "def15", "map:test.map+lef:tech.lef+def:test.def", "au2.oas.gz", opt); +} + TEST(100) { run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false); @@ -720,7 +794,7 @@ TEST(117_mapfile_all) "'+M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/SPNET/...\\' (1/5)';" "'+M1.NET;M1.SPNET : \\'M1.NET/SPNET\\' (16/0)';" "'+M1.NET : M1.NET (18/0)';" - "'+M1.BLK;M1.FILL;M1.FILLOPC;M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/FILL/...\\' (22/2)';" + "'+M1.FILL;M1.FILLOPC;M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/FILL/...\\' (22/2)';" "'+\\'M1.NET:1\\';\\'M1.PIN:1\\';\\'M1.SPNET:1\\';\\'M1.VIA:1\\' : \\'M1.NET:1/PIN:1/...\\' (6/0)';" "'+\\'M1.NET:1\\' : \\'M1.NET:1\\' (7/0)';" "'+M1.PIN : M1.PIN (3/0)';" @@ -736,7 +810,7 @@ TEST(117_mapfile_all) "'M1.LABEL : M1.LABEL (26/0)';" // NAME M1/NET not supported: "'+M1.LABEL : M1.LABEL (27/0)';" // NAME M1/SPNET not supported: "'+M1.LABEL : M1.LABEL (28/1)';" - "'+M1.BLK : M1.BLK (13/0)';" + "'M1.BLK : M1.BLK (13/0)';" "'M1_TEXT.LABEL;M1_TEXT.LEFLABEL : \\'M1_TEXT.LABEL/M1_TEXT.LEFLABEL\\' (29/0)'" ")" ) @@ -780,6 +854,18 @@ TEST(130_viasize) run_test (_this, "viasize", "map:test.map+lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); } +// issue-1065 +TEST(130_viasize2) +{ + run_test (_this, "viasize2", "map:test_ok.map+lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); + run_test (_this, "viasize2", "map:test_fail.map+lef:test.lef+def:test.def", "au.oas.gz", default_options (), false); +} + +TEST(131_patternname) +{ + run_test (_this, "patternname", "map:v.map+lef:v.lef+def:v.def", "au.oas.gz", default_options (), false); +} + TEST(200_lefdef_plugin) { db::Layout ly; @@ -826,3 +912,21 @@ TEST(201_lefdef_plugin_explicit_lef) db::compare_layouts (_this, ly, fn_path + "au_plugin_alt_lef.oas.gz", db::WriteOAS); } +TEST(202_lefdef_blend_mode) +{ + db::LEFDEFReaderOptions lefdef_opt = default_options (); + + run_test2 (_this, "blend_mode", "map:layers.map+lef:sub.lef+def:top.def", "map:layers.map+def:sub.def", "au1.oas.gz", lefdef_opt, false); + run_test2 (_this, "blend_mode", "map:layers.map+lef:sub.lef+def:top.def", "map:layers.map+def:sub.def", "au2.oas.gz", lefdef_opt, false, db::AddToCell); + + lefdef_opt.set_macro_resolution_mode (2); + run_test2 (_this, "blend_mode", "map:layers.map+lef:sub.lef+def:top.def", "map:layers.map+def:sub.def", "au3.oas.gz", lefdef_opt, false); +} + +TEST(203_regionsAndMapfileConcat) +{ + db::LEFDEFReaderOptions lefdef_opt = default_options (); + + run_test (_this, "map_regions", "map:'test.map,test.add.map'+lef:test.lef+def:test.def", "au.oas.gz", lefdef_opt, false); +} + diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc index 0ce2ac13f..9e732deb0 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISReader.cc @@ -104,8 +104,9 @@ OASISReader::init (const db::LoadLayoutOptions &options) { CommonReader::init (options); - m_read_texts = common_options ().enable_text_objects; - m_read_properties = common_options ().enable_properties; + db::CommonReaderOptions common_options = options.get_options (); + m_read_texts = common_options.enable_text_objects; + m_read_properties = common_options.enable_properties; db::OASISReaderOptions oasis_options = options.get_options (); m_read_all_properties = oasis_options.read_all_properties; diff --git a/testdata/lefdef/blend_mode/au1.oas.gz b/testdata/lefdef/blend_mode/au1.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..e0e95c3a56e40b4127e3ef8b83e69be54b9ab0ea GIT binary patch literal 630 zcmY!lcJ=kt^>+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>uojmlsTj%#@-Ua=7qIgM$Gf`(#|H%Y z2e<}>L~=3%Wtl-T%wQHoF*mz^Xo!!epDS|;GXoDYhg;a!P|wdbL_fgOPv6bc$46gJ zPmh@gs0x<^P=^tw4nD9B>=N9fVV;gyY~cm!!7athC~`Q3A%&L-M4e#dWe_~TD5K86 S!N|`55_!SS)G(3(0|NlH-_Rof literal 0 HcmV?d00001 diff --git a/testdata/lefdef/blend_mode/au2.oas.gz b/testdata/lefdef/blend_mode/au2.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..b05825a58ce1a8deb53006e0634912275e5c8bee GIT binary patch literal 610 zcmY!lcJ=kt^>+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>Fqh;Pu=54SySoI(2L$;CxCVtpaxxc} zCNYC#m_aOVcK^^2A5TA5<`iZI9%K%;u&<$>pKFMIfTy3no2QSDzMh^QGY?P|E(xFx zBTOB9U>(>cxJAP}9kJNL3)F*KikDI3a0+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>Fqh;Pu=54SySoI(2L$;CxCVtpaxxc} zCNYC#m_aOVcK^^2A5TA5<`iZI9%K%;u&<$>pKFMIfTy3no2QSDzMh^QGY?P|E(xFx zBTOB9U>(>cxJAP}9kJNL3)F*KikDI3a0=L73?Pvg>`VfBa{%R#F;2uV5Jl~bk&zusTf_|t zB@zXTpxiPfv%w;9R_jF2x#9%u0VwtWIS>UBO^(13IKq}BEDMps4Vc36fB(;nG-nP= zGp`b7oDvkSFR#c4C*z9siSuRh;GM}WX5QEub6op-lhwD!ELQQ}ZtP!ySPSRtYUNWb zijZv{pEmIIN?tW}VJw0G5{`vbt0GCUL|glt;trzTpCZZEn48KvphN#i$naZuTlEuJ zZ%>F+2eL$)A_T*Z3HnXtjmZ#TocckEL~o+MnqEXS=x9f`e9QG||7k&zm!p|JANXt7 qQGG#!7FyT|N#5B^Q>N#^zG<3Wz#+U7!SjDELOubEcHDNS0ssIqK!?8o literal 0 HcmV?d00001 diff --git a/testdata/lefdef/map_regions/test.add.map b/testdata/lefdef/map_regions/test.add.map new file mode 100644 index 000000000..456e24df8 --- /dev/null +++ b/testdata/lefdef/map_regions/test.add.map @@ -0,0 +1,5 @@ +BLOCKAGE ALL 20 0 +REGION ALL 1 0 +REGION FENCE 2 0 +REGION GUIDE 3 0 +REGION NONE 4 0 diff --git a/testdata/lefdef/map_regions/test.def b/testdata/lefdef/map_regions/test.def new file mode 100644 index 000000000..ecd8a07ca --- /dev/null +++ b/testdata/lefdef/map_regions/test.def @@ -0,0 +1,12 @@ +DESIGN test ; +DIEAREA ( 0 0 ) ( 1000 1000 ) ; +UNITS DISTANCE MICRONS 1000 ; +REGIONS 3 ; +- a ( 100 700 ) ( 300 900 ) ; +- b ( 700 700 ) ( 900 900 ) + TYPE GUIDE ; +- c ( 100 100 ) ( 900 200 ) ( 100 200 ) ( 200 300 ) ( 800 200 ) ( 900 300 ) + TYPE FENCE ; +END REGIONS +BLOCKAGES 51 ; + - PLACEMENT RECT ( 450 450 ) ( 550 550 ) ; +END BLOCKAGES +END DESIGN diff --git a/testdata/lefdef/map_regions/test.lef b/testdata/lefdef/map_regions/test.lef new file mode 100644 index 000000000..cd60781a0 --- /dev/null +++ b/testdata/lefdef/map_regions/test.lef @@ -0,0 +1,4 @@ +UNITS + DATABASE MICRONS 1000 ; +END UNITS +END LIBRARY diff --git a/testdata/lefdef/map_regions/test.map b/testdata/lefdef/map_regions/test.map new file mode 100644 index 000000000..0c067d4ba --- /dev/null +++ b/testdata/lefdef/map_regions/test.map @@ -0,0 +1 @@ +DIEAREA ALL 10 0 diff --git a/testdata/lefdef/mapfile/au.oas.gz b/testdata/lefdef/mapfile/au.oas.gz index bf3c4bea7585299965d8ea76b58a552e58947610..ceadab9801d9f02b72daceee0d03eeb9c3703bcb 100644 GIT binary patch literal 537 zcmV+!0_Oc6iwFqMJyT);19WY0UomB7Wid86VJ>fBa{%R&KX21O7{>2>ah%+}ZWYzB zROE#L0RwKF2~}c9>PxWjKjqx=XR)F>m5``_A_mBU)Rm~ZgfGBN&+mDjdv$k~ZwMZEccPx~gibMW><*e~sJyK9HIW9rN2&0JA$LxB%crF$3;-Z;#TrmrB~_G1BNm%Bj_%9^EG*>l?gNDfjUbvmVd?7S+UPqlIe?mD>7X%zEcFcZXAPZ z95bZj*12Mw5QeB08`BI8zLMcLV!VM{*}W5D+&#s&(Z&=3ZGTpbw|E}wsCA~yw3*gA z%N^?`YT$Kb>}T@V`m%2RqMIthKeW7IU6&Cye**!E@TdAIKBtAJw6_(kyvG?r=Fi$@ b9plUT#uNkX4wQHQ^Frtk?jq&Ay959LGe-=3 literal 1213 zcmd^;KX21O7{>2>ah%+p8%1?2HS)rMfPpm0geoy4wG%A-PdT^zS*)l|B_t}Khyk)7 zb!F)UBVT~;(UA!TzChS2rXm(zUmO~jgfGBN_q@O7eRQv1`MPj?_jcG5uFxqaomLyo zG_-uIMpGny?_na`Vc^(_8^q4g86^)~JHA&bS-LgHd%-G$)u1AY!zkHxJdbNfasKowj=#z6|d*5{h}lWwU9 ze+NF(tZRU<`HK@?Yc>)7SU$rSR92P7j)IkUI7P_(QQ9hFeA%!$#hi8r%G>|>AoLpt CaYIf3 diff --git a/testdata/lefdef/patternname/Makefile b/testdata/lefdef/patternname/Makefile new file mode 100644 index 000000000..ab7ddeb27 --- /dev/null +++ b/testdata/lefdef/patternname/Makefile @@ -0,0 +1,6 @@ +v: + time strm2oas \ + --lefdef-map v.map \ + --lefdef-lefs v.lef \ + v.def v.oas + diff --git a/testdata/lefdef/patternname/au.oas.gz b/testdata/lefdef/patternname/au.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..f63a9686369c1962f863620e32d92e82d07bdf41 GIT binary patch literal 249 zcmVJUCcncx52cp?=sD$cS}#m!=Nh6P;OVFD=IP_3ucxQS zEYHlqgG&Oa!w6GC0jvYN1h**A30Mp>2I|2r#mgvaEziKnv_bfT=ufVjoT8Qrj7%Ry zJA{vN{^Sz1HD+Y`!TN)BBj-j=Zl*140#X9J41xz3nHokiU|;|Mw6XlpW&!{J-nDgL literal 0 HcmV?d00001 diff --git a/testdata/lefdef/patternname/v.def b/testdata/lefdef/patternname/v.def new file mode 100644 index 000000000..c9349c1da --- /dev/null +++ b/testdata/lefdef/patternname/v.def @@ -0,0 +1,15 @@ +DESIGN top ; +VIAS 1 ; + - M1H_M2V-1400-1400-ALL-2-2 + PATTERNNAME M1H_M2V-1400-1400-I3 + + + RECT M1 ( -700 -620 ) ( 700 620 ) + + RECT M2 ( -610 -700 ) ( 610 700 ) + + RECT VIA1 ( -600 -600 ) ( -220 -220 ) + + RECT VIA1 ( 220 -600 ) ( 600 -220 ) + + RECT VIA1 ( -600 220 ) ( -220 600 ) + + RECT VIA1 ( 220 220 ) ( 600 600 ) ; +END VIAS +NETS 1 ; +- dummy + ROUTED M1 ( 0 0 ) M1H_M2V-1400-1400-ALL-2-2 ; +END NETS +END DESIGN diff --git a/testdata/lefdef/patternname/v.lef b/testdata/lefdef/patternname/v.lef new file mode 100644 index 000000000..ef4695646 --- /dev/null +++ b/testdata/lefdef/patternname/v.lef @@ -0,0 +1,26 @@ +VERSION 5.4 ; + +NAMESCASESENSITIVE ON ; +BUSBITCHARS "[]" ; +DIVIDERCHAR "/" ; +NOWIREEXTENSIONATPIN OFF ; + +UNITS + DATABASE MICRONS 2000 ; +END UNITS + +MANUFACTURINGGRID 0.005 ; + +LAYER M1 + TYPE ROUTING ; +END M1 + +LAYER VIA1 + TYPE CUT ; +END VIA1 + +LAYER M2 + TYPE ROUTING ; +END M2 + +END LIBRARY diff --git a/testdata/lefdef/patternname/v.map b/testdata/lefdef/patternname/v.map new file mode 100644 index 000000000..e86897c72 --- /dev/null +++ b/testdata/lefdef/patternname/v.map @@ -0,0 +1,3 @@ +M1 ALL 31 0 +M2 ALL 32 0 +VIA1 ALL 51 0 diff --git a/testdata/lefdef/viasize2/au.oas.gz b/testdata/lefdef/viasize2/au.oas.gz new file mode 100644 index 0000000000000000000000000000000000000000..5da4dd619c09b1b68a4422c59bb31f10d52a30e7 GIT binary patch literal 424 zcmV;Z0ayMXiwFoh6Jufk17US8Z((x)<&C>a13?sqXU?qIjl1g-aH5e-VIkTWH^D-* z3TB84$tGmhYcs?PDkLag3cHjR7I_4*vas|4L_vaxm57gEsUX(QDu(q!Ucfob;r##i z&zvF7itcDB%Uy1EW0Foe=t)K4W77dHirEFh-Mq(g!u5QXXB9E;=KL8=u}%9E&w76a zY}(C*Un+}fRwx+S%Esol*xTAxd$`EwxF}ajWmfSQqg|`}_4)y62Z%A}W`(?Iv0U9D zJ#DpHuhwcIU90Y_ujy)O)-SjoBbXo~EOeuoPI=59<7L^2D)BEzW-=is`jPqJ=vuHX zB^%Ks|EBc#mzw165_3{cW+7;jVWR`n`~GI*5`xhQ>ixgqc$*TVBQ*(~lFPwy5(yLJ zj4_OiP-