diff --git a/src/db/db/db.pro b/src/db/db/db.pro index f45a74d1a..8401e0aef 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -160,7 +160,8 @@ SOURCES = \ dbSubCircuit.cc \ dbPin.cc \ dbLayoutToNetlistReader.cc \ - dbLayoutToNetlistWriter.cc + dbLayoutToNetlistWriter.cc \ + dbDeviceModel.cc HEADERS = \ dbArray.h \ @@ -285,7 +286,8 @@ HEADERS = \ dbPin.h \ dbSubCircuit.h \ dbLayoutToNetlistReader.h \ - dbLayoutToNetlistWriter.h + dbLayoutToNetlistWriter.h \ + dbDeviceModel.h !equals(HAVE_QT, "0") { diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index 7acd9c544..4fff06e8c 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -330,6 +330,17 @@ void Circuit::translate_device_classes (const std::map &map) +{ + for (device_iterator i = m_devices.begin (); i != m_devices.end (); ++i) { + if (i->device_model ()) { + std::map::const_iterator m = map.find (i->device_model ()); + tl_assert (m != map.end ()); + i->set_device_model (m->second); + } + } +} + void Circuit::set_pin_ref_for_pin (size_t pin_id, Net::pin_iterator iter) { if (m_pin_refs.size () < pin_id + 1) { diff --git a/src/db/db/dbCircuit.h b/src/db/db/dbCircuit.h index 98c01ecdb..14426b3f3 100644 --- a/src/db/db/dbCircuit.h +++ b/src/db/db/dbCircuit.h @@ -620,6 +620,7 @@ private: void translate_circuits (const std::map &map); void translate_device_classes (const std::map &map); + void translate_device_models (const std::map &map); void set_netlist (Netlist *netlist); bool combine_parallel_devices (const db::DeviceClass &cls); bool combine_serial_devices (const db::DeviceClass &cls); diff --git a/src/db/db/dbDevice.cc b/src/db/db/dbDevice.cc index 8e0f6ce54..65cacbad4 100644 --- a/src/db/db/dbDevice.cc +++ b/src/db/db/dbDevice.cc @@ -31,7 +31,7 @@ namespace db // Device class implementation Device::Device () - : mp_device_class (0), m_cell_index (std::numeric_limits::max ()), m_id (0), mp_circuit (0) + : mp_device_class (0), mp_device_model (0), m_id (0), mp_circuit (0) { // .. nothing yet .. } @@ -46,13 +46,19 @@ Device::~Device () } Device::Device (DeviceClass *device_class, const std::string &name) - : mp_device_class (device_class), m_name (name), m_cell_index (std::numeric_limits::max ()), m_id (0), mp_circuit (0) + : mp_device_class (device_class), mp_device_model (0), m_name (name), m_id (0), mp_circuit (0) +{ + // .. nothing yet .. +} + +Device::Device (DeviceClass *device_class, DeviceModel *device_model, const std::string &name) + : mp_device_class (device_class), mp_device_model (device_model), m_name (name), m_id (0), mp_circuit (0) { // .. nothing yet .. } Device::Device (const Device &other) - : tl::Object (other), mp_device_class (0), m_cell_index (std::numeric_limits::max ()), m_id (0), mp_circuit (0) + : tl::Object (other), mp_device_class (0), mp_device_model (0), m_id (0), mp_circuit (0) { operator= (other); } @@ -62,10 +68,9 @@ Device &Device::operator= (const Device &other) if (this != &other) { m_name = other.m_name; m_position = other.m_position; - m_cell_index = other.m_cell_index; - m_terminal_cluster_ids = other.m_terminal_cluster_ids; m_parameters = other.m_parameters; mp_device_class = other.mp_device_class; + mp_device_model = other.mp_device_model; } return *this; } @@ -88,24 +93,6 @@ void Device::set_position (const db::DPoint &pt) m_position = pt; } -void Device::set_cell_index (db::cell_index_type ci) -{ - m_cell_index = ci; -} - -size_t Device::cluster_id_for_terminal (size_t terminal_id) const -{ - return terminal_id < m_terminal_cluster_ids.size () ? m_terminal_cluster_ids [terminal_id] : 0; -} - -void Device::set_cluster_id_for_terminal (size_t terminal_id, size_t cluster_id) -{ - if (m_terminal_cluster_ids.size () <= terminal_id) { - m_terminal_cluster_ids.resize (terminal_id + 1, 0); - } - m_terminal_cluster_ids [terminal_id] = cluster_id; -} - void Device::set_terminal_ref_for_terminal (size_t terminal_id, Net::terminal_iterator iter) { if (m_terminal_refs.size () < terminal_id + 1) { diff --git a/src/db/db/dbDevice.h b/src/db/db/dbDevice.h index 8074e66fb..b3f6109c9 100644 --- a/src/db/db/dbDevice.h +++ b/src/db/db/dbDevice.h @@ -36,6 +36,7 @@ namespace db class Circuit; class DeviceClass; +class DeviceModel; /** * @brief An actual device @@ -63,6 +64,11 @@ public: */ Device (DeviceClass *device_class, const std::string &name = std::string ()); + /** + * @brief The constructor + */ + Device (DeviceClass *device_class, DeviceModel *device_model, const std::string &name = std::string ()); + /** * @brief Copy constructor */ @@ -86,6 +92,29 @@ public: return mp_device_class; } + /** + * @brief Sets the device class + */ + void set_device_class (DeviceClass *dc) + { + mp_device_class = dc; + } + /** + * @brief Gets the device model + */ + const DeviceModel *device_model () const + { + return mp_device_model; + } + + /** + * @brief Sets the device model + */ + void set_device_model (DeviceModel *dm) + { + mp_device_model = dm; + } + /** * @brief Gets the device ID * The ID is a unique integer which identifies the device. @@ -145,32 +174,6 @@ public: return m_position; } - /** - * @brief Sets the device cell index - * In the layout, a device is represented by a cell. This attribute gives the index of this - * cell. - */ - void set_cell_index (db::cell_index_type ci); - - /** - * @brief Gets the device cell index - */ - db::cell_index_type cell_index () const - { - return m_cell_index; - } - - /** - * @brief Gets the cluster ID for a given terminal - * This attribute connects the device terminal with a terminal cluster - */ - size_t cluster_id_for_terminal (size_t terminal_id) const; - - /** - * @brief Sets the cluster ID for a given terminal - */ - void set_cluster_id_for_terminal (size_t terminal_id, size_t cluster_id); - /** * @brief Gets the net attached to a specific terminal * Returns 0 if no net is attached. @@ -223,11 +226,10 @@ private: friend class Net; DeviceClass *mp_device_class; + DeviceModel *mp_device_model; std::string m_name; db::DPoint m_position; - db::cell_index_type m_cell_index; std::vector m_terminal_refs; - std::vector m_terminal_cluster_ids; std::vector m_parameters; size_t m_id; Circuit *mp_circuit; @@ -237,14 +239,6 @@ private: */ void set_terminal_ref_for_terminal (size_t terminal_id, Net::terminal_iterator iter); - /** - * @brief Sets the device class - */ - void set_device_class (DeviceClass *dc) - { - mp_device_class = dc; - } - /** * @brief Sets the device ID */ diff --git a/src/db/db/dbDeviceModel.cc b/src/db/db/dbDeviceModel.cc new file mode 100644 index 000000000..e33d9dc3d --- /dev/null +++ b/src/db/db/dbDeviceModel.cc @@ -0,0 +1,87 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2019 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbDeviceModel.h" +#include "dbCircuit.h" + +namespace db +{ + +// -------------------------------------------------------------------------------- +// DeviceModel class implementation + +DeviceModel::~DeviceModel () +{ + // .. nothing yet .. +} + +DeviceModel::DeviceModel (const std::string &name) + : m_name (name), m_cell_index (std::numeric_limits::max ()), mp_netlist (0) +{ + // .. nothing yet .. +} + +DeviceModel::DeviceModel (const DeviceModel &other) + : tl::Object (other), m_cell_index (std::numeric_limits::max ()), mp_netlist (0) +{ + operator= (other); +} + +DeviceModel &DeviceModel::operator= (const DeviceModel &other) +{ + if (this != &other) { + m_name = other.m_name; + m_cell_index = other.m_cell_index; + m_terminal_cluster_ids = other.m_terminal_cluster_ids; + } + return *this; +} + +void DeviceModel::set_netlist (Netlist *netlist) +{ + mp_netlist = netlist; +} + +void DeviceModel::set_name (const std::string &n) +{ + m_name = n; +} + +void DeviceModel::set_cell_index (db::cell_index_type ci) +{ + m_cell_index = ci; +} + +size_t DeviceModel::cluster_id_for_terminal (size_t terminal_id) const +{ + return terminal_id < m_terminal_cluster_ids.size () ? m_terminal_cluster_ids [terminal_id] : 0; +} + +void DeviceModel::set_cluster_id_for_terminal (size_t terminal_id, size_t cluster_id) +{ + if (m_terminal_cluster_ids.size () <= terminal_id) { + m_terminal_cluster_ids.resize (terminal_id + 1, 0); + } + m_terminal_cluster_ids [terminal_id] = cluster_id; +} + +} diff --git a/src/db/db/dbDeviceModel.h b/src/db/db/dbDeviceModel.h new file mode 100644 index 000000000..1b0406179 --- /dev/null +++ b/src/db/db/dbDeviceModel.h @@ -0,0 +1,142 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2019 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _HDR_dbDeviceModel +#define _HDR_dbDeviceModel + +#include "dbCommon.h" +#include "dbNet.h" +#include "dbPoint.h" + +#include "tlObject.h" + +#include + +namespace db +{ + +class Netlist; + +/** + * @brief A device model + * + * A device model represents the geometrical properties of a device. It basically links + * to a cell and clusters for indicating the terminal geometry of the device. + */ +class DB_PUBLIC DeviceModel + : public tl::Object +{ +public: + /** + * @brief The constructor + */ + DeviceModel (const std::string &name = std::string ()); + + /** + * @brief Copy constructor + */ + DeviceModel (const DeviceModel &other); + + /** + * @brief Assignment + */ + DeviceModel &operator= (const DeviceModel &other); + + /** + * @brief Destructor + */ + ~DeviceModel (); + + /** + * @brief Gets the netlist the device lives in (const version) + * This pointer is 0 if the device model isn't added to a netlist + */ + const Netlist *netlist () const + { + return mp_netlist; + } + + /** + * @brief Gets the netlist the device lives in (non-const version) + * This pointer is 0 if the device model isn't added to a netlist + */ + Netlist *netlist () + { + return mp_netlist; + } + + /** + * @brief Sets the name + */ + void set_name (const std::string &n); + + /** + * @brief Gets the name + */ + const std::string &name () const + { + return m_name; + } + + /** + * @brief Sets the device cell index + * In the layout, a device is represented by a cell. This attribute gives the index of this + * cell. + */ + void set_cell_index (db::cell_index_type ci); + + /** + * @brief Gets the device cell index + */ + db::cell_index_type cell_index () const + { + return m_cell_index; + } + + /** + * @brief Gets the cluster ID for a given terminal + * This attribute connects the device terminal with a terminal cluster + */ + size_t cluster_id_for_terminal (size_t terminal_id) const; + + /** + * @brief Sets the cluster ID for a given terminal + */ + void set_cluster_id_for_terminal (size_t terminal_id, size_t cluster_id); + +private: + friend class Netlist; + + std::string m_name; + db::cell_index_type m_cell_index; + std::vector m_terminal_cluster_ids; + Netlist *mp_netlist; + + /** + * @brief Sets the netlist + */ + void set_netlist (Netlist *netlist); +}; + +} + +#endif diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index 8a5135d05..d48fb90bf 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -68,10 +68,18 @@ Netlist &Netlist::operator= (const Netlist &other) m_device_classes.push_back (dc_new); } + std::map dmt; + for (const_device_model_iterator dm = other.begin_device_models (); dm != other.end_device_models (); ++dm) { + DeviceModel *dm_new = new DeviceModel (*dm); + dmt [dm.operator-> ()] = dm_new; + m_device_models.push_back (dm_new); + } + std::map ct; for (const_circuit_iterator i = other.begin_circuits (); i != other.end_circuits (); ++i) { Circuit *ct_new = new Circuit (*i); ct_new->translate_device_classes (dct); + ct_new->translate_device_models (dmt); ct [i.operator-> ()] = ct_new; add_circuit (ct_new); } @@ -332,6 +340,7 @@ Netlist::const_bottom_up_circuit_iterator Netlist::end_bottom_up () const void Netlist::clear () { m_device_classes.clear (); + m_device_models.clear (); m_circuits.clear (); } @@ -359,6 +368,18 @@ void Netlist::remove_device_class (DeviceClass *device_class) m_device_classes.erase (device_class); } +void Netlist::add_device_model (DeviceModel *device_model) +{ + m_device_models.push_back (device_model); + device_model->set_netlist (this); +} + +void Netlist::remove_device_model (DeviceModel *device_model) +{ + device_model->set_netlist (0); + m_device_models.erase (device_model); +} + void Netlist::purge_nets () { for (circuit_iterator c = begin_circuits (); c != end_circuits (); ++c) { diff --git a/src/db/db/dbNetlist.h b/src/db/db/dbNetlist.h index 36dc2676c..739c7888a 100644 --- a/src/db/db/dbNetlist.h +++ b/src/db/db/dbNetlist.h @@ -26,6 +26,7 @@ #include "dbCommon.h" #include "dbCircuit.h" #include "dbDeviceClass.h" +#include "dbDeviceModel.h" #include "tlVector.h" @@ -51,6 +52,9 @@ public: typedef tl::shared_collection device_class_list; typedef device_class_list::const_iterator const_device_class_iterator; typedef device_class_list::iterator device_class_iterator; + typedef tl::shared_collection device_model_list; + typedef device_model_list::const_iterator const_device_model_iterator; + typedef device_model_list::iterator device_model_iterator; typedef tl::vector::const_iterator top_down_circuit_iterator; typedef tl::vector::const_iterator const_top_down_circuit_iterator; typedef tl::vector::const_reverse_iterator bottom_up_circuit_iterator; @@ -301,6 +305,50 @@ public: return m_device_classes.end (); } + /** + * @brief Adds a device model to this netlist + * + * The netlist takes over ownership of the object. + */ + void add_device_model (DeviceModel *device_model); + + /** + * @brief Deletes a device model from the netlist + */ + void remove_device_model (DeviceModel *device_model); + + /** + * @brief Begin iterator for the device models of the netlist (non-const version) + */ + device_model_iterator begin_device_models () + { + return m_device_models.begin (); + } + + /** + * @brief End iterator for the device models of the netlist (non-const version) + */ + device_model_iterator end_device_models () + { + return m_device_models.end (); + } + + /** + * @brief Begin iterator for the device models of the netlist (const version) + */ + const_device_model_iterator begin_device_models () const + { + return m_device_models.begin (); + } + + /** + * @brief End iterator for the device models of the netlist (const version) + */ + const_device_model_iterator end_device_models () const + { + return m_device_models.end (); + } + /** * @brief Purge unused nets * @@ -338,6 +386,7 @@ private: circuit_list m_circuits; device_class_list m_device_classes; + device_model_list m_device_models; bool m_valid_topology; int m_lock_count; tl::vector m_top_down_circuits; diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index 74b38e3b9..0f12dd3c8 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -281,12 +281,17 @@ void NetlistDeviceExtractor::push_new_devices () db::PropertiesRepository::properties_set ps; - std::map::iterator c = m_device_cells.find (key); + std::map >::iterator c = m_device_cells.find (key); if (c == m_device_cells.end ()) { std::string cell_name = "D$" + mp_device_class->name (); db::Cell &device_cell = mp_layout->cell (mp_layout->add_cell (cell_name.c_str ())); - c = m_device_cells.insert (std::make_pair (key, device_cell.cell_index ())).first; + + db::DeviceModel *dm = new db::DeviceModel (mp_layout->cell_name (device_cell.cell_index ())); + m_netlist->add_device_model (dm); + dm->set_cell_index (device_cell.cell_index ()); + + c = m_device_cells.insert (std::make_pair (key, std::make_pair (device_cell.cell_index (), dm))).first; // attach the device class ID to the cell ps.clear (); @@ -305,6 +310,7 @@ void NetlistDeviceExtractor::push_new_devices () // initialize the local cluster (will not be extracted) db::local_cluster *lc = cc.insert (); lc->add_attr (pi); + dm->set_cluster_id_for_terminal (t->first, lc->id ()); // build the cell shapes and local cluster for (geometry_per_layer_type::const_iterator l = t->second.begin (); l != t->second.end (); ++l) { @@ -322,14 +328,14 @@ void NetlistDeviceExtractor::push_new_devices () } // make the cell index known to the device - device->set_cell_index (c->second); + device->set_device_model (c->second.second); // Build a property set for the device ID ps.clear (); ps.insert (std::make_pair (m_device_id_propname_id, tl::Variant (d->first))); db::properties_id_type pi = mp_layout->properties_repository ().properties_id (ps); - db::CellInstArrayWithProperties inst (db::CellInstArray (db::CellInst (c->second), db::Trans (disp)), pi); + db::CellInstArrayWithProperties inst (db::CellInstArray (db::CellInst (c->second.first), db::Trans (disp)), pi); mp_layout->cell (m_cell_index).insert (inst); } diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index 3626e4876..0cc045ceb 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -513,7 +513,7 @@ private: std::vector m_layers; error_list m_errors; std::map m_new_devices; - std::map m_device_cells; + std::map > m_device_cells; // no copying NetlistDeviceExtractor (const NetlistDeviceExtractor &); diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 2d0b95248..8f88932e2 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -208,7 +208,6 @@ void NetlistExtractor::connect_devices (db::Circuit *circuit, size_t tid = j->second.to (); device->connect_terminal (tid, net); - device->set_cluster_id_for_terminal (tid, i->id ()); } diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index c088750cd..1009f26fd 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -134,6 +134,36 @@ Class decl_dbDevice ("db", "Device", "This class has been added in version 0.26." ); +#if 0 +// TODO: activate once the geometry API is opened (clusters at al.) +Class decl_dbDeviceModel ("db", "DeviceModel", + gsi::method ("netlist", (db::Netlist *(db::DeviceModel::*) ()) &db::DeviceModel::netlist, + "@brief Gets the netlist the device model lives in." + ) + + gsi::method ("name=", &db::DeviceModel::set_name, gsi::arg ("name"), + "@brief Sets the name of the device model.\n" + "Device names are used to name a device model inside a netlist file. " + "Device names should be unique within a netlist." + ) + + gsi::method ("name", &db::DeviceModel::name, + "@brief Gets the name of the device model.\n" + ) + + gsi::method ("cell_index", &db::DeviceModel::cell_index, + "@brief Gets the cell index of the device model.\n" + "This is the cell that represents the device." + ) + + gsi::method ("cluster_id_for_terminal", &db::DeviceModel::cluster_id_for_terminal, gsi::arg ("terminal_id"), + "@brief Gets the cluster ID for the given terminal.\n" + "The cluster ID links the terminal to geometrical shapes within the clusters of the cell (see \\cell_index)" + ), + "@brief A geometrical device model\n" + "This class represents the geometrical model for the device. It links into the extracted layout " + "to a cell which holds the terminal shapes for the device.\n" + "\n" + "This class has been added in version 0.26." +); +#endif + static void subcircuit_connect_pin1 (db::SubCircuit *subcircuit, const db::Pin *pin, db::Net *net) { if (pin) { diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index 44d09a4a9..4eab0b589 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -93,12 +93,14 @@ static void dump_nets_to_layout (const db::Netlist &nl, const db::hier_clusters< for (db::Circuit::const_device_iterator d = c->begin_devices (); d != c->end_devices (); ++d) { - if (device_cells_seen.find (d->cell_index ()) != device_cells_seen.end ()) { + db::cell_index_type dci = d->device_model ()->cell_index (); + + if (device_cells_seen.find (dci) != device_cells_seen.end ()) { continue; } - db::Cell &device_cell = ly.cell (cmap.cell_mapping (d->cell_index ())); - device_cells_seen.insert (d->cell_index ()); + db::Cell &device_cell = ly.cell (cmap.cell_mapping (dci)); + device_cells_seen.insert (dci); std::string ps; const std::vector &pd = d->device_class ()->parameter_definitions (); @@ -112,7 +114,7 @@ static void dump_nets_to_layout (const db::Netlist &nl, const db::hier_clusters< const std::vector &td = d->device_class ()->terminal_definitions (); for (std::vector::const_iterator t = td.begin (); t != td.end (); ++t) { - const db::local_cluster &dc = clusters.clusters_per_cell (d->cell_index ()).cluster_by_id (d->cluster_id_for_terminal (t->id ())); + const db::local_cluster &dc = clusters.clusters_per_cell (dci).cluster_by_id (d->device_model ()->cluster_id_for_terminal (t->id ())); for (std::map::const_iterator m = lmap.begin (); m != lmap.end (); ++m) { db::Shapes &target = device_cell.shapes (m->second); diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index ab1e4df29..91a2f5058 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -124,7 +124,11 @@ static std::string netlist2 (const db::Circuit &c) pins += "="; pins += net ? net->name () : std::string ("(null)"); } - res += " D" + d->name () + ":" + pins + "\n"; + res += " D" + d->name (); + if (d->device_model ()) { + res += "/" + d->device_model ()->name (); + } + res += ":" + pins + "\n"; } for (db::Circuit::const_subcircuit_iterator s = c.begin_subcircuits (); s != c.end_subcircuits (); ++s) { @@ -497,6 +501,12 @@ TEST(4_NetlistSubcircuits) dc->add_terminal_definition (db::DeviceTerminalDefinition ("B", "")); nl->add_device_class (dc); + db::DeviceModel *dm = new db::DeviceModel (); + dm->set_name ("dm2"); + dm->set_cell_index (42); + dm->set_cluster_id_for_terminal (0, 17); + nl->add_device_model (dm); + db::Circuit *c1 = new db::Circuit (); c1->set_cell_index (17); EXPECT_EQ (c1->netlist (), 0); @@ -526,8 +536,9 @@ TEST(4_NetlistSubcircuits) EXPECT_EQ (nl->circuit_by_cell_index (41) == 0, true); EXPECT_EQ (nl->circuit_by_cell_index (42) == c2, true); - db::Device *d = new db::Device (dc, "D"); + db::Device *d = new db::Device (dc, dm, "D"); c2->add_device (d); + EXPECT_EQ (d->device_model ()->name (), "dm2"); EXPECT_EQ (refs2string (c2), ""); db::SubCircuit *sc1 = new db::SubCircuit (c2); @@ -601,7 +612,7 @@ TEST(4_NetlistSubcircuits) " Xsc1:c2p1=n1a,c2p2=n1b\n" " Xsc2:c2p1=n1b,c2p2=n1c\n" "c2:c2p1=n2a,c2p2=n2b\n" - " DD:A=n2a,B=n2b\n" + " DD/dm2:A=n2a,B=n2b\n" ); // check netlist @@ -636,7 +647,7 @@ TEST(4_NetlistSubcircuits) " Xsc1:c2p1=n1a,c2p2=n1b\n" " Xsc2:c2p1=n1b,c2p2=n1c\n" "c2:c2p1=n2a,c2p2=n2b\n" - " DD:A=n2a,B=n2b\n" + " DD/dm2:A=n2a,B=n2b\n" ); // check netlist @@ -1028,3 +1039,30 @@ TEST(12_NetlistTopology) EXPECT_EQ (td2string (nl.get ()), "c1,c3,c2"); EXPECT_EQ (bu2string (nl.get ()), "c2,c3,c1"); } + +TEST(13_DeviceModel) +{ + db::Netlist nl; + + db::DeviceModel *dm = new db::DeviceModel ("name"); + EXPECT_EQ (dm->name (), "name"); + dm->set_name ("name2"); + EXPECT_EQ (dm->name (), "name2"); + + dm->set_cluster_id_for_terminal (1, 17); + dm->set_cluster_id_for_terminal (0, 42); + EXPECT_EQ (dm->cluster_id_for_terminal (0), size_t (42)); + EXPECT_EQ (dm->cluster_id_for_terminal (1), size_t (17)); + + dm->set_cell_index (5); + 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"); + + nl.remove_device_model (dm); + + EXPECT_EQ (nl.begin_device_models () == nl.end_device_models (), true); +}