WIP: reimplementing connect_implicit on netlist basis

This commit is contained in:
Matthias Koefferlein 2023-09-19 23:10:51 +02:00
parent 033d630992
commit e7a8569052
6 changed files with 151 additions and 9 deletions

View File

@ -366,14 +366,11 @@ void Circuit::remove_net (Net *net)
void Circuit::join_nets (Net *net, Net *with)
{
if (! net) {
return;
}
if (net == with || ! with) {
if (net == with || ! with || ! net) {
return;
}
if (net->circuit () != this || with->circuit () != this) {
throw tl::Exception (tl::to_string (tr ("Nets not withing given circuit")));
throw tl::Exception (tl::to_string (tr ("Nets not within given circuit")));
}
while (with->begin_terminals () != with->end_terminals ()) {
@ -390,7 +387,6 @@ void Circuit::join_nets (Net *net, Net *with)
connect_pin (with->begin_pins ()->pin_id (), net);
}
// TODO: join clusters too, join net properties(?)
if (netlist ()->callbacks ()) {
netlist ()->callbacks ()->link_nets (net, with);
}
@ -676,7 +672,42 @@ void Circuit::connect_pin (size_t pin_id, Net *net)
}
if (net) {
net->add_pin (NetPinRef (pin_id));
if (net->begin_pins () != net->end_pins ()) {
join_pins (net->begin_pins ()->pin_id (), pin_id);
} else {
net->add_pin (NetPinRef (pin_id));
}
}
}
void Circuit::join_pins (size_t pin, size_t with)
{
if (with < m_pin_by_id.size () && ! tl::is_null_iterator (m_pin_by_id [with])) {
m_pins.erase (m_pin_by_id [with]);
m_pin_by_id.erase (m_pin_by_id.begin () + with);
m_pin_refs.erase (m_pin_refs.begin () + with);
// join nets in calls
for (auto s = begin_refs (); s != end_refs (); ++s) {
db::SubCircuit &sc = *s;
db::Net *with_net = sc.net_for_pin (with);
// remove the subcircuit pin reference from the "with" net
for (auto sc_pin = with_net->begin_subcircuit_pins (); sc_pin != with_net->end_subcircuit_pins (); ++sc_pin) {
if (sc_pin->subcircuit () == &sc && sc_pin->pin_id () == with) {
with_net->erase_subcircuit_pin (sc_pin);
break;
}
}
sc.circuit ()->join_nets (sc.net_for_pin (pin), with_net);
sc.erase_pin_ref (with);
}
}
}

View File

@ -819,7 +819,7 @@ private:
bool combine_parallel_devices (const db::DeviceClass &cls);
bool combine_serial_devices (const db::DeviceClass &cls);
void do_purge_nets (bool keep_pins);
void join_pins (size_t pin_id, size_t with);
void devices_changed ();
void subcircuits_changed ();
void nets_changed ();

View File

@ -414,7 +414,7 @@ void LayoutToNetlist::extract_netlist ()
netex.set_include_floating_subcircuits (m_include_floating_subcircuits);
netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters);
// @@@ join_nets ();
do_join_nets ();
if (tl::verbosity () >= 41) {
MemStatisticsCollector m (false);
@ -425,6 +425,102 @@ void LayoutToNetlist::extract_netlist ()
m_netlist_extracted = true;
}
static std::vector<db::Net *> nets_from_pattern (db::Circuit &c, const tl::GlobPattern &p)
{
std::vector<db::Net *> result;
for (auto n = c.begin_nets (); n != c.end_nets (); ++n) {
if (p.match (n->name ())) {
result.push_back (n.operator-> ());
}
}
return result;
}
static std::vector<db::Net *> nets_from_pattern (db::Circuit &c, const std::set<std::string> &p)
{
std::vector<db::Net *> result;
for (auto n = p.begin (); n != p.end (); ++n) {
db::Net *net = c.net_by_name (*n);
if (net) {
result.push_back (net);
}
}
return result;
}
void LayoutToNetlist::do_join_nets (db::Circuit &c, const std::vector<db::Net *> &nets)
{
if (nets.size () <= 1) {
return;
}
std::set<std::string> names;
for (auto n = nets.begin (); n != nets.end (); ++n) {
if (! (*n)->name ().empty ()) {
names.insert ((*n)->name ());
}
}
nets [0]->set_name (tl::join (names.begin (), names.end (), ","));
for (auto n = nets.begin () + 1; n != nets.end (); ++n) {
c.join_nets (nets [0], *n);
}
}
void LayoutToNetlist::do_join_nets ()
{
if (! mp_netlist) {
return;
}
// prevents updates
NetlistLocker locked_netlist (mp_netlist.get ());
for (auto jn = m_joined_net_names.begin (); jn != m_joined_net_names.end (); ++jn) {
for (auto c = mp_netlist->begin_top_down (); c != mp_netlist->end_top_down (); ++c) {
do_join_nets (*c, nets_from_pattern (*c, *jn));
}
}
for (auto jn = m_joined_nets.begin (); jn != m_joined_nets.end (); ++jn) {
for (auto c = mp_netlist->begin_top_down (); c != mp_netlist->end_top_down (); ++c) {
do_join_nets (*c, nets_from_pattern (*c, *jn));
}
}
for (auto jn = m_joined_net_names_per_cell.begin (); jn != m_joined_net_names_per_cell.end (); ++jn) {
for (auto c = mp_netlist->begin_top_down (); c != mp_netlist->end_top_down (); ++c) {
if (jn->first.match (c->name ())) {
do_join_nets (*c, nets_from_pattern (*c, jn->second));
}
}
}
for (auto jn = m_joined_nets_per_cell.begin (); jn != m_joined_nets_per_cell.end (); ++jn) {
for (auto c = mp_netlist->begin_top_down (); c != mp_netlist->end_top_down (); ++c) {
if (jn->first.match (c->name ())) {
do_join_nets (*c, nets_from_pattern (*c, jn->second));
}
}
}
}
void LayoutToNetlist::error (const std::string &msg)
{
m_log_entries.push_back (db::LogEntryData (db::Error, msg));
}
void LayoutToNetlist::warn (const std::string &msg)
{
m_log_entries.push_back (db::LogEntryData (db::Warning, msg));
}
void LayoutToNetlist::info (const std::string &msg)
{
m_log_entries.push_back (db::LogEntryData (db::Info, msg));
}
void LayoutToNetlist::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (! no_self) {

View File

@ -993,6 +993,11 @@ private:
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
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 error (const std::string &msg);
void warn (const std::string &msg);
void info (const std::string &msg);
// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);

View File

@ -90,6 +90,11 @@ void SubCircuit::set_trans (const db::DCplxTrans &t)
m_trans = t;
}
void SubCircuit::erase_pin_ref (size_t pin_id)
{
m_pin_refs.erase (m_pin_refs.begin () + pin_id);
}
void SubCircuit::set_pin_ref_for_pin (size_t pin_id, Net::subcircuit_pin_iterator iter)
{
if (m_pin_refs.size () < pin_id + 1) {

View File

@ -230,6 +230,11 @@ private:
*/
void set_circuit_ref (Circuit *c);
/**
* @brief Erases the given pin reference
*/
void erase_pin_ref (size_t pin_id);
/**
* @brief Sets the circuit the subcircuit belongs to
*/