mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-03 16:30:20 +02:00
WIP: moved netlist extractor into right place.
This commit is contained in:
@@ -22,8 +22,8 @@
|
||||
|
||||
|
||||
#include "dbNetlistDeviceExtractor.h"
|
||||
#include "dbNetlistExtractor.h"
|
||||
#include "dbNetlistDeviceClasses.h"
|
||||
#include "dbHierNetworkProcessor.h"
|
||||
#include "dbLayout.h"
|
||||
#include "dbDeepShapeStore.h"
|
||||
#include "dbRegion.h"
|
||||
@@ -234,177 +234,6 @@ static unsigned int layer_of (const db::Region ®ion)
|
||||
return db::DeepLayer (region).layer ();
|
||||
}
|
||||
|
||||
// @@@ TODO: move somewhere else
|
||||
class NetExtractor
|
||||
{
|
||||
public:
|
||||
typedef db::hier_clusters<db::PolygonRef> hier_clusters_type;
|
||||
typedef db::connected_clusters<db::PolygonRef> connected_clusters_type;
|
||||
typedef db::local_cluster<db::PolygonRef> local_cluster_type;
|
||||
|
||||
NetExtractor ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void extract_nets (const db::DeepShapeStore &dss, const db::Connectivity &conn, db::Netlist *nl)
|
||||
{
|
||||
const db::Layout &layout = dss.const_layout ();
|
||||
const db::Cell &cell = dss.const_initial_cell ();
|
||||
|
||||
// gets the text annotation property ID -
|
||||
// this is how the texts are passed for annotating the net names
|
||||
std::pair<bool, db::property_names_id_type> text_annot_name_id (false, 0);
|
||||
if (! dss.text_property_name ().is_nil ()) {
|
||||
text_annot_name_id = layout.properties_repository ().get_id_of_name (dss.text_property_name ());
|
||||
}
|
||||
|
||||
// gets the device terminal annotation property ID -
|
||||
// this is how the device extractor conveys terminal shape annotations.
|
||||
std::pair<bool, db::property_names_id_type> terminal_annot_name_id;
|
||||
terminal_annot_name_id = layout.properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::terminal_property_name ());
|
||||
|
||||
// the big part: actually extract the nets
|
||||
|
||||
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) {
|
||||
tl_assert (layout.is_valid_cell_index (c->cell_index ()));
|
||||
circuits.insert (std::make_pair (c->cell_index (), c.operator-> ()));
|
||||
}
|
||||
|
||||
std::map<db::cell_index_type, std::map<size_t, size_t> > pins_per_cluster;
|
||||
|
||||
for (db::Layout::bottom_up_const_iterator cid = layout.begin_bottom_up (); cid != layout.end_bottom_up (); ++cid) {
|
||||
|
||||
const connected_clusters_type &clusters = m_net_clusters.clusters_per_cell (*cid);
|
||||
if (clusters.empty ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// a cell makes a new circuit (or uses an existing one)
|
||||
|
||||
db::Circuit *circuit = 0;
|
||||
|
||||
std::map<db::cell_index_type, db::Circuit *>::const_iterator k = circuits.find (*cid);
|
||||
if (k == circuits.end ()) {
|
||||
circuit = new db::Circuit ();
|
||||
nl->add_circuit (circuit);
|
||||
circuit->set_name (layout.cell_name (*cid));
|
||||
circuit->set_cell_index (*cid);
|
||||
circuits.insert (std::make_pair (*cid, circuit));
|
||||
} else {
|
||||
circuit = k->second;
|
||||
}
|
||||
|
||||
std::map<size_t, size_t> &c2p = pins_per_cluster [*cid];
|
||||
|
||||
std::map<db::InstElement, db::SubCircuit *> subcircuits;
|
||||
|
||||
for (connected_clusters_type::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) {
|
||||
|
||||
db::Net *net = new db::Net ();
|
||||
net->set_cluster_id (*c);
|
||||
circuit->add_net (net);
|
||||
|
||||
if (! clusters.is_root (*c)) {
|
||||
|
||||
// a non-root cluster makes a pin
|
||||
db::Pin pin (net->name ());
|
||||
size_t pin_id = circuit->add_pin (pin).id ();
|
||||
net->add_pin (db::NetPinRef (pin_id));
|
||||
c2p.insert (std::make_pair (*c, pin_id));
|
||||
circuit->connect_pin (pin_id, net);
|
||||
|
||||
}
|
||||
|
||||
const connected_clusters_type::connections_type &connections = clusters.connections_for_cluster (*c);
|
||||
for (connected_clusters_type::connections_type::const_iterator i = connections.begin (); i != connections.end (); ++i) {
|
||||
|
||||
db::SubCircuit *subcircuit = 0;
|
||||
db::cell_index_type ccid = i->inst ().inst_ptr.cell_index ();
|
||||
|
||||
std::map<db::InstElement, db::SubCircuit *>::const_iterator j = subcircuits.find (i->inst ());
|
||||
if (j == subcircuits.end ()) {
|
||||
|
||||
// make subcircuit if required
|
||||
|
||||
std::map<db::cell_index_type, db::Circuit *>::const_iterator k = circuits.find (ccid);
|
||||
tl_assert (k != circuits.end ()); // because we walk bottom-up
|
||||
|
||||
subcircuit = new db::SubCircuit (k->second);
|
||||
db::CplxTrans dbu_trans (layout.dbu ());
|
||||
subcircuit->set_trans (dbu_trans * i->inst ().complex_trans () * dbu_trans.inverted ());
|
||||
circuit->add_subcircuit (subcircuit);
|
||||
subcircuits.insert (std::make_pair (i->inst (), subcircuit));
|
||||
|
||||
} else {
|
||||
subcircuit = j->second;
|
||||
}
|
||||
|
||||
// create the pin connection to the subcircuit
|
||||
std::map<db::cell_index_type, std::map<size_t, size_t> >::const_iterator icc2p = pins_per_cluster.find (ccid);
|
||||
tl_assert (icc2p != pins_per_cluster.end ());
|
||||
std::map<size_t, size_t>::const_iterator ip = icc2p->second.find (i->id ());
|
||||
tl_assert (ip != icc2p->second.end ());
|
||||
subcircuit->connect_pin (ip->second, net);
|
||||
|
||||
}
|
||||
|
||||
// collect the properties - we know that the cluster attributes are property ID's because the
|
||||
// cluster processor converts shape property IDs to attributes
|
||||
const local_cluster_type &lc = clusters.cluster_by_id (*c);
|
||||
for (local_cluster_type::attr_iterator a = lc.begin_attr (); a != lc.end_attr (); ++a) {
|
||||
|
||||
const db::PropertiesRepository::properties_set &ps = layout.properties_repository ().properties (*a);
|
||||
for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) {
|
||||
|
||||
if (terminal_annot_name_id.first && j->first == terminal_annot_name_id.second) {
|
||||
|
||||
if (j->second.is_user<db::NetlistProperty> ()) {
|
||||
const db::NetlistProperty *np = &j->second.to_user<db::NetlistProperty> ();
|
||||
const db::DeviceTerminalProperty *tp = dynamic_cast<const db::DeviceTerminalProperty *> (np);
|
||||
if (tp) {
|
||||
db::Device *device = circuit->device_by_id (tp->device_id ());
|
||||
tl_assert (device != 0);
|
||||
device->connect_terminal (tp->terminal_id (), net);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (text_annot_name_id.first && j->first == text_annot_name_id.second) {
|
||||
|
||||
std::string n = j->second.to_string ();
|
||||
if (! n.empty ()) {
|
||||
if (! net->name ().empty ()) {
|
||||
n = net->name () + "," + n;
|
||||
}
|
||||
net->set_name (n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const hier_clusters_type clusters () const
|
||||
{
|
||||
return m_net_clusters;
|
||||
}
|
||||
|
||||
private:
|
||||
hier_clusters_type m_net_clusters;
|
||||
};
|
||||
|
||||
static std::string net_name (const db::Net *net)
|
||||
{
|
||||
return net ? net->expanded_name () : "(null)";
|
||||
@@ -614,7 +443,7 @@ TEST(1_DeviceNetExtraction)
|
||||
|
||||
// perform the net extraction
|
||||
|
||||
NetExtractor net_ex;
|
||||
db::NetlistExtractor net_ex;
|
||||
|
||||
db::Connectivity conn;
|
||||
// Intra-layer
|
||||
|
||||
Reference in New Issue
Block a user