WIP: moved netlist extractor into right place.

This commit is contained in:
Matthias Koefferlein
2018-12-27 10:57:46 +01:00
parent 8b2902c31b
commit d6473b4d84
4 changed files with 287 additions and 175 deletions
@@ -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 &region)
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