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:
Matthias Koefferlein 2018-12-30 13:00:03 +01:00
parent 425acda31a
commit 293c6f496e
5 changed files with 435 additions and 84 deletions

View File

@ -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)

View File

@ -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 ();

View File

@ -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. "

View File

@ -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);

View File

@ -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)