mirror of https://github.com/KLayout/klayout.git
WIP: added concept of device model.
This commit is contained in:
parent
5962d66940
commit
4cb8982ca2
|
|
@ -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") {
|
||||
|
||||
|
|
|
|||
|
|
@ -330,6 +330,17 @@ void Circuit::translate_device_classes (const std::map<const DeviceClass *, Devi
|
|||
}
|
||||
}
|
||||
|
||||
void Circuit::translate_device_models (const std::map<const DeviceModel *, DeviceModel *> &map)
|
||||
{
|
||||
for (device_iterator i = m_devices.begin (); i != m_devices.end (); ++i) {
|
||||
if (i->device_model ()) {
|
||||
std::map<const DeviceModel *, DeviceModel *>::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) {
|
||||
|
|
|
|||
|
|
@ -620,6 +620,7 @@ private:
|
|||
|
||||
void translate_circuits (const std::map<const Circuit *, Circuit *> &map);
|
||||
void translate_device_classes (const std::map<const DeviceClass *, DeviceClass *> &map);
|
||||
void translate_device_models (const std::map<const DeviceModel *, DeviceModel *> &map);
|
||||
void set_netlist (Netlist *netlist);
|
||||
bool combine_parallel_devices (const db::DeviceClass &cls);
|
||||
bool combine_serial_devices (const db::DeviceClass &cls);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace db
|
|||
// Device class implementation
|
||||
|
||||
Device::Device ()
|
||||
: mp_device_class (0), m_cell_index (std::numeric_limits<db::cell_index_type>::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<db::cell_index_type>::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<db::cell_index_type>::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) {
|
||||
|
|
|
|||
|
|
@ -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<Net::terminal_iterator> m_terminal_refs;
|
||||
std::vector<size_t> m_terminal_cluster_ids;
|
||||
std::vector<double> 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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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<db::cell_index_type>::max ()), mp_netlist (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
DeviceModel::DeviceModel (const DeviceModel &other)
|
||||
: tl::Object (other), m_cell_index (std::numeric_limits<db::cell_index_type>::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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 <vector>
|
||||
|
||||
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<size_t> m_terminal_cluster_ids;
|
||||
Netlist *mp_netlist;
|
||||
|
||||
/**
|
||||
* @brief Sets the netlist
|
||||
*/
|
||||
void set_netlist (Netlist *netlist);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -68,10 +68,18 @@ Netlist &Netlist::operator= (const Netlist &other)
|
|||
m_device_classes.push_back (dc_new);
|
||||
}
|
||||
|
||||
std::map<const DeviceModel *, DeviceModel *> 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<const Circuit *, Circuit *> 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) {
|
||||
|
|
|
|||
|
|
@ -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<DeviceClass> 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<DeviceModel> device_model_list;
|
||||
typedef device_model_list::const_iterator const_device_model_iterator;
|
||||
typedef device_model_list::iterator device_model_iterator;
|
||||
typedef tl::vector<Circuit *>::const_iterator top_down_circuit_iterator;
|
||||
typedef tl::vector<const Circuit *>::const_iterator const_top_down_circuit_iterator;
|
||||
typedef tl::vector<Circuit *>::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<Circuit *> m_top_down_circuits;
|
||||
|
|
|
|||
|
|
@ -281,12 +281,17 @@ void NetlistDeviceExtractor::push_new_devices ()
|
|||
|
||||
db::PropertiesRepository::properties_set ps;
|
||||
|
||||
std::map<DeviceCellKey, db::cell_index_type>::iterator c = m_device_cells.find (key);
|
||||
std::map<DeviceCellKey, std::pair<db::cell_index_type, db::DeviceModel *> >::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<db::PolygonRef> *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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ private:
|
|||
std::vector<unsigned int> m_layers;
|
||||
error_list m_errors;
|
||||
std::map<size_t, geometry_per_terminal_type> m_new_devices;
|
||||
std::map<DeviceCellKey, db::cell_index_type> m_device_cells;
|
||||
std::map<DeviceCellKey, std::pair<db::cell_index_type, db::DeviceModel *> > m_device_cells;
|
||||
|
||||
// no copying
|
||||
NetlistDeviceExtractor (const NetlistDeviceExtractor &);
|
||||
|
|
|
|||
|
|
@ -208,7 +208,6 @@ void NetlistExtractor::connect_devices (db::Circuit *circuit,
|
|||
|
||||
size_t tid = j->second.to<size_t> ();
|
||||
device->connect_terminal (tid, net);
|
||||
device->set_cluster_id_for_terminal (tid, i->id ());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,6 +134,36 @@ Class<db::Device> 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<db::DeviceModel> 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) {
|
||||
|
|
|
|||
|
|
@ -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<db::DeviceParameterDefinition> &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<db::DeviceTerminalDefinition> &td = d->device_class ()->terminal_definitions ();
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator t = td.begin (); t != td.end (); ++t) {
|
||||
|
||||
const db::local_cluster<db::PolygonRef> &dc = clusters.clusters_per_cell (d->cell_index ()).cluster_by_id (d->cluster_id_for_terminal (t->id ()));
|
||||
const db::local_cluster<db::PolygonRef> &dc = clusters.clusters_per_cell (dci).cluster_by_id (d->device_model ()->cluster_id_for_terminal (t->id ()));
|
||||
|
||||
for (std::map<unsigned int, unsigned int>::const_iterator m = lmap.begin (); m != lmap.end (); ++m) {
|
||||
db::Shapes &target = device_cell.shapes (m->second);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue