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::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)
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue