This commit is contained in:
Matthias Koefferlein 2024-03-14 22:14:20 +01:00
parent c4fb287eb7
commit befbde0f43
5 changed files with 75 additions and 13 deletions

View File

@ -1001,6 +1001,8 @@ local_clusters<T>::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<cluster_value>::iterator ic1, typename std::list<cluster_value>::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<cluster_value>::iterator ic1, typename std::list<cluster_value>::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));
}
}
};

View File

@ -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
{

View File

@ -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) {

View File

@ -1093,6 +1093,7 @@ private:
bool is_persisted_impl (const db::ShapeCollection &coll) const;
void do_join_nets (db::Circuit &c, const std::vector<Net *> &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<std::string> &p);
void check_must_connect (const db::Circuit &c, const db::Net &a, const db::Net &b);

View File

@ -288,7 +288,9 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
const db::local_cluster<db::NetShape> &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<size_t> &sc_up = clusters.upward_soft_connections (*c);
const std::set<size_t> &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;