diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 247c9cf4c..d44349231 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -1001,6 +1001,8 @@ local_clusters::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpo db::mem_stat (stat, purpose, cat, m_bbox, true, (void *) this); db::mem_stat (stat, purpose, cat, m_clusters, true, (void *) this); db::mem_stat (stat, purpose, cat, m_next_dummy_id, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_soft_connections, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_soft_connections_rev, true, (void *) this); } namespace @@ -1268,6 +1270,10 @@ private: void join (typename std::list::iterator ic1, typename std::list::iterator ic2) { + if (ic1 == ic2) { + return; + } + ic1->first.insert (ic1->first.end (), ic2->first.begin (), ic2->first.end ()); ic1->second.insert (ic2->second.begin (), ic2->second.end ()); @@ -1280,21 +1286,35 @@ private: m_clusters.erase (ic2); - auto i1 = m_soft_connections.find (std::make_pair (ic1.operator-> (), ic2.operator-> ())); - if (i1 != m_soft_connections.end ()) { - i1->second = 0; + // remap soft connections: remove soft connections between ic1 and ic2 and + // remap ic2 connections to ic1 as first + + auto i2 = m_soft_connections.lower_bound (std::make_pair (ic2.operator-> (), (const cluster_value *) 0)); + for (auto i = i2; i != m_soft_connections.end () && i->first.first == ic2.operator-> (); ++i) { + m_soft_connections.erase (std::make_pair (i->first.second, i->first.first)); } - auto i2 = m_soft_connections.find (std::make_pair (ic2.operator-> (), ic1.operator-> ())); - if (i2 != m_soft_connections.end ()) { - i2->second = 0; + for (auto i = i2; i != m_soft_connections.end () && i->first.first == ic2.operator-> (); ++i) { + if (i->first.second != ic1.operator-> ()) { + register_soft_connection (ic1.operator-> (), i->first.second, i->second); + } } + + auto i2_from = i2; + for ( ; i2 != m_soft_connections.end () && i2->first.first == ic2.operator-> (); ++i2) + ; + m_soft_connections.erase (i2_from, i2); } void register_soft_connection (typename std::list::iterator ic1, typename std::list::iterator ic2, int soft) { - auto i1 = m_soft_connections.find (std::make_pair (ic1.operator-> (), ic2.operator-> ())); - auto i2 = m_soft_connections.find (std::make_pair (ic2.operator-> (), ic1.operator-> ())); + register_soft_connection (ic1.operator-> (), ic2.operator-> (), soft); + } + + void register_soft_connection (const cluster_value *c1, const cluster_value *c2, int soft) + { + auto i1 = m_soft_connections.find (std::make_pair (c1, c2)); + auto i2 = m_soft_connections.find (std::make_pair (c2, c1)); if (i1 != m_soft_connections.end () && i1->second != 0 && i1->second != soft) { i1->second = 0; @@ -1305,8 +1325,8 @@ private: if (i1 == m_soft_connections.end ()) { tl_assert (i2 == m_soft_connections.end ()); - m_soft_connections.insert (std::make_pair (std::make_pair (ic1.operator-> (), ic2.operator-> ()), soft)); - m_soft_connections.insert (std::make_pair (std::make_pair (ic2.operator-> (), ic1.operator-> ()), -soft)); + m_soft_connections.insert (std::make_pair (std::make_pair (c1, c2), soft)); + m_soft_connections.insert (std::make_pair (std::make_pair (c2, c1), -soft)); } } }; diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index 4b5cb5679..efec69dd5 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -338,7 +338,7 @@ public: bool interacts (const db::Cell &cell, const db::ICplxTrans &trans, const Connectivity &conn) const; /** - * @brief Gets the bounding box of this cluster + * @brief Gets the bounding box ofF this cluster */ const box_type &bbox () const { diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 4bf49e1d3..1795c4cdb 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -33,6 +33,7 @@ #include "dbLayoutToNetlistFormatDefs.h" #include "dbLayoutVsSchematicFormatDefs.h" #include "dbShapeProcessor.h" +#include "dbNetlistDeviceClasses.h" #include "dbLog.h" #include "tlGlobPattern.h" @@ -425,7 +426,9 @@ void LayoutToNetlist::extract_netlist () netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters); // @@@ NOTE: can we have multiple pins on a net? Will this happen later maybe? - // @@@ do_soft_connections () + tl_assert (check_many_pins (mp_netlist.get ())); // @@@ + do_soft_connections (); + tl_assert (check_many_pins (mp_netlist.get ())); // @@@ do_join_nets (); tl_assert (check_many_pins (mp_netlist.get ())); // @@@ @@ -640,6 +643,42 @@ void LayoutToNetlist::check_must_connect_impl (const db::Circuit &c, const db::N } } +void LayoutToNetlist::do_soft_connections () +{ + +// @@@ NetlistLocker locked_netlist (mp_netlist.get ()); + + db::DeviceClassDiode *soft_diode = new db::DeviceClassDiode (); + soft_diode->set_name ("SOFT"); + mp_netlist->add_device_class (soft_diode); + + for (auto c = mp_netlist->begin_bottom_up (); c != mp_netlist->end_bottom_up (); ++c) { + + // @@@ create diodes as of now + + auto clusters = net_clusters ().clusters_per_cell (c->cell_index ()); + + for (auto n = c->begin_nets (); n != c->end_nets (); ++n) { + + auto soft_connections = clusters.upward_soft_connections (n->cluster_id ()); + for (auto sc = soft_connections.begin (); sc != soft_connections.end (); ++sc) { + + db::Device *sc_device = new db::Device (soft_diode); + c->add_device (sc_device); + + auto nn = c->net_by_cluster_id (*sc); + if (nn) { + sc_device->connect_terminal (db::DeviceClassDiode::terminal_id_C, n.operator-> ()); + sc_device->connect_terminal (db::DeviceClassDiode::terminal_id_A, nn); + } + + } + + } + + } +} + void LayoutToNetlist::do_join_nets () { if (! mp_netlist) { diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index e18a11e5d..01f945e97 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -1093,6 +1093,7 @@ private: bool is_persisted_impl (const db::ShapeCollection &coll) const; void do_join_nets (db::Circuit &c, const std::vector &nets); void do_join_nets (); + void do_soft_connections (); void join_nets_from_pattern (db::Circuit &c, const tl::GlobPattern &p); void join_nets_from_pattern (db::Circuit &c, const std::set &p); void check_must_connect (const db::Circuit &c, const db::Net &a, const db::Net &b); diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index ddcef72c2..dd4ac0c23 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -288,7 +288,9 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo const db::local_cluster &lc = clusters.cluster_by_id (*c); const connected_clusters_type::connections_type &cc = clusters.connections_for_cluster (*c); - if (cc.empty () && lc.empty ()) { + const std::set &sc_up = clusters.upward_soft_connections (*c); + const std::set &sc_down = clusters.downward_soft_connections (*c); + if (cc.empty () && sc_up.empty () && sc_down.empty () && lc.empty ()) { // this is an entirely empty cluster so we skip it. // Such clusters are left over when joining clusters. continue;