diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index a69e8b4bb..56d650b1e 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -707,14 +707,12 @@ Layout::set_technology_name (const std::string &tech) for (db::Layout::iterator c = begin (); c != end (); ++c) { - std::map::const_iterator m; - db::LibraryProxy *lib_proxy = dynamic_cast (&*c); if (! lib_proxy) { continue; } - if ((m = mapping.find (lib_proxy->lib_id ())) != mapping.end ()) { + if (mapping.find (lib_proxy->lib_id ()) != mapping.end ()) { db::Library *lib = db::LibraryManager::instance ().lib (lib_proxy->lib_id ()); db::Cell *lib_cell = &lib->layout ().cell (lib_proxy->library_cell_index ()); @@ -745,7 +743,10 @@ Layout::set_technology_name (const std::string &tech) db::cell_index_type ci = lp->first->Cell::cell_index (); db::PCellVariant *lib_pcell = lp->second; - std::pair pn = lib_pcell->layout ()->pcell_by_name (lp->first->get_basic_name ().c_str ()); + db::Library *new_lib = db::LibraryManager::instance ().lib (mapping [lp->first->lib_id ()]); + tl_assert (new_lib != 0); + + std::pair pn = new_lib->layout ().pcell_by_name (lp->first->get_basic_name ().c_str ()); if (! pn.first) { @@ -756,8 +757,6 @@ Layout::set_technology_name (const std::string &tech) } else { - db::Library *new_lib = db::LibraryManager::instance ().lib (mapping [lp->first->lib_id ()]); - const db::PCellDeclaration *old_pcell_decl = lib_pcell->layout ()->pcell_declaration (lib_pcell->pcell_id ()); const db::PCellDeclaration *new_pcell_decl = new_lib->layout ().pcell_declaration (pn.second); if (! old_pcell_decl || ! new_pcell_decl) { diff --git a/src/rba/unit_tests/rbaTests.cc b/src/rba/unit_tests/rbaTests.cc index 5a1cfa730..0fe2b1d0d 100644 --- a/src/rba/unit_tests/rbaTests.cc +++ b/src/rba/unit_tests/rbaTests.cc @@ -129,6 +129,7 @@ RUBYTEST (dbNetlistReaderTests, "dbNetlistReaderTests.rb") RUBYTEST (dbNetlistCompare, "dbNetlistCompare.rb") RUBYTEST (dbPathTest, "dbPathTest.rb") RUBYTEST (dbPCells, "dbPCells.rb") +RUBYTEST (dbPCellsRebind, "dbPCellsRebind.rb") RUBYTEST (dbPointTest, "dbPointTest.rb") RUBYTEST (dbPolygonTest, "dbPolygonTest.rb") RUBYTEST (dbRegionTest, "dbRegionTest.rb") diff --git a/testdata/ruby/dbPCellsRebind.rb b/testdata/ruby/dbPCellsRebind.rb new file mode 100644 index 000000000..88150ac78 --- /dev/null +++ b/testdata/ruby/dbPCellsRebind.rb @@ -0,0 +1,202 @@ +# encoding: UTF-8 + +# KLayout Layout Viewer +# Copyright (C) 2006-2026 Matthias Koefferlein +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +if !$:.member?(File::dirname($0)) + $:.push(File::dirname($0)) +end + +load("test_prologue.rb") + +class PCellRebindVar < RBA::PCellDeclaration + + def initialize(name, layer, w_name, w_default) + @name = name + @layer = layer + @w_name = w_name + @w_default = w_default + end + + def display_text(parameters) + return "#{@name}(L=#{@layer},#{@w_name}=#{parameters[0].to_s},H=#{parameters[1].to_s})" + end + + def get_parameters + + # prepare a set of parameter declarations + param = [] + + param.push(RBA::PCellParameterDeclaration.new(@w_name, RBA::PCellParameterDeclaration::TypeDouble, "Width", @w_default)) + param.push(RBA::PCellParameterDeclaration.new("H", RBA::PCellParameterDeclaration::TypeDouble, "Height", 1.0)) + + return param + + end + + def get_layers(parameters) + return [ RBA::LayerInfo::new(@layer, 0) ] + end + + def produce(layout, layers, parameters, cell) + + # fetch the parameters + w = parameters[0] + h = parameters[1] + + # create the shape + cell.shapes(layout.layer(@layer, 0)).insert(RBA::DBox.new(-w / 2, -h / 2, w / 2, h / 2)) + + end + +end + +class RebindTestLib < RBA::Library + + def initialize(var) + + # set the description + self.description = "PCell rebind test lib" + + # create the PCell declarations + if var == 0 + layout.register_pcell("Box0", PCellRebindVar::new("Box0", 0, "W", 3.0)) + layout.register_pcell("Box1", PCellRebindVar::new("Box1", 1, "W", 2.0)) + layout.register_pcell("Box2A", PCellRebindVar::new("Box2A", 2, "W", 1.0)) + else + layout.register_pcell("Box2B", PCellRebindVar::new("Box2B", 12, "W", 1.5)) + layout.register_pcell("Box1", PCellRebindVar::new("Box1", 11, "WW", 2.5)) + layout.register_pcell("Box0", PCellRebindVar::new("Box0", 10, "W", 3.5)) + end + + self.technology = (var == 0 ? "T0" : "T1") + + register("RebindTestLib") + + end + +end + +def c2s(cell) + ly = cell.layout + s = [] + ly.layer_indexes.collect { |li| ly.get_info(li) }.sort { |a,b| [ a.layer, a.datatype ] <=> [ b.layer, b.datatype ] }.each do |lp| + bbox = cell.dbbox(ly.layer(lp)) + bbox.empty? || (s << lp.to_s + ":" + bbox.to_s) + end + s.join(";") +end + +class DBPCellRebind_TestClass < TestBase + + def test_1 + + tl0 = RebindTestLib::new(0) + tl1 = RebindTestLib::new(1) + + assert_equal(tl0.is_for_technology("T0"), true) + assert_equal(tl0.is_for_technology("T1"), false) + assert_equal(tl1.is_for_technology("T0"), false) + assert_equal(tl1.is_for_technology("T1"), true) + + ly = RBA::Layout::new + ly.technology_name = "T0" + + top = ly.create_cell("TOP") + + # in T0: + # Box0 -> on layer 0, w parameter is "W" with default 3.0 + # Box1 -> on layer 1, w parameter is "W" with default 2.0 + # Box2A -> on layer 2, w parameter is "W" with default 1.0 + # Box2B does not exist + + c0 = ly.create_cell("Box0", "RebindTestLib", { "W" => 0.3, "H" => 0.5 }) + c1 = ly.create_cell("Box1", "RebindTestLib", { "W" => 0.4, "H" => 0.6 }) + c2 = ly.create_cell("Box2A", "RebindTestLib", { "W" => 0.5, "H" => 0.7 }) + + top.insert(RBA::CellInstArray::new(c0.cell_index(), RBA::Trans::new)) + top.insert(RBA::CellInstArray::new(c1.cell_index(), RBA::Trans::new)) + top.insert(RBA::CellInstArray::new(c2.cell_index(), RBA::Trans::new)) + + assert_equal(c0.display_title, "RebindTestLib.Box0(L=0,W=0.3,H=0.5)") + assert_equal(c2s(c0), "0/0:(-0.15,-0.25;0.15,0.25)") + + assert_equal(c1.display_title, "RebindTestLib.Box1(L=1,W=0.4,H=0.6)") + assert_equal(c2s(c1), "1/0:(-0.2,-0.3;0.2,0.3)") + + assert_equal(c2.display_title, "RebindTestLib.Box2A(L=2,W=0.5,H=0.7)") + assert_equal(c2s(c2), "2/0:(-0.25,-0.35;0.25,0.35)") + + # in T0: + # Box0 -> on layer 0, w parameter is "W" with default 3.5 + # Box1 -> on layer 1, w parameter is "WW" with default 2.5 + # Box2A does not exist + # Box2B -> on layer 2, w parameter is "W" with default 1.5 + + ly.technology_name = "T1" + + assert_equal(c0.destroyed, false) + assert_equal(c1.destroyed, false) + assert_equal(c2.destroyed, true) # becomes a cold proxy + + c0 = ly.cell("Box0") + c1 = ly.cell("Box1") + c2 = ly.cell("Box2A") + + # layer changed, but parameters can be translated + assert_equal(c0.display_title, "RebindTestLib.Box0(L=10,W=0.3,H=0.5)") + assert_equal(c2s(c0), "10/0:(-0.15,-0.25;0.15,0.25)") + + # Layer changed and "W" parameter can't be translated as the name changed to "WW" + assert_equal(c1.display_title, "RebindTestLib.Box1(L=11,WW=2.5,H=0.6)") + assert_equal(c2s(c1), "11/0:(-1.25,-0.3;1.25,0.3)") + + # Box2A does no longer exist -> cold proxy + assert_equal(c2.display_title, "RebindTestLib.Box2A") + assert_equal(c2s(c2), "2/0:(-0.25,-0.35;0.25,0.35)") + + ly.technology_name = "T0" + + assert_equal(c0.destroyed, false) + assert_equal(c1.destroyed, false) + assert_equal(c2.destroyed, true) # became an active PCell variant again + + c0 = ly.cell("Box0") + c1 = ly.cell("Box1") + c2 = ly.cell("Box2A") + + # layer changed, but parameters can be translated + assert_equal(c0.display_title, "RebindTestLib.Box0(L=0,W=0.3,H=0.5)") + assert_equal(c2s(c0), "0/0:(-0.15,-0.25;0.15,0.25)") + + # Layer changed and "WW" parameter can't be translated as the name changed back to "W" + assert_equal(c1.display_title, "RebindTestLib.Box1(L=1,W=2.0,H=0.6)") + assert_equal(c2s(c1), "1/0:(-1,-0.3;1,0.3)") + + # Box2A is back to normal as the cold proxy kept the information + assert_equal(c2.display_title, "RebindTestLib.Box2A(L=2,W=0.5,H=0.7)") + assert_equal(c2s(c2), "2/0:(-0.25,-0.35;0.25,0.35)") + + tl0._destroy + tl1._destroy + + end + +end + +load("test_epilogue.rb") +