diff --git a/src/db/db/dbCommonReader.cc b/src/db/db/dbCommonReader.cc index 8728f986d..741cf1f0d 100644 --- a/src/db/db/dbCommonReader.cc +++ b/src/db/db/dbCommonReader.cc @@ -305,55 +305,60 @@ CommonReader::finish (db::Layout &layout) new_cells.insert (std::make_pair (i->second.second, i->first)); } - // NOTE: by iterating bottom up we don't need to update the layout (we need the parents for merge_cell) + std::vector > cells_with_conflict; + + // First treat all the cells without conflict for (db::Layout::bottom_up_iterator bu = layout.begin_bottom_up (); bu != layout.end_bottom_up (); ++bu) { db::cell_index_type ci_new = *bu; + std::map::const_iterator i = new_cells.find (ci_new); - if (new_cells.find (ci_new) == new_cells.end ()) { + if (i == new_cells.end ()) { // not a new cell continue; - } else if (! layout.is_valid_cell_index (ci_new)) { - // this can happen if the new cell has been deleted by "prune_subcells" - continue; } - std::map::const_iterator i = new_cells.find (ci_new); - std::pair c2n = layout.cell_by_name (i->second.c_str ()); db::cell_index_type ci_org = c2n.second; - if (c2n.first) { + // NOTE: proxy cells are never resolved. "RenameCell" is a plain and simple case. + if (c2n.first && m_cc_resolution != RenameCell && ! layout.cell (ci_org).is_proxy ()) { + cells_with_conflict.push_back (std::make_pair (ci_new, ci_org)); + } else { + layout.rename_cell (ci_new, layout.uniquify_cell_name (i->second.c_str ()).c_str ()); + } - if (m_cc_resolution == RenameCell || layout.cell (ci_org).is_proxy ()) { + } - // NOTE: we never reopen proxies (they are always local to their layout). Instead we - // always rename for proxies - layout.rename_cell (ci_new, layout.uniquify_cell_name (i->second.c_str ()).c_str ()); + // Then treat all the cells with conflict + for (std::vector >::const_iterator cc = cells_with_conflict.begin (); cc != cells_with_conflict.end (); ++cc) { - } else { + db::cell_index_type ci_new = cc->first; + db::cell_index_type ci_org = cc->second; - // we have a cell conflict + // we have a cell conflict - if (m_cc_resolution == OverwriteCell && ! layout.cell (ci_new).is_ghost_cell ()) { + layout.force_update (); - layout.prune_subcells (ci_org); - layout.cell (ci_org).clear_shapes (); + if (m_cc_resolution == OverwriteCell && ! layout.cell (ci_new).is_ghost_cell ()) { - } else if (m_cc_resolution == SkipNewCell && ! layout.cell (ci_org).is_ghost_cell ()) { + layout.prune_subcells (ci_org); + layout.cell (ci_org).clear_shapes (); - layout.prune_subcells (ci_new); - layout.cell (ci_new).clear_shapes (); + merge_cell (layout, ci_org, ci_new); - } + } else if (m_cc_resolution == SkipNewCell && ! layout.cell (ci_org).is_ghost_cell ()) { - merge_cell (layout, ci_org, ci_new); + layout.prune_subcells (ci_new); + layout.cell (ci_new).clear_shapes (); - } + // we need the instances of the cell we just cleaned + layout.force_update (); + merge_cell (layout, ci_org, ci_new); } else { - layout.rename_cell (ci_new, layout.uniquify_cell_name (i->second.c_str ()).c_str ()); + merge_cell (layout, ci_org, ci_new); } diff --git a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc index 58b4cb80f..838260bf3 100644 --- a/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc +++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Reader.cc @@ -436,3 +436,100 @@ TEST(3_AdvancedMapping) std::string fn_au (tl::testsrc () + "/testdata/gds/alm_au.gds"); db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1); } + +TEST(4_CollectModeRename) +{ + db::Manager m (false); + db::Layout layout (&m); + + db::LoadLayoutOptions options; + options.get_options ().cell_conflict_resolution = db::CommonReader::RenameCell; + + { + tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds"); + db::Reader reader (file); + reader.read (layout, options); + } + + { + tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_added.gds"); + db::Reader reader (file); + reader.read (layout, options); + } + + std::string fn_au (tl::testsrc () + "/testdata/gds/collect_rename_au.gds"); + db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1); +} + +TEST(4_CollectModeOverwrite) +{ + db::Manager m (false); + db::Layout layout (&m); + + db::LoadLayoutOptions options; + options.get_options ().cell_conflict_resolution = db::CommonReader::OverwriteCell; + + { + tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds"); + db::Reader reader (file); + reader.read (layout, options); + } + + { + tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_added.gds"); + db::Reader reader (file); + reader.read (layout, options); + } + + std::string fn_au (tl::testsrc () + "/testdata/gds/collect_overwrite_au.gds"); + db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1); +} + +TEST(4_CollectModeSkip) +{ + db::Manager m (false); + db::Layout layout (&m); + + db::LoadLayoutOptions options; + options.get_options ().cell_conflict_resolution = db::CommonReader::SkipNewCell; + + { + tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds"); + db::Reader reader (file); + reader.read (layout, options); + } + + { + tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_added.gds"); + db::Reader reader (file); + reader.read (layout, options); + } + + std::string fn_au (tl::testsrc () + "/testdata/gds/collect_skip_au.gds"); + db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1); +} + +TEST(4_CollectModeAdd) +{ + db::Manager m (false); + db::Layout layout (&m); + + db::LoadLayoutOptions options; + options.get_options ().cell_conflict_resolution = db::CommonReader::AddToCell; + + { + tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds"); + db::Reader reader (file); + reader.read (layout, options); + } + + { + tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_added.gds"); + db::Reader reader (file); + reader.read (layout, options); + } + + std::string fn_au (tl::testsrc () + "/testdata/gds/collect_add_au.gds"); + db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1); +} + diff --git a/testdata/gds/collect_add_au.gds b/testdata/gds/collect_add_au.gds new file mode 100644 index 000000000..ca0206610 Binary files /dev/null and b/testdata/gds/collect_add_au.gds differ diff --git a/testdata/gds/collect_added.gds b/testdata/gds/collect_added.gds new file mode 100644 index 000000000..e4882b6d8 Binary files /dev/null and b/testdata/gds/collect_added.gds differ diff --git a/testdata/gds/collect_basic.gds b/testdata/gds/collect_basic.gds new file mode 100644 index 000000000..9fad7517e Binary files /dev/null and b/testdata/gds/collect_basic.gds differ diff --git a/testdata/gds/collect_overwrite_au.gds b/testdata/gds/collect_overwrite_au.gds new file mode 100644 index 000000000..e4790a23d Binary files /dev/null and b/testdata/gds/collect_overwrite_au.gds differ diff --git a/testdata/gds/collect_rename_au.gds b/testdata/gds/collect_rename_au.gds new file mode 100644 index 000000000..af98c817f Binary files /dev/null and b/testdata/gds/collect_rename_au.gds differ diff --git a/testdata/gds/collect_skip_au.gds b/testdata/gds/collect_skip_au.gds new file mode 100644 index 000000000..5a0b96fa9 Binary files /dev/null and b/testdata/gds/collect_skip_au.gds differ