diff --git a/src/db/db/dbSaveLayoutOptions.cc b/src/db/db/dbSaveLayoutOptions.cc index 77c7663a3..355ed11c8 100644 --- a/src/db/db/dbSaveLayoutOptions.cc +++ b/src/db/db/dbSaveLayoutOptions.cc @@ -26,6 +26,7 @@ #include "tlClassRegistry.h" #include "tlStream.h" #include "tlExpression.h" +#include "tlInternational.h" namespace db { @@ -327,7 +328,7 @@ SaveLayoutOptions::get_valid_layers (const db::Layout &layout, std::vector &cells, const std::vector > &valid_layers) const +SaveLayoutOptions::get_cells (const db::Layout &layout, std::set &cells, const std::vector > &valid_layers, bool require_unique_names) const { if (m_all_cells) { @@ -408,6 +409,26 @@ SaveLayoutOptions::get_cells (const db::Layout &layout, std::set use_count; + for (std::set ::const_iterator c = cells.begin (); c != cells.end (); ++c) { + use_count.insert (std::make_pair (std::string (layout.cell_name (*c)), 0)).first->second += 1; + } + + std::vector multi; + for (std::map::const_iterator u = use_count.begin (); u != use_count.end (); ++u) { + if (u->second > 1) { + multi.push_back (u->first); + } + } + + if (! multi.empty ()) { + throw tl::Exception (tl::to_string (tr ("The following cell name(s) are used for more than one cell - can't write this layout:\n ")) + tl::join (multi, "\n ")); + } + + } } bool diff --git a/src/db/db/dbSaveLayoutOptions.h b/src/db/db/dbSaveLayoutOptions.h index 5dd0a1a80..7c6da0c74 100644 --- a/src/db/db/dbSaveLayoutOptions.h +++ b/src/db/db/dbSaveLayoutOptions.h @@ -413,7 +413,7 @@ public: * * It must be given a list of valid layers which is used to determine empty cells if dont_save_empty_cells is true. */ - void get_cells (const db::Layout &layout, std::set &cells, const std::vector > &valid_layers) const; + void get_cells (const db::Layout &layout, std::set &cells, const std::vector > &valid_layers, bool require_unique_names = true) const; /** * @brief Sets a layout reader option by name diff --git a/src/plugins/streamers/gds2/unit_tests/dbGDS2Writer.cc b/src/plugins/streamers/gds2/unit_tests/dbGDS2Writer.cc index c42911e4d..6565c2cee 100644 --- a/src/plugins/streamers/gds2/unit_tests/dbGDS2Writer.cc +++ b/src/plugins/streamers/gds2/unit_tests/dbGDS2Writer.cc @@ -1129,6 +1129,40 @@ TEST(117) EXPECT_EQ (pp == poly, true); } +// error on duplicate cell name +TEST(118) +{ + db::Manager m (false); + db::Layout layout_org (&m); + + db::cell_index_type cid1 = layout_org.add_cell ("A"); + db::cell_index_type cid2 = layout_org.add_cell ("B"); + layout_org.rename_cell (cid2, "A"); // creates a duplicate cell + + db::LayerProperties lp; + lp.layer = 1; + lp.datatype = 0; + unsigned int lid = layout_org.insert_layer (lp); + + layout_org.cell (cid1).shapes (lid).insert (db::Box (0, 0, 1000, 2000)); + layout_org.cell (cid2).shapes (lid).insert (db::Box (0, 0, 1000, 2000)); + + std::string tmp_file = tl::TestBase::tmp_file ("tmp_GDS2Writer_117.gds"); + + bool error = false; + try { + tl::OutputStream stream (tmp_file); + db::SaveLayoutOptions options; + db::Writer writer (options); + writer.write (layout_org, stream); + } catch (tl::Exception &ex) { + tl::warn << ex.msg (); + error = true; + } + + EXPECT_EQ (error, true); +} + // Extreme fracturing by max. points TEST(120) { @@ -1153,3 +1187,4 @@ TEST(166) opt.max_vertex_count = 4; run_test (_this, "t166.oas.gz", "t166_au.gds.gz", false, opt); } +