mirror of https://github.com/KLayout/klayout.git
Some enhancements for strong matching of nets
* same_nets! method for strong matching * same_nets and same_nets! except glob pattern to circuits and nets * both observe case sensitivity * helper functions for case sensitivity Netlist#is_case_sensitive?, Netlist#case_sensitive= * Netlist#nets_by_name to get nets from pattern
This commit is contained in:
parent
72dc94197e
commit
ab70c42c68
|
|
@ -1013,6 +1013,14 @@ public:
|
|||
return j->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether there is a node for the given net
|
||||
*/
|
||||
bool has_node_index_for_net (const db::Net *net) const
|
||||
{
|
||||
return m_net_index.find (net) != m_net_index.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the node for a given node index
|
||||
*/
|
||||
|
|
@ -2880,9 +2888,16 @@ NetlistComparer::exclude_resistors (double threshold)
|
|||
}
|
||||
|
||||
void
|
||||
NetlistComparer::same_nets (const db::Net *na, const db::Net *nb)
|
||||
NetlistComparer::same_nets (const db::Net *na, const db::Net *nb, bool must_match)
|
||||
{
|
||||
m_same_nets [std::make_pair (na->circuit (), nb->circuit ())].push_back (std::make_pair (na, nb));
|
||||
tl_assert (na && na);
|
||||
m_same_nets [std::make_pair (na->circuit (), nb->circuit ())].push_back (std::make_pair (std::make_pair (na, nb), must_match));
|
||||
}
|
||||
|
||||
void
|
||||
NetlistComparer::same_nets (const db::Circuit *ca, const db::Circuit *cb, const db::Net *na, const db::Net *nb, bool must_match)
|
||||
{
|
||||
m_same_nets [std::make_pair (ca, cb)].push_back (std::make_pair (std::make_pair (na, nb), must_match));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3114,9 +3129,9 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
|||
tl_assert (i->second.second.size () == size_t (1));
|
||||
const db::Circuit *cb = i->second.second.front ();
|
||||
|
||||
std::vector<std::pair<const Net *, const Net *> > empty;
|
||||
const std::vector<std::pair<const Net *, const Net *> > *net_identity = ∅
|
||||
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<const Net *, const Net *> > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb));
|
||||
std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > empty;
|
||||
const std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > *net_identity = ∅
|
||||
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb));
|
||||
if (sn != m_same_nets.end ()) {
|
||||
net_identity = &sn->second;
|
||||
}
|
||||
|
|
@ -3525,7 +3540,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
db::DeviceCategorizer &device_categorizer,
|
||||
db::CircuitCategorizer &circuit_categorizer,
|
||||
db::CircuitPinMapper &circuit_pin_mapper,
|
||||
const std::vector<std::pair<const Net *, const Net *> > &net_identity,
|
||||
const std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > &net_identity,
|
||||
bool &pin_mismatch,
|
||||
std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping,
|
||||
std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping) const
|
||||
|
|
@ -3551,11 +3566,39 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
g1.identify (0, 0);
|
||||
g2.identify (0, 0);
|
||||
|
||||
for (std::vector<std::pair<const Net *, const Net *> >::const_iterator p = net_identity.begin (); p != net_identity.end (); ++p) {
|
||||
size_t ni1 = g1.node_index_for_net (p->first);
|
||||
size_t ni2 = g2.node_index_for_net (p->second);
|
||||
g1.identify (ni1, ni2);
|
||||
g2.identify (ni2, ni1);
|
||||
for (std::vector<std::pair<std::pair<const Net *, const Net *>, bool> >::const_iterator p = net_identity.begin (); p != net_identity.end (); ++p) {
|
||||
|
||||
// NOTE: nets may vanish, hence there
|
||||
if (g1.has_node_index_for_net (p->first.first) && g2.has_node_index_for_net (p->first.second)) {
|
||||
|
||||
size_t ni1 = g1.node_index_for_net (p->first.first);
|
||||
size_t ni2 = g2.node_index_for_net (p->first.second);
|
||||
g1.identify (ni1, ni2);
|
||||
g2.identify (ni2, ni1);
|
||||
|
||||
// in must_match mode, check if the nets are identical
|
||||
if (p->second && ! (g1.node(ni1) == g2.node(ni2))) {
|
||||
mp_logger->net_mismatch (p->first.first, p->first.second);
|
||||
} else {
|
||||
mp_logger->match_nets (p->first.first, p->first.second);
|
||||
}
|
||||
|
||||
} else if (p->second && g1.has_node_index_for_net (p->first.first)) {
|
||||
|
||||
mp_logger->net_mismatch (p->first.first, 0);
|
||||
|
||||
size_t ni1 = g1.node_index_for_net (p->first.first);
|
||||
g1.identify (ni1, 0);
|
||||
|
||||
} else if (p->second && g2.has_node_index_for_net (p->first.second)) {
|
||||
|
||||
mp_logger->net_mismatch (0, p->first.second);
|
||||
|
||||
size_t ni2 = g2.node_index_for_net (p->first.second);
|
||||
g2.identify (ni2, 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int iter = 0;
|
||||
|
|
|
|||
|
|
@ -181,7 +181,17 @@ public:
|
|||
* net nb in netlist b.
|
||||
* By default nets are not identical expect through their topology.
|
||||
*/
|
||||
void same_nets (const db::Net *na, const db::Net *nb);
|
||||
void same_nets (const db::Net *na, const db::Net *nb, bool must_match = false);
|
||||
|
||||
/**
|
||||
* @brief Mark two nets as identical
|
||||
*
|
||||
* This makes a net na in netlist a identical to the corresponding
|
||||
* net nb in netlist b.
|
||||
* By default nets are not identical expect through their topology.
|
||||
* This version allows mapping one net to a null net because the circuits are explicitly specified.
|
||||
*/
|
||||
void same_nets (const db::Circuit *ca, const db::Circuit *cb, const db::Net *na, const db::Net *nb, bool must_match);
|
||||
|
||||
/**
|
||||
* @brief Mark two pins as equivalent (i.e. can be swapped)
|
||||
|
|
@ -344,7 +354,7 @@ private:
|
|||
NetlistComparer &operator= (const NetlistComparer &);
|
||||
|
||||
protected:
|
||||
bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector<std::pair<const Net *, const Net *> > &net_identity, bool &pin_mismatch, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping) const;
|
||||
bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > &net_identity, bool &pin_mismatch, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping) const;
|
||||
bool all_subcircuits_verified (const db::Circuit *c, const std::set<const db::Circuit *> &verified_circuits) const;
|
||||
std::string generate_subcircuits_not_verified_warning (const db::Circuit *ca, const std::set<const db::Circuit *> &verified_circuits_a, const db::Circuit *cb, const std::set<const db::Circuit *> &verified_circuits_b) const;
|
||||
static void derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinMapper *circuit_pin_mapper);
|
||||
|
|
@ -354,7 +364,7 @@ protected:
|
|||
bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const;
|
||||
|
||||
mutable NetlistCompareLogger *mp_logger;
|
||||
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<const Net *, const Net *> > > m_same_nets;
|
||||
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > > m_same_nets;
|
||||
std::unique_ptr<CircuitPinMapper> mp_circuit_pin_mapper;
|
||||
std::unique_ptr<DeviceCategorizer> mp_device_categorizer;
|
||||
std::unique_ptr<CircuitCategorizer> mp_circuit_categorizer;
|
||||
|
|
|
|||
|
|
@ -1238,8 +1238,14 @@ static std::vector<db::Net *>
|
|||
nets_by_name (db::Circuit *circuit, const std::string &name_pattern)
|
||||
{
|
||||
std::vector<db::Net *> res;
|
||||
if (! circuit) {
|
||||
return res;
|
||||
}
|
||||
|
||||
tl::GlobPattern glob (name_pattern);
|
||||
if (circuit->netlist ()) {
|
||||
glob.set_case_sensitive (circuit->netlist ()->is_case_sensitive ());
|
||||
}
|
||||
for (db::Circuit::net_iterator n = circuit->begin_nets (); n != circuit->end_nets (); ++n) {
|
||||
db::Net *net = n.operator-> ();
|
||||
if (glob.match (net->name ())) {
|
||||
|
|
@ -1254,8 +1260,14 @@ static std::vector<const db::Net *>
|
|||
nets_by_name_const (const db::Circuit *circuit, const std::string &name_pattern)
|
||||
{
|
||||
std::vector<const db::Net *> res;
|
||||
if (! circuit) {
|
||||
return res;
|
||||
}
|
||||
|
||||
tl::GlobPattern glob (name_pattern);
|
||||
if (circuit->netlist ()) {
|
||||
glob.set_case_sensitive (circuit->netlist ()->is_case_sensitive ());
|
||||
}
|
||||
for (db::Circuit::const_net_iterator n = circuit->begin_nets (); n != circuit->end_nets (); ++n) {
|
||||
const db::Net *net = n.operator-> ();
|
||||
if (glob.match (net->name ())) {
|
||||
|
|
@ -1681,8 +1693,13 @@ static std::vector<db::Circuit *>
|
|||
circuits_by_name (db::Netlist *netlist, const std::string &name_pattern)
|
||||
{
|
||||
std::vector<db::Circuit *> res;
|
||||
if (! netlist) {
|
||||
return res;
|
||||
}
|
||||
|
||||
tl::GlobPattern glob (name_pattern);
|
||||
glob.set_case_sensitive (netlist->is_case_sensitive ());
|
||||
|
||||
for (db::Netlist::circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
|
||||
db::Circuit *circuit = c.operator-> ();
|
||||
if (glob.match (circuit->name ())) {
|
||||
|
|
@ -1697,8 +1714,13 @@ static std::vector<const db::Circuit *>
|
|||
circuits_by_name_const (const db::Netlist *netlist, const std::string &name_pattern)
|
||||
{
|
||||
std::vector<const db::Circuit *> res;
|
||||
if (! netlist) {
|
||||
return res;
|
||||
}
|
||||
|
||||
tl::GlobPattern glob (name_pattern);
|
||||
glob.set_case_sensitive (netlist->is_case_sensitive ());
|
||||
|
||||
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
|
||||
const db::Circuit *circuit = c.operator-> ();
|
||||
if (glob.match (circuit->name ())) {
|
||||
|
|
@ -1710,6 +1732,14 @@ circuits_by_name_const (const db::Netlist *netlist, const std::string &name_patt
|
|||
}
|
||||
|
||||
Class<db::Netlist> decl_dbNetlist ("db", "Netlist",
|
||||
gsi::method ("is_case_sensitive?", &db::Netlist::is_case_sensitive,
|
||||
"@brief Returns a value indicating whether the netlist names are case sensitive\n"
|
||||
"This method has been added in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("case_sensitive=", &db::Netlist::set_case_sensitive, gsi::arg ("cs"),
|
||||
"@brief Sets a value indicating whether the netlist names are case sensitive\n"
|
||||
"This method has been added in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("add", &gsi::add_circuit, gsi::arg ("circuit"),
|
||||
"@brief Adds the circuit to the netlist\n"
|
||||
"This method will add the given circuit object to the netlist. "
|
||||
|
|
|
|||
|
|
@ -476,13 +476,32 @@ Class<db::NetlistComparer> decl_dbNetlistComparer ("db", "NetlistComparer",
|
|||
"The logger is a delegate or event receiver which the comparer will send compare events to. "
|
||||
"See the class description for more details."
|
||||
) +
|
||||
gsi::method ("same_nets", &db::NetlistComparer::same_nets, gsi::arg ("net_a"), gsi::arg ("net_b"),
|
||||
gsi::method ("same_nets", (void (db::NetlistComparer::*) (const db::Net *, const db::Net *, bool)) &db::NetlistComparer::same_nets, gsi::arg ("net_a"), gsi::arg ("net_b"), gsi::arg ("must_match", false),
|
||||
"@brief Marks two nets as identical.\n"
|
||||
"This makes a net net_a in netlist a identical to the corresponding\n"
|
||||
"net net_b in netlist b (see \\compare).\n"
|
||||
"Otherwise, the algorithm will try to identify nets according to their topology. "
|
||||
"This method can be used to supply hints to the compare algorithm. It will use "
|
||||
"these hints to derive further identities."
|
||||
"these hints to derive further identities.\n"
|
||||
"\n"
|
||||
"If 'must_match' is true, the nets are required to match. If they don't, an error is reported.\n"
|
||||
"\n"
|
||||
"The 'must_match' optional argument has been added in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("same_nets", (void (db::NetlistComparer::*) (const db::Circuit *, const db::Circuit *, const db::Net *, const db::Net *, bool)) &db::NetlistComparer::same_nets, gsi::arg ("circuit_a"), gsi::arg ("circuit_b"), gsi::arg ("net_a"), gsi::arg ("net_b"), gsi::arg ("must_match", false),
|
||||
"@brief Marks two nets as identical.\n"
|
||||
"This makes a net net_a in netlist a identical to the corresponding\n"
|
||||
"net net_b in netlist b (see \\compare).\n"
|
||||
"Otherwise, the algorithm will try to identify nets according to their topology. "
|
||||
"This method can be used to supply hints to the compare algorithm. It will use "
|
||||
"these hints to derive further identities.\n"
|
||||
"\n"
|
||||
"If 'must_match' is true, the nets are required to match. If they don't, an error is reported.\n"
|
||||
"\n"
|
||||
"This variant allows specifying nil for the nets indicating the nets are mismatched by definition. "
|
||||
"with 'must_match' this will render a net mismatch error.\n"
|
||||
"\n"
|
||||
"This variant has been added in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("equivalent_pins", (void (db::NetlistComparer::*) (const db::Circuit *, size_t, size_t)) &db::NetlistComparer::equivalent_pins, gsi::arg ("circuit_b"), gsi::arg ("pin_id1"), gsi::arg ("pin_id2"),
|
||||
"@brief Marks two pins of the given circuit as equivalent (i.e. they can be swapped).\n"
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ The filter is a glob expression.
|
|||
This has the following effects:
|
||||
</p><p>
|
||||
<ul>
|
||||
<li>The circuits are no longer compared against each other </li>
|
||||
<li>The circuits are no longer compared (netlist vs. schematic) </li>
|
||||
<li>Named pins are required to match (use labels on the nets to name pins in the layout) </li>
|
||||
<li>Unnamed pins are treated as equivalent and can be swapped </li>
|
||||
<li>The selected circuits will not be purged on netlist simplification </li>
|
||||
|
|
@ -91,6 +91,8 @@ Using this method can be useful to reduce the verification overhead for
|
|||
blocks which are already verifified by other ways or for which no schematic
|
||||
is available - e.g. hard macros.
|
||||
</p><p>
|
||||
Example:
|
||||
</p><p>
|
||||
<pre>
|
||||
# skips all MEMORY* circuits from compare
|
||||
blank_circuit("MEMORY*")
|
||||
|
|
@ -317,7 +319,8 @@ Use this method andwhere in the script before the <a href="#compare">compare</a>
|
|||
<keyword name="same_nets"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>same_nets(circuit, net_a, net_b)</tt></li>
|
||||
<li><tt>same_nets(circuit_pattern, net_pattern)</tt></li>
|
||||
<li><tt>same_nets(circuit_pattern, net_a, net_b)</tt></li>
|
||||
<li><tt>same_nets(circuit_a, net_a, circuit_b, net_b)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
|
|
@ -325,8 +328,17 @@ This method will force an equivalence between the net_a and net_b from circuit_a
|
|||
and circuit_b (circuit in the three-argument form is for both circuit_a and circuit_b).
|
||||
</p><p>
|
||||
In the four-argument form, the circuits can be either given by name or as Circuit
|
||||
objects. In the three-argument form, the circuit has to be given by name.
|
||||
objects. In the three-argument form, the circuits have to be given by name pattern.
|
||||
Nets can be either given by name or as Net objects.
|
||||
In the two-argument form, the circuits and nets have to be given as name pattern.
|
||||
</p><p>
|
||||
"name pattern" are glob-style pattern - e.g. the following will identify the
|
||||
all nets starting with "A" from the extracted netlist with the same net from
|
||||
the schematic netlist for all circuits starting with "INV":
|
||||
</p><p>
|
||||
<pre>
|
||||
same_nets("INV*", "A*")
|
||||
</pre>
|
||||
</p><p>
|
||||
After using this function, the compare algorithm will consider these nets equivalent.
|
||||
Use this method to provide hints for the comparer in cases which are difficult to
|
||||
|
|
@ -337,6 +349,18 @@ Names are case sensitive for layout-derived netlists and case-insensitive for SP
|
|||
</p><p>
|
||||
Use this method andwhere in the script before the <a href="#compare">compare</a> call.
|
||||
</p>
|
||||
<a name="same_nets!"/><h2>"same_nets!" - Establishes an equivalence between the nets with matching requirement</h2>
|
||||
<keyword name="same_nets!"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>same_nets!(circuit_pattern, net_pattern)</tt></li>
|
||||
<li><tt>same_nets!(circuit_pattern, net_a, net_b)</tt></li>
|
||||
<li><tt>same_nets!(circuit_a, net_a, circuit_b, net_b)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method is equivalent to <a href="#same_nets">same_nets</a>, but requires identity of the given nets.
|
||||
If the specified nets do not match, an error is reported.
|
||||
</p>
|
||||
<a name="schematic"/><h2>"schematic" - Gets, sets or reads the reference netlist</h2>
|
||||
<keyword name="schematic"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
|
@ -115,10 +115,19 @@ module LVS
|
|||
# %LVS%
|
||||
# @name same_nets
|
||||
# @brief Establishes an equivalence between the nets
|
||||
# @synopsis same_nets(circuit, net_a, net_b)
|
||||
# @synopsis same_nets(circuit_pattern, net_pattern)
|
||||
# @synopsis same_nets(circuit_pattern, net_a, net_b)
|
||||
# @synopsis same_nets(circuit_a, net_a, circuit_b, net_b)
|
||||
# See \Netter#same_nets for a description of that function.
|
||||
|
||||
# %LVS%
|
||||
# @name same_nets!
|
||||
# @brief Establishes an equivalence between the nets (must match)
|
||||
# @synopsis same_nets!(circuit_pattern, net_pattern)
|
||||
# @synopsis same_nets!(circuit_pattern, net_a, net_b)
|
||||
# @synopsis same_nets!(circuit_a, net_a, circuit_b, net_b)
|
||||
# See \Netter#same_nets! for a description of that function.
|
||||
|
||||
# %LVS%
|
||||
# @name same_circuits
|
||||
# @brief Establishes an equivalence between the circuits
|
||||
|
|
@ -174,7 +183,7 @@ module LVS
|
|||
# @synopsis tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance])
|
||||
# See \Netter#tolerance for a description of that function.
|
||||
|
||||
%w(schematic compare join_symmetric_nets tolerance blank_circuit align same_nets same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity consider_net_names).each do |f|
|
||||
%w(schematic compare join_symmetric_nets tolerance blank_circuit align same_nets same_nets! same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity consider_net_names).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(*args)
|
||||
_netter.#{f}(*args)
|
||||
|
|
|
|||
|
|
@ -370,14 +370,24 @@ module LVS
|
|||
# %LVS%
|
||||
# @name same_nets
|
||||
# @brief Establishes an equivalence between the nets
|
||||
# @synopsis same_nets(circuit, net_a, net_b)
|
||||
# @synopsis same_nets(circuit_pattern, net_pattern)
|
||||
# @synopsis same_nets(circuit_pattern, net_a, net_b)
|
||||
# @synopsis same_nets(circuit_a, net_a, circuit_b, net_b)
|
||||
# This method will force an equivalence between the net_a and net_b from circuit_a
|
||||
# and circuit_b (circuit in the three-argument form is for both circuit_a and circuit_b).
|
||||
#
|
||||
#
|
||||
# In the four-argument form, the circuits can be either given by name or as Circuit
|
||||
# objects. In the three-argument form, the circuit has to be given by name.
|
||||
# objects. In the three-argument form, the circuits have to be given by name pattern.
|
||||
# Nets can be either given by name or as Net objects.
|
||||
# In the two-argument form, the circuits and nets have to be given as name pattern.
|
||||
#
|
||||
# "name pattern" are glob-style pattern - e.g. the following will identify the
|
||||
# all nets starting with "A" from the extracted netlist with the same net from
|
||||
# the schematic netlist for all circuits starting with "INV":
|
||||
#
|
||||
# @code
|
||||
# same_nets("INV*", "A*")
|
||||
# @/code
|
||||
#
|
||||
# After using this function, the compare algorithm will consider these nets equivalent.
|
||||
# Use this method to provide hints for the comparer in cases which are difficult to
|
||||
|
|
@ -389,65 +399,125 @@ module LVS
|
|||
# Use this method andwhere in the script before the \compare call.
|
||||
|
||||
def same_nets(*args)
|
||||
_same_nets_impl(false, *args)
|
||||
end
|
||||
|
||||
if args.size < 3
|
||||
raise("Too few arguments to 'same_nets' (need at least 3)")
|
||||
# %LVS%
|
||||
# @name same_nets!
|
||||
# @brief Establishes an equivalence between the nets with matching requirement
|
||||
# @synopsis same_nets!(circuit_pattern, net_pattern)
|
||||
# @synopsis same_nets!(circuit_pattern, net_a, net_b)
|
||||
# @synopsis same_nets!(circuit_a, net_a, circuit_b, net_b)
|
||||
# This method is equivalent to \same_nets, but requires identity of the given nets.
|
||||
# If the specified nets do not match, an error is reported.
|
||||
|
||||
def same_nets!(*args)
|
||||
_same_nets_impl(true, *args)
|
||||
end
|
||||
|
||||
def _same_nets_impl(force, *args)
|
||||
|
||||
if args.size < 2
|
||||
raise("Too few arguments to 'same_nets' (need at least 2)")
|
||||
end
|
||||
if args.size > 4
|
||||
raise("Too many arguments to 'same_nets' (need max 4)")
|
||||
end
|
||||
|
||||
if args.size == 3
|
||||
( ca, a, b ) = args
|
||||
cb = ca
|
||||
( ca, a ) = args
|
||||
cb = nil
|
||||
ca.is_a?(String) || raise("Circuit argument of 'same_nets' must be a string")
|
||||
b = nil
|
||||
a.is_a?(String) || raise("Net argument of 'same_nets' must be a string")
|
||||
elsif args.size == 3
|
||||
( ca, a, b ) = args
|
||||
cb = nil
|
||||
ca.is_a?(String) || raise("Circuit argument of 'same_nets' must be a string")
|
||||
[ a, b ].each do |n|
|
||||
n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects")
|
||||
end
|
||||
else
|
||||
( ca, a, cb, b ) = args
|
||||
[ ca, cb ].each do |n|
|
||||
n.is_a?(String) || n.is_a?(RBA::Net) || raise("Circuit arguments of 'same_nets' must be strings or Net objects")
|
||||
n.is_a?(String) || n.is_a?(RBA::Circuit) || raise("Circuit arguments of 'same_nets' must be strings or Circuit objects")
|
||||
end
|
||||
[ a, b ].each do |n|
|
||||
n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects")
|
||||
end
|
||||
end
|
||||
|
||||
[ a, b ].each do |n|
|
||||
n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects")
|
||||
end
|
||||
|
||||
@comparer_config << lambda { |comparer| self._same_nets(comparer, ca, a, cb, b) }
|
||||
@comparer_config << lambda { |comparer| self._same_nets(comparer, ca, a, cb, b, force) }
|
||||
|
||||
end
|
||||
|
||||
def _same_nets(comparer, ca, a, cb, b)
|
||||
def _same_nets(comparer, ca, a, cb, b, force)
|
||||
|
||||
( nl_a, nl_b ) = _ensure_two_netlists
|
||||
|
||||
if ca.is_a?(String)
|
||||
circuit_a = nl_a.circuit_by_name(ca)
|
||||
cs = !(nl_a.is_case_sensitive? && nl_b.is_case_sensitive?)
|
||||
|
||||
if ca.is_a?(String) && !cb
|
||||
|
||||
n2c = {}
|
||||
nl_a.circuits_by_name(ca).each { |c| name = cs ? c.name.upcase : c.name; n2c[name] ||= [ nil, nil ]; n2c[name][0] = c }
|
||||
nl_b.circuits_by_name(ca).each { |c| name = cs ? c.name.upcase : c.name; n2c[name] ||= [ nil, nil ]; n2c[name][1] = c }
|
||||
|
||||
circuits = []
|
||||
n2c.keys.sort.each do |n|
|
||||
if n2c[n][0] && n2c[n][1]
|
||||
circuits << n2c[n]
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
circuit_a = ca
|
||||
end
|
||||
|
||||
if cb.is_a?(String)
|
||||
circuit_b = nl_b.circuit_by_name(cb)
|
||||
else
|
||||
circuit_b = cb
|
||||
end
|
||||
circuit_a = ca.is_a?(String) ? nl_a.circuit_by_name(ca) : ca
|
||||
circuit_b = cb.is_a?(String) ? nl_b.circuit_by_name(cb) : cb
|
||||
|
||||
if circuit_a && circuit_b
|
||||
|
||||
if a.is_a?(String)
|
||||
net_a = circuit_a.net_by_name(a) || raise("Not a valid net name in extracted netlist in 'same_nets': #{a} (for circuit #{circuit_a})")
|
||||
else
|
||||
net_a = a
|
||||
circuits = []
|
||||
if circuit_a && circuit_b
|
||||
circuits << [ circuit_a, circuit_b ]
|
||||
end
|
||||
|
||||
if b.is_a?(String)
|
||||
net_b = circuit_b.net_by_name(b) || raise("Not a valid net name in extracted netlist in 'same_nets': #{b} (for circuit #{circuit_b})")
|
||||
end
|
||||
|
||||
circuits.each do |circuit_a, circuit_b|
|
||||
|
||||
if a.is_a?(String) && !b
|
||||
|
||||
n2n = {}
|
||||
circuit_a.nets_by_name(a).each { |n| name = cs ? n.name.upcase : n.name; n2n[name] ||= [ nil, nil ]; n2n[name][0] = n }
|
||||
circuit_b.nets_by_name(a).each { |n| name = cs ? n.name.upcase : n.name; n2n[name] ||= [ nil, nil ]; n2n[name][1] = n }
|
||||
|
||||
nets = []
|
||||
n2n.keys.sort.each do |n|
|
||||
nets << n2n[n]
|
||||
end
|
||||
|
||||
else
|
||||
net_b = b
|
||||
|
||||
if a.is_a?(String)
|
||||
net_a = circuit_a.net_by_name(a) || raise("Not a valid net name in extracted netlist in 'same_nets': #{a} (for circuit #{circuit_a})")
|
||||
else
|
||||
net_a = a
|
||||
end
|
||||
|
||||
if b.is_a?(String)
|
||||
net_b = circuit_b.net_by_name(b) || raise("Not a valid net name in extracted netlist in 'same_nets': #{b} (for circuit #{circuit_b})")
|
||||
else
|
||||
net_b = b
|
||||
end
|
||||
|
||||
nets = []
|
||||
if net_a && net_b
|
||||
nets << [ net_a, net_b ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if net_a && net_b
|
||||
comparer.same_nets(net_a, net_b)
|
||||
nets.each do |net_a, net_b|
|
||||
comparer.same_nets(circuit_a, circuit_b, net_a, net_b, force)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -881,6 +881,7 @@ xref(
|
|||
net(7 12 match)
|
||||
net(8 13 match)
|
||||
net(9 14 match)
|
||||
net(14 4 match)
|
||||
net(11 3 match)
|
||||
net(13 5 match)
|
||||
net(12 2 match)
|
||||
|
|
|
|||
|
|
@ -881,6 +881,7 @@ xref(
|
|||
net(7 12 match)
|
||||
net(8 13 match)
|
||||
net(9 14 match)
|
||||
net(14 4 match)
|
||||
net(11 3 match)
|
||||
net(13 5 match)
|
||||
net(12 2 match)
|
||||
|
|
|
|||
|
|
@ -63,6 +63,13 @@ class DBNetlist_TestClass < TestBase
|
|||
assert_equal(nl.circuit_by_cell_index(17).inspect, "nil")
|
||||
assert_equal(nl.circuit_by_name("DOESNOTEXIST").inspect, "nil")
|
||||
|
||||
assert_equal(nl.is_case_sensitive?, true)
|
||||
assert_equal(nl.circuit_by_name("xyz").inspect, "nil")
|
||||
nl.case_sensitive = false
|
||||
assert_equal(nl.is_case_sensitive?, false)
|
||||
assert_equal(nl.circuit_by_name("xyz").name, "XYZ")
|
||||
nl.case_sensitive = true
|
||||
|
||||
cc = RBA::Circuit::new
|
||||
assert_equal(cc.dont_purge, false)
|
||||
cc.dont_purge = true
|
||||
|
|
@ -103,6 +110,11 @@ class DBNetlist_TestClass < TestBase
|
|||
assert_equal(names, [ c.name, cc.name ])
|
||||
|
||||
assert_equal(nl.circuits_by_name("X*").collect { |x| x.name }, [ "XYZ" ])
|
||||
assert_equal(nl.circuits_by_name("x*").collect { |x| x.name }, [])
|
||||
nl.case_sensitive = false
|
||||
assert_equal(nl.circuits_by_name("X*").collect { |x| x.name }, [ "XYZ" ])
|
||||
assert_equal(nl.circuits_by_name("x*").collect { |x| x.name }, [ "XYZ" ])
|
||||
nl.case_sensitive = true
|
||||
assert_equal(nl.circuits_by_name("???").collect { |x| x.name }, [ "XYZ", "UVW" ])
|
||||
assert_equal(nl.circuits_by_name("*").collect { |x| x.name }, [ "XYZ", "UVW" ])
|
||||
assert_equal(nl.circuits_by_name("P*").collect { |x| x.name }, [])
|
||||
|
|
@ -702,6 +714,11 @@ class DBNetlist_TestClass < TestBase
|
|||
assert_equal(c.net_by_name("DOESNOTEXIST").inspect, "nil")
|
||||
assert_equal(c.nets_by_name("DOESNOTEXIST").collect(&:name), [])
|
||||
|
||||
assert_equal(c.net_by_name("net1").inspect, "nil")
|
||||
nl.case_sensitive = false
|
||||
assert_equal(c.net_by_name("net1").name, "NET1")
|
||||
nl.case_sensitive = true
|
||||
|
||||
net2 = c.create_net
|
||||
net2.name = "NET2"
|
||||
|
||||
|
|
@ -709,6 +726,11 @@ class DBNetlist_TestClass < TestBase
|
|||
c.each_net { |n| names << n.name }
|
||||
assert_equal(names, [ "NET1", "NET2" ])
|
||||
assert_equal(c.nets_by_name("NET*").collect(&:name), ["NET1", "NET2"])
|
||||
assert_equal(c.nets_by_name("net*").collect(&:name), [])
|
||||
nl.case_sensitive = false
|
||||
assert_equal(c.nets_by_name("NET*").collect(&:name), ["NET1", "NET2"])
|
||||
assert_equal(c.nets_by_name("net*").collect(&:name), ["NET1", "NET2"])
|
||||
nl.case_sensitive = true
|
||||
|
||||
assert_equal(net1.pin_count, 0)
|
||||
c.connect_pin(pina1, net1)
|
||||
|
|
|
|||
|
|
@ -333,6 +333,8 @@ END
|
|||
|
||||
assert_equal(logger.text(), <<"END")
|
||||
begin_circuit INV INV
|
||||
match_nets VDD VDD
|
||||
match_nets VSS VSS
|
||||
match_nets OUT OUT
|
||||
match_nets IN IN
|
||||
match_pins $0 $1
|
||||
|
|
@ -459,6 +461,8 @@ END
|
|||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets VDD VDD
|
||||
match_nets VSS VSS
|
||||
match_nets OUT OUT
|
||||
match_nets INT $10
|
||||
net_mismatch IN IN
|
||||
|
|
@ -487,6 +491,8 @@ END
|
|||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets VDD VDD
|
||||
match_nets VSS VSS
|
||||
match_nets OUT OUT
|
||||
match_nets IN IN
|
||||
match_ambiguous_nets INT $10
|
||||
|
|
@ -515,6 +521,8 @@ END
|
|||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets VDD VDD
|
||||
match_nets VSS VSS
|
||||
match_nets OUT OUT
|
||||
match_nets INT $10
|
||||
net_mismatch IN IN
|
||||
|
|
@ -545,6 +553,8 @@ END
|
|||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets VDD VDD
|
||||
match_nets VSS VSS
|
||||
match_nets OUT OUT
|
||||
match_nets IN IN
|
||||
match_ambiguous_nets INT $10
|
||||
|
|
@ -574,6 +584,8 @@ END
|
|||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets VDD VDD
|
||||
match_nets VSS VSS
|
||||
match_nets OUT OUT
|
||||
match_nets IN IN
|
||||
match_ambiguous_nets INT $10
|
||||
|
|
@ -636,17 +648,20 @@ END
|
|||
# NOTE: adding this power hint makes the device class error harder to detect
|
||||
ca = nl1.circuit_by_name("BUF")
|
||||
cb = nl2.circuit_by_name("BUF")
|
||||
comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD"))
|
||||
comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS"))
|
||||
comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD"), false)
|
||||
comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS"), false)
|
||||
comp.same_nets(ca.net_by_name("OUT"), cb.net_by_name("OUT"), false)
|
||||
|
||||
good = comp.compare(nl1, nl2)
|
||||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets VDD VDD
|
||||
match_nets VSS VSS
|
||||
match_nets OUT OUT
|
||||
match_nets INT $10
|
||||
match_nets IN IN
|
||||
net_mismatch INT2 $11
|
||||
net_mismatch OUT OUT
|
||||
match_pins $0 $1
|
||||
match_pins $1 $3
|
||||
match_pins $2 $0
|
||||
|
|
@ -666,6 +681,157 @@ END
|
|||
|
||||
end
|
||||
|
||||
def test_6b
|
||||
|
||||
nls1 = <<"END"
|
||||
circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS);
|
||||
device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $3 (S=VDD,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $4 (S=VSS,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOSB $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOSB $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
end;
|
||||
END
|
||||
|
||||
nls2 = <<"END"
|
||||
circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT);
|
||||
device PMOS $1 (S=VDD,G=IN,D=$10) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $2 (S=VDD,G=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $5 (S=$10,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $7 (S=$11,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOSB $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
end;
|
||||
END
|
||||
|
||||
nl1 = RBA::Netlist::new
|
||||
nl2 = RBA::Netlist::new
|
||||
prep_nl(nl1, nls1)
|
||||
prep_nl(nl2, nls2)
|
||||
|
||||
logger = NetlistCompareTestLogger::new
|
||||
comp = RBA::NetlistComparer::new(logger)
|
||||
|
||||
# NOTE: adding this power hint makes the device class error harder to detect
|
||||
ca = nl1.circuit_by_name("BUF")
|
||||
cb = nl2.circuit_by_name("BUF")
|
||||
comp.same_nets(ca.net_by_name("VDD"), cb.net_by_name("VDD"), true)
|
||||
comp.same_nets(ca.net_by_name("VSS"), cb.net_by_name("VSS"), true)
|
||||
comp.same_nets(ca.net_by_name("OUT"), cb.net_by_name("OUT"), true)
|
||||
|
||||
good = comp.compare(nl1, nl2)
|
||||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
net_mismatch VDD VDD
|
||||
match_nets VSS VSS
|
||||
net_mismatch OUT OUT
|
||||
match_nets INT $10
|
||||
match_nets IN IN
|
||||
net_mismatch INT2 $11
|
||||
match_pins $0 $1
|
||||
match_pins $1 $3
|
||||
match_pins $2 $0
|
||||
match_pins $3 $2
|
||||
match_devices $1 $1
|
||||
match_devices $3 $2
|
||||
match_devices $5 $3
|
||||
match_devices_with_different_device_classes $7 $4
|
||||
match_devices $2 $5
|
||||
match_devices $4 $6
|
||||
match_devices $6 $7
|
||||
match_devices $8 $8
|
||||
end_circuit BUF BUF NOMATCH
|
||||
END
|
||||
|
||||
assert_equal(good, false)
|
||||
|
||||
end
|
||||
|
||||
def test_6c
|
||||
|
||||
nls1 = <<"END"
|
||||
circuit BUF ($1=IN,$2=OUT,$3=VDD,$4=VSS);
|
||||
device PMOS $1 (S=VDD,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $2 (S=VSS,G=IN,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $3 (S=VDD,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $4 (S=VSS,G=INT,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $5 (S=VDD,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $6 (S=VSS,G=IN,D=INT2) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOSB $7 (S=VDD,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOSB $8 (S=VSS,G=INT2,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
end;
|
||||
END
|
||||
|
||||
nls2 = <<"END"
|
||||
circuit BUF ($1=VDD,$2=IN,$3=VSS,$4=OUT);
|
||||
device PMOS $1 (S=VDD,G=IN,D=$10) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $2 (S=VDD,G=$10,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $3 (S=VDD,G=IN,D=$11) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device PMOS $4 (S=VDD,G=$11,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $5 (S=$10,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $6 (S=OUT,G=$10,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOS $7 (S=$11,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
device NMOSB $8 (S=OUT,G=$11,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
|
||||
end;
|
||||
END
|
||||
|
||||
nl1 = RBA::Netlist::new
|
||||
nl2 = RBA::Netlist::new
|
||||
prep_nl(nl1, nls1)
|
||||
prep_nl(nl2, nls2)
|
||||
|
||||
logger = NetlistCompareTestLogger::new
|
||||
comp = RBA::NetlistComparer::new(logger)
|
||||
|
||||
# NOTE: adding this power hint makes the device class error harder to detect
|
||||
ca = nl1.circuit_by_name("BUF")
|
||||
cb = nl2.circuit_by_name("BUF")
|
||||
comp.same_nets(ca, cb, ca.net_by_name("VDD"), cb.net_by_name("VDD"), true)
|
||||
comp.same_nets(ca, cb, ca.net_by_name("VSS"), nil, false)
|
||||
comp.same_nets(ca, cb, ca.net_by_name("OUT"), nil, true)
|
||||
|
||||
good = comp.compare(nl1, nl2)
|
||||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
net_mismatch VDD VDD
|
||||
match_nets VSS (null)
|
||||
net_mismatch OUT (null)
|
||||
match_nets INT $10
|
||||
match_nets IN IN
|
||||
net_mismatch INT2 (null)
|
||||
net_mismatch (null) VSS
|
||||
net_mismatch (null) OUT
|
||||
net_mismatch (null) $11
|
||||
match_pins $0 $1
|
||||
match_pins $2 $0
|
||||
match_pins $1 (null)
|
||||
match_pins $3 (null)
|
||||
match_pins (null) $2
|
||||
match_pins (null) $3
|
||||
match_devices $1 $1
|
||||
device_mismatch $3 $2
|
||||
device_mismatch $5 $3
|
||||
device_mismatch (null) $4
|
||||
device_mismatch $6 $5
|
||||
device_mismatch $4 $6
|
||||
device_mismatch $2 $7
|
||||
device_mismatch (null) $8
|
||||
device_mismatch $7 (null)
|
||||
device_mismatch $8 (null)
|
||||
end_circuit BUF BUF NOMATCH
|
||||
END
|
||||
|
||||
assert_equal(good, false)
|
||||
|
||||
end
|
||||
|
||||
def test_7
|
||||
|
||||
nls1 = <<"END"
|
||||
|
|
@ -713,6 +879,8 @@ END
|
|||
|
||||
assert_equal(logger.text, <<"END")
|
||||
begin_circuit BUF BUF
|
||||
match_nets VDD VDD
|
||||
match_nets VSS VSS
|
||||
net_mismatch INT $10
|
||||
match_nets IN IN
|
||||
net_mismatch INT2 $11
|
||||
|
|
|
|||
Loading…
Reference in New Issue