From 57f9efa6113f912c7b2189d3ccdf60a6fb0072fc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 22 May 2019 23:47:38 +0200 Subject: [PATCH] WIP: debugged cross-reference model --- src/db/db/dbNetlistCrossReference.cc | 32 ++-- src/db/db/dbNetlistCrossReference.h | 17 +-- .../laybasic/layNetlistCrossReferenceModel.cc | 33 ++++- .../unit_tests/layNetlistBrowserModelTests.cc | 139 +++++++++++++++++- 4 files changed, 185 insertions(+), 36 deletions(-) diff --git a/src/db/db/dbNetlistCrossReference.cc b/src/db/db/dbNetlistCrossReference.cc index 70115c885..471c35950 100644 --- a/src/db/db/dbNetlistCrossReference.cc +++ b/src/db/db/dbNetlistCrossReference.cc @@ -39,12 +39,15 @@ NetlistCrossReference::~NetlistCrossReference () const NetlistCrossReference::PerCircuitData * NetlistCrossReference::per_circuit_data_for (const std::pair &circuits) const { - per_circuit_data_iterator i = m_per_circuit_data.find (circuits); - if (i == m_per_circuit_data.end ()) { - return 0; - } else { - return & i->second; + std::map::const_iterator i = m_data_refs.find (circuits.first); + if (i != m_data_refs.end ()) { + return i->second; } + i = m_data_refs.find (circuits.second); + if (i != m_data_refs.end ()) { + return i->second; + } + return 0; } const db::Net * @@ -77,6 +80,7 @@ NetlistCrossReference::clear () mp_netlist_b.reset (0); m_circuits.clear (); m_per_circuit_data.clear (); + m_data_refs.clear (); m_per_net_data.clear (); m_other_circuit.clear (); m_other_net.clear (); @@ -228,18 +232,17 @@ struct SortNetSubCircuitPins void NetlistCrossReference::gen_end_netlist (const db::Netlist *, const db::Netlist *) { - m_circuits.reserve (m_per_circuit_data.size ()); - for (per_circuit_data_iterator i = begin_per_circuit_data (); i != end_per_circuit_data (); ++i) { - m_circuits.push_back (i->first); - } - std::sort (m_circuits.begin (), m_circuits.end (), CircuitsCompareByName ()); } void NetlistCrossReference::establish_pair (const db::Circuit *a, const db::Circuit *b) { - mp_per_circuit_data = & m_per_circuit_data [std::make_pair (a, b)]; + m_circuits.push_back (std::make_pair (a, b)); + m_per_circuit_data.push_back (PerCircuitData ()); + mp_per_circuit_data = & m_per_circuit_data.back (); + m_data_refs [a] = mp_per_circuit_data; + m_data_refs [b] = mp_per_circuit_data; if (a) { m_other_circuit [a] = b; @@ -423,7 +426,7 @@ NetlistCrossReference::build_terminal_refs (const std::pairsecond)); } - std::sort (data.terminals.begin (), data.terminals.end (), SortNetTerminals ()); + std::stable_sort (data.terminals.begin (), data.terminals.end (), SortNetTerminals ()); } void @@ -454,7 +457,6 @@ NetlistCrossReference::build_pin_refs (const std::pairsecond; // remove the entry so we won't find it again p2r_b.erase (b); - break; } } @@ -467,7 +469,7 @@ NetlistCrossReference::build_pin_refs (const std::pairsecond)); } - std::sort (data.pins.begin (), data.pins.end (), SortNetPins ()); + std::stable_sort (data.pins.begin (), data.pins.end (), SortNetPins ()); } void @@ -520,7 +522,7 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::pairsecond)); } - std::sort (data.subcircuit_pins.begin (), data.subcircuit_pins.end (), SortNetSubCircuitPins ()); + std::stable_sort (data.subcircuit_pins.begin (), data.subcircuit_pins.end (), SortNetSubCircuitPins ()); } void diff --git a/src/db/db/dbNetlistCrossReference.h b/src/db/db/dbNetlistCrossReference.h index 27cfa2978..86f4af52a 100644 --- a/src/db/db/dbNetlistCrossReference.h +++ b/src/db/db/dbNetlistCrossReference.h @@ -237,19 +237,7 @@ public: size_t circuit_count () const { - return m_per_circuit_data.size (); - } - - typedef std::map, PerCircuitData>::const_iterator per_circuit_data_iterator; - - per_circuit_data_iterator begin_per_circuit_data () const - { - return m_per_circuit_data.begin (); - } - - per_circuit_data_iterator end_per_circuit_data () const - { - return m_per_circuit_data.end (); + return m_circuits.size (); } const PerCircuitData *per_circuit_data_for (const std::pair &circuits) const; @@ -282,7 +270,8 @@ public: private: tl::weak_ptr mp_netlist_a, mp_netlist_b; std::vector > m_circuits; - std::map, PerCircuitData> m_per_circuit_data; + std::list m_per_circuit_data; + std::map m_data_refs; mutable std::map, PerNetData> m_per_net_data; std::map m_other_circuit; std::map m_other_net; diff --git a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc index 00c2aa652..b10c9c303 100644 --- a/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc +++ b/src/laybasic/laybasic/layNetlistCrossReferenceModel.cc @@ -115,13 +115,20 @@ static IndexedNetlistModel::circuit_pair get_parent_of (const Pair &pair, const typename std::map::iterator i = cache.find (pair); if (i == cache.end ()) { - for (db::NetlistCrossReference::per_circuit_data_iterator c = cross_ref->begin_per_circuit_data (); c != cross_ref->end_per_circuit_data (); ++c) { + for (db::NetlistCrossReference::circuits_iterator c = cross_ref->begin_circuits (); c != cross_ref->end_circuits (); ++c) { + const db::NetlistCrossReference::PerCircuitData *data = cross_ref->per_circuit_data_for (*c); typedef DataGetter getter_type; typedef typename getter_type::iterator_type iterator_type; - iterator_type b = getter_type ().begin (c->second); - iterator_type e = getter_type ().end (c->second); + iterator_type b = getter_type ().begin (*data); + iterator_type e = getter_type ().end (*data); for (iterator_type j = b; j != e; ++j) { - cache.insert (std::make_pair (j->pair, c->first)); + cache.insert (std::make_pair (j->pair, *c)); + if (j->pair.first) { + cache.insert (std::make_pair (Pair (j->pair.first, 0), *c)); + } + if (j->pair.second) { + cache.insert (std::make_pair (Pair (0, j->pair.second), *c)); + } } } @@ -210,15 +217,22 @@ template static size_t get_index_of (const Pair &pair, Iter begin, Iter end, std::map &cache) { typename std::map::iterator i = cache.find (pair); - if (i != cache.end ()) { + if (i == cache.end ()) { size_t index = 0; for (Iter j = begin; j != end; ++j, ++index) { cache.insert (std::make_pair (j->pair, index)); + if (j->pair.first) { + cache.insert (std::make_pair (Pair (j->pair.first, 0), index)); + } + if (j->pair.second) { + cache.insert (std::make_pair (Pair (0, j->pair.second), index)); + } } i = cache.find (pair); tl_assert (i != cache.end ()); + } return i->second; @@ -228,15 +242,22 @@ static size_t get_index_of (const Pair &pair, Iter begin, Iter end, std::map::iterator i = m_index_of_circuits.find (circuits); - if (i != m_index_of_circuits.end ()) { + if (i == m_index_of_circuits.end ()) { size_t index = 0; for (db::NetlistCrossReference::circuits_iterator j = mp_cross_ref->begin_circuits (); j != mp_cross_ref->end_circuits (); ++j, ++index) { m_index_of_circuits.insert (std::make_pair (*j, index)); + if (j->first) { + m_index_of_circuits.insert (std::make_pair (circuit_pair (j->first, 0), index)); + } + if (j->second) { + m_index_of_circuits.insert (std::make_pair (circuit_pair (0, j->second), index)); + } } i = m_index_of_circuits.find (circuits); tl_assert (i != m_index_of_circuits.end ()); + } return i->second; diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc index d62813e65..d10d1b9d1 100644 --- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc +++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc @@ -243,8 +243,145 @@ TEST (2) QModelIndex inv2Index = model->index (1, 0, QModelIndex ()); + // INV2 circuit node EXPECT_EQ (model->hasChildren (inv2Index), true); EXPECT_EQ (model->rowCount (inv2Index), 14); - // ... + // first of pins in INV2 circuit + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Index), Qt::UserRole).toString ()), "$0|$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Index), Qt::DisplayRole).toString ()), "$0/$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 1, inv2Index), Qt::DisplayRole).toString ()), "$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2Index), Qt::DisplayRole).toString ()), "$0"); + + // INV2, pin 0 node + QModelIndex inv2Pin0Index = model->index (0, 0, inv2Index); + EXPECT_EQ (model->hasChildren (inv2Pin0Index), true); + EXPECT_EQ (model->rowCount (inv2Pin0Index), 1); + + // INV2, pin 0 has one net node + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Pin0Index), Qt::UserRole).toString ()), "$1|1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Pin0Index), Qt::DisplayRole).toString ()), "$1/1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 1, inv2Pin0Index), Qt::DisplayRole).toString ()), "$1/1"); + std::pair nets = model->net_from_index (model->index_from_id ((void *) 9, 0)); + EXPECT_EQ (nets.first != 0, true); + if (nets.first != 0) { + EXPECT_EQ (nets.first->expanded_name (), "$1"); + } + EXPECT_EQ (nets.second != 0, true); + if (nets.second != 0) { + EXPECT_EQ (nets.second->expanded_name (), "1"); + } + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2Pin0Index), Qt::DisplayRole).toString ()), "$1/1"); + + // first of nets in INV2 circuit + EXPECT_EQ (tl::to_string (model->data (model->index (6, 0, inv2Index), Qt::UserRole).toString ()), "$1|1"); + EXPECT_EQ (tl::to_string (model->data (model->index (6, 0, inv2Index), Qt::DisplayRole).toString ()), "$1/1"); + EXPECT_EQ (tl::to_string (model->data (model->index (6, 1, inv2Index), Qt::DisplayRole).toString ()), "$1 (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (6, 2, inv2Index), Qt::DisplayRole).toString ()), "1 (2)"); + + // INV2, net 1 node + QModelIndex inv2Net0Index = model->index (6, 0, inv2Index); + EXPECT_EQ (model->hasChildren (inv2Net0Index), true); + EXPECT_EQ (model->rowCount (inv2Net0Index), 2); + + // INV2, net 1 has one pin and one terminal at BULK + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Net0Index), Qt::UserRole).toString ()), "B|B|PMOS|PMOS|$1|$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2Net0Index), Qt::DisplayRole).toString ()), "B/B - PMOS/PMOS"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 1, inv2Net0Index), Qt::DisplayRole).toString ()), "$1/$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2Net0Index), Qt::DisplayRole).toString ()), "$1/$1"); + + // This terminal connects to a device with four other terminals .. + QModelIndex inv2Net0TerminalIndex = model->index (0, 0, inv2Net0Index); + EXPECT_EQ (model->hasChildren (inv2Net0TerminalIndex), true); + EXPECT_EQ (model->rowCount (inv2Net0TerminalIndex), 4); + // .. 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/G"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 1, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "IN/2"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0TerminalIndex), Qt::DisplayRole).toString ()), "IN/2"); + + // The Pin + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0Index), Qt::UserRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2Net0Index), Qt::DisplayRole).toString ()), "$0/$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 1, inv2Net0Index), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2Net0Index), Qt::DisplayRole).toString ()), ""); + + // This pin does not have children + QModelIndex inv2Net0PinIndex = model->index (1, 0, inv2Net0Index); + EXPECT_EQ (model->hasChildren (inv2Net0PinIndex), false); + EXPECT_EQ (model->rowCount (inv2Net0PinIndex), 0); + + // second of nets in INV2 circuit + EXPECT_EQ (tl::to_string (model->data (model->index (7, 0, inv2Index), Qt::UserRole).toString ()), "BULK|6"); + EXPECT_EQ (tl::to_string (model->data (model->index (7, 0, inv2Index), Qt::DisplayRole).toString ()), "BULK/6"); + EXPECT_EQ (tl::to_string (model->data (model->index (7, 1, inv2Index), Qt::DisplayRole).toString ()), "BULK (2)"); + EXPECT_EQ (tl::to_string (model->data (model->index (7, 2, inv2Index), Qt::DisplayRole).toString ()), "6 (2)"); + + // first of devices in INV2 circuit + EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, inv2Index), Qt::UserRole).toString ()), "$1|$1|PMOS|PMOS"); + EXPECT_EQ (tl::to_string (model->data (model->index (12, 0, inv2Index), Qt::DisplayRole).toString ()), "PMOS/PMOS"); + EXPECT_EQ (tl::to_string (model->data (model->index (12, 1, inv2Index), Qt::DisplayRole).toString ()), "$1 - PMOS [L=0.25, W=3.5]"); + EXPECT_EQ (tl::to_string (model->data (model->index (12, 2, inv2Index), Qt::DisplayRole).toString ()), "$1 - PMOS [L=0.25, W=3.5]"); + + QModelIndex inv2PairIndex = model->index (2, 0, QModelIndex ()); + + // INV2PAIR circuit node + EXPECT_EQ (model->hasChildren (inv2PairIndex), true); + EXPECT_EQ (model->rowCount (inv2PairIndex), 18); + + // first of pins in INV2 circuit + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairIndex), Qt::UserRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairIndex), Qt::DisplayRole).toString ()), "-/$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 1, inv2PairIndex), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairIndex), Qt::DisplayRole).toString ()), "$4"); + + // INV2, pin 0 node + QModelIndex inv2PairPin0Index = model->index (0, 0, inv2PairIndex); + EXPECT_EQ (model->hasChildren (inv2PairPin0Index), true); + EXPECT_EQ (model->rowCount (inv2PairPin0Index), 1); + + // INV2, pin 0 has one net node + // The pin isnt't connected to any net, left side because there is no match, right side because the pin isn't connected + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairPin0Index), Qt::UserRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairPin0Index), Qt::DisplayRole).toString ()), "-/-"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 1, inv2PairPin0Index), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairPin0Index), Qt::DisplayRole).toString ()), ""); + + // first of nets in INV2 circuit + EXPECT_EQ (tl::to_string (model->data (model->index (8, 0, inv2PairIndex), Qt::UserRole).toString ()), "$4"); + EXPECT_EQ (tl::to_string (model->data (model->index (8, 0, inv2PairIndex), Qt::DisplayRole).toString ()), "$4/-"); + EXPECT_EQ (tl::to_string (model->data (model->index (8, 1, inv2PairIndex), Qt::DisplayRole).toString ()), "$4 (3)"); + EXPECT_EQ (tl::to_string (model->data (model->index (8, 2, inv2PairIndex), Qt::DisplayRole).toString ()), ""); + + // This net has only left side which has one pin and two subcircuits + QModelIndex inv2PairNet0Index = model->index (8, 0, inv2PairIndex); + EXPECT_EQ (model->hasChildren (inv2PairNet0Index), true); + EXPECT_EQ (model->rowCount (inv2PairNet0Index), 3); + + // The pin + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0Index), Qt::UserRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0Index), Qt::DisplayRole).toString ()), "$3/-"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 1, inv2PairNet0Index), Qt::DisplayRole).toString ()), ""); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairNet0Index), Qt::DisplayRole).toString ()), ""); + + // This pin does not have children + QModelIndex inv2PairNet0Pin0Index = model->index (0, 0, inv2PairNet0Index); + EXPECT_EQ (model->hasChildren (inv2PairNet0Pin0Index), false); + EXPECT_EQ (model->rowCount (inv2PairNet0Pin0Index), 0); + + // The first subcircuit + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2PairNet0Index), Qt::UserRole).toString ()), "OUT|INV2|$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 0, inv2PairNet0Index), Qt::DisplayRole).toString ()), "OUT/- - INV2/-"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 1, inv2PairNet0Index), Qt::DisplayRole).toString ()), "$1/-"); + EXPECT_EQ (tl::to_string (model->data (model->index (1, 2, inv2PairNet0Index), Qt::DisplayRole).toString ()), ""); + + // This subcircuit has 6 other pins + QModelIndex inv2PairNet0SubCircuit0Index = model->index (1, 0, inv2PairNet0Index); + EXPECT_EQ (model->hasChildren (inv2PairNet0SubCircuit0Index), true); + EXPECT_EQ (model->rowCount (inv2PairNet0SubCircuit0Index), 6); + + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0SubCircuit0Index), Qt::UserRole).toString ()), "$1"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 0, inv2PairNet0SubCircuit0Index), Qt::DisplayRole).toString ()), "$0/$0"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 1, inv2PairNet0SubCircuit0Index), Qt::DisplayRole).toString ()), "$7/-"); + EXPECT_EQ (tl::to_string (model->data (model->index (0, 2, inv2PairNet0SubCircuit0Index), Qt::DisplayRole).toString ()), "$7/-"); }