mirror of https://github.com/KLayout/klayout.git
WIP: more query functions for netlist classes (i.e. net by name, device by name etc.), some refactoring, GSI bindings, tests.
This commit is contained in:
parent
425acda31a
commit
293c6f496e
|
|
@ -89,6 +89,9 @@ void Device::set_circuit (Circuit *circuit)
|
|||
void Device::set_name (const std::string &n)
|
||||
{
|
||||
m_name = n;
|
||||
if (mp_circuit) {
|
||||
mp_circuit->m_device_by_name.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
void Device::set_terminal_ref_for_terminal (size_t terminal_id, Net::terminal_iterator iter)
|
||||
|
|
@ -220,6 +223,9 @@ SubCircuit &SubCircuit::operator= (const SubCircuit &other)
|
|||
void SubCircuit::set_name (const std::string &n)
|
||||
{
|
||||
m_name = n;
|
||||
if (mp_circuit) {
|
||||
mp_circuit->m_subcircuit_by_name.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
void SubCircuit::set_trans (const db::DCplxTrans &t)
|
||||
|
|
@ -435,6 +441,9 @@ void Net::clear ()
|
|||
void Net::set_name (const std::string &name)
|
||||
{
|
||||
m_name = name;
|
||||
if (mp_circuit) {
|
||||
mp_circuit->m_net_by_name.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Net::expanded_name () const
|
||||
|
|
@ -454,6 +463,9 @@ std::string Net::expanded_name () const
|
|||
void Net::set_cluster_id (size_t ci)
|
||||
{
|
||||
m_cluster_id = ci;
|
||||
if (mp_circuit) {
|
||||
mp_circuit->m_net_by_cluster_id.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
void Net::add_pin (const NetPinRef &pin)
|
||||
|
|
@ -510,13 +522,27 @@ void Net::set_circuit (Circuit *circuit)
|
|||
// Circuit class implementation
|
||||
|
||||
Circuit::Circuit ()
|
||||
: mp_netlist (0), m_valid_device_id_table (false), m_valid_subcircuit_id_table (false), m_index (0)
|
||||
: mp_netlist (0),
|
||||
m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices),
|
||||
m_subcircuit_by_id (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
|
||||
m_net_by_cluster_id (this, &Circuit::begin_nets, &Circuit::end_nets),
|
||||
m_device_by_name (this, &Circuit::begin_devices, &Circuit::end_devices),
|
||||
m_subcircuit_by_name (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
|
||||
m_net_by_name (this, &Circuit::begin_nets, &Circuit::end_nets),
|
||||
m_index (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Circuit::Circuit (const Circuit &other)
|
||||
: mp_netlist (0), m_valid_device_id_table (false), m_valid_subcircuit_id_table (false), m_index (0)
|
||||
: mp_netlist (0),
|
||||
m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices),
|
||||
m_subcircuit_by_id (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
|
||||
m_net_by_cluster_id (this, &Circuit::begin_nets, &Circuit::end_nets),
|
||||
m_device_by_name (this, &Circuit::begin_devices, &Circuit::end_devices),
|
||||
m_subcircuit_by_name (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
|
||||
m_net_by_name (this, &Circuit::begin_nets, &Circuit::end_nets),
|
||||
m_index (0)
|
||||
{
|
||||
operator= (other);
|
||||
}
|
||||
|
|
@ -526,8 +552,12 @@ Circuit &Circuit::operator= (const Circuit &other)
|
|||
if (this != &other) {
|
||||
|
||||
m_name = other.m_name;
|
||||
invalidate_device_id_table ();
|
||||
invalidate_subcircuit_id_table ();
|
||||
m_device_by_id.invalidate ();
|
||||
m_subcircuit_by_id.invalidate ();
|
||||
m_net_by_cluster_id.invalidate ();
|
||||
m_device_by_name.invalidate ();
|
||||
m_subcircuit_by_name.invalidate ();
|
||||
m_net_by_name.invalidate ();
|
||||
|
||||
for (const_pin_iterator i = other.begin_pins (); i != other.end_pins (); ++i) {
|
||||
add_pin (*i);
|
||||
|
|
@ -592,6 +622,16 @@ const Pin *Circuit::pin_by_id (size_t id) const
|
|||
}
|
||||
}
|
||||
|
||||
const Pin *Circuit::pin_by_name (const std::string &name) const
|
||||
{
|
||||
for (Circuit::const_pin_iterator p = begin_pins (); p != end_pins (); ++p) {
|
||||
if (p->name () == name) {
|
||||
return p.operator-> ();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Circuit::clear ()
|
||||
{
|
||||
m_name.clear ();
|
||||
|
|
@ -599,20 +639,28 @@ void Circuit::clear ()
|
|||
m_devices.clear ();
|
||||
m_nets.clear ();
|
||||
m_subcircuits.clear ();
|
||||
m_device_id_table.clear ();
|
||||
m_subcircuit_id_table.clear ();
|
||||
m_valid_device_id_table = false;
|
||||
m_valid_subcircuit_id_table = false;
|
||||
m_device_by_id.invalidate ();
|
||||
m_subcircuit_by_id.invalidate ();
|
||||
m_net_by_cluster_id.invalidate ();
|
||||
m_device_by_name.invalidate ();
|
||||
m_subcircuit_by_name.invalidate ();
|
||||
m_net_by_name.invalidate ();
|
||||
}
|
||||
|
||||
void Circuit::set_name (const std::string &name)
|
||||
{
|
||||
m_name = name;
|
||||
if (mp_netlist) {
|
||||
mp_netlist->m_circuit_by_name.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
void Circuit::set_cell_index (const db::cell_index_type ci)
|
||||
{
|
||||
m_cell_index = ci;
|
||||
if (mp_netlist) {
|
||||
mp_netlist->m_circuit_by_cell_index.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
Circuit::child_circuit_iterator Circuit::begin_children ()
|
||||
|
|
@ -674,11 +722,15 @@ void Circuit::add_net (Net *net)
|
|||
{
|
||||
m_nets.push_back (net);
|
||||
net->set_circuit (this);
|
||||
m_net_by_cluster_id.invalidate ();
|
||||
m_net_by_name.invalidate ();
|
||||
}
|
||||
|
||||
void Circuit::remove_net (Net *net)
|
||||
{
|
||||
m_nets.erase (net);
|
||||
m_net_by_cluster_id.invalidate ();
|
||||
m_net_by_name.invalidate ();
|
||||
}
|
||||
|
||||
void Circuit::add_device (Device *device)
|
||||
|
|
@ -693,39 +745,15 @@ void Circuit::add_device (Device *device)
|
|||
device->set_id (id + 1);
|
||||
|
||||
m_devices.push_back (device);
|
||||
invalidate_device_id_table ();
|
||||
m_device_by_id.invalidate ();
|
||||
m_device_by_name.invalidate ();
|
||||
}
|
||||
|
||||
void Circuit::remove_device (Device *device)
|
||||
{
|
||||
m_devices.erase (device);
|
||||
invalidate_device_id_table ();
|
||||
}
|
||||
|
||||
void Circuit::validate_device_id_table ()
|
||||
{
|
||||
m_device_id_table.clear ();
|
||||
for (device_iterator d = begin_devices (); d != end_devices (); ++d) {
|
||||
m_device_id_table.insert (std::make_pair (d->id (), d.operator-> ()));
|
||||
}
|
||||
|
||||
m_valid_device_id_table = true;
|
||||
}
|
||||
|
||||
void Circuit::invalidate_device_id_table ()
|
||||
{
|
||||
m_valid_device_id_table = false;
|
||||
m_device_id_table.clear ();
|
||||
}
|
||||
|
||||
Device *Circuit::device_by_id (size_t id)
|
||||
{
|
||||
if (! m_valid_device_id_table) {
|
||||
validate_device_id_table ();
|
||||
}
|
||||
|
||||
std::map<size_t, Device *>::const_iterator d = m_device_id_table.find (id);
|
||||
return d != m_device_id_table.end () ? d->second : 0;
|
||||
m_device_by_id.invalidate ();
|
||||
m_device_by_name.invalidate ();
|
||||
}
|
||||
|
||||
void Circuit::add_subcircuit (SubCircuit *subcircuit)
|
||||
|
|
@ -740,7 +768,8 @@ void Circuit::add_subcircuit (SubCircuit *subcircuit)
|
|||
subcircuit->set_id (id + 1);
|
||||
|
||||
m_subcircuits.push_back (subcircuit);
|
||||
invalidate_subcircuit_id_table ();
|
||||
m_subcircuit_by_id.invalidate ();
|
||||
m_subcircuit_by_name.invalidate ();
|
||||
|
||||
if (mp_netlist) {
|
||||
mp_netlist->invalidate_topology ();
|
||||
|
|
@ -750,39 +779,14 @@ void Circuit::add_subcircuit (SubCircuit *subcircuit)
|
|||
void Circuit::remove_subcircuit (SubCircuit *subcircuit)
|
||||
{
|
||||
m_subcircuits.erase (subcircuit);
|
||||
invalidate_subcircuit_id_table ();
|
||||
m_subcircuit_by_id.invalidate ();
|
||||
m_subcircuit_by_name.invalidate ();
|
||||
|
||||
if (mp_netlist) {
|
||||
mp_netlist->invalidate_topology ();
|
||||
}
|
||||
}
|
||||
|
||||
void Circuit::validate_subcircuit_id_table ()
|
||||
{
|
||||
m_subcircuit_id_table.clear ();
|
||||
for (subcircuit_iterator d = begin_subcircuits (); d != end_subcircuits (); ++d) {
|
||||
m_subcircuit_id_table.insert (std::make_pair (d->id (), d.operator-> ()));
|
||||
}
|
||||
|
||||
m_valid_subcircuit_id_table = true;
|
||||
}
|
||||
|
||||
void Circuit::invalidate_subcircuit_id_table ()
|
||||
{
|
||||
m_valid_subcircuit_id_table = false;
|
||||
m_subcircuit_id_table.clear ();
|
||||
}
|
||||
|
||||
SubCircuit *Circuit::subcircuit_by_id (size_t id)
|
||||
{
|
||||
if (! m_valid_subcircuit_id_table) {
|
||||
validate_subcircuit_id_table ();
|
||||
}
|
||||
|
||||
std::map<size_t, SubCircuit *>::const_iterator d = m_subcircuit_id_table.find (id);
|
||||
return d != m_subcircuit_id_table.end () ? d->second : 0;
|
||||
}
|
||||
|
||||
void Circuit::register_ref (SubCircuit *r)
|
||||
{
|
||||
m_refs.push_back (r);
|
||||
|
|
@ -1160,13 +1164,17 @@ size_t DeviceClass::terminal_id_for_name (const std::string &name) const
|
|||
// Netlist class implementation
|
||||
|
||||
Netlist::Netlist ()
|
||||
: m_valid_topology (false), m_lock_count (0)
|
||||
: 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_circuits.changed ().add (this, &Netlist::invalidate_topology);
|
||||
}
|
||||
|
||||
Netlist::Netlist (const Netlist &other)
|
||||
: m_valid_topology (false), m_lock_count (0)
|
||||
: 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)
|
||||
{
|
||||
operator= (other);
|
||||
m_circuits.changed ().add (this, &Netlist::invalidate_topology);
|
||||
|
|
@ -1444,18 +1452,24 @@ void Netlist::clear ()
|
|||
{
|
||||
m_device_classes.clear ();
|
||||
m_circuits.clear ();
|
||||
m_circuit_by_name.invalidate ();
|
||||
m_circuit_by_cell_index.invalidate ();
|
||||
}
|
||||
|
||||
void Netlist::add_circuit (Circuit *circuit)
|
||||
{
|
||||
m_circuits.push_back (circuit);
|
||||
circuit->set_netlist (this);
|
||||
m_circuit_by_name.invalidate ();
|
||||
m_circuit_by_cell_index.invalidate ();
|
||||
}
|
||||
|
||||
void Netlist::remove_circuit (Circuit *circuit)
|
||||
{
|
||||
circuit->set_netlist (0);
|
||||
m_circuits.erase (circuit);
|
||||
m_circuit_by_name.invalidate ();
|
||||
m_circuit_by_cell_index.invalidate ();
|
||||
}
|
||||
|
||||
void Netlist::add_device_class (DeviceClass *device_class)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,100 @@ class DeviceTerminalDefinition;
|
|||
class Netlist;
|
||||
class Net;
|
||||
|
||||
/**
|
||||
* @brief A getter for the ID of an object
|
||||
*/
|
||||
template <class T>
|
||||
struct id_attribute
|
||||
{
|
||||
typedef size_t attr_type;
|
||||
size_t operator() (const T *t) const { return t->id (); }
|
||||
bool has (const T * /*t*/) const { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A getter for the cluster ID of an object
|
||||
*/
|
||||
template <class T>
|
||||
struct cluster_id_attribute
|
||||
{
|
||||
typedef size_t attr_type;
|
||||
attr_type operator() (const T *t) const { return t->cluster_id (); }
|
||||
bool has (const T * /*t*/) const { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A getter for the cluster ID of an object
|
||||
*/
|
||||
template <class T>
|
||||
struct cell_index_attribute
|
||||
{
|
||||
typedef db::cell_index_type attr_type;
|
||||
attr_type operator() (const T *t) const { return t->cell_index (); }
|
||||
bool has (const T * /*t*/) const { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A getter for the name of an object
|
||||
*/
|
||||
template <class T>
|
||||
struct name_attribute
|
||||
{
|
||||
typedef std::string attr_type;
|
||||
const attr_type &operator() (const T *t) const { return t->name (); }
|
||||
bool has (const T *t) const { return ! t->name ().empty (); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An id-to-object translation table
|
||||
*/
|
||||
template <class T, class I, class ATTR>
|
||||
class object_by_attr
|
||||
{
|
||||
public:
|
||||
typedef typename ATTR::attr_type attr_type;
|
||||
typedef typename I::value_type value_type;
|
||||
|
||||
object_by_attr (T *self, I (T::*bi) (), I (T::*ei) ()) : mp_self (self), m_bi (bi), m_ei (ei), m_valid (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void invalidate ()
|
||||
{
|
||||
m_valid = false;
|
||||
m_map.clear ();
|
||||
}
|
||||
|
||||
value_type *object_by (const attr_type &attr) const
|
||||
{
|
||||
if (! m_valid) {
|
||||
validate ();
|
||||
}
|
||||
typename std::map<attr_type, value_type *>::const_iterator m = m_map.find (attr);
|
||||
return m == m_map.end () ? 0 : m->second;
|
||||
}
|
||||
|
||||
private:
|
||||
T *mp_self;
|
||||
I (T::*m_bi) ();
|
||||
I (T::*m_ei) ();
|
||||
mutable bool m_valid;
|
||||
mutable std::map<attr_type, value_type *> m_map;
|
||||
|
||||
void validate () const
|
||||
{
|
||||
ATTR attr;
|
||||
m_map.clear ();
|
||||
for (I i = (mp_self->*m_bi) (); i != (mp_self->*m_ei) (); ++i) {
|
||||
if (attr.has (i.operator-> ())) {
|
||||
m_map.insert (std::make_pair (attr (i.operator-> ()), i.operator-> ()));
|
||||
}
|
||||
}
|
||||
m_valid = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A reference to a terminal of a device
|
||||
*
|
||||
|
|
@ -1124,6 +1218,14 @@ public:
|
|||
*/
|
||||
const Pin *pin_by_id (size_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the pin by name
|
||||
*
|
||||
* If there is no pin with that name, null is returned.
|
||||
* NOTE: this is a linear search, so it's performance may not be good for many pins.
|
||||
*/
|
||||
const Pin *pin_by_name (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the pins of the circuit (const version)
|
||||
*/
|
||||
|
|
@ -1184,6 +1286,46 @@ public:
|
|||
return m_nets.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net from a given cluster ID (const version)
|
||||
*
|
||||
* If the cluster ID is not valid, null is returned.
|
||||
*/
|
||||
const Net *net_by_cluster_id (size_t cluster_id) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->net_by_cluster_id (cluster_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net from a given cluster ID (non-const version)
|
||||
*
|
||||
* If the cluster ID is not valid, null is returned.
|
||||
*/
|
||||
Net *net_by_cluster_id (size_t cluster_id)
|
||||
{
|
||||
return m_net_by_cluster_id.object_by (cluster_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net from a given name (const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
const Net *net_by_name (const std::string &name) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->net_by_name (name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the net from a given name (non-const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
Net *net_by_name (const std::string &name)
|
||||
{
|
||||
return m_net_by_name.object_by (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a device to this circuit
|
||||
*
|
||||
|
|
@ -1207,11 +1349,34 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device from a given ID (const version)
|
||||
* @brief Gets the device from a given ID (non-const version)
|
||||
*
|
||||
* If the ID is not valid, null is returned.
|
||||
*/
|
||||
Device *device_by_id (size_t id);
|
||||
Device *device_by_id (size_t id)
|
||||
{
|
||||
return m_device_by_id.object_by (id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device from a given name (const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
const Device *device_by_name (const std::string &name) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->device_by_name (name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device from a given name (non-const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
Device *device_by_name (const std::string &name)
|
||||
{
|
||||
return m_device_by_name.object_by (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the devices of the circuit (non-const version)
|
||||
|
|
@ -1268,11 +1433,34 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit from a given ID (const version)
|
||||
* @brief Gets the subcircuit from a given ID (non-const version)
|
||||
*
|
||||
* If the ID is not valid, null is returned.
|
||||
*/
|
||||
SubCircuit *subcircuit_by_id (size_t id);
|
||||
SubCircuit *subcircuit_by_id (size_t id)
|
||||
{
|
||||
return m_subcircuit_by_id.object_by (id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit from a given name (const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
const SubCircuit *subcircuit_by_name (const std::string &name) const
|
||||
{
|
||||
return (const_cast<Circuit *> (this)->subcircuit_by_name (name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the subcircuit from a given name (non-const version)
|
||||
*
|
||||
* If the name is not valid, null is returned.
|
||||
*/
|
||||
SubCircuit *subcircuit_by_name (const std::string &name)
|
||||
{
|
||||
return m_subcircuit_by_name.object_by (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the subcircuits of the circuit (non-const version)
|
||||
|
|
@ -1350,6 +1538,7 @@ private:
|
|||
friend class Netlist;
|
||||
friend class Net;
|
||||
friend class SubCircuit;
|
||||
friend class Device;
|
||||
|
||||
std::string m_name;
|
||||
db::cell_index_type m_cell_index;
|
||||
|
|
@ -1359,10 +1548,12 @@ private:
|
|||
subcircuit_list m_subcircuits;
|
||||
Netlist *mp_netlist;
|
||||
std::vector<Net::pin_iterator> m_pin_refs;
|
||||
bool m_valid_device_id_table;
|
||||
std::map<size_t, Device *> m_device_id_table;
|
||||
bool m_valid_subcircuit_id_table;
|
||||
std::map<size_t, SubCircuit *> m_subcircuit_id_table;
|
||||
object_by_attr<Circuit, Circuit::device_iterator, id_attribute<Device> > m_device_by_id;
|
||||
object_by_attr<Circuit, Circuit::subcircuit_iterator, id_attribute<SubCircuit> > m_subcircuit_by_id;
|
||||
object_by_attr<Circuit, Circuit::net_iterator, cluster_id_attribute<Net> > m_net_by_cluster_id;
|
||||
object_by_attr<Circuit, Circuit::device_iterator, name_attribute<Device> > m_device_by_name;
|
||||
object_by_attr<Circuit, Circuit::subcircuit_iterator, name_attribute<SubCircuit> > m_subcircuit_by_name;
|
||||
object_by_attr<Circuit, Circuit::net_iterator, name_attribute<Net> > m_net_by_name;
|
||||
tl::weak_collection<SubCircuit> m_refs;
|
||||
size_t m_index;
|
||||
|
||||
|
|
@ -1381,11 +1572,6 @@ private:
|
|||
void set_netlist (Netlist *netlist);
|
||||
bool combine_parallel_devices (const db::DeviceClass &cls);
|
||||
bool combine_serial_devices (const db::DeviceClass &cls);
|
||||
|
||||
void validate_device_id_table ();
|
||||
void invalidate_device_id_table ();
|
||||
void validate_subcircuit_id_table ();
|
||||
void invalidate_subcircuit_id_table ();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1886,6 +2072,46 @@ public:
|
|||
return m_circuits.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit with the given name
|
||||
*
|
||||
* If no circuit with that name exists, null is returned.
|
||||
*/
|
||||
Circuit *circuit_by_name (const std::string &name)
|
||||
{
|
||||
return m_circuit_by_name.object_by (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit with the given name (const version)
|
||||
*
|
||||
* If no circuit with that name exists, null is returned.
|
||||
*/
|
||||
const Circuit *circuit_by_name (const std::string &name) const
|
||||
{
|
||||
return m_circuit_by_name.object_by (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit with the given cell index
|
||||
*
|
||||
* If no circuit with that cell index exists, null is returned.
|
||||
*/
|
||||
Circuit *circuit_by_cell_index (db::cell_index_type cell_index)
|
||||
{
|
||||
return m_circuit_by_cell_index.object_by (cell_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the circuit with the given cell index (const version)
|
||||
*
|
||||
* If no circuit with that cell index exists, null is returned.
|
||||
*/
|
||||
const Circuit *circuit_by_cell_index (db::cell_index_type cell_index) const
|
||||
{
|
||||
return m_circuit_by_cell_index.object_by (cell_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the top-down circuits iterator (begin)
|
||||
* This iterator will deliver the circuits in a top-down way - i.e. child circuits
|
||||
|
|
@ -2032,6 +2258,8 @@ private:
|
|||
tl::vector<tl::vector<Circuit *> > m_child_circuits;
|
||||
tl::vector<tl::vector<Circuit *> > m_parent_circuits;
|
||||
size_t m_top_circuits;
|
||||
object_by_attr<Netlist, Netlist::circuit_iterator, name_attribute<Circuit> > m_circuit_by_name;
|
||||
object_by_attr<Netlist, Netlist::circuit_iterator, cell_index_attribute<Circuit> > m_circuit_by_cell_index;
|
||||
|
||||
void invalidate_topology ();
|
||||
void validate_topology ();
|
||||
|
|
|
|||
|
|
@ -651,14 +651,34 @@ Class<db::Circuit> decl_dbCircuit ("db", "Circuit",
|
|||
"@brief Gets the device object for a given ID.\n"
|
||||
"If the ID is not a valid device ID, nil is returned."
|
||||
) +
|
||||
gsi::method ("device_by_name", (db::Device *(db::Circuit::*) (const std::string &)) &db::Circuit::device_by_name, gsi::arg ("name"),
|
||||
"@brief Gets the device object for a given name.\n"
|
||||
"If the ID is not a valid device name, nil is returned."
|
||||
) +
|
||||
gsi::method ("subcircuit_by_id", (db::SubCircuit *(db::Circuit::*) (size_t)) &db::Circuit::subcircuit_by_id, gsi::arg ("id"),
|
||||
"@brief Gets the subcircuit object for a given ID.\n"
|
||||
"If the ID is not a valid subcircuit ID, nil is returned."
|
||||
) +
|
||||
gsi::method ("subcircuit_by_name", (db::SubCircuit *(db::Circuit::*) (const std::string &)) &db::Circuit::subcircuit_by_name, gsi::arg ("name"),
|
||||
"@brief Gets the subcircuit object for a given name.\n"
|
||||
"If the ID is not a valid subcircuit name, nil is returned."
|
||||
) +
|
||||
gsi::method ("net_by_cluster_id", (db::Net *(db::Circuit::*) (size_t)) &db::Circuit::net_by_cluster_id, gsi::arg ("cluster_id"),
|
||||
"@brief Gets the net object corresponding to a specific cluster ID\n"
|
||||
"If the ID is not a valid pin cluster ID, nil is returned."
|
||||
) +
|
||||
gsi::method ("net_by_name", (db::Net *(db::Circuit::*) (const std::string &)) &db::Circuit::net_by_name, gsi::arg ("name"),
|
||||
"@brief Gets the net object for a given name.\n"
|
||||
"If the ID is not a valid net name, nil is returned."
|
||||
) +
|
||||
gsi::method ("pin_by_id", &db::Circuit::pin_by_id, gsi::arg ("id"),
|
||||
"@brief Gets the \\Pin object corresponding to a specific ID\n"
|
||||
"If the ID is not a valid pin ID, nil is returned."
|
||||
) +
|
||||
gsi::method ("pin_by_name", &db::Circuit::pin_by_name, gsi::arg ("name"),
|
||||
"@brief Gets the \\Pin object corresponding to a specific name\n"
|
||||
"If the ID is not a valid pin name, nil is returned."
|
||||
) +
|
||||
gsi::method ("pin_count", &db::Circuit::pin_count,
|
||||
"@brief Gets the number of pins in the circuit"
|
||||
) +
|
||||
|
|
@ -814,6 +834,14 @@ Class<db::Netlist> decl_dbNetlist ("db", "Netlist",
|
|||
"@brief Removes the given circuit object from the netlist\n"
|
||||
"After the object has been removed, it becomes invalid and cannot be used further."
|
||||
) +
|
||||
gsi::method ("circuit_by_cell_index", (db::Circuit *(db::Netlist::*) (db::cell_index_type)) &db::Netlist::circuit_by_cell_index, gsi::arg ("cell_index"),
|
||||
"@brief Gets the circuit object for a given cell index.\n"
|
||||
"If the cell index is not valid or no circuit is registered with this index, nil is returned."
|
||||
) +
|
||||
gsi::method ("circuit_by_name", (db::Circuit *(db::Netlist::*) (const std::string &)) &db::Netlist::circuit_by_name, gsi::arg ("name"),
|
||||
"@brief Gets the circuit object for a given name.\n"
|
||||
"If the ID is not a valid circuit name, nil is returned."
|
||||
) +
|
||||
gsi::iterator ("each_circuit_top_down", (db::Netlist::top_down_circuit_iterator (db::Netlist::*) ()) &db::Netlist::begin_top_down, (db::Netlist::top_down_circuit_iterator (db::Netlist::*) ()) &db::Netlist::end_top_down,
|
||||
"@brief Iterates over the circuits top-down\n"
|
||||
"Iterating top-down means the parent circuits come before the child circuits. "
|
||||
|
|
|
|||
|
|
@ -139,6 +139,9 @@ TEST(3_CircuitBasic)
|
|||
EXPECT_EQ (c.pin_by_id (0)->name (), "p1");
|
||||
EXPECT_EQ (c.pin_by_id (1)->name (), "p2");
|
||||
EXPECT_EQ (c.pin_by_id (2), 0);
|
||||
EXPECT_EQ (c.pin_by_name ("p1")->name (), "p1");
|
||||
EXPECT_EQ (c.pin_by_name ("doesnt_exist") == 0, true);
|
||||
EXPECT_EQ (c.pin_by_name ("p2")->name (), "p2");
|
||||
|
||||
db::Circuit c2 = c;
|
||||
EXPECT_EQ (c2.name (), "name");
|
||||
|
|
@ -267,7 +270,7 @@ TEST(4_CircuitDevices)
|
|||
db::Device *dd = new db::Device (&dc1, "dd");
|
||||
db::Device *d1 = new db::Device (&dc1, "d1");
|
||||
db::Device *d2a = new db::Device (&dc2, "d2a");
|
||||
db::Device *d2b = new db::Device (&dc2, "d2b");
|
||||
db::Device *d2b = new db::Device (&dc2, "d2x");
|
||||
|
||||
EXPECT_EQ (d1->circuit () == 0, true);
|
||||
|
||||
|
|
@ -275,19 +278,34 @@ TEST(4_CircuitDevices)
|
|||
EXPECT_EQ (d1->circuit () == c.get (), true);
|
||||
EXPECT_EQ (d1->id (), size_t (1));
|
||||
EXPECT_EQ (c->device_by_id (d1->id ()) == d1, true);
|
||||
EXPECT_EQ (c->device_by_name (d1->name ()) == d1, true);
|
||||
|
||||
c->add_device (dd);
|
||||
EXPECT_EQ (dd->id (), size_t (2));
|
||||
EXPECT_EQ (c->device_by_id (dd->id ()) == dd, true);
|
||||
EXPECT_EQ (c->device_by_name (dd->name ()) == dd, true);
|
||||
|
||||
c->add_device (d2a);
|
||||
EXPECT_EQ (d2a->id (), size_t (3));
|
||||
EXPECT_EQ (c->device_by_id (d2a->id ()) == d2a, true);
|
||||
EXPECT_EQ (c->device_by_name (d2a->name ()) == d2a, true);
|
||||
|
||||
c->add_device (d2b);
|
||||
EXPECT_EQ (d2b->id (), size_t (4));
|
||||
EXPECT_EQ (c->device_by_id (d2b->id ()) == d2b, true);
|
||||
EXPECT_EQ (c->device_by_name (d2b->name ()) == d2b, true);
|
||||
|
||||
d2b->set_name ("d2b");
|
||||
EXPECT_EQ (c->device_by_id (d2b->id ()) == d2b, true);
|
||||
EXPECT_EQ (c->device_by_name (d2b->name ()) == d2b, true);
|
||||
EXPECT_EQ (c->device_by_name ("d2x") == 0, true);
|
||||
|
||||
c->remove_device (dd);
|
||||
dd = 0;
|
||||
EXPECT_EQ (c->device_by_id (d2a->id ()) == d2a, true);
|
||||
EXPECT_EQ (c->device_by_id (2) == 0, true);
|
||||
EXPECT_EQ (c->device_by_name (d2a->name ()) == d2a, true);
|
||||
EXPECT_EQ (c->device_by_name ("doesnt_exist") == 0, true);
|
||||
|
||||
EXPECT_EQ (d1->parameter_value (0), 1.0);
|
||||
EXPECT_EQ (d1->parameter_value (1), 2.0);
|
||||
|
|
@ -313,18 +331,33 @@ TEST(4_CircuitDevices)
|
|||
|
||||
db::Net *n1 = new db::Net ();
|
||||
n1->set_name ("n1");
|
||||
n1->set_cluster_id (41);
|
||||
EXPECT_EQ (n1->circuit (), 0);
|
||||
c->add_net (n1);
|
||||
n1->add_terminal (db::NetTerminalRef (d1, 0));
|
||||
n1->add_terminal (db::NetTerminalRef (d2a, 0));
|
||||
EXPECT_EQ (n1->circuit (), c.get ());
|
||||
EXPECT_EQ (c->net_by_cluster_id (17) == 0, true);
|
||||
EXPECT_EQ (c->net_by_cluster_id (41) == n1, true);
|
||||
EXPECT_EQ (c->net_by_name ("doesnt_exist") == 0, true);
|
||||
EXPECT_EQ (c->net_by_name ("n1") == n1, true);
|
||||
|
||||
db::Net *n2 = new db::Net ();
|
||||
n2->set_name ("n2");
|
||||
n2->set_name ("n2x");
|
||||
n2->set_cluster_id (17);
|
||||
c->add_net (n2);
|
||||
n2->add_terminal (db::NetTerminalRef (d1, 1));
|
||||
n2->add_terminal (db::NetTerminalRef (d2a, 1));
|
||||
n2->add_terminal (db::NetTerminalRef (d2b, 0));
|
||||
EXPECT_EQ (c->net_by_cluster_id (17) == n2, true);
|
||||
EXPECT_EQ (c->net_by_name ("n2x") == n2, true);
|
||||
|
||||
n2->set_name ("n2");
|
||||
n2->set_cluster_id (42);
|
||||
EXPECT_EQ (c->net_by_cluster_id (17) == 0, true);
|
||||
EXPECT_EQ (c->net_by_name ("n2x") == 0, true);
|
||||
EXPECT_EQ (c->net_by_cluster_id (42) == n2, true);
|
||||
EXPECT_EQ (c->net_by_name ("n2") == n2, true);
|
||||
|
||||
EXPECT_EQ (netlist2 (*c),
|
||||
"c:\n"
|
||||
|
|
@ -413,18 +446,33 @@ TEST(4_NetlistSubcircuits)
|
|||
nl->add_device_class (dc);
|
||||
|
||||
db::Circuit *c1 = new db::Circuit ();
|
||||
c1->set_cell_index (17);
|
||||
EXPECT_EQ (c1->netlist (), 0);
|
||||
c1->set_name ("c1");
|
||||
c1->add_pin (db::Pin ("c1p1"));
|
||||
c1->add_pin (db::Pin ("c1p2"));
|
||||
nl->add_circuit (c1);
|
||||
EXPECT_EQ (c1->netlist (), nl.get ());
|
||||
EXPECT_EQ (nl->circuit_by_name ("c1") == c1, true);
|
||||
EXPECT_EQ (nl->circuit_by_name ("doesnt_exist") == 0, true);
|
||||
EXPECT_EQ (nl->circuit_by_cell_index (17) == c1, true);
|
||||
EXPECT_EQ (nl->circuit_by_cell_index (42) == 0, true);
|
||||
|
||||
db::Circuit *c2 = new db::Circuit ();
|
||||
c2->set_name ("c2");
|
||||
c2->set_name ("c2x");
|
||||
c2->add_pin (db::Pin ("c2p1"));
|
||||
c2->add_pin (db::Pin ("c2p2"));
|
||||
c2->set_cell_index (41);
|
||||
nl->add_circuit (c2);
|
||||
EXPECT_EQ (nl->circuit_by_name ("c2x") == c2, true);
|
||||
EXPECT_EQ (nl->circuit_by_cell_index (41) == c2, true);
|
||||
|
||||
c2->set_name ("c2");
|
||||
EXPECT_EQ (nl->circuit_by_name ("c2x") == 0, true);
|
||||
EXPECT_EQ (nl->circuit_by_name ("c2") == c2, true);
|
||||
c2->set_cell_index (42);
|
||||
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");
|
||||
c2->add_device (d);
|
||||
|
|
@ -438,13 +486,23 @@ TEST(4_NetlistSubcircuits)
|
|||
EXPECT_EQ (sc1->circuit () == c1, true);
|
||||
EXPECT_EQ (sc1->id (), size_t (1));
|
||||
EXPECT_EQ (c1->subcircuit_by_id (sc1->id ()) == sc1, true);
|
||||
EXPECT_EQ (c1->subcircuit_by_id (2) == 0, true);
|
||||
EXPECT_EQ (c1->subcircuit_by_name (sc1->name ()) == sc1, true);
|
||||
EXPECT_EQ (c1->subcircuit_by_name ("doesnt_exist") == 0, true);
|
||||
|
||||
db::SubCircuit *sc2 = new db::SubCircuit (c2);
|
||||
sc2->set_name ("sc2");
|
||||
EXPECT_EQ (refs2string (c2), "sc1,sc2");
|
||||
sc2->set_name ("scx");
|
||||
EXPECT_EQ (refs2string (c2), "sc1,scx");
|
||||
c1->add_subcircuit (sc2);
|
||||
EXPECT_EQ (sc2->id (), size_t (2));
|
||||
EXPECT_EQ (c1->subcircuit_by_id (sc2->id ()) == sc2, true);
|
||||
EXPECT_EQ (c1->subcircuit_by_name (sc2->name ()) == sc2, true);
|
||||
|
||||
sc2->set_name ("sc2");
|
||||
EXPECT_EQ (refs2string (c2), "sc1,sc2");
|
||||
EXPECT_EQ (c1->subcircuit_by_id (sc2->id ()) == sc2, true);
|
||||
EXPECT_EQ (c1->subcircuit_by_name (sc2->name ()) == sc2, true);
|
||||
EXPECT_EQ (c1->subcircuit_by_name ("scx") == 0, true);
|
||||
|
||||
db::Net *n2a = new db::Net ();
|
||||
c2->add_net (n2a);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ class DBNetlist_TestClass < TestBase
|
|||
c.cell_index = 42
|
||||
assert_equal(c.cell_index, 42)
|
||||
|
||||
assert_equal(nl.circuit_by_cell_index(42).name, "XYZ")
|
||||
assert_equal(nl.circuit_by_name("XYZ").name, "XYZ")
|
||||
assert_equal(nl.circuit_by_cell_index(17).inspect, "nil")
|
||||
assert_equal(nl.circuit_by_name("DOESNOTEXIST").inspect, "nil")
|
||||
|
||||
cc = RBA::Circuit::new
|
||||
nl.add(cc)
|
||||
cc.name = "ABC"
|
||||
|
|
@ -160,6 +165,9 @@ class DBNetlist_TestClass < TestBase
|
|||
assert_equal(d1.id, 1)
|
||||
assert_equal(c.device_by_id(d1.id).id, 1)
|
||||
assert_equal(c.device_by_id(2).inspect, "nil")
|
||||
assert_equal(c.device_by_name(d1.name).name, "D1")
|
||||
assert_equal(c.device_by_id(2).inspect, "nil")
|
||||
assert_equal(c.device_by_name("doesnt_exist").inspect, "nil")
|
||||
|
||||
d2 = c.create_device(dc)
|
||||
assert_equal(d2.device_class.id, dc.id)
|
||||
|
|
@ -263,6 +271,9 @@ class DBNetlist_TestClass < TestBase
|
|||
assert_equal(sc1.circuit_ref.name, "CC")
|
||||
assert_equal(c.subcircuit_by_id(sc1.id).id, 1)
|
||||
assert_equal(c.subcircuit_by_id(2).inspect, "nil")
|
||||
assert_equal(c.subcircuit_by_name(sc1.name).name, "SC1")
|
||||
assert_equal(c.subcircuit_by_id(2).inspect, "nil")
|
||||
assert_equal(c.subcircuit_by_name("doesnt_exist").inspect, "nil")
|
||||
|
||||
refs = []
|
||||
cc.each_ref { |r| refs << r.name }
|
||||
|
|
@ -460,15 +471,25 @@ class DBNetlist_TestClass < TestBase
|
|||
assert_equal(pinb1.id, 2)
|
||||
assert_equal(pinb2.id, 3)
|
||||
assert_equal(c.pin_by_id(0).name, "A1")
|
||||
assert_equal(c.pin_by_name("A1").name, "A1")
|
||||
assert_equal(c.pin_by_id(3).name, "B2")
|
||||
assert_equal(c.pin_by_name("B2").name, "B2")
|
||||
assert_equal(c.pin_by_id(17).inspect, "nil")
|
||||
assert_equal(c.pin_by_name("DOESNOTEXIST").inspect, "nil")
|
||||
|
||||
names = []
|
||||
c.each_pin { |p| names << p.name }
|
||||
assert_equal(names, [ "A1", "A2", "B1", "B2" ])
|
||||
|
||||
net1 = c.create_net
|
||||
net1.cluster_id = 17
|
||||
net1.name = "NET1"
|
||||
|
||||
assert_equal(c.net_by_cluster_id(17).name, "NET1")
|
||||
assert_equal(c.net_by_cluster_id(42).inspect, "nil")
|
||||
assert_equal(c.net_by_name("NET1").name, "NET1")
|
||||
assert_equal(c.net_by_name("DOESNOTEXIST").inspect, "nil")
|
||||
|
||||
net2 = c.create_net
|
||||
net2.name = "NET2"
|
||||
|
||||
|
|
@ -575,11 +596,13 @@ END
|
|||
|
||||
c1 = RBA::Circuit::new
|
||||
c1.name = "C1"
|
||||
c1.cell_index = 17
|
||||
nl.add(c1)
|
||||
assert_equal(nl.top_circuit_count, 1)
|
||||
|
||||
c2 = RBA::Circuit::new
|
||||
c2.name = "C2"
|
||||
c1.cell_index = 42
|
||||
nl.add(c2)
|
||||
assert_equal(nl.top_circuit_count, 2)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue