From db1e813635dd349b8c9b212e72e490deae096a36 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 9 May 2019 01:07:54 +0200 Subject: [PATCH] WIP: combined devices and geometry/L2N DB representation. Yet to do: device cell transformation beyond vector? --- src/db/db/dbDevice.cc | 28 ++++-- src/db/db/dbDevice.h | 29 ++++++ src/db/db/dbLayoutToNetlistFormatDefs.h | 19 +++- src/db/db/dbLayoutToNetlistReader.cc | 117 ++++++++++++++++++------ src/db/db/dbLayoutToNetlistReader.h | 5 +- src/db/db/dbLayoutToNetlistWriter.cc | 39 +++++++- 6 files changed, 196 insertions(+), 41 deletions(-) diff --git a/src/db/db/dbDevice.cc b/src/db/db/dbDevice.cc index da17710cf..f1215d59d 100644 --- a/src/db/db/dbDevice.cc +++ b/src/db/db/dbDevice.cc @@ -189,17 +189,15 @@ void Device::set_parameter_value (const std::string &name, double v) void Device::add_others_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal) { + std::vector &terminals = m_reconnected_terminals [this_terminal]; + std::map >::const_iterator ot = other->m_reconnected_terminals.find (other_terminal); if (ot == other->m_reconnected_terminals.end ()) { - return; - } - if (other->m_reconnected_terminals.empty ()) { - m_reconnected_terminals.insert (std::make_pair (this_terminal, ot->second)); + terminals.push_back (OtherTerminalRef (other->device_abstract (), other->position () - position (), other_terminal)); + } else { - std::vector &terminals = m_reconnected_terminals [this_terminal]; - size_t n = terminals.size (); terminals.insert (terminals.end (), ot->second.begin (), ot->second.end ()); @@ -212,10 +210,22 @@ void Device::add_others_terminals (unsigned int this_terminal, db::Device *other } } +void Device::init_terminal_routes () +{ + if (! device_class ()) { + return; + } + + size_t n = device_class ()->terminal_definitions ().size (); + for (size_t i = 0; i < n; ++i) { + m_reconnected_terminals [i].push_back (OtherTerminalRef (device_abstract (), db::DVector (), i)); + } +} + void Device::join_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal) { if (m_reconnected_terminals.empty ()) { - m_reconnected_terminals [this_terminal].push_back (OtherTerminalRef (device_abstract (), db::DVector (), this_terminal)); + init_terminal_routes (); } other->connect_terminal (other_terminal, 0); @@ -227,6 +237,10 @@ void Device::reroute_terminal (unsigned int this_terminal, db::Device *other, un { // TODO: the internal connection is not represented currently ... + if (m_reconnected_terminals.empty ()) { + init_terminal_routes (); + } + if (! m_reconnected_terminals.empty ()) { m_reconnected_terminals.erase (this_terminal); } diff --git a/src/db/db/dbDevice.h b/src/db/db/dbDevice.h index c71fa3ac7..e18171fe8 100644 --- a/src/db/db/dbDevice.h +++ b/src/db/db/dbDevice.h @@ -280,6 +280,14 @@ public: } } + /** + * @brief Gets the map of reconnected terminals + */ + const std::map > &reconnected_terminals () const + { + return m_reconnected_terminals; + } + /** * @brief Gets the set of other device abstracts * @@ -291,6 +299,26 @@ public: return m_other_abstracts; } + /** + * @brief Gets the map of reconnected terminals (non-const version) + * + * NOTE: don't use this method to modify this container! It's provided for persistence implementation only. + */ + std::map > &reconnected_terminals () + { + return m_reconnected_terminals; + } + + /** + * @brief Gets the set of other device abstracts (non-const version) + * + * NOTE: don't use this method to modify this container! It's provided for persistence implementation only. + */ + std::vector > &other_abstracts () + { + return m_other_abstracts; + } + private: friend class Circuit; friend class Net; @@ -335,6 +363,7 @@ private: void set_circuit (Circuit *circuit); void add_others_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal); + void init_terminal_routes (); }; } diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.h b/src/db/db/dbLayoutToNetlistFormatDefs.h index 6d29c676e..2a3a9faac 100644 --- a/src/db/db/dbLayoutToNetlistFormatDefs.h +++ b/src/db/db/dbLayoutToNetlistFormatDefs.h @@ -69,11 +69,26 @@ namespace db * A net declaration shall be there also if no geometry * is present. The ID is a numerical shortcut for the net. * pin( ) - outgoing pin connection [short key: P] - * device( [device-def]) + * device( [combined-device]* [terminal-route]* [device-def]) * - device with connections [short key: D] * circuit( [circuit-def]) - subcircuit with connections [short key: X] * + * [combined-device]: + * + * device( ) - specifies an additional device component + * (for combined devices) with abstract + * and offset dx, dy. + * + * [terminal-route]: + * + * connect( ) + * - connects the outer terminal with the terminal + * of the device component with : + * 0 is the basic device, 1 the first combined + * device etc. + * * [net-name]: + * * name() - specify net name [short key: I] * * [geometry-def]: @@ -82,7 +97,9 @@ namespace db * "*" for or means take previous * rect( [coord] [coord]) - defines a rectangle [short key: R] * coordinates are bottom/left and top/right + * * [coord] + * * - absolute coordinates * ( ) - relative coordinates (reference is reset to 0,0 * for each net or terminal in device abstract) diff --git a/src/db/db/dbLayoutToNetlistReader.cc b/src/db/db/dbLayoutToNetlistReader.cc index cb649c419..79d056f25 100644 --- a/src/db/db/dbLayoutToNetlistReader.cc +++ b/src/db/db/dbLayoutToNetlistReader.cc @@ -309,7 +309,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n) std::map >::const_iterator c = connections.find (i->cell_inst ()); if (c != connections.end ()) { for (std::list::const_iterator j = c->second.begin (); j != c->second.end (); ++j) { - l2n->net_clusters ().clusters_per_cell (ci).add_connection (j->from_cluster, db::ClusterInstance (j->to_cluster, i->cell_index (), i->complex_trans (), i->prop_id ())); + l2n->net_clusters ().clusters_per_cell (ci).add_connection (j->from_cluster, db::ClusterInstance (j->to_cluster, i->cell_index (), i->complex_trans () * db::ICplxTrans (j->offset), i->prop_id ())); } } } @@ -486,6 +486,31 @@ LayoutToNetlistStandardReader::read_pin (db::LayoutToNetlist * /*l2n*/, db::Circ circuit->connect_pin (pin.id (), net); } +static size_t +terminal_id (const db::DeviceClass *device_class, const std::string &tname) +{ + const std::vector &td = device_class->terminal_definitions (); + for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { + if (t->name () == tname) { + return t->id (); + } + } + + throw tl::Exception (tl::to_string (tr ("Not a valid terminal name: ")) + tname + tl::to_string (tr (" for device class: ")) + device_class->name ()); +} + +static db::DeviceAbstract * +device_model_by_name (db::Netlist *netlist, const std::string &dmname) +{ + for (db::Netlist::device_abstract_iterator i = netlist->begin_device_abstracts (); i != netlist->end_device_abstracts (); ++i) { + if (i->name () == dmname) { + return i.operator-> (); + } + } + + throw tl::Exception (tl::to_string (tr ("Not a valid device abstract name: ")) + dmname); +} + db::CellInstArray LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::list &refs, std::map &id2net) { @@ -497,16 +522,7 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui std::string dmname; read_word_or_quoted (dmname); - db::DeviceAbstract *dm = 0; - for (db::Netlist::device_abstract_iterator i = l2n->netlist ()->begin_device_abstracts (); i != l2n->netlist ()->end_device_abstracts (); ++i) { - if (i->name () == dmname) { - dm = i.operator-> (); - } - } - - if (! dm) { - throw tl::Exception (tl::to_string (tr ("Not a valid device abstract name: ")) + dmname); - } + db::DeviceAbstract *dm = device_model_by_name (l2n->netlist (), dmname); db::Device *device = new db::Device (); device->set_device_class (const_cast (dm->device_class ())); @@ -515,6 +531,8 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui circuit->add_device (device); db::Coord x = 0, y = 0; + double dbu = l2n->internal_layout ()->dbu (); + db::VCplxTrans dbu_inv (1.0 / dbu); while (br) { @@ -525,6 +543,44 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui y = read_coord (); br2.done (); + } else if (test (skeys::device_key) || test (lkeys::device_key)) { + + std::string n; + + Brace br2 (this); + + read_word_or_quoted (n); + + db::Coord dx = read_coord (); + db::Coord dy = read_coord (); + + br2.done (); + + device->other_abstracts ().push_back (std::make_pair (device_model_by_name (l2n->netlist (), n), db::DVector (dbu * dx, dbu * dy))); + + } else if (test (skeys::connect_key) || test (lkeys::connect_key)) { + + Brace br2 (this); + + int device_comp_index = read_int (); + + std::string touter, tinner; + read_word_or_quoted (touter); + read_word_or_quoted (tinner); + + br2.done (); + + if (device_comp_index < 0 || device_comp_index > int (device->other_abstracts ().size ())) { + throw tl::Exception (tl::to_string (tr ("Not a valid device component index: ")) + tl::to_string (device_comp_index)); + } + + size_t touter_id = terminal_id (dm->device_class (), touter); + size_t tinner_id = terminal_id (dm->device_class (), tinner); + + const db::DeviceAbstract *da = device_comp_index > 0 ? device->other_abstracts () [device_comp_index - 1].first : dm; + db::DVector da_offset = device_comp_index > 0 ? device->other_abstracts () [device_comp_index - 1].second : db::DVector (); + device->reconnected_terminals () [touter_id].push_back (db::Device::OtherTerminalRef (da, da_offset, tinner_id)); + } else if (test (skeys::terminal_key) || test (lkeys::terminal_key)) { Brace br2 (this); @@ -533,18 +589,7 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui unsigned int netid = (unsigned int) read_int (); br2.done (); - size_t tid = std::numeric_limits::max (); - const std::vector &td = dm->device_class ()->terminal_definitions (); - for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { - if (t->name () == tname) { - tid = t->id (); - break; - } - } - - if (tid == std::numeric_limits::max ()) { - throw tl::Exception (tl::to_string (tr ("Not a valid terminal name: ")) + tname + tl::to_string (tr (" for device class: ")) + dm->device_class ()->name ()); - } + size_t tid = terminal_id (dm->device_class (), tname); db::Net *net = id2net [netid]; if (!net) { @@ -552,7 +597,15 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui } device->connect_terminal (tid, net); - refs.push_back (Connections (net->cluster_id (), dm->cluster_id_for_terminal (tid))); + + const std::vector *tr = device->reconnected_terminals_for (tid); + if (tr) { + for (std::vector::const_iterator i = tr->begin (); i != tr->end (); ++i) { + refs.push_back (Connections (net->cluster_id (), i->device_abstract->cluster_id_for_terminal (i->other_terminal_id), dbu_inv * i->offset)); + } + } else { + refs.push_back (Connections (net->cluster_id (), dm->cluster_id_for_terminal (tid), db::Vector ())); + } } else if (test (skeys::param_key) || test (lkeys::param_key)) { @@ -586,16 +639,24 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui } - double dbu = l2n->internal_layout ()->dbu (); device->set_position (db::DPoint (dbu * x, dbu * y)); br.done (); - // make device cell instance - db::CellInstArray inst (db::CellInst (dm->cell_index ()), db::Trans (db::Vector (x, y))); db::Cell &ccell = l2n->internal_layout ()->cell (circuit->cell_index ()); + + // make device cell instances + db::CellInstArray inst (db::CellInst (dm->cell_index ()), db::Trans (db::Vector (x, y))); ccell.insert (inst); + const std::vector > &other_devices = device->other_abstracts (); + for (std::vector >::const_iterator i = other_devices.begin (); i != other_devices.end (); ++i) { + + db::CellInstArray other_inst (db::CellInst (i->first->cell_index ()), db::Trans (db::Vector (x, y) + dbu_inv * i->second)); + ccell.insert (other_inst); + + } + return inst; } @@ -688,7 +749,7 @@ LayoutToNetlistStandardReader::read_subcircuit (db::LayoutToNetlist *l2n, db::Ci subcircuit->connect_pin (sc_pin->id (), net); db::Net *sc_net = circuit_ref->net_for_pin (sc_pin->id ()); if (sc_net) { - refs.push_back (Connections (net->cluster_id (), sc_net->cluster_id ())); + refs.push_back (Connections (net->cluster_id (), sc_net->cluster_id (), db::Vector ())); } } else { diff --git a/src/db/db/dbLayoutToNetlistReader.h b/src/db/db/dbLayoutToNetlistReader.h index 49ff51c97..8a4e95efc 100644 --- a/src/db/db/dbLayoutToNetlistReader.h +++ b/src/db/db/dbLayoutToNetlistReader.h @@ -74,11 +74,12 @@ private: struct Connections { - Connections (size_t _from_cluster, size_t _to_cluster) - : from_cluster (_from_cluster), to_cluster (_to_cluster) + Connections (size_t _from_cluster, size_t _to_cluster, const db::Vector &_offset) + : from_cluster (_from_cluster), to_cluster (_to_cluster), offset (_offset) { } size_t from_cluster, to_cluster; + db::Vector offset; }; tl::TextInputStream m_stream; diff --git a/src/db/db/dbLayoutToNetlistWriter.cc b/src/db/db/dbLayoutToNetlistWriter.cc index 0368a5073..b93910ce7 100644 --- a/src/db/db/dbLayoutToNetlistWriter.cc +++ b/src/db/db/dbLayoutToNetlistWriter.cc @@ -489,20 +489,53 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Dev { const db::Layout *ly = l2n->internal_layout (); double dbu = ly->dbu (); + db::VCplxTrans dbu_inv (1.0 / dbu); + + tl_assert (device.device_class () != 0); + const std::vector &td = device.device_class ()->terminal_definitions (); + const std::vector &pd = device.device_class ()->parameter_definitions (); *mp_stream << indent1 << Keys::device_key << "(" << tl::to_word_or_quoted_string (device.expanded_name ()); tl_assert (device.device_abstract () != 0); *mp_stream << " " << tl::to_word_or_quoted_string (device.device_abstract ()->name ()) << endl; - *mp_stream << indent2 << Keys::location_key << "(" << device.position ().x () / dbu << " " << device.position ().y () / dbu << ")" << endl; + std::map, size_t> abstracts; + abstracts.insert (std::make_pair (std::make_pair (device.device_abstract (), db::Vector ()), 0)); + + const std::vector > &other_abstracts = device.other_abstracts (); + for (std::vector >::const_iterator a = other_abstracts.begin (); a != other_abstracts.end (); ++a) { + + db::Vector pos = dbu_inv * a->second; + abstracts.insert (std::make_pair (std::make_pair (a->first, pos), a - other_abstracts.begin () + 1)); + + *mp_stream << " " << Keys::device_key << "(" << tl::to_word_or_quoted_string (a->first->name ()) << " " << pos.x () << " " << pos.y () << ")" << endl; + + } + + const std::map > &reconnected_terminals = device.reconnected_terminals (); + for (std::map >::const_iterator t = reconnected_terminals.begin (); t != reconnected_terminals.end (); ++t) { + + for (std::vector::const_iterator c = t->second.begin (); c != t->second.end (); ++c) { + + db::Vector pos = dbu_inv * c->offset; + std::map, size_t>::const_iterator a = abstracts.find (std::make_pair (c->device_abstract, pos)); + tl_assert (a != abstracts.end ()); + + *mp_stream << " " << Keys::connect_key << "(" << a->second << " " << tl::to_word_or_quoted_string (td [t->first].name ()) << " " << tl::to_word_or_quoted_string (td [c->other_terminal_id].name ()) << ")" << endl; + + } + + } + + db::Point pos = dbu_inv * device.position (); + + *mp_stream << indent2 << Keys::location_key << "(" << pos.x () << " " << pos.y () << ")" << endl; - const std::vector &pd = device.device_class ()->parameter_definitions (); for (std::vector::const_iterator i = pd.begin (); i != pd.end (); ++i) { *mp_stream << indent2 << Keys::param_key << "(" << tl::to_word_or_quoted_string (i->name ()) << " " << device.parameter_value (i->id ()) << ")" << endl; } - const std::vector &td = device.device_class ()->terminal_definitions (); for (std::vector::const_iterator i = td.begin (); i != td.end (); ++i) { const db::Net *net = device.net_for_terminal (i->id ()); if (net) {