mirror of https://github.com/KLayout/klayout.git
Updated a test.
This commit is contained in:
parent
9f295523e4
commit
6ceac2c6ba
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ()), "");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue