diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index ec404f7c8..a8dac54e5 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -223,8 +223,13 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d // NOTE: missing cuts due to pattern holes don't change mask assignment - db::Vector vs ((m_cutsize.x () * m_columns + m_cutspacing.x () * (m_columns - 1)) / 2, (m_cutsize.y () * m_rows + m_cutspacing.y () * (m_rows - 1)) / 2); - db::Box via_box (m_offset - vs, m_offset + vs); + // special rounding to ensure the dimensions are correct for non-even width or height (issue #1877) + db::Vector vs ((m_cutsize.x () * m_columns + m_cutspacing.x () * (m_columns - 1)), (m_cutsize.y () * m_rows + m_cutspacing.y () * (m_rows - 1))); + if (vs.x () % 2 != 0 || vs.y () % 2 != 0) { + reader.warn (tl::sprintf (tl::to_string (tr ("Via has odd width or height (x,y dimension of cut array is %s database units) - this may lead to inaccurate positioning of the via")), vs.to_string ())); + } + db::Point via_ll = m_offset - db::Vector (vs.x () / 2, vs.y () / 2); + db::Box via_box (via_ll, via_ll + vs); std::set dl; @@ -975,7 +980,7 @@ LEFDEFReaderState::~LEFDEFReaderState () } void -LEFDEFReaderState::common_reader_error (const std::string &msg) +LEFDEFReaderState::error (const std::string &msg) { if (mp_importer) { mp_importer->error (msg); @@ -983,7 +988,7 @@ LEFDEFReaderState::common_reader_error (const std::string &msg) } void -LEFDEFReaderState::common_reader_warn (const std::string &msg, int warn_level) +LEFDEFReaderState::warn (const std::string &msg, int warn_level) { if (mp_importer) { mp_importer->warn (msg, warn_level); @@ -1117,7 +1122,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map::const_iterator l = layers.begin (); l != layers.end (); ++l) { @@ -1176,7 +1181,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::mapsecond == ViaGeometry) { @@ -1284,7 +1289,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::mapsecond == All) { @@ -1379,7 +1384,7 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu msg += tl::to_string (tr (" Via size ")) + via_size.to_string (); } #endif - common_reader_warn (msg + tl::to_string (tr (" - layer is ignored"))); + warn (msg + tl::to_string (tr (" - layer is ignored"))); } return ll; diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index 647e3afd2..9720d6edf 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -1354,9 +1354,19 @@ class DB_PLUGIN_PUBLIC LEFDEFReaderState return m_foreign_cells; } + /** + * @brief Issues an error + */ + void error (const std::string &msg); + + /** + * @brief Issues a warning + */ + void warn (const std::string &msg, int warn_level = 1); + protected: - virtual void common_reader_error (const std::string &msg); - virtual void common_reader_warn (const std::string &msg, int warn_level = 1); + virtual void common_reader_error (const std::string &msg) { error (msg); } + virtual void common_reader_warn (const std::string &msg, int warn_level) { warn (msg, warn_level); } private: /** diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 6c1127863..fd890f96b 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -1077,3 +1077,26 @@ TEST(213_no_duplicate_LEF) db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS); } +// issue-1877 (VIA placement rounding) +TEST(214_issue1877) +{ + db::Layout ly; + + std::string fn_path (tl::testdata ()); + fn_path += "/lefdef/issue-1877/"; + + db::LEFDEFReaderOptions lefdef_opt = default_options (); + lefdef_opt.set_map_file ("tech.map"); + lefdef_opt.set_read_lef_with_def (true); + db::LoadLayoutOptions opt; + opt.set_options (lefdef_opt); + + { + tl::InputStream is (fn_path + "test.def"); + db::Reader reader (is); + reader.read (ly, opt); + } + + db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS); +} + diff --git a/testdata/lefdef/issue-1877/au.oas b/testdata/lefdef/issue-1877/au.oas new file mode 100644 index 000000000..3cf8767c5 Binary files /dev/null and b/testdata/lefdef/issue-1877/au.oas differ diff --git a/testdata/lefdef/issue-1877/tech.lef b/testdata/lefdef/issue-1877/tech.lef new file mode 100644 index 000000000..e96c48b57 --- /dev/null +++ b/testdata/lefdef/issue-1877/tech.lef @@ -0,0 +1,27 @@ +VERSION 5.6 ; +BUSBITCHARS "[]" ; +DIVIDERCHAR "/" ; + +UNITS + DATABASE MICRONS 1000 ; +END UNITS +MANUFACTURINGGRID 0.001 ; + +LAYER METAL_1 + TYPE ROUTING ; + DIRECTION HORIZONTAL ; + WIDTH 0.6 ; +END METAL_1 + +LAYER VIA_1 + TYPE CUT ; +END VIA_1 + +LAYER METAL_2 + TYPE ROUTING ; + DIRECTION VERTICAL ; + WIDTH 0.6 ; +END METAL_2 + +END LIBRARY + diff --git a/testdata/lefdef/issue-1877/tech.map b/testdata/lefdef/issue-1877/tech.map new file mode 100644 index 000000000..6d3fd1898 --- /dev/null +++ b/testdata/lefdef/issue-1877/tech.map @@ -0,0 +1,4 @@ +DIEAREA ALL 1 0 +METAL_1 ALL 2 0 +VIA_1 ALL 3 0 +METAL_2 ALL 4 0 diff --git a/testdata/lefdef/issue-1877/test.def b/testdata/lefdef/issue-1877/test.def new file mode 100644 index 000000000..cf273a04c --- /dev/null +++ b/testdata/lefdef/issue-1877/test.def @@ -0,0 +1,21 @@ +VERSION 5.8 ; +DIVIDERCHAR "/" ; +BUSBITCHARS "[]" ; +DESIGN dummy_design ; +UNITS DISTANCE MICRONS 1000 ; + +DIEAREA ( 21500 7000 ) ( 26000 9000 ) ; + +VIAS 1 ; + - via1_2_XXXX_XXX_X_X_XXX_XXX + VIARULE MYVIA1_ARRAY + CUTSIZE 246 246 + LAYERS METAL_1 VIA_1 METAL_2 + CUTSPACING 231 231 + ENCLOSURE 62 137 8 61 + ROWCOL 1 8 ; +END VIAS + + +SPECIALNETS 1 ; + - VDD +# ( PIN VDD ) ( * vdd ) + + USE POWER + + ROUTED METAL_1 0 + SHAPE STRIPE ( 23620 7840 ) via1_2_XXXX_XXX_X_X_XXX_XXX ; +END SPECIALNETS + +END DESIGN