mirror of https://github.com/KLayout/klayout.git
WIP: added subcircuit IDs for easier referencing.
This commit is contained in:
parent
795a77f7ce
commit
f0f620b1cd
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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."
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue