From 6ceac2c6ba89fd57bc3f77edfee5b155bfabfd6c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 27 Mar 2021 23:14:33 +0100 Subject: [PATCH] Updated a test. --- src/drc/drc/built-in-macros/_drc_engine.rb | 9 ++ src/drc/drc/built-in-macros/_drc_netter.rb | 104 ++++++++++++++---- .../unit_tests/layNetlistBrowserModelTests.cc | 8 +- src/lvs/unit_tests/lvsTests.cc | 6 + 4 files changed, 104 insertions(+), 23 deletions(-) diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index 65c76b590..d5d419e76 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -1790,6 +1790,14 @@ CODE # @synopsis connect_implicit(cell_pattern, label_pattern) # See \Netter#connect_implicit for a description of that function. + # %DRC% + # @name connect_explicit + # @brief Specifies explicit net connections + # @synopsis connect_explicit(net_names) + # @synopsis connect_explicit(cell_pattern, net_names) + # See \Netter#connect_explicit for a description of that function. + # Net names is an array (use square brackets to list the net names). + # %DRC% # @name antenna_check # @brief Performs an antenna check @@ -1828,6 +1836,7 @@ CODE connect connect_global connect_implicit + connect_explicit device_scaling extract_devices l2n_data diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb index 747179495..05b7fb6c2 100644 --- a/src/drc/drc/built-in-macros/_drc_netter.rb +++ b/src/drc/drc/built-in-macros/_drc_netter.rb @@ -67,6 +67,8 @@ module DRC @netlisted = false @connect_implicit = [] @connect_implicit_per_cell = {} + @connect_explicit = [] + @connect_explicit_per_cell = {} @l2n = nil @lnum = 0 @device_scaling = 1.0 @@ -241,6 +243,8 @@ module DRC @netlisted = false @connect_implicit = [] @connect_implicit_per_cell = {} + @connect_explicit = [] + @connect_explicit_per_cell = {} _clear_data end @@ -286,6 +290,67 @@ module DRC end + # %DRC% + # @name connect_explicit + # @brief Specifies a list of net names for nets to connect explicitly + # @synopsis connect_explicit(net_names) + # @synopsis connect_explicit(cell_pattern, net_names) + # Use this method to explicitly connect nets even if there is no physical connection. + # As this breaks with the concept of physical verification, this feature should be used + # with care. + # + # The first version of this function will connect all nets listed in the "net_names" array + # in the top level cell. The second version takes a cell name pattern and connects all nets listed + # in "net_names" for cells matching this pattern. + # + # A use case for this method is the following: consider a set of standard cells. These do not have a bulk + # or n-well pin in the schematics. They also do not have build in tie-down diodes for the + # substrate connections. In this case there is a build-in discrepancy between the + # schematics and the layout: bulk and VSS are separate nets within the layout, but the + # schematic does not list them as separate. The solution is to make an explicit connection + # between VDD and n-well and VSS and bulk, provided VDD and VSS are properly labelled as "VDD" and "VSS" + # and n-well and bulk are accessible as named nets (for bulk you can use "connect_global"). + # + # The following code will establish an explicit connection for all cells called "INV.." between + # BULK and VSS nets: + # + # @code + # connect_global(bulk, "BULK") + # ... + # connect_explicit("INV*", [ "BULK", "VSS" ]) + # @/code + # + # Explicit connections also imply implicit connections between different parts of + # one of the nets. In the example before, "VSS" pieces without a physical connection + # will also be connected. + # + # When you use explicit connections you should make sure by other ways that the connection + # is made physically. For example, for the bulk/n-well pin example above, by enforcing at least one + # tie-down diode per n-well island and in the substrate by means of a DRC rule. + # + # The explicit connections are applied on the next net extraction and cleared + # on "clear_connections". + + def connect_explicit(arg1, arg2 = nil) + + @engine._context("connect_explicit") do + + cleanup + if arg2 + arg2.is_a?(Array) || raise("The second argument has to be an array of strings") + arg2.find { |a| !a.is_a?(String) } && raise("The second argument has to be an array of strings") + arg1.is_a?(String) || raise("The first argument has to be a string") + @connect_explicit_per_cell[arg1] ||= [] + @connect_explicit_per_cell[arg1] << arg2 + else + arg1.is_a?(String) || raise("The argument has to be a string") + @connect_explicit << arg1 + end + + end + + end + # %DRC% # @brief Performs an antenna check # @name antenna_check @@ -481,16 +546,29 @@ module DRC # run extraction in a timed environment if ! @netlisted - # build a glob expression from the parts - expr = _join_glob_pattern(@connect_implicit) - - # build cell-pattern specific glob expressions from the parts - per_cell_expr = {} + # configure implicit net connections + @l2n.clear_join_net_names + @connect_implicit.each do |label_pattern| + @l2n.join_net_names(label_pattern) + end @connect_implicit_per_cell.each do |cell_pattern,label_pattern| - per_cell_expr[cell_pattern] = _join_glob_pattern(label_pattern) + label_pattern.each do |lp| + @l2n.join_net_names(cell_pattern, lp) + end end - @engine._cmd(@l2n, :extract_netlist, expr, per_cell_expr) + # configure explicit net connections + @l2n.clear_join_nets + @connect_explicit.each do |names| + @l2n.join_nets(names) + end + @connect_explicit_per_cell.each do |cell_pattern,name_lists| + name_lists.each do |names| + @l2n.join_nets(cell_pattern, names) + end + end + + @engine._cmd(@l2n, :extract_netlist) @netlisted = true end @@ -548,18 +626,6 @@ module DRC end end - def _join_glob_pattern(exprs) - - if exprs.size > 1 - expr = "{" + exprs.join(",") + "}" - else - expr = exprs[0] || "" - end - - expr - - end - def _make_data if @engine._dss diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index 83a7d059c..d57531088 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -330,10 +330,10 @@ TEST (2) EXPECT_EQ (model->rowCount (inv2Net0TerminalIndex), 4); EXPECT_EQ (model->parent (inv2Net0TerminalIndex) == inv2Net0Index, true); // .. whose second terminal is gate - EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0TerminalIndex), Qt::UserRole).toString ()), "G|G|IN|2"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "G"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "IN (3)"); - EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "2 (3)"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0TerminalIndex), Qt::UserRole).toString ()), "D|D|VDD|5"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "D"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "VDD (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 3, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "5 (2)"); // The Pin EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0Index), Qt::UserRole).toString ()), ""); diff --git a/src/lvs/unit_tests/lvsTests.cc b/src/lvs/unit_tests/lvsTests.cc index aa147204c..f4938f530 100644 --- a/src/lvs/unit_tests/lvsTests.cc +++ b/src/lvs/unit_tests/lvsTests.cc @@ -161,3 +161,9 @@ TEST(18_private) run_test (_this, "test_18.lvs", "test_18.cir.gz", "test_18.gds.gz", true); } +TEST(19_private) +{ + // test_is_long_runner (); + run_test (_this, "test_19.lvs", "test_19.cir.gz", "test_19.gds.gz", true); +} +