WIP: added subcircuit IDs for easier referencing.

This commit is contained in:
Matthias Koefferlein 2018-12-27 01:58:34 +01:00
parent 795a77f7ce
commit f0f620b1cd
6 changed files with 112 additions and 16 deletions

View File

@ -176,6 +176,7 @@ void Device::set_parameter_value (const std::string &name, double v)
// SubCircuit class implementation
SubCircuit::SubCircuit ()
: m_id (0)
{
// .. nothing yet ..
}
@ -190,12 +191,13 @@ SubCircuit::~SubCircuit()
}
SubCircuit::SubCircuit (Circuit *circuit, const std::string &name)
: m_circuit (circuit), m_name (name)
: m_circuit (circuit), m_name (name), m_id (0)
{
// .. nothing yet ..
}
SubCircuit::SubCircuit (const SubCircuit &other)
: m_id (0)
{
operator= (other);
}
@ -472,13 +474,13 @@ void Net::set_circuit (Circuit *circuit)
// Circuit class implementation
Circuit::Circuit ()
: mp_netlist (0), m_valid_device_id_table (false)
: mp_netlist (0), m_valid_device_id_table (false), m_valid_subcircuit_id_table (false)
{
// .. nothing yet ..
}
Circuit::Circuit (const Circuit &other)
: mp_netlist (0), m_valid_device_id_table (false)
: mp_netlist (0), m_valid_device_id_table (false), m_valid_subcircuit_id_table (false)
{
operator= (other);
}
@ -489,6 +491,7 @@ Circuit &Circuit::operator= (const Circuit &other)
m_name = other.m_name;
invalidate_device_id_table ();
invalidate_subcircuit_id_table ();
for (const_pin_iterator i = other.begin_pins (); i != other.end_pins (); ++i) {
add_pin (*i);
@ -560,6 +563,10 @@ void Circuit::clear ()
m_devices.clear ();
m_nets.clear ();
m_sub_circuits.clear ();
m_device_id_table.clear ();
m_subcircuit_id_table.clear ();
m_valid_device_id_table = false;
m_valid_subcircuit_id_table = false;
}
void Circuit::set_name (const std::string &name)
@ -637,12 +644,47 @@ Device *Circuit::device_by_id (size_t id)
void Circuit::add_sub_circuit (SubCircuit *sub_circuit)
{
size_t id = 0;
if (! m_sub_circuits.empty ()) {
tl_assert (m_sub_circuits.back () != 0);
id = m_sub_circuits.back ()->id ();
}
sub_circuit->set_id (id + 1);
m_sub_circuits.push_back (sub_circuit);
invalidate_subcircuit_id_table ();
}
void Circuit::remove_sub_circuit (SubCircuit *sub_circuit)
{
m_sub_circuits.erase (sub_circuit);
invalidate_subcircuit_id_table ();
}
void Circuit::validate_subcircuit_id_table ()
{
m_subcircuit_id_table.clear ();
for (sub_circuit_iterator d = begin_sub_circuits (); d != end_sub_circuits (); ++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::translate_circuits (const std::map<const Circuit *, Circuit *> &map)

View File

@ -726,6 +726,17 @@ public:
*/
~SubCircuit ();
/**
* @brief Gets the subcircuit ID
* The ID is a unique integer which identifies the subcircuit.
* It can be used to retrieve the subcircuit from the circuit using Circuit::subcircuit_by_id.
* When assigned, the subcircuit ID is not 0.
*/
size_t id () const
{
return m_id;
}
/**
* @brief Gets the circuit the reference points to (const version)
*/
@ -805,6 +816,7 @@ private:
std::string m_name;
db::DCplxTrans m_trans;
std::vector<Net::pin_iterator> m_pin_refs;
size_t m_id;
/**
* @brief Sets the pin reference for a specific pin
@ -818,6 +830,14 @@ private:
{
m_circuit.reset (c);
}
/**
* @brief Sets the device ID
*/
void set_id (size_t id)
{
m_id = id;
}
};
/**
@ -1080,6 +1100,23 @@ public:
*/
void remove_sub_circuit (SubCircuit *sub_circuit);
/**
* @brief Gets the subcircuit from a given ID (const version)
*
* If the ID is not valid, null is returned.
*/
const SubCircuit *subcircuit_by_id (size_t id) const
{
return (const_cast<Circuit *> (this)->subcircuit_by_id (id));
}
/**
* @brief Gets the subcircuit from a given ID (const version)
*
* If the ID is not valid, null is returned.
*/
SubCircuit *subcircuit_by_id (size_t id);
/**
* @brief Begin iterator for the subcircuits of the circuit (non-const version)
*/
@ -1166,6 +1203,8 @@ private:
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;
/**
* @brief Sets the pin reference for a specific pin
@ -1180,6 +1219,8 @@ private:
void validate_device_id_table ();
void invalidate_device_id_table ();
void validate_subcircuit_id_table ();
void invalidate_subcircuit_id_table ();
};
/**

View File

@ -128,6 +128,12 @@ Class<db::SubCircuit> decl_dbSubCircuit ("db", "SubCircuit",
gsi::method ("circuit", (db::Circuit *(db::SubCircuit::*) ()) &db::SubCircuit::circuit,
"@brief Gets the circuit referenced by the subcircuit.\n"
) +
gsi::method ("id", &db::SubCircuit::id,
"@brief Gets the subcircuit ID.\n"
"The ID is a unique integer which identifies the subcircuit.\n"
"It can be used to retrieve the subcircuit from the circuit using \\Circuit#subcircuit_by_id.\n"
"When assigned, the subcircuit ID is not 0.\n"
) +
gsi::method ("name=", &db::SubCircuit::set_name, gsi::arg ("name"),
"@brief Sets the name of the subcircuit.\n"
"SubCircuit names are used to name a subcircuits inside a netlist file. "
@ -617,6 +623,10 @@ 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 ("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 ("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."

View File

@ -279,10 +279,12 @@ public:
m_net_clusters.build (*layout, cell, db::ShapeIterator::Polygons, conn);
// reverse lookup for Circuit vs. cell index
std::map<db::cell_index_type, db::Circuit *> circuits;
// some circuits may be there because of device extraction
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) {
// @@@ TODO: what if the circuits don't have a cell index?
tl_assert (layout->is_valid_cell_index (c->cell_index ()));
circuits.insert (std::make_pair (c->cell_index (), c.operator-> ()));
}
@ -345,7 +347,6 @@ public:
std::map<db::cell_index_type, db::Circuit *>::const_iterator k = circuits.find (ccid);
tl_assert (k != circuits.end ()); // because we walk bottom-up
// @@@ name?
subcircuit = new db::SubCircuit (k->second);
db::CplxTrans dbu_trans (layout->dbu ());
subcircuit->set_trans (dbu_trans * i->inst ().complex_trans () * dbu_trans.inverted ());
@ -440,14 +441,10 @@ static std::string device_name (const db::Device &device)
}
}
// @@@ TODO: refactor. This is inefficient. Give an ID automatically.
static std::string subcircuit_name (const db::SubCircuit &subcircuit, const db::Circuit &circuit)
static std::string subcircuit_name (const db::SubCircuit &subcircuit)
{
if (subcircuit.name ().empty ()) {
int id = 1;
for (db::Circuit::const_sub_circuit_iterator d = circuit.begin_sub_circuits (); d != circuit.end_sub_circuits () && d.operator-> () != &subcircuit; ++d, ++id)
;
return "$" + tl::to_string (id);
return "$" + tl::to_string (subcircuit.id ());
} else {
return subcircuit.name ();
}
@ -543,7 +540,7 @@ static std::string netlist2string (const db::Netlist &nl)
const db::Pin &pin = *p;
ps += pin_name (pin) + "=" + net_name (subcircuit.net_for_pin (pin.id ()));
}
res += std::string (" X") + sc->circuit ()->name () + " " + subcircuit_name (*sc, *c) + " (" + ps + ")\n";
res += std::string (" X") + sc->circuit ()->name () + " " + subcircuit_name (*sc) + " (" + ps + ")\n";
}
}

View File

@ -269,16 +269,16 @@ TEST(4_CircuitDevices)
db::Device *d2a = new db::Device (&dc2, "d2a");
db::Device *d2b = new db::Device (&dc2, "d2b");
c->add_device (d1);
EXPECT_EQ (d1->id (), 1);
EXPECT_EQ (d1->id (), size_t (1));
EXPECT_EQ (c->device_by_id (d1->id ()) == d1, true);
c->add_device (dd);
EXPECT_EQ (dd->id (), 2);
EXPECT_EQ (dd->id (), size_t (2));
EXPECT_EQ (c->device_by_id (dd->id ()) == dd, true);
c->add_device (d2a);
EXPECT_EQ (d2a->id (), 3);
EXPECT_EQ (d2a->id (), size_t (3));
EXPECT_EQ (c->device_by_id (d2a->id ()) == d2a, true);
c->add_device (d2b);
EXPECT_EQ (d2b->id (), 4);
EXPECT_EQ (d2b->id (), size_t (4));
EXPECT_EQ (c->device_by_id (d2b->id ()) == d2b, true);
c->remove_device (dd);
dd = 0;
@ -416,10 +416,14 @@ TEST(4_NetlistSubcircuits)
db::SubCircuit *sc1 = new db::SubCircuit (c2);
sc1->set_name ("sc1");
c1->add_sub_circuit (sc1);
EXPECT_EQ (sc1->id (), size_t (1));
EXPECT_EQ (c1->subcircuit_by_id (sc1->id ()) == sc1, true);
db::SubCircuit *sc2 = new db::SubCircuit (c2);
sc2->set_name ("sc2");
c1->add_sub_circuit (sc2);
EXPECT_EQ (sc2->id (), size_t (2));
EXPECT_EQ (c1->subcircuit_by_id (sc2->id ()) == sc2, true);
db::Net *n2a = new db::Net ();
c2->add_net (n2a);

View File

@ -260,6 +260,8 @@ class DBNetlist_TestClass < TestBase
sc1.name = "SC1"
assert_equal(sc1.name, "SC1")
assert_equal(sc1.circuit.name, "CC")
assert_equal(c.subcircuit_by_id(sc1.id).id, 1)
assert_equal(c.subcircuit_by_id(2).inspect, "nil")
sc2 = c.create_subcircuit(cc)
sc2.name = "SC2"