mirror of https://github.com/KLayout/klayout.git
WIP: better matching of subcircuits - attempt to map them even if not identical. This hopefully makes solving subcircuit connection problems easier.
This commit is contained in:
parent
3310d34cf3
commit
910a36b83d
|
|
@ -1942,6 +1942,89 @@ compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetGraph &g,
|
|||
return k;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
inline double size_dist (size_t a, size_t b)
|
||||
{
|
||||
double d = a - b;
|
||||
return d * d;
|
||||
}
|
||||
|
||||
struct KeyDistance
|
||||
{
|
||||
typedef std::pair<std::vector<std::pair<size_t, size_t> >, const db::SubCircuit *> value_type;
|
||||
|
||||
double operator() (const value_type &a, const value_type &b) const
|
||||
{
|
||||
tl_assert (a.first.size () == b.first.size ());
|
||||
double d = 0.0;
|
||||
for (std::vector<std::pair<size_t, size_t> >::const_iterator i = a.first.begin (), j = b.first.begin (); i != a.first.end (); ++i, ++j) {
|
||||
d += size_dist (i->first, j->first) + size_dist (i->second, j->second);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
};
|
||||
|
||||
struct KeySize
|
||||
{
|
||||
typedef std::pair<std::vector<std::pair<size_t, size_t> >, const db::SubCircuit *> value_type;
|
||||
|
||||
bool operator() (const value_type &a, const value_type &b) const
|
||||
{
|
||||
return (a.first.size () < b.first.size ());
|
||||
}
|
||||
};
|
||||
|
||||
template <class Iter, class Distance>
|
||||
void align (Iter i1, Iter i2, Iter j1, Iter j2, Distance distance)
|
||||
{
|
||||
// TODO: this can probably be done more efficiently
|
||||
|
||||
std::vector<Iter> vi, vj;
|
||||
vi.reserve (std::max (i2 - i1, j2 - j1));
|
||||
vj.reserve (std::max (i2 - i1, j2 - j1));
|
||||
|
||||
for (Iter i = i1; i != i2; ++i) {
|
||||
vi.push_back (i);
|
||||
}
|
||||
|
||||
for (Iter j = j1; j != j2; ++j) {
|
||||
vj.push_back (j);
|
||||
}
|
||||
|
||||
while (vi.size () < vj.size ()) {
|
||||
vi.push_back (Iter ());
|
||||
}
|
||||
|
||||
while (vj.size () < vi.size ()) {
|
||||
vj.push_back (Iter ());
|
||||
}
|
||||
|
||||
if (vi.size () <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Caution: this is an O(2) algorithm ...
|
||||
bool any_swapped = true;
|
||||
for (size_t n = 0; n < vi.size () - 1 && any_swapped; ++n) {
|
||||
|
||||
any_swapped = false;
|
||||
|
||||
for (size_t m = n + 1; m < vj.size () - 1; ++m) {
|
||||
if (vi [n] == Iter () || vi [m] == Iter () || vj [n] == Iter () || vj [m] == Iter ()) {
|
||||
continue;
|
||||
} else if (distance (*vi [n], *vj [m]) + distance (*vi [m], *vj [n]) < distance (*vi [n], *vj [n]) + distance (*vi [m], *vj [m])) {
|
||||
// this will reduce the overall distance:
|
||||
std::swap (vj [n], vj [m]);
|
||||
any_swapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
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, 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
|
||||
{
|
||||
|
|
@ -2325,6 +2408,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
|
||||
}
|
||||
|
||||
typedef std::vector<std::pair<std::vector<std::pair<size_t, size_t> >, const db::SubCircuit *> > unmatched_list;
|
||||
unmatched_list unmatched_a, unmatched_b;
|
||||
|
||||
for (db::Circuit::const_subcircuit_iterator sc = c2->begin_subcircuits (); sc != c2->end_subcircuits (); ++sc) {
|
||||
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper);
|
||||
|
|
@ -2345,7 +2431,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
if (! mapped || scm == subcircuit_map.end ()) {
|
||||
|
||||
if (mp_logger) {
|
||||
mp_logger->subcircuit_mismatch (0, sc.operator-> ());
|
||||
unmatched_b.push_back (std::make_pair (k, sc.operator-> ()));
|
||||
}
|
||||
good = false;
|
||||
|
||||
|
|
@ -2373,11 +2459,81 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
|
||||
for (std::multimap<std::vector<std::pair<size_t, size_t> >, std::pair<const db::SubCircuit *, size_t> >::const_iterator scm = subcircuit_map.begin (); scm != subcircuit_map.end (); ++scm) {
|
||||
if (mp_logger) {
|
||||
mp_logger->subcircuit_mismatch (scm->second.first, 0);
|
||||
unmatched_a.push_back (std::make_pair (scm->first, scm->second.first));
|
||||
}
|
||||
good = false;
|
||||
}
|
||||
|
||||
// try to do some pairing between the mismatching subcircuits - even though we will still report them as
|
||||
// mismatches it will give some better hint about what needs to be fixed
|
||||
|
||||
if (mp_logger) {
|
||||
|
||||
size_t max_analysis_set = 1000;
|
||||
if (unmatched_a.size () + unmatched_b.size () > max_analysis_set) {
|
||||
|
||||
// don't try too much analysis - this may be a waste of time
|
||||
for (unmatched_list::const_iterator i = unmatched_a.begin (); i != unmatched_a.end (); ++i) {
|
||||
mp_logger->subcircuit_mismatch (i->second, 0);
|
||||
}
|
||||
for (unmatched_list::const_iterator i = unmatched_b.begin (); i != unmatched_b.end (); ++i) {
|
||||
mp_logger->subcircuit_mismatch (0, i->second);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
std::sort (unmatched_a.begin (), unmatched_a.end (), KeySize ());
|
||||
std::sort (unmatched_b.begin (), unmatched_b.end (), KeySize ());
|
||||
|
||||
for (unmatched_list::iterator i = unmatched_a.begin (), j = unmatched_b.begin (); i != unmatched_a.end () || j != unmatched_b.end (); ) {
|
||||
|
||||
while (j != unmatched_b.end () && (i == unmatched_a.end () || j->first.size () < i->first.size ())) {
|
||||
mp_logger->subcircuit_mismatch (0, j->second);
|
||||
++j;
|
||||
}
|
||||
|
||||
while (i != unmatched_a.end () && (j == unmatched_b.end () || i->first.size () < j->first.size ())) {
|
||||
mp_logger->subcircuit_mismatch (i->second, 0);
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i == unmatched_a.end () && j == unmatched_b.end ()) {
|
||||
break;
|
||||
}
|
||||
|
||||
unmatched_list::iterator ii = i, jj = j;
|
||||
++i, ++j;
|
||||
size_t n = ii->first.size ();
|
||||
tl_assert (n == jj->first.size ());
|
||||
|
||||
while (i != unmatched_a.end () && i->first.size () == n) {
|
||||
++i;
|
||||
}
|
||||
|
||||
while (j != unmatched_b.end () && j->first.size () == n) {
|
||||
++j;
|
||||
}
|
||||
|
||||
align (ii, i, jj, j, KeyDistance ());
|
||||
|
||||
for ( ; ii != i && jj != j; ++ii, ++jj) {
|
||||
mp_logger->subcircuit_mismatch (ii->second, jj->second);
|
||||
}
|
||||
|
||||
for ( ; jj != j; ++jj) {
|
||||
mp_logger->subcircuit_mismatch (0, jj->second);
|
||||
}
|
||||
|
||||
for ( ; ii != i; ++ii) {
|
||||
mp_logger->subcircuit_mismatch (ii->second, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return good;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -830,6 +830,11 @@ std::string devices_string (const std::pair<const db::Device *, const db::Device
|
|||
|
||||
static QString build_url (void *id, const std::string &tag, const std::string &title)
|
||||
{
|
||||
if (id == 0) {
|
||||
// no link
|
||||
return tl::to_qstring (tl::escaped_to_html (title));
|
||||
}
|
||||
|
||||
std::string s = std::string ("<a href='int:");
|
||||
s += tag;
|
||||
s += "?id=";
|
||||
|
|
@ -849,7 +854,15 @@ NetlistBrowserModel::make_link_to (const std::pair<const db::Net *, const db::Ne
|
|||
if ((! nets.first || column == m_second_column) && (! nets.second || column == m_first_column)) {
|
||||
return QString ();
|
||||
} else {
|
||||
void *id = make_id_circuit_net (mp_indexer->circuit_index (mp_indexer->parent_of (nets)), mp_indexer->net_index (nets));
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (nets);
|
||||
void *id = 0;
|
||||
// NOTE: the nets may not be a valid net pair. In this case, circuits is (0, 0) and
|
||||
// no link is generated
|
||||
if (circuits.first || circuits.second) {
|
||||
id = make_id_circuit_net (mp_indexer->circuit_index (circuits), mp_indexer->net_index (nets));
|
||||
}
|
||||
|
||||
if (mp_indexer->is_single () || column == m_first_column) {
|
||||
return build_url (id, "net", str_from_expanded_name (nets.first));
|
||||
} else if (column == m_second_column) {
|
||||
|
|
@ -857,6 +870,7 @@ NetlistBrowserModel::make_link_to (const std::pair<const db::Net *, const db::Ne
|
|||
} else {
|
||||
return build_url (id, "net", str_from_expanded_names (nets, mp_indexer->is_single ()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -866,7 +880,15 @@ NetlistBrowserModel::make_link_to (const std::pair<const db::Device *, const db:
|
|||
if ((! devices.first || column == m_second_column) && (! devices.second || column == m_first_column)) {
|
||||
return QString ();
|
||||
} else {
|
||||
void *id = make_id_circuit_device (mp_indexer->circuit_index (mp_indexer->parent_of (devices)), mp_indexer->device_index (devices));
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (devices);
|
||||
void *id = 0;
|
||||
// NOTE: the devices may not be a valid device pair. In this case, circuits is (0, 0) and
|
||||
// no link is generated
|
||||
if (circuits.first || circuits.second) {
|
||||
id = make_id_circuit_device (mp_indexer->circuit_index (circuits), mp_indexer->device_index (devices));
|
||||
}
|
||||
|
||||
if (mp_indexer->is_single () || column == m_first_column) {
|
||||
return build_url (id, "device", str_from_expanded_name (devices.first));
|
||||
} else if (column == m_second_column) {
|
||||
|
|
@ -874,6 +896,7 @@ NetlistBrowserModel::make_link_to (const std::pair<const db::Device *, const db:
|
|||
} else {
|
||||
return build_url (id, "device", str_from_expanded_names (devices, mp_indexer->is_single ()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -917,7 +940,15 @@ NetlistBrowserModel::make_link_to (const std::pair<const db::SubCircuit *, const
|
|||
if ((! subcircuits.first || column == m_second_column) && (! subcircuits.second || column == m_first_column)) {
|
||||
return QString ();
|
||||
} else {
|
||||
void *id = make_id_circuit_subcircuit (mp_indexer->circuit_index (mp_indexer->parent_of (subcircuits)), mp_indexer->subcircuit_index (subcircuits));
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuits = mp_indexer->parent_of (subcircuits);
|
||||
void *id = 0;
|
||||
// NOTE: the subcircuits may not be a valid subcircuit pair. In this case, circuits is (0, 0) and
|
||||
// no link is generated
|
||||
if (circuits.first || circuits.second) {
|
||||
id = make_id_circuit_subcircuit (mp_indexer->circuit_index (circuits), mp_indexer->subcircuit_index (subcircuits));
|
||||
}
|
||||
|
||||
if (mp_indexer->is_single () || column == m_first_column) {
|
||||
return build_url (id, "subcircuit", str_from_expanded_name (subcircuits.first));
|
||||
} else if (column == m_second_column) {
|
||||
|
|
@ -925,6 +956,7 @@ NetlistBrowserModel::make_link_to (const std::pair<const db::SubCircuit *, const
|
|||
} else {
|
||||
return build_url (id, "subcircuit", str_from_expanded_names (subcircuits, mp_indexer->is_single ()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1313,6 +1345,13 @@ static std::string search_string_from_names (const std::pair<const Obj *, const
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
NetlistBrowserModel::is_valid_net_pair (const std::pair<const db::Net *, const db::Net *> &nets) const
|
||||
{
|
||||
IndexedNetlistModel::circuit_pair net_parent = mp_indexer->parent_of (nets);
|
||||
return (net_parent.first != 0 || net_parent.second != 0);
|
||||
}
|
||||
|
||||
db::NetlistCrossReference::Status
|
||||
NetlistBrowserModel::status (const QModelIndex &index) const
|
||||
{
|
||||
|
|
@ -1347,7 +1386,17 @@ NetlistBrowserModel::status (const QModelIndex &index) const
|
|||
IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits);
|
||||
IndexedNetlistModel::pin_pair pins = pins_from_id (id);
|
||||
|
||||
return mp_indexer->pin_from_index (circuit_refs, mp_indexer->pin_index (pins, circuit_refs)).second;
|
||||
db::NetlistCrossReference::Status status = mp_indexer->pin_from_index (circuit_refs, mp_indexer->pin_index (pins, circuit_refs)).second;
|
||||
if (status == db::NetlistCrossReference::Mismatch || status == db::NetlistCrossReference::NoMatch) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Another test here is to check whether the pins may be attached to an invalid net pair
|
||||
if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, pins))) {
|
||||
// This indicates a wrong connection: the nets are associated in a way which is a not
|
||||
// corresponding to a mapped net pair. Report Mismatch here.
|
||||
return db::NetlistCrossReference::Mismatch;
|
||||
}
|
||||
|
||||
} else if (is_id_circuit_net (id)) {
|
||||
|
||||
|
|
@ -1371,11 +1420,31 @@ NetlistBrowserModel::status (const QModelIndex &index) const
|
|||
|
||||
return mp_indexer->subcircuit_from_index (circuits, mp_indexer->subcircuit_index (subcircuits)).second;
|
||||
|
||||
} else if (is_id_circuit_net_subcircuit_pin_others (id)) {
|
||||
|
||||
IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id);
|
||||
IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs);
|
||||
size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id);
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits);
|
||||
IndexedNetlistModel::pin_pair pins = mp_indexer->pin_from_index (circuit_refs, other_index).first;
|
||||
|
||||
if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, pins))) {
|
||||
// This indicates a wrong connection: the nets are associated in a way which is a not
|
||||
// corresponding to a mapped net pair. Report Mismatch here.
|
||||
return db::NetlistCrossReference::Mismatch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return db::NetlistCrossReference::None;
|
||||
}
|
||||
|
||||
static std::string rewire_subcircuit_pins_status_hint ()
|
||||
{
|
||||
return tl::to_string (tr ("The nets attached to the pins are not equivalent.\nRewire the circuit or use 'equivalent_pins' in the LVS script to fix this issue."));
|
||||
}
|
||||
|
||||
QVariant
|
||||
NetlistBrowserModel::tooltip (const QModelIndex &index) const
|
||||
{
|
||||
|
|
@ -1412,6 +1481,14 @@ NetlistBrowserModel::tooltip (const QModelIndex &index) const
|
|||
IndexedNetlistModel::pin_pair pins = pins_from_id (id);
|
||||
|
||||
hint = mp_indexer->pin_status_hint (circuit_refs, mp_indexer->pin_index (pins, circuit_refs));
|
||||
if (hint.empty ()) {
|
||||
|
||||
// Another test here is to check whether the pins may be attached to an invalid net pair
|
||||
if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, pins))) {
|
||||
hint = rewire_subcircuit_pins_status_hint ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (is_id_circuit_net (id)) {
|
||||
|
||||
|
|
@ -1435,6 +1512,21 @@ NetlistBrowserModel::tooltip (const QModelIndex &index) const
|
|||
|
||||
hint = mp_indexer->subcircuit_status_hint (circuits, mp_indexer->subcircuit_index (subcircuits));
|
||||
|
||||
} else if (is_id_circuit_net_subcircuit_pin_others (id)) {
|
||||
|
||||
IndexedNetlistModel::net_subcircuit_pin_pair pinrefs = net_subcircuit_pinrefs_from_id (id);
|
||||
IndexedNetlistModel::subcircuit_pair subcircuits = subcircuits_from_pinrefs (pinrefs);
|
||||
size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id);
|
||||
|
||||
IndexedNetlistModel::circuit_pair circuit_refs = circuit_refs_from_subcircuits (subcircuits);
|
||||
IndexedNetlistModel::pin_pair pins = mp_indexer->pin_from_index (circuit_refs, other_index).first;
|
||||
|
||||
if (! is_valid_net_pair (nets_from_subcircuit_pins (subcircuits, pins))) {
|
||||
// This indicates a wrong connection: the nets are associated in a way which is a not
|
||||
// corresponding to a mapped net pair. Report Mismatch here.
|
||||
hint = rewire_subcircuit_pins_status_hint ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (hint.empty ()) {
|
||||
|
|
@ -1773,7 +1865,7 @@ NetlistBrowserModel::icon (const QModelIndex &index) const
|
|||
|
||||
} else if (is_id_circuit_subcircuit (id)) {
|
||||
return icon_for_circuit ();
|
||||
} else if (is_id_circuit_subcircuit_pin (id) || is_id_circuit_net_pin (id) || is_id_circuit_net_subcircuit_pin_others (id)) {
|
||||
} else if (is_id_circuit_subcircuit_pin (id) || is_id_circuit_net_pin (id)) {
|
||||
return icon_for_pin ();
|
||||
} else if (is_id_circuit_net_subcircuit_pin (id)) {
|
||||
return icon_for_circuit ();
|
||||
|
|
|
|||
|
|
@ -219,6 +219,8 @@ private:
|
|||
return std::pair<const db::Netlist *, const db::Netlist *> (mp_l2ndb->netlist (), (const db::Netlist *)0);
|
||||
}
|
||||
|
||||
bool is_valid_net_pair (const std::pair<const db::Net *, const db::Net *> &net) const;
|
||||
|
||||
QIcon icon_for_nets (const std::pair<const db::Net *, const db::Net *> &net) const;
|
||||
QIcon icon_for_connection (const std::pair<const db::Net *, const db::Net *> &net) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -238,10 +238,14 @@ static IndexedNetlistModel::circuit_pair get_parent_of (const Pair &pair, const
|
|||
}
|
||||
|
||||
i = cache.find (pair);
|
||||
tl_assert (i != cache.end ());
|
||||
|
||||
}
|
||||
return i->second;
|
||||
|
||||
if (i == cache.end ()) {
|
||||
return IndexedNetlistModel::circuit_pair ((const db::Circuit *) 0, (const db::Circuit *) 0);
|
||||
} else {
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
|
||||
IndexedNetlistModel::circuit_pair NetlistCrossReferenceModel::parent_of (const IndexedNetlistModel::net_pair &net_pair) const
|
||||
|
|
@ -436,19 +440,19 @@ std::string NetlistCrossReferenceModel::circuit_pair_status_hint (const std::pai
|
|||
if (cps.second == db::NetlistCrossReference::Mismatch || cps.second == db::NetlistCrossReference::NoMatch) {
|
||||
if (! cps.first.first || ! cps.first.second) {
|
||||
return tl::to_string (tr ("No matching circuit found in the other netlist.\n"
|
||||
"By default, circuits are identified by their name. "
|
||||
"By default, circuits are identified by their name.\n"
|
||||
"A missing circuit probably means there is no circuit in the other netlist with this name.\n"
|
||||
"If circuits with different names need to be associated, use 'same_circuits' in the "
|
||||
"If circuits with different names need to be associated, use 'same_circuits' in the\n"
|
||||
"LVS script to establish such an association."));
|
||||
} else {
|
||||
return tl::to_string (tr ("Circuits could be paired, but there is a mismatch inside.\n"
|
||||
"Browse the circuit's component list to identify the mismatching elements."));
|
||||
}
|
||||
} else if (cps.second == db::NetlistCrossReference::Skipped) {
|
||||
return tl::to_string (tr ("Circuits can only be matched if their child circuits have a known counterpart and a pin-to-pin "
|
||||
"correspondence could be established for each child circuit.\n"
|
||||
return tl::to_string (tr ("Circuits can only be matched if their child circuits have a known counterpart and a\n"
|
||||
"pin-to-pin correspondence could be established for each child circuit.\n"
|
||||
"This is not the case here. Browse the child circuits to identify the blockers.\n"
|
||||
"Potential blockers are subcircuits without a corresponding other circuit or circuits "
|
||||
"Potential blockers are subcircuits without a corresponding other circuit or circuits\n"
|
||||
"where some pins could not be mapped to pins from the corresponding other circuit."));
|
||||
}
|
||||
return std::string ();
|
||||
|
|
@ -469,15 +473,15 @@ std::string NetlistCrossReferenceModel::child_circuit_status_hint (const circuit
|
|||
std::pair<IndexedNetlistModel::circuit_pair, NetlistCrossReferenceModel::Status> cps = child_circuit_from_index (circuits, index);
|
||||
if (cps.second == db::NetlistCrossReference::Mismatch || cps.second == db::NetlistCrossReference::NoMatch) {
|
||||
if (!cps.first.first || !cps.first.second) {
|
||||
return tl::to_string (tr ("No matching subcircuit was found in the other netlist - this is likely because pin assignment "
|
||||
"could not be derived from the nets connected to the pins.\n"
|
||||
"Check, if the pins are attached properly. If pins need to be swappable, consider using 'equivalent_pins' "
|
||||
"in the LVS script."));
|
||||
return tl::to_string (tr ("No matching subcircuit was found in the other netlist - this is likely because pin\n"
|
||||
"assignment could not be derived from the nets connected to the pins.\n"
|
||||
"Check, if the pins are attached properly. If pins need to be swappable, consider using\n"
|
||||
"'equivalent_pins' in the LVS script."));
|
||||
} else {
|
||||
return tl::to_string (tr ("Two different subcircuits fit here in the same way, but they are not "
|
||||
return tl::to_string (tr ("Two different subcircuits fit here in the same way, but they are not\n"
|
||||
"originating from equivalent circuits.\n"
|
||||
"If the circuits behind the subcircuits are identical, using 'same_circuits' in the LVS script "
|
||||
"helps to associate them."));
|
||||
"If the circuits behind the subcircuits are identical, using 'same_circuits'\n"
|
||||
"in the LVS script will associate them."));
|
||||
}
|
||||
}
|
||||
return std::string ();
|
||||
|
|
@ -487,9 +491,9 @@ std::string NetlistCrossReferenceModel::net_status_hint (const circuit_pair &cir
|
|||
{
|
||||
std::pair<IndexedNetlistModel::net_pair, NetlistCrossReferenceModel::Status> cps = net_from_index (circuits, index);
|
||||
if (cps.second == db::NetlistCrossReference::Mismatch || cps.second == db::NetlistCrossReference::NoMatch) {
|
||||
return tl::to_string (tr ("Nets don't match. Nets match, if connected subcircuit pins and device terminals match to a counterpart in "
|
||||
"the other netlist (component-wise and pin/terminal-wise).\n"
|
||||
"If there already is a net candidate from the other netlist, scan the net members for "
|
||||
return tl::to_string (tr ("Nets don't match. Nets match, if connected subcircuit pins and device terminals match to a\n"
|
||||
"counterpart in the other netlist (component-wise and pin/terminal-wise).\n"
|
||||
"If there already is a net candidate from the other netlist, scan the net members for\n"
|
||||
"mismatching items (with errors or warnings) and fix these issues.\n"
|
||||
"Otherwise, look for the corresponding other net.\n"
|
||||
"Net items not found in the reference netlist indicate additional connections.\n"
|
||||
|
|
@ -504,15 +508,15 @@ std::string NetlistCrossReferenceModel::device_status_hint (const circuit_pair &
|
|||
if (cps.second == db::NetlistCrossReference::Mismatch || cps.second == db::NetlistCrossReference::NoMatch) {
|
||||
if (!cps.first.first || !cps.first.second) {
|
||||
return tl::to_string (tr ("No matching device was found in the other netlist.\n"
|
||||
"Devices are identified by the nets they are attached to. Unmatched devices mean that "
|
||||
"Devices are identified by the nets they are attached to. Unmatched devices mean that\n"
|
||||
"at least one terminal net isn't matched with a corresponding net from the other netlist.\n"
|
||||
"Make all terminal nets match and the devices will match too."));
|
||||
}
|
||||
} else if (cps.second == db::NetlistCrossReference::MatchWithWarning) {
|
||||
return tl::to_string (tr ("Topologically matching devices are found here but either the parameters or the "
|
||||
return tl::to_string (tr ("Topologically matching devices are found here but either the parameters or the\n"
|
||||
"device classes don't match.\n"
|
||||
"If the device class is different but should be considered the same, "
|
||||
"using 'same_device_class' in the LVS script will solve this issue."));
|
||||
"If the device class is different but should be considered the same, using\n"
|
||||
"'same_device_classed' in the LVS script will solve this issue."));
|
||||
}
|
||||
return std::string ();
|
||||
}
|
||||
|
|
@ -523,8 +527,8 @@ std::string NetlistCrossReferenceModel::pin_status_hint (const circuit_pair &cir
|
|||
if (cps.second == db::NetlistCrossReference::Mismatch || cps.second == db::NetlistCrossReference::NoMatch) {
|
||||
if (!cps.first.first || !cps.first.second) {
|
||||
return tl::to_string (tr ("No matching pin was found in the other netlist.\n"
|
||||
"Pins are identified by the nets they are attached to - pins on equivalent nets are also equivalent.\n"
|
||||
"Making the nets match will make the pins match too."));
|
||||
"Pins are identified by the nets they are attached to - pins on equivalent nets are also\n"
|
||||
"equivalent. Making the nets match will make the pins match too."));
|
||||
}
|
||||
}
|
||||
return std::string ();
|
||||
|
|
@ -535,15 +539,15 @@ std::string NetlistCrossReferenceModel::subcircuit_status_hint (const circuit_pa
|
|||
std::pair<IndexedNetlistModel::subcircuit_pair, NetlistCrossReferenceModel::Status> cps = subcircuit_from_index (circuits, index);
|
||||
if (cps.second == db::NetlistCrossReference::Mismatch || cps.second == db::NetlistCrossReference::NoMatch) {
|
||||
if (!cps.first.first || !cps.first.second) {
|
||||
return tl::to_string (tr ("No matching subcircuit was found in the other netlist - this is likely because pin assignment "
|
||||
return tl::to_string (tr ("No matching subcircuit was found in the other netlist - this is likely because pin assignment\n"
|
||||
"could not be derived from the nets connected to the pins.\n"
|
||||
"Check, if the pins are attached properly. If pins need to be swappable, consider using 'equivalent_pins' "
|
||||
"in the LVS script."));
|
||||
"Check, if the pins are attached properly. If pins need to be swappable, consider using\n"
|
||||
"'equivalent_pins' in the LVS script."));
|
||||
} else {
|
||||
return tl::to_string (tr ("Two different subcircuits fit here in the same way, but they are not "
|
||||
"originating from equivalent circuits.\n"
|
||||
"If the circuits behind the subcircuits are identical, using 'same_circuits' in the LVS script "
|
||||
"helps to associate them."));
|
||||
return tl::to_string (tr ("Two different subcircuits fit here in the same way, but they are not originating from\n"
|
||||
"equivalent circuits.\n"
|
||||
"If the circuits behind the subcircuits are identical, using 'same_circuits' in the LVS script\n"
|
||||
"will associate them."));
|
||||
}
|
||||
}
|
||||
return std::string ();
|
||||
|
|
|
|||
Loading…
Reference in New Issue