diff --git a/src/db/db/dbDeviceModel.cc b/src/db/db/dbDeviceModel.cc index 69245cc8f..a6d3b9d77 100644 --- a/src/db/db/dbDeviceModel.cc +++ b/src/db/db/dbDeviceModel.cc @@ -22,6 +22,7 @@ #include "dbDeviceModel.h" #include "dbCircuit.h" +#include "dbNetlist.h" namespace db { @@ -71,11 +72,17 @@ void DeviceModel::set_netlist (Netlist *netlist) void DeviceModel::set_name (const std::string &n) { m_name = n; + if (mp_netlist) { + mp_netlist->m_device_model_by_name.invalidate (); + } } void DeviceModel::set_cell_index (db::cell_index_type ci) { m_cell_index = ci; + if (mp_netlist) { + mp_netlist->m_device_model_by_cell_index.invalidate (); + } } size_t DeviceModel::cluster_id_for_terminal (size_t terminal_id) const diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 81127318e..daeda3f53 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -260,13 +260,9 @@ db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell unsigned int layout_index = 0; std::set device_cells; - - if (! with_device_cells) { - const db::Layout &src_layout = m_dss.layout (layout_index); - for (db::Layout::const_iterator c = src_layout.begin (); c != src_layout.end (); ++c) { - if (db::NetlistDeviceExtractor::is_device_cell (src_layout, c->cell_index ())) { - device_cells.insert (c->cell_index ()); - } + if (! with_device_cells && mp_netlist.get ()) { + for (db::Netlist::device_model_iterator i = mp_netlist->begin_device_models (); i != mp_netlist->end_device_models (); ++i) { + device_cells.insert (i->cell_index ()); } } @@ -404,7 +400,7 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout & if (cm == cmap.end ()) { const char *name_prefix = 0; - if (db::NetlistDeviceExtractor::is_device_cell (*internal_layout (), subci)) { + if (mp_netlist->device_model_by_cell_index (subci)) { name_prefix = device_cell_name_prefix; } else { name_prefix = cell_name_prefix; diff --git a/src/db/db/dbLayoutToNetlistWriter.cc b/src/db/db/dbLayoutToNetlistWriter.cc index a84c9289c..2daa621be 100644 --- a/src/db/db/dbLayoutToNetlistWriter.cc +++ b/src/db/db/dbLayoutToNetlistWriter.cc @@ -149,7 +149,6 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n) *mp_stream << "# Circuits are the hierarchical building blocks of the netlist." << endl; for (db::Netlist::const_bottom_up_circuit_iterator i = nl->begin_bottom_up (); i != nl->end_bottom_up (); ++i) { const db::Circuit *x = *i; - *mp_stream << endl << "# Circuit " << x->name () << endl; *mp_stream << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (x->name ()) << endl; write (l2n, *x); *mp_stream << ")" << endl; @@ -233,6 +232,10 @@ void std_writer_impl::write (const db::PolygonRef *s, const db::ICplxTrans template void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Net &net) { + if (! l2n->netlist ()) { + throw tl::Exception (tl::to_string (tr ("Can't write annotated netlist before extraction has been done"))); + } + const db::Layout *ly = l2n->internal_layout (); const db::hier_clusters &clusters = l2n->net_clusters (); const db::Circuit *circuit = net.circuit (); @@ -251,7 +254,7 @@ void std_writer_impl::write (const db::LayoutToNetlist *l2n, const db::Net // vanish in "purge" but the clusters will still be there we need to recursive into clusters from // unknown cells. db::cell_index_type ci = si.cell_index (); - if (ci != prev_ci && ci != cci && l2n->netlist ()->circuit_by_cell_index (ci)) { + if (ci != prev_ci && ci != cci && (l2n->netlist ()->circuit_by_cell_index (ci) || l2n->netlist ()->device_model_by_cell_index (ci))) { si.skip_cell (); diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index d48fb90bf..bbeb53ca0 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -33,26 +33,33 @@ namespace db Netlist::Netlist () : m_valid_topology (false), m_lock_count (0), m_circuit_by_name (this, &Netlist::begin_circuits, &Netlist::end_circuits), - m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits) + m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits), + m_device_model_by_name (this, &Netlist::begin_device_models, &Netlist::end_device_models), + m_device_model_by_cell_index (this, &Netlist::begin_device_models, &Netlist::end_device_models) { m_circuits.changed ().add (this, &Netlist::invalidate_topology); m_circuits.changed ().add (this, &Netlist::circuits_changed); + m_device_models.changed ().add (this, &Netlist::device_models_changed); } Netlist::Netlist (const Netlist &other) : gsi::ObjectBase (other), tl::Object (other), m_valid_topology (false), m_lock_count (0), m_circuit_by_name (this, &Netlist::begin_circuits, &Netlist::end_circuits), - m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits) + m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits), + m_device_model_by_name (this, &Netlist::begin_device_models, &Netlist::end_device_models), + m_device_model_by_cell_index (this, &Netlist::begin_device_models, &Netlist::end_device_models) { operator= (other); m_circuits.changed ().add (this, &Netlist::invalidate_topology); m_circuits.changed ().add (this, &Netlist::circuits_changed); + m_device_models.changed ().add (this, &Netlist::device_models_changed); } Netlist::~Netlist () { m_circuits.changed ().remove (this, &Netlist::invalidate_topology); m_circuits.changed ().remove (this, &Netlist::circuits_changed); + m_device_models.changed ().remove (this, &Netlist::device_models_changed); } Netlist &Netlist::operator= (const Netlist &other) @@ -98,6 +105,12 @@ void Netlist::circuits_changed () m_circuit_by_name.invalidate (); } +void Netlist::device_models_changed () +{ + m_device_model_by_cell_index.invalidate (); + m_device_model_by_name.invalidate (); +} + void Netlist::invalidate_topology () { if (m_valid_topology) { diff --git a/src/db/db/dbNetlist.h b/src/db/db/dbNetlist.h index 739c7888a..cbb822a36 100644 --- a/src/db/db/dbNetlist.h +++ b/src/db/db/dbNetlist.h @@ -349,6 +349,46 @@ public: return m_device_models.end (); } + /** + * @brief Gets the device model with the given name + * + * If no device model with that name exists, null is returned. + */ + DeviceModel *device_model_by_name (const std::string &name) + { + return m_device_model_by_name.object_by (name); + } + + /** + * @brief Gets the device model with the given name (const version) + * + * If no device model with that name exists, null is returned. + */ + const DeviceModel *device_model_by_name (const std::string &name) const + { + return m_device_model_by_name.object_by (name); + } + + /** + * @brief Gets the device model with the given cell index + * + * If no device model with that cell index exists, null is returned. + */ + DeviceModel *device_model_by_cell_index (db::cell_index_type cell_index) + { + return m_device_model_by_cell_index.object_by (cell_index); + } + + /** + * @brief Gets the device model with the given cell index (const version) + * + * If no device model with that cell index exists, null is returned. + */ + const DeviceModel *device_model_by_cell_index (db::cell_index_type cell_index) const + { + return m_device_model_by_cell_index.object_by (cell_index); + } + /** * @brief Purge unused nets * @@ -383,6 +423,7 @@ public: private: friend class Circuit; + friend class DeviceModel; circuit_list m_circuits; device_class_list m_device_classes; @@ -395,10 +436,13 @@ private: size_t m_top_circuits; object_by_attr > m_circuit_by_name; object_by_attr > m_circuit_by_cell_index; + object_by_attr > m_device_model_by_name; + object_by_attr > m_device_model_by_cell_index; void invalidate_topology (); void validate_topology (); void circuits_changed (); + void device_models_changed (); const tl::vector &child_circuits (Circuit *circuit); const tl::vector &parent_circuits (Circuit *circuit); diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index 19b1a4803..5749bcb86 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -169,7 +169,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db: for (std::set::const_iterator ci = called_cells.begin (); ci != called_cells.end (); ++ci) { // skip device cells from previous extractions - if (is_device_cell (*ci)) { + if (m_netlist->device_model_by_cell_index (*ci)) { continue; } @@ -223,33 +223,6 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db: } } -bool NetlistDeviceExtractor::is_device_cell (const db::Layout &layout, db::cell_index_type ci) -{ - db::properties_id_type pi = layout.cell (ci).prop_id (); - if (pi == 0) { - return false; - } - - std::pair pn = layout.properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::device_class_property_name ()); - if (! pn.first) { - return false; - } - - const db::PropertiesRepository::properties_set &ps = layout.properties_repository ().properties (pi); - for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) { - if (j->first == pn.second) { - return true; - } - } - - return false; -} - -bool NetlistDeviceExtractor::is_device_cell (db::cell_index_type ci) const -{ - return is_device_cell (*mp_layout, ci); -} - void NetlistDeviceExtractor::push_new_devices () { db::VCplxTrans dbu_inv = db::CplxTrans (mp_layout->dbu ()).inverted (); @@ -298,8 +271,6 @@ void NetlistDeviceExtractor::push_new_devices () ps.insert (std::make_pair (m_device_class_propname_id, tl::Variant (mp_device_class->name ()))); device_cell.prop_id (mp_layout->properties_repository ().properties_id (ps)); - db::connected_clusters &cc = mp_clusters->clusters_per_cell (device_cell.cell_index ()); - for (geometry_per_terminal_type::const_iterator t = d->second.begin (); t != d->second.end (); ++t) { // Build a property set for the device terminal ID diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index 0cc045ceb..8c6734c63 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -234,11 +234,6 @@ public: */ static const tl::Variant &device_class_property_name (); - /** - * @brief Returns true, if the given cell is a device cell - */ - static bool is_device_cell (const db::Layout &layout, db::cell_index_type ci); - /** * @brief Performs the extraction * @@ -527,7 +522,6 @@ private: void extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector &layers); void push_new_devices (); - bool is_device_cell (db::cell_index_type ci) const; }; } diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index e4881f0db..5bf37763e 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -63,12 +63,6 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect circuits.insert (std::make_pair (c->cell_index (), c.operator-> ())); } - // reverse lookup for DeviceModel vs. cell index - std::map device_models; - for (db::Netlist::device_model_iterator dm = nl.begin_device_models (); dm != nl.end_device_models (); ++dm) { - device_models.insert (std::make_pair (dm->cell_index (), dm.operator-> ())); - } - std::map > pins_per_cluster_per_cell; for (db::Layout::bottom_up_const_iterator cid = mp_layout->begin_bottom_up (); cid != mp_layout->end_bottom_up (); ++cid) { @@ -77,28 +71,11 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect continue; } - std::map::const_iterator dmc = device_models.find (*cid); - if (dmc != device_models.end ()) { - + db::DeviceModel *dm = nl.device_model_by_cell_index (*cid); + if (dm) { // make the terminal to cluster ID connections for the device model from the device cells - - if (m_terminal_annot_name_id.first) { - - for (connected_clusters_type::const_iterator dc = clusters.begin (); dc != clusters.end (); ++dc) { - for (local_cluster_type::attr_iterator a = dc->begin_attr (); a != dc->end_attr (); ++a) { - const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (*a); - for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) { - if (j->first == m_terminal_annot_name_id.second) { - dmc->second->set_cluster_id_for_terminal (j->second.to (), dc->id ()); - } - } - } - } - - } - + make_device_model_connections (dm, clusters); continue; - } // a cell makes a new circuit (or uses an existing one) @@ -151,6 +128,31 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect } } +void +NetlistExtractor::make_device_model_connections (db::DeviceModel *dm, const connected_clusters_type &clusters) +{ + // make the terminal to cluster ID connections for the device model from the device cells + + if (m_terminal_annot_name_id.first) { + + for (connected_clusters_type::const_iterator dc = clusters.begin (); dc != clusters.end (); ++dc) { + + for (local_cluster_type::attr_iterator a = dc->begin_attr (); a != dc->end_attr (); ++a) { + + const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (*a); + for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) { + if (j->first == m_terminal_annot_name_id.second) { + dm->set_cluster_id_for_terminal (j->second.to (), dc->id ()); + } + } + + } + + } + + } +} + void NetlistExtractor::collect_labels (const connected_clusters_type &clusters, size_t cid, db::Net *net) diff --git a/src/db/db/dbNetlistExtractor.h b/src/db/db/dbNetlistExtractor.h index 5447f63b5..c896d349d 100644 --- a/src/db/db/dbNetlistExtractor.h +++ b/src/db/db/dbNetlistExtractor.h @@ -37,6 +37,7 @@ class Circuit; class SubCircuit; class Net; class Device; +class DeviceModel; /** * @brief The Netlist Extractor @@ -151,6 +152,12 @@ private: void collect_labels (const connected_clusters_type &clusters, size_t cid, db::Net *net); + + /** + * @brief Makes the terminal to cluster ID connections of the device model + */ + void make_device_model_connections (db::DeviceModel *dm, const connected_clusters_type &clusters); + }; } diff --git a/src/db/unit_tests/dbLayoutToNetlistReaderTests.cc b/src/db/unit_tests/dbLayoutToNetlistReaderTests.cc index 9e37f997a..8aa43816a 100644 --- a/src/db/unit_tests/dbLayoutToNetlistReaderTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistReaderTests.cc @@ -63,4 +63,27 @@ TEST(1_ReaderBasic) tl::absolute_file_path (path), tl::absolute_file_path (au_path))); } + + +#if 0 + + std::string path = tmp_file ("tmp_l2nwriter_1.txt"); + { + tl::OutputStream stream (path); + db::LayoutToNetlistStandardWriter writer (stream, false); + writer.write (&l2n); + } + + std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au.txt"); + + tl::InputStream is (path); + tl::InputStream is_au (au_path); + + if (is.read_all () != is_au.read_all ()) { + _this->raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s", + tl::absolute_file_path (path), + tl::absolute_file_path (au_path))); + } + +#endif } diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 799d1c791..4af8413b8 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -1047,10 +1047,19 @@ TEST(13_DeviceModel) db::Netlist nl; db::DeviceModel *dm = new db::DeviceModel (0, "name"); + nl.add_device_model (dm); + EXPECT_EQ (dm->netlist () == &nl, true); + EXPECT_EQ (dm->device_class () == 0, true); EXPECT_EQ (dm->name (), "name"); + EXPECT_EQ (nl.device_model_by_name ("name") == dm, true); + EXPECT_EQ (nl.device_model_by_name ("name2") == 0, true); + EXPECT_EQ (nl.device_model_by_name ("does_not_exist") == 0, true); dm->set_name ("name2"); EXPECT_EQ (dm->name (), "name2"); + EXPECT_EQ (nl.device_model_by_name ("name") == 0, true); + EXPECT_EQ (nl.device_model_by_name ("name2") == dm, true); + EXPECT_EQ (nl.device_model_by_name ("does_not_exist") == 0, true); dm->set_cluster_id_for_terminal (1, 17); dm->set_cluster_id_for_terminal (0, 42); @@ -1058,10 +1067,10 @@ TEST(13_DeviceModel) EXPECT_EQ (dm->cluster_id_for_terminal (1), size_t (17)); dm->set_cell_index (5); + EXPECT_EQ (nl.device_model_by_cell_index (5) == dm, true); + EXPECT_EQ (nl.device_model_by_cell_index (17) == 0, true); EXPECT_EQ (dm->cell_index (), db::cell_index_type (5)); - nl.add_device_model (dm); - EXPECT_EQ (dm->netlist () == &nl, true); EXPECT_EQ (nl.begin_device_models () == nl.end_device_models (), false); EXPECT_EQ (nl.begin_device_models ()->name (), "name2"); diff --git a/testdata/algo/l2n_writer_au.txt b/testdata/algo/l2n_writer_au.txt index 7329fa2ce..901b8799a 100644 --- a/testdata/algo/l2n_writer_au.txt +++ b/testdata/algo/l2n_writer_au.txt @@ -82,8 +82,6 @@ device(D$NMOS$1 NMOS # Circuit section # Circuits are the hierarchical building blocks of the netlist. - -# Circuit INV2 circuit(INV2 # Nets with their geometries @@ -91,9 +89,7 @@ circuit(INV2 rect(poly -525 -250 -275 2250) rect(poly -1700 1620 -400 1980) rect(poly -525 -800 -275 800) - rect(poly -525 -475 -275 475) rect(poly -525 2000 -275 3600) - rect(poly -525 2325 -275 3275) rect(poly_lbl -801 1799 -799 1801) rect(poly_cont -1630 1690 -1410 1910) ) @@ -101,9 +97,7 @@ circuit(INV2 rect(poly 275 -250 525 2250) rect(poly 220 820 580 1180) rect(poly 275 2000 525 3600) - rect(poly 275 2325 525 3275) rect(poly 275 -800 525 800) - rect(poly 275 -475 525 475) rect(diff_cont -910 2490 -690 2710) rect(diff_cont -910 2890 -690 3110) rect(diff_cont -910 -310 -690 -90) @@ -114,8 +108,6 @@ circuit(INV2 rect(metal1 -980 2420 -620 3180) rect(metal1 -980 -380 -620 380) rect(psd -1050 2325 -525 3275) - rect(psd -1050 2325 -525 3275) - rect(nsd -1050 -475 -525 475) rect(nsd -1050 -475 -525 475) ) net(OUT @@ -128,8 +120,6 @@ circuit(INV2 rect(metal1 620 -380 980 380) rect(metal1_lbl 799 1799 801 1801) rect(psd 525 2325 1050 3275) - rect(psd 525 2325 1050 3275) - rect(nsd 525 -475 1050 475) rect(nsd 525 -475 1050 475) ) net($4 @@ -143,8 +133,6 @@ circuit(INV2 rect(via1 -125 75 125 325) rect(metal2 -1400 -450 1400 450) rect(nsd -275 -475 275 475) - rect(nsd -275 -475 275 475) - rect(nsd -275 -475 275 475) ) net($5 rect(diff_cont -110 2490 110 2710) @@ -157,8 +145,6 @@ circuit(INV2 rect(via1 -125 2875 125 3125) rect(metal2 -1400 2350 1400 3250) rect(psd -275 2325 275 3275) - rect(psd -275 2325 275 3275) - rect(psd -275 2325 275 3275) ) # Outgoing pins and their connections to nets @@ -211,8 +197,6 @@ circuit(INV2 ) ) - -# Circuit RINGO circuit(RINGO # Nets with their geometries