mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-04 00:39:53 +02:00
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:
@@ -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 ();
|
||||
|
||||
Reference in New Issue
Block a user