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 class implementation
SubCircuit::SubCircuit () SubCircuit::SubCircuit ()
: m_id (0)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
@ -190,12 +191,13 @@ SubCircuit::~SubCircuit()
} }
SubCircuit::SubCircuit (Circuit *circuit, const std::string &name) 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 .. // .. nothing yet ..
} }
SubCircuit::SubCircuit (const SubCircuit &other) SubCircuit::SubCircuit (const SubCircuit &other)
: m_id (0)
{ {
operator= (other); operator= (other);
} }
@ -472,13 +474,13 @@ void Net::set_circuit (Circuit *circuit)
// Circuit class implementation // Circuit class implementation
Circuit::Circuit () 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 .. // .. nothing yet ..
} }
Circuit::Circuit (const Circuit &other) 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); operator= (other);
} }
@ -489,6 +491,7 @@ Circuit &Circuit::operator= (const Circuit &other)
m_name = other.m_name; m_name = other.m_name;
invalidate_device_id_table (); invalidate_device_id_table ();
invalidate_subcircuit_id_table ();
for (const_pin_iterator i = other.begin_pins (); i != other.end_pins (); ++i) { for (const_pin_iterator i = other.begin_pins (); i != other.end_pins (); ++i) {
add_pin (*i); add_pin (*i);
@ -560,6 +563,10 @@ void Circuit::clear ()
m_devices.clear (); m_devices.clear ();
m_nets.clear (); m_nets.clear ();
m_sub_circuits.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) 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) 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); m_sub_circuits.push_back (sub_circuit);
invalidate_subcircuit_id_table ();
} }
void Circuit::remove_sub_circuit (SubCircuit *sub_circuit) void Circuit::remove_sub_circuit (SubCircuit *sub_circuit)
{ {
m_sub_circuits.erase (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) void Circuit::translate_circuits (const std::map<const Circuit *, Circuit *> &map)

View File

@ -726,6 +726,17 @@ public:
*/ */
~SubCircuit (); ~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) * @brief Gets the circuit the reference points to (const version)
*/ */
@ -805,6 +816,7 @@ private:
std::string m_name; std::string m_name;
db::DCplxTrans m_trans; db::DCplxTrans m_trans;
std::vector<Net::pin_iterator> m_pin_refs; std::vector<Net::pin_iterator> m_pin_refs;
size_t m_id;
/** /**
* @brief Sets the pin reference for a specific pin * @brief Sets the pin reference for a specific pin
@ -818,6 +830,14 @@ private:
{ {
m_circuit.reset (c); 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); 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) * @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; std::vector<Net::pin_iterator> m_pin_refs;
bool m_valid_device_id_table; bool m_valid_device_id_table;
std::map<size_t, Device *> m_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 * @brief Sets the pin reference for a specific pin
@ -1180,6 +1219,8 @@ private:
void validate_device_id_table (); void validate_device_id_table ();
void invalidate_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, gsi::method ("circuit", (db::Circuit *(db::SubCircuit::*) ()) &db::SubCircuit::circuit,
"@brief Gets the circuit referenced by the subcircuit.\n" "@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"), gsi::method ("name=", &db::SubCircuit::set_name, gsi::arg ("name"),
"@brief Sets the name of the subcircuit.\n" "@brief Sets the name of the subcircuit.\n"
"SubCircuit names are used to name a subcircuits inside a netlist file. " "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" "@brief Gets the device object for a given ID.\n"
"If the ID is not a valid device ID, nil is returned." "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"), gsi::method ("pin_by_id", &db::Circuit::pin_by_id, gsi::arg ("id"),
"@brief Gets the \\Pin object corresponding to a specific ID\n" "@brief Gets the \\Pin object corresponding to a specific ID\n"
"If the ID is not a valid pin ID, nil is returned." "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); 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; std::map<db::cell_index_type, db::Circuit *> circuits;
// some circuits may be there because of device extraction // some circuits may be there because of device extraction
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) { 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-> ())); 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); std::map<db::cell_index_type, db::Circuit *>::const_iterator k = circuits.find (ccid);
tl_assert (k != circuits.end ()); // because we walk bottom-up tl_assert (k != circuits.end ()); // because we walk bottom-up
// @@@ name?
subcircuit = new db::SubCircuit (k->second); subcircuit = new db::SubCircuit (k->second);
db::CplxTrans dbu_trans (layout->dbu ()); db::CplxTrans dbu_trans (layout->dbu ());
subcircuit->set_trans (dbu_trans * i->inst ().complex_trans () * dbu_trans.inverted ()); 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)
static std::string subcircuit_name (const db::SubCircuit &subcircuit, const db::Circuit &circuit)
{ {
if (subcircuit.name ().empty ()) { if (subcircuit.name ().empty ()) {
int id = 1; return "$" + tl::to_string (subcircuit.id ());
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);
} else { } else {
return subcircuit.name (); return subcircuit.name ();
} }
@ -543,7 +540,7 @@ static std::string netlist2string (const db::Netlist &nl)
const db::Pin &pin = *p; const db::Pin &pin = *p;
ps += pin_name (pin) + "=" + net_name (subcircuit.net_for_pin (pin.id ())); 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 *d2a = new db::Device (&dc2, "d2a");
db::Device *d2b = new db::Device (&dc2, "d2b"); db::Device *d2b = new db::Device (&dc2, "d2b");
c->add_device (d1); 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); EXPECT_EQ (c->device_by_id (d1->id ()) == d1, true);
c->add_device (dd); 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); EXPECT_EQ (c->device_by_id (dd->id ()) == dd, true);
c->add_device (d2a); 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); EXPECT_EQ (c->device_by_id (d2a->id ()) == d2a, true);
c->add_device (d2b); 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); EXPECT_EQ (c->device_by_id (d2b->id ()) == d2b, true);
c->remove_device (dd); c->remove_device (dd);
dd = 0; dd = 0;
@ -416,10 +416,14 @@ TEST(4_NetlistSubcircuits)
db::SubCircuit *sc1 = new db::SubCircuit (c2); db::SubCircuit *sc1 = new db::SubCircuit (c2);
sc1->set_name ("sc1"); sc1->set_name ("sc1");
c1->add_sub_circuit (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); db::SubCircuit *sc2 = new db::SubCircuit (c2);
sc2->set_name ("sc2"); sc2->set_name ("sc2");
c1->add_sub_circuit (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 (); db::Net *n2a = new db::Net ();
c2->add_net (n2a); c2->add_net (n2a);

View File

@ -260,6 +260,8 @@ class DBNetlist_TestClass < TestBase
sc1.name = "SC1" sc1.name = "SC1"
assert_equal(sc1.name, "SC1") assert_equal(sc1.name, "SC1")
assert_equal(sc1.circuit.name, "CC") 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 = c.create_subcircuit(cc)
sc2.name = "SC2" sc2.name = "SC2"