WIP: refactoring. Goal is to supply a netlist builder object for caching netlist build information

This commit is contained in:
Matthias Koefferlein 2023-01-19 12:08:50 +01:00
parent c16082654f
commit fb60e01f45
9 changed files with 613 additions and 364 deletions

View File

@ -38,7 +38,10 @@
namespace db
{
// the iterator provides the hierarchical selection (enabling/disabling cells etc.)
// -----------------------------------------------------------------------------------------------
// LayoutToNetlist implementation
// Note: the iterator provides the hierarchical selection (enabling/disabling cells etc.)
LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter)
: m_iter (iter), m_layout_index (0), m_netlist_extracted (false), m_is_flat (false), m_device_scaling (1.0), m_include_floating_subcircuits (false)
@ -877,279 +880,39 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
return res.release ();
}
void
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const db::ICplxTrans &tr) const
{
const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0);
build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, &net, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, tr);
}
void
LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const db::ICplxTrans &tr) const
{
db::Cell *target_cell = &tc;
if (net_cell_name_prefix) {
const db::connected_clusters<db::NetShape> &ccl = m_net_clusters.clusters_per_cell (ci);
bool any_connections = circuit_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
if (! any_connections) {
StopOnFirst sof;
std::map<unsigned int, StopOnFirst *> sof_lmap;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
sof_lmap.insert (std::make_pair (layer_of (*l->second), &sof));
}
}
bool consider_cell = ! deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, sof_lmap, tr, 0);
if (! consider_cell) {
// shortcut if cell is empty -> no net cell will be produced
return;
}
}
// make a specific cell for the net if requested
target_cell = &target.cell (target.add_cell ((std::string (net_cell_name_prefix) + net->expanded_name ()).c_str ()));
tc.insert (db::CellInstArray (db::CellInst (target_cell->cell_index ()), db::Trans ()));
}
std::map<unsigned int, db::Shapes *> target_lmap;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
target_lmap.insert (std::make_pair (layer_of (*l->second), &target_cell->shapes (l->first)));
}
}
deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, target_lmap, tr, netname_propid);
if (hier_mode != BNH_SubcircuitCells && ! device_cell_name_prefix) {
return;
}
// NOTE: we propagate the magnification part of tr down, but keep the rotation/translation part in the instance
// (we want to avoid magnified instances)
db::ICplxTrans tr_wo_mag = tr * db::ICplxTrans (1.0 / tr.mag ());
db::ICplxTrans tr_mag (tr.mag ());
const db::connected_clusters<db::NetShape> &clusters = m_net_clusters.clusters_per_cell (ci);
typedef db::connected_clusters<db::NetShape>::connections_type connections_type;
const connections_type &connections = clusters.connections_for_cluster (cid);
for (connections_type::const_iterator c = connections.begin (); c != connections.end (); ++c) {
db::cell_index_type subci = c->inst_cell_index ();
size_t subcid = c->id ();
CellReuseTableKey cmap_key (subci, netname_propid, subcid);
cell_reuse_table_type::const_iterator cm = reuse_table.find (cmap_key);
if (cm == reuse_table.end ()) {
const char *name_prefix = 0;
if (mp_netlist->device_abstract_by_cell_index (subci)) {
name_prefix = device_cell_name_prefix;
} else {
name_prefix = circuit_cell_name_prefix;
}
if (name_prefix) {
std::string cell_name = internal_layout ()->cell_name (subci);
db::cell_index_type target_ci = target.add_cell ((std::string (name_prefix) + cell_name).c_str ());
cm = reuse_table.insert (std::make_pair (cmap_key, target_ci)).first;
build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, 0, 0, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, reuse_table, tr_mag);
} else {
cm = reuse_table.insert (std::make_pair (cmap_key, std::numeric_limits<db::cell_index_type>::max ())).first;
}
}
if (cm->second != std::numeric_limits<db::cell_index_type>::max ()) {
db::CellInstArray ci (db::CellInst (cm->second), tr_wo_mag * c->inst_trans ());
ci.transform_into (tr_mag);
target_cell->insert (ci);
}
}
}
db::properties_id_type
LayoutToNetlist::make_netname_propid (db::Layout &ly, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, const db::Net &net) const
{
if (net_prop_mode == NoProperties) {
return 0;
} else if (! netname_prop.is_nil () || (net_prop_mode == AllProperties && net.begin_properties () != net.end_properties ())) {
db::PropertiesRepository::properties_set propset;
// add the user properties too (TODO: make this configurable?)
for (db::Net::property_iterator p = net.begin_properties (); p != net.end_properties (); ++p) {
db::property_names_id_type key_propnameid = ly.properties_repository ().prop_name_id (p->first);
propset.insert (std::make_pair (key_propnameid, p->second));
}
if (! netname_prop.is_nil ()) {
db::property_names_id_type name_propnameid = ly.properties_repository ().prop_name_id (netname_prop);
if (net_prop_mode == NetNameAndIDOnly) {
std::vector<tl::Variant> l;
l.reserve (2);
l.push_back (tl::Variant (net.expanded_name ()));
l.push_back (tl::Variant (reinterpret_cast <size_t> (&net)));
propset.insert (std::make_pair (name_propnameid, tl::Variant (l)));
} else if (net_prop_mode == NetIDOnly) {
propset.insert (std::make_pair (name_propnameid, tl::Variant (reinterpret_cast <size_t> (&net))));
} else {
propset.insert (std::make_pair (name_propnameid, tl::Variant (net.expanded_name ())));
}
}
return ly.properties_repository ().properties_id (propset);
} else {
return 0;
}
}
void
LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const
{
if (! m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
NetBuilder builder (&target, this);
builder.set_hier_mode (hier_mode);
builder.set_cell_name_prefix (cell_name_prefix);
builder.set_device_cell_name_prefix (device_cell_name_prefix);
cell_reuse_table_type cell_reuse_table;
double mag = internal_layout ()->dbu () / target.dbu ();
db::properties_id_type netname_propid = make_netname_propid (target, net_prop_mode, netname_prop, net);
build_net_rec (net, target, target_cell, lmap, 0, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans (mag));
builder.build_net (target_cell, net, lmap, net_prop_mode, netname_prop);
}
void
LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
{
build_nets (0, cmap, target, lmap, net_cell_name_prefix, net_prop_mode, netname_prop, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix);
}
NetBuilder builder (&target, cmap, this);
builder.set_hier_mode (hier_mode);
builder.set_net_cell_name_prefix (net_cell_name_prefix);
builder.set_cell_name_prefix (circuit_cell_name_prefix);
builder.set_device_cell_name_prefix (device_cell_name_prefix);
void
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const
{
if (! cmap.has_mapping (circuit_cell)) {
const db::Cell &cc = internal_layout ()->cell (circuit_cell);
for (db::Cell::parent_inst_iterator p = cc.begin_parent_insts (); ! p.at_end (); ++p) {
db::CellInstArray ci = p->child_inst ().cell_inst ();
for (db::CellInstArray::iterator ia = ci.begin (); ! ia.at_end(); ++ia) {
db::ICplxTrans tr_parent = ci.complex_trans (*ia) * tr;
build_net_rec (net, target, p->parent_cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, tr_parent);
}
}
} else {
double mag = internal_layout ()->dbu () / target.dbu ();
db::cell_index_type target_ci = cmap.cell_mapping (circuit_cell);
build_net_rec (net, target, target.cell (target_ci), lmap, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, db::ICplxTrans (mag) * tr);
}
builder.build_nets (0, lmap, net_prop_mode, netname_prop);
}
void
LayoutToNetlist::build_nets (const std::vector<const db::Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
{
if (! m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
NetBuilder builder (&target, cmap, this);
builder.set_hier_mode (hier_mode);
builder.set_net_cell_name_prefix (net_cell_name_prefix);
builder.set_cell_name_prefix (circuit_cell_name_prefix);
builder.set_device_cell_name_prefix (device_cell_name_prefix);
std::set<const db::Net *> net_set;
if (nets) {
net_set.insert (nets->begin (), nets->end ());
}
cell_reuse_table_type cell_reuse_table;
const db::Netlist *netlist = mp_netlist.get ();
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
bool is_top_circuit = c->begin_parents () == c->end_parents ();
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
// exclude local nets in recursive mode except if they are explicitly selected
if (! nets && hier_mode != BNH_Disconnected && ! is_top_circuit && n->pin_count () > 0) {
continue;
}
if (! nets || net_set.find (n.operator-> ()) != net_set.end ()) {
db::properties_id_type netname_propid = make_netname_propid (target, net_prop_mode, netname_prop, *n);
build_net_rec (*n, target, c->cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans ());
}
}
if (hier_mode != BNH_Disconnected && ! nets) {
// With recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
// subcircuits as part of the circuit which calls the subcircuit - but NOT in a subcircuit cell, because
// this will just apply to nets from certain instances. But the net cell name will be formed as "subcircuit:net"
//
// In explicit selection mode we don't care about this as nets are explicitly taken or not.
const db::Circuit &circuit = *c;
for (db::Circuit::const_subcircuit_iterator sc = circuit.begin_subcircuits (); sc != circuit.end_subcircuits (); ++sc) {
const db::SubCircuit &subcircuit = *sc;
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) {
if (! subcircuit.net_for_pin (p->id ())) {
const db::Net *n = subcircuit.circuit_ref ()->net_for_pin (p->id ());
if (n) {
double dbu = target.dbu ();
db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
db::properties_id_type netname_propid = make_netname_propid (target, net_prop_mode, netname_prop, *n);
if (net_cell_name_prefix) {
std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":";
build_net_rec (*n, target, c->cell_index (), cmap, lmap, ncn.c_str (), netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr);
} else {
build_net_rec (*n, target, c->cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr);
}
}
}
}
}
}
}
builder.build_nets (nets, lmap, net_prop_mode, netname_prop);
}
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector<db::SubCircuit *> *sc_path_out, db::Circuit *initial_circuit)
@ -1708,4 +1471,357 @@ void LayoutToNetlist::set_generator (const std::string &g)
m_generator = g;
}
// -----------------------------------------------------------------------------------------------
// NetBuilder implementation
NetBuilder::NetBuilder ()
: m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
{
// .. nothing yet ..
}
NetBuilder::NetBuilder (db::Layout *target, const db::CellMapping &cmap, const db::LayoutToNetlist *source)
: mp_target (target), m_cmap (cmap), mp_source (const_cast <db::LayoutToNetlist *> (source)),
m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
{
// .. nothing yet ..
}
NetBuilder::NetBuilder (db::Layout *target, const db::LayoutToNetlist *source)
: mp_target (target), mp_source (const_cast <db::LayoutToNetlist *> (source)),
m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
{
// .. nothing yet ..
}
NetBuilder::NetBuilder (const db::NetBuilder &other)
{
operator=(other);
}
NetBuilder::NetBuilder (db::NetBuilder &&other)
{
operator=(other);
}
NetBuilder &
NetBuilder::operator= (const db::NetBuilder &other)
{
if (this != &other) {
mp_target = other.mp_target;
mp_source = other.mp_source;
m_cmap = other.m_cmap;
m_reuse_table = other.m_reuse_table;
m_hier_mode = other.m_hier_mode;
m_has_net_cell_name_prefix = other.m_has_net_cell_name_prefix;
m_net_cell_name_prefix = other.m_net_cell_name_prefix;
m_has_cell_name_prefix = other.m_has_cell_name_prefix;
m_cell_name_prefix = other.m_cell_name_prefix;
m_has_device_cell_name_prefix = other.m_has_device_cell_name_prefix;
m_device_cell_name_prefix = other.m_device_cell_name_prefix;
}
return *this;
}
NetBuilder &
NetBuilder::operator= (db::NetBuilder &&other)
{
if (this != &other) {
mp_target = other.mp_target;
other.mp_target.reset (0);
mp_source = other.mp_source;
other.mp_source.reset (0);
m_cmap.swap (other.m_cmap);
m_reuse_table.swap (other.m_reuse_table);
std::swap (m_hier_mode, other.m_hier_mode);
std::swap (m_has_net_cell_name_prefix, other.m_has_net_cell_name_prefix);
m_net_cell_name_prefix.swap (other.m_net_cell_name_prefix);
std::swap (m_has_cell_name_prefix, other.m_has_cell_name_prefix);
m_cell_name_prefix.swap (other.m_cell_name_prefix);
std::swap (m_has_device_cell_name_prefix, other.m_has_device_cell_name_prefix);
m_device_cell_name_prefix.swap (other.m_device_cell_name_prefix);
}
return *this;
}
void
NetBuilder::build_net (db::Cell &target_cell, const db::Net &net, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop) const
{
tl_assert (mp_target.get ());
tl_assert (mp_source.get ());
if (! mp_source->is_netlist_extracted ()) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
double mag = mp_source->internal_layout ()->dbu () / mp_target->dbu ();
db::properties_id_type netname_propid = make_netname_propid (target (), net_prop_mode, netname_prop, net);
build_net_rec (net, target_cell, lmap, std::string (), netname_propid, db::ICplxTrans (mag));
}
void
NetBuilder::build_all_nets (const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop) const
{
tl_assert (mp_target.get ());
tl_assert (mp_source.get ());
build_nets (0, lmap, net_prop_mode, netname_prop);
}
void
NetBuilder::build_nets (const std::vector<const Net *> *nets, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const
{
tl_assert (mp_target.get ());
tl_assert (mp_source.get ());
if (! mp_source->is_netlist_extracted ()) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
std::set<const db::Net *> net_set;
if (nets) {
net_set.insert (nets->begin (), nets->end ());
}
const db::Netlist *netlist = mp_source->netlist ();
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
bool is_top_circuit = c->begin_parents () == c->end_parents ();
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
// exclude local nets in recursive mode except if they are explicitly selected
if (! nets && m_hier_mode != BNH_Disconnected && ! is_top_circuit && n->pin_count () > 0) {
continue;
}
if (! nets || net_set.find (n.operator-> ()) != net_set.end ()) {
db::properties_id_type netname_propid = make_netname_propid (target (), prop_mode, netname_prop, *n);
build_net_rec (*n, c->cell_index (), lmap, std::string (), netname_propid, db::ICplxTrans ());
}
}
if (m_hier_mode != BNH_Disconnected && ! nets) {
// With recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
// subcircuits as part of the circuit which calls the subcircuit - but NOT in a subcircuit cell, because
// this will just apply to nets from certain instances. But the net cell name will be formed as "subcircuit:net"
//
// In explicit selection mode we don't care about this as nets are explicitly taken or not.
const db::Circuit &circuit = *c;
for (db::Circuit::const_subcircuit_iterator sc = circuit.begin_subcircuits (); sc != circuit.end_subcircuits (); ++sc) {
const db::SubCircuit &subcircuit = *sc;
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) {
if (! subcircuit.net_for_pin (p->id ())) {
const db::Net *n = subcircuit.circuit_ref ()->net_for_pin (p->id ());
if (n) {
double dbu = mp_target->dbu ();
db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
db::properties_id_type netname_propid = make_netname_propid (target (), prop_mode, netname_prop, *n);
build_net_rec (*n, c->cell_index (), lmap, subcircuit.expanded_name () + ":", netname_propid, tr);
}
}
}
}
}
}
}
void
NetBuilder::build_net_rec (const db::Net &net, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const db::ICplxTrans &tr) const
{
const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0);
build_net_rec (circuit->cell_index (), net.cluster_id (), target_cell, lmap, &net, add_net_cell_name_prefix, netname_propid, tr);
}
void
NetBuilder::build_net_rec (db::cell_index_type ci, size_t cid, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const db::ICplxTrans &tr) const
{
db::Cell *target_cell = &tc;
if (net && m_has_net_cell_name_prefix) {
const db::connected_clusters<db::NetShape> &ccl = mp_source->net_clusters ().clusters_per_cell (ci);
bool any_connections = m_has_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
if (! any_connections) {
StopOnFirst sof;
std::map<unsigned int, StopOnFirst *> sof_lmap;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
sof_lmap.insert (std::make_pair (mp_source->layer_of (*l->second), &sof));
}
}
bool consider_cell = ! deliver_shapes_of_net (m_hier_mode == BNH_Flatten, mp_source->netlist (), mp_source->net_clusters (), ci, cid, sof_lmap, tr, 0);
if (! consider_cell) {
// shortcut if cell is empty -> no net cell will be produced
return;
}
}
// make a specific cell for the net if requested
target_cell = &target ().cell (target ().add_cell ((m_net_cell_name_prefix + add_net_cell_name_prefix + net->expanded_name ()).c_str ()));
tc.insert (db::CellInstArray (db::CellInst (target_cell->cell_index ()), db::Trans ()));
}
std::map<unsigned int, db::Shapes *> target_lmap;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
target_lmap.insert (std::make_pair (mp_source->layer_of (*l->second), &target_cell->shapes (l->first)));
}
}
deliver_shapes_of_net (m_hier_mode == BNH_Flatten, mp_source->netlist (), mp_source->net_clusters (), ci, cid, target_lmap, tr, netname_propid);
if (m_hier_mode != BNH_SubcircuitCells && ! m_has_device_cell_name_prefix) {
return;
}
// NOTE: we propagate the magnification part of tr down, but keep the rotation/translation part in the instance
// (we want to avoid magnified instances)
db::ICplxTrans tr_wo_mag = tr * db::ICplxTrans (1.0 / tr.mag ());
db::ICplxTrans tr_mag (tr.mag ());
const db::connected_clusters<db::NetShape> &clusters = mp_source->net_clusters ().clusters_per_cell (ci);
typedef db::connected_clusters<db::NetShape>::connections_type connections_type;
const connections_type &connections = clusters.connections_for_cluster (cid);
for (connections_type::const_iterator c = connections.begin (); c != connections.end (); ++c) {
db::cell_index_type subci = c->inst_cell_index ();
size_t subcid = c->id ();
CellReuseTableKey cmap_key (subci, netname_propid, subcid);
cell_reuse_table_type::const_iterator cm = m_reuse_table.find (cmap_key);
if (cm == m_reuse_table.end ()) {
bool has_name_prefix = false;
std::string name_prefix;
if (mp_source->netlist ()->device_abstract_by_cell_index (subci)) {
name_prefix = m_device_cell_name_prefix;
has_name_prefix = m_has_device_cell_name_prefix;
} else {
name_prefix = m_cell_name_prefix;
has_name_prefix = m_has_cell_name_prefix;
}
if (has_name_prefix) {
std::string cell_name = mp_source->internal_layout ()->cell_name (subci);
db::cell_index_type target_ci = target ().add_cell ((name_prefix + cell_name).c_str ());
cm = m_reuse_table.insert (std::make_pair (cmap_key, target_ci)).first;
build_net_rec (subci, subcid, target ().cell (target_ci), lmap, 0, std::string (), netname_propid, tr_mag);
} else {
cm = m_reuse_table.insert (std::make_pair (cmap_key, std::numeric_limits<db::cell_index_type>::max ())).first;
}
}
if (cm->second != std::numeric_limits<db::cell_index_type>::max ()) {
db::CellInstArray ci (db::CellInst (cm->second), tr_wo_mag * c->inst_trans ());
ci.transform_into (tr_mag);
target_cell->insert (ci);
}
}
}
void
NetBuilder::build_net_rec (const db::Net &net, db::cell_index_type circuit_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const
{
if (! m_cmap.has_mapping (circuit_cell)) {
const db::Cell &cc = mp_source->internal_layout ()->cell (circuit_cell);
for (db::Cell::parent_inst_iterator p = cc.begin_parent_insts (); ! p.at_end (); ++p) {
db::CellInstArray ci = p->child_inst ().cell_inst ();
for (db::CellInstArray::iterator ia = ci.begin (); ! ia.at_end(); ++ia) {
db::ICplxTrans tr_parent = ci.complex_trans (*ia) * tr;
build_net_rec (net, p->parent_cell_index (), lmap, add_net_cell_name_prefix, netname_propid, tr_parent);
}
}
} else {
double mag = mp_source->internal_layout ()->dbu () / mp_target->dbu ();
db::cell_index_type target_ci = m_cmap.cell_mapping (circuit_cell);
build_net_rec (net, target ().cell (target_ci), lmap, add_net_cell_name_prefix, netname_propid, db::ICplxTrans (mag) * tr);
}
}
db::properties_id_type
NetBuilder::make_netname_propid (db::Layout &ly, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, const db::Net &net) const
{
if (net_prop_mode == NPM_NoProperties) {
return 0;
} else if (! netname_prop.is_nil () || (net_prop_mode == NPM_AllProperties && net.begin_properties () != net.end_properties ())) {
db::PropertiesRepository::properties_set propset;
// add the user properties too (TODO: make this configurable?)
for (db::Net::property_iterator p = net.begin_properties (); p != net.end_properties (); ++p) {
db::property_names_id_type key_propnameid = ly.properties_repository ().prop_name_id (p->first);
propset.insert (std::make_pair (key_propnameid, p->second));
}
if (! netname_prop.is_nil ()) {
db::property_names_id_type name_propnameid = ly.properties_repository ().prop_name_id (netname_prop);
if (net_prop_mode == NPM_NetNameAndIDOnly) {
std::vector<tl::Variant> l;
l.reserve (2);
l.push_back (tl::Variant (net.expanded_name ()));
l.push_back (tl::Variant (reinterpret_cast <size_t> (&net)));
propset.insert (std::make_pair (name_propnameid, tl::Variant (l)));
} else if (net_prop_mode == NPM_NetIDOnly) {
propset.insert (std::make_pair (name_propnameid, tl::Variant (reinterpret_cast <size_t> (&net))));
} else {
propset.insert (std::make_pair (name_propnameid, tl::Variant (net.expanded_name ())));
}
}
return ly.properties_repository ().properties_id (propset);
} else {
return 0;
}
}
}

View File

@ -32,6 +32,62 @@
namespace db
{
class NetlistBuilder;
/**
* @brief An enum describing the way how net information is attached to shapes as properties in "build_nets"
*/
enum NetPropertyMode
{
/**
* @brief Do no generate properties
*/
NPM_NoProperties,
/**
* @brief Attach all net properties plus the net name (if a "netname_prop" is specified to "build_nets")
*/
NPM_AllProperties,
/**
* @brief Attach net name only (if a "netname_prop" is specified to "build_nets")
*/
NPM_NetNameOnly,
/**
* @brief Like NetNameOnly, but use a unique net ID (db::Net address actually) instead of name
*/
NPM_NetIDOnly,
/**
* @brief Like NetNameOnly, but use a tuple of name and ID
*/
NPM_NetNameAndIDOnly,
};
/**
* @brief An enum describing the way the net hierarchy is mapped
*/
enum BuildNetHierarchyMode
{
/**
* @brief Flatten the net
* Collects all shapes of a net and puts that into the net cell or circuit cell
*/
BNH_Flatten = 0,
/**
* @brief Build a net hierarchy adding cells for each subcircuit on the net
* Uses the circuit_cell_prefix to build the subcircuit cell names
*/
BNH_SubcircuitCells = 1,
/**
* @brief No hierarchy
* Just output the shapes of the net belonging to the circuit cell.
* Connections are not indicated!
*/
BNH_Disconnected = 2
};
/**
* @brief A generic framework for extracting netlists from layouts
*
@ -703,60 +759,6 @@ public:
*/
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0) const;
/**
* @brief An enum describing the way how net information is attached to shapes as properties in "build_nets"
*/
enum NetPropertyMode
{
/**
* @brief Do no generate properties
*/
NoProperties,
/**
* @brief Attach all net properties plus the net name (if a "netname_prop" is specified to "build_nets")
*/
AllProperties,
/**
* @brief Attach net name only (if a "netname_prop" is specified to "build_nets")
*/
NetNameOnly,
/**
* @brief Like NetNameOnly, but use a unique net ID (db::Net address actually) instead of name
*/
NetIDOnly,
/**
* @brief Like NetNameOnly, but use a tuple of name and ID
*/
NetNameAndIDOnly,
};
/**
* @brief An enum describing the way the net hierarchy is mapped
*/
enum BuildNetHierarchyMode
{
/**
* @brief Flatten the net
* Collects all shapes of a net and puts that into the net cell or circuit cell
*/
BNH_Flatten = 0,
/**
* @brief Build a net hierarchy adding cells for each subcircuit on the net
* Uses the circuit_cell_prefix to build the subcircuit cell names
*/
BNH_SubcircuitCells = 1,
/**
* @brief No hierarchy
* Just output the shapes of the net belonging to the circuit cell.
* Connections are not indicated!
*/
BNH_Disconnected = 2
};
/**
* @brief Builds a net representation in the given layout and cell
*
@ -980,6 +982,133 @@ private:
std::list<std::set<std::string> > m_joined_nets;
std::list<std::pair<tl::GlobPattern, std::set<std::string> > > m_joined_nets_per_cell;
void init ();
void ensure_netlist ();
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<NetShape> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
db::DeepLayer deep_layer_of (const ShapeCollection &coll) const;
void ensure_layout () const;
std::string make_new_name (const std::string &stem = std::string ());
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells);
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);
virtual void link_nets (const db::Net *net, const db::Net *with);
};
/**
* @brief An object building nets (net-to-layout)
*
* This object can be used to persist netlist builder information - e.g. reusing net cells when building individual
* layers from nets. In this case, build nets with a layer selection and call the build_net function many times.
*/
class DB_PUBLIC NetBuilder
{
public:
/**
* @brief Default constructor
*/
NetBuilder ();
/**
* @brief Constructs a net builder with a target layout, a cell mapping table and a LayoutToNetlist source
*
* @param target The target layout
* @param cmap The cell mapping from the internal layout (inside LayoutToNetlist) to the target - use LayoutInfo::cell_mapping_into to generate this map
* @param source The LayoutToNetlist source.
*
* A cell map needs to be supplied only if intending to build many nets in hierarchical mode from multiple circuits.
*/
NetBuilder (db::Layout *target, const db::CellMapping &cmap, const db::LayoutToNetlist *source);
/**
* @brief Constructs a net builder with a source only
*
* @param source The LayoutToNetlist source.
*
* This net builder can be used to build single nets into dedicated target cells.
*/
NetBuilder (db::Layout *target, const db::LayoutToNetlist *source);
/**
* @brief Copy constructor
*/
NetBuilder (const db::NetBuilder &other);
/**
* @brief Move constructor
*/
NetBuilder (db::NetBuilder &&other);
/**
* @brief Assignment
*/
NetBuilder &operator= (const db::NetBuilder &other);
/**
* @brief Move
*/
NetBuilder &operator= (db::NetBuilder &&other);
/**
* @brief Sets the net-to-hierarchy generation mode
*/
void set_hier_mode (BuildNetHierarchyMode hm)
{
m_hier_mode = hm;
}
/**
* @brief Sets or resets the net cell name prefix
*
* Pass 0 to this string value to reset it.
*/
void set_net_cell_name_prefix (const char *s)
{
m_has_net_cell_name_prefix = (s != 0);
m_net_cell_name_prefix = std::string (s ? s : "");
}
/**
* @brief Sets or resets the circuit cell name prefix
*
* Pass 0 to this string value to reset it.
*/
void set_cell_name_prefix (const char *s)
{
m_has_cell_name_prefix = (s != 0);
m_cell_name_prefix = std::string (s ? s : "");
}
/**
* @brief Sets or resets the device cell name prefix
*
* Pass 0 to this string value to reset it.
*/
void set_device_cell_name_prefix (const char *s)
{
m_has_device_cell_name_prefix = (s != 0);
m_device_cell_name_prefix = std::string (s ? s : "");
}
/**
* @brief See \LayoutToNetlist for details of this function
*/
void build_net (db::Cell &target_cell, const db::Net &net, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
/**
* @brief See \LayoutToNetlist for details of this function
*/
void build_all_nets (const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
/**
* @brief See \LayoutToNetlist for details of this function
*/
void build_nets (const std::vector<const Net *> *nets, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
private:
struct CellReuseTableKey
{
CellReuseTableKey (db::cell_index_type _cell_index, db::properties_id_type _netname_propid, size_t _cluster_id)
@ -1009,23 +1138,27 @@ private:
typedef std::map<CellReuseTableKey, db::cell_index_type> cell_reuse_table_type;
void init ();
void ensure_netlist ();
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<NetShape> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
void build_net_rec (const db::Net &net, db::Layout &target, cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
db::DeepLayer deep_layer_of (const ShapeCollection &coll) const;
void ensure_layout () const;
std::string make_new_name (const std::string &stem = std::string ());
db::properties_id_type make_netname_propid (db::Layout &ly, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, const db::Net &net) const;
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells);
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
tl::weak_ptr<db::Layout> mp_target;
db::CellMapping m_cmap;
tl::weak_ptr<db::LayoutToNetlist> mp_source;
mutable cell_reuse_table_type m_reuse_table;
BuildNetHierarchyMode m_hier_mode;
bool m_has_net_cell_name_prefix;
std::string m_net_cell_name_prefix;
bool m_has_cell_name_prefix;
std::string m_cell_name_prefix;
bool m_has_device_cell_name_prefix;
std::string m_device_cell_name_prefix;
// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);
virtual void link_nets (const db::Net *net, const db::Net *with);
void build_net_rec (const db::Net &net, cell_index_type circuit_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
void build_net_rec (const db::Net &net, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
void build_net_rec (db::cell_index_type ci, size_t cid, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const Net *net, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
db::properties_id_type make_netname_propid (db::Layout &ly, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, const db::Net &net) const;
db::Layout &target () const
{
return const_cast<db::Layout &> (*mp_target);
}
};
/**

View File

@ -66,27 +66,27 @@ static db::Cell *l2n_internal_top_cell (db::LayoutToNetlist *l2n)
return const_cast<db::Cell *> (l2n->internal_top_cell ());
}
static void build_net (const db::LayoutToNetlist *l2n, const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, db::LayoutToNetlist::BuildNetHierarchyMode hier_mode, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix)
static void build_net (const db::LayoutToNetlist *l2n, const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, db::BuildNetHierarchyMode hier_mode, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix)
{
std::string p = circuit_cell_name_prefix.to_string ();
std::string dp = device_cell_name_prefix.to_string ();
l2n->build_net (net, target, target_cell, lmap, db::LayoutToNetlist::AllProperties, netname_prop, hier_mode, circuit_cell_name_prefix.is_nil () ? 0 : p.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ());
l2n->build_net (net, target, target_cell, lmap, db::NPM_AllProperties, netname_prop, hier_mode, circuit_cell_name_prefix.is_nil () ? 0 : p.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ());
}
static void build_all_nets (const db::LayoutToNetlist *l2n, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &net_cell_name_prefix, const tl::Variant &netname_prop, db::LayoutToNetlist::BuildNetHierarchyMode hier_mode, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix)
static void build_all_nets (const db::LayoutToNetlist *l2n, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &net_cell_name_prefix, const tl::Variant &netname_prop, db::BuildNetHierarchyMode hier_mode, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix)
{
std::string cp = circuit_cell_name_prefix.to_string ();
std::string np = net_cell_name_prefix.to_string ();
std::string dp = device_cell_name_prefix.to_string ();
l2n->build_all_nets (cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), db::LayoutToNetlist::AllProperties, netname_prop, hier_mode, circuit_cell_name_prefix.is_nil () ? 0 : cp.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ());
l2n->build_all_nets (cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), db::NPM_AllProperties, netname_prop, hier_mode, circuit_cell_name_prefix.is_nil () ? 0 : cp.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ());
}
static void build_nets (const db::LayoutToNetlist *l2n, const std::vector<const db::Net *> &nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &net_cell_name_prefix, const tl::Variant &netname_prop, db::LayoutToNetlist::BuildNetHierarchyMode hier_mode, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix)
static void build_nets (const db::LayoutToNetlist *l2n, const std::vector<const db::Net *> &nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &net_cell_name_prefix, const tl::Variant &netname_prop, db::BuildNetHierarchyMode hier_mode, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix)
{
std::string cp = circuit_cell_name_prefix.to_string ();
std::string np = net_cell_name_prefix.to_string ();
std::string dp = device_cell_name_prefix.to_string ();
l2n->build_nets (&nets, cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), db::LayoutToNetlist::AllProperties, netname_prop, hier_mode, circuit_cell_name_prefix.is_nil () ? 0 : cp.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ());
l2n->build_nets (&nets, cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), db::NPM_AllProperties, netname_prop, hier_mode, circuit_cell_name_prefix.is_nil () ? 0 : cp.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ());
}
static std::vector<std::string> l2n_layer_names (const db::LayoutToNetlist *l2n)
@ -585,7 +585,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"all subcircuits too.\n"
"\"prop_id\" is an optional properties ID. If given, this property set will be attached to the shapes."
) +
gsi::method_ext ("build_net", &build_net, gsi::arg ("net"), gsi::arg ("target"), gsi::arg ("target_cell"), gsi::arg ("lmap"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::LayoutToNetlist::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
gsi::method_ext ("build_net", &build_net, gsi::arg ("net"), gsi::arg ("target"), gsi::arg ("target_cell"), gsi::arg ("lmap"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
"@brief Builds a net representation in the given layout and cell\n"
"\n"
"This method puts the shapes of a net into the given target cell using a variety of options\n"
@ -615,7 +615,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"@param cell_name_prefix Chooses recursive mode if non-null\n"
"@param device_cell_name_prefix See above\n"
) +
gsi::method_ext ("build_all_nets", &build_all_nets, gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::LayoutToNetlist::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
gsi::method_ext ("build_all_nets", &build_all_nets, gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
"@brief Builds a full hierarchical representation of the nets\n"
"\n"
"This method copies all nets into cells corresponding to the circuits. It uses the 'cmap'\n"
@ -657,7 +657,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"@param net_cell_name_prefix See method description\n"
"@param device_cell_name_prefix See above\n"
) +
gsi::method_ext ("build_nets", &build_nets, gsi::arg ("nets"), gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::LayoutToNetlist::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
gsi::method_ext ("build_nets", &build_nets, gsi::arg ("nets"), gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
"@brief Like \\build_all_nets, but with the ability to select some nets."
) +
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &, std::vector<db::SubCircuit *> *, db::Circuit *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector<db::SubCircuit *> *) 0, "nil"), gsi::arg ("initial_circuit", (db::Circuit *) 0, "nil"),
@ -836,14 +836,14 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"This class has been introduced in version 0.26."
);
gsi::EnumIn<db::LayoutToNetlist, db::LayoutToNetlist::BuildNetHierarchyMode> decl_dbLayoutToNetlist_BuildNetHierarchyMode ("db", "BuildNetHierarchyMode",
gsi::enum_const ("BNH_Flatten", db::LayoutToNetlist::BNH_Flatten,
gsi::EnumIn<db::LayoutToNetlist, db::BuildNetHierarchyMode> decl_dbLayoutToNetlist_BuildNetHierarchyMode ("db", "BuildNetHierarchyMode",
gsi::enum_const ("BNH_Flatten", db::BNH_Flatten,
"@brief This constant tells \\build_net and \\build_all_nets to flatten the nets (used for the \"hier_mode\" parameter)."
) +
gsi::enum_const ("BNH_Disconnected", db::LayoutToNetlist::BNH_Disconnected,
gsi::enum_const ("BNH_Disconnected", db::BNH_Disconnected,
"@brief This constant tells \\build_net and \\build_all_nets to produce local nets without connections to subcircuits (used for the \"hier_mode\" parameter)."
) +
gsi::enum_const ("BNH_SubcircuitCells", db::LayoutToNetlist::BNH_SubcircuitCells,
gsi::enum_const ("BNH_SubcircuitCells", db::BNH_SubcircuitCells,
"@brief This constant tells \\build_net and \\build_all_nets to produce a hierarchy of subcircuit cells per net (used for the \"hier_mode\" parameter)."
),
"@brief This class represents the LayoutToNetlist::BuildNetHierarchyMode enum\n"

View File

@ -124,7 +124,7 @@ TEST(0_Develop)
lmap_write [wvia1 = ly2.insert_layer (db::LayerProperties (16, 0))] = l2n.layer_by_name ("via1");
lmap_write [wmetal2 = ly2.insert_layer (db::LayerProperties (17, 0))] = l2n.layer_by_name ("metal2");
l2n.build_all_nets (cm, ly2, lmap_write, "NET_", db::LayoutToNetlist::NetNameAndIDOnly, tl::Variant (1), db::LayoutToNetlist::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/);
l2n.build_all_nets (cm, ly2, lmap_write, "NET_", db::NPM_NetNameAndIDOnly, tl::Variant (1), db::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/);
unsigned int out1 = ly2.insert_layer (db::LayerProperties (1000, 0));
unsigned int out2 = ly2.insert_layer (db::LayerProperties (1001, 0));

View File

@ -74,7 +74,7 @@ TEST(1_ReaderBasic)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_by_name ("via1");
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_by_name ("metal2");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_Disconnected, 0, "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -104,7 +104,7 @@ TEST(1_ReaderBasic)
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, "DEVICE_");
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_Disconnected, 0, "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -134,7 +134,7 @@ TEST(1_ReaderBasic)
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_Flatten, 0, "DEVICE_");
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_Flatten, 0, "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -164,7 +164,7 @@ TEST(1_ReaderBasic)
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -195,7 +195,7 @@ TEST(1_ReaderBasic)
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", 0);
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -226,7 +226,7 @@ TEST(1_ReaderBasic)
db::CellMapping cm = l2n.const_cell_mapping_into (ly2, top2);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -305,7 +305,7 @@ TEST(1c_ReaderBasicShortWithProps)
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2);
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::AllProperties, tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_AllProperties, tl::Variant (), db::BNH_Disconnected, 0, "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -361,7 +361,7 @@ TEST(2_ReaderWithGlobalNets)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_by_name ("via1");
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_by_name ("metal2");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -417,7 +417,7 @@ TEST(3_ReaderAbsoluteCoordinates)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_by_name ("via1");
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_by_name ("metal2");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -463,7 +463,7 @@ TEST(4_ReaderCombinedDevices)
std::map<unsigned int, const db::Region *> lmap = l2n.create_layermap (ly2, 1000);
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");

View File

@ -395,7 +395,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, 0, db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, 0);
l2n.build_all_nets (cm, ly2, lmap, 0, db::NPM_NoProperties, tl::Variant (), db::BNH_Disconnected, 0, 0);
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -421,7 +421,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, 0);
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_Disconnected, 0, 0);
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -447,7 +447,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, 0, db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
l2n.build_all_nets (cm, ly2, lmap, 0, db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", 0);
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -473,7 +473,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, 0, db::LayoutToNetlist::AllProperties, tl::Variant (42), db::LayoutToNetlist::BNH_Flatten, 0, 0);
l2n.build_all_nets (cm, ly2, lmap, 0, db::NPM_AllProperties, tl::Variant (42), db::BNH_Flatten, 0, 0);
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -499,7 +499,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, 0, db::LayoutToNetlist::AllProperties, tl::Variant (42), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
l2n.build_all_nets (cm, ly2, lmap, 0, db::NPM_AllProperties, tl::Variant (42), db::BNH_SubcircuitCells, "CIRCUIT_", 0);
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -525,7 +525,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -636,7 +636,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");

View File

@ -207,7 +207,7 @@ TEST(1_WriterBasic)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_Disconnected, 0, "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");
@ -440,7 +440,7 @@ TEST(2_WriterWithGlobalNets)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testdata ();
au = tl::combine_path (au, "algo");

View File

@ -1781,9 +1781,9 @@ NetlistBrowserPage::export_nets (const std::vector<const db::Net *> *nets)
database->build_nets (nets, cm, target_layout, lm,
dialog->net_prefix ().empty () ? 0 : dialog->net_prefix ().c_str (),
db::LayoutToNetlist::AllProperties,
db::NPM_AllProperties,
dialog->net_propname (),
dialog->produce_circuit_cells () ? db::LayoutToNetlist::BNH_SubcircuitCells : db::LayoutToNetlist::BNH_Flatten,
dialog->produce_circuit_cells () ? db::BNH_SubcircuitCells : db::BNH_Flatten,
dialog->produce_circuit_cells () ? dialog->circuit_cell_prefix ().c_str () : 0,
dialog->produce_device_cells () ? dialog->device_cell_prefix ().c_str () : 0);

View File

@ -78,7 +78,7 @@ void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracer
db::Cell &top_cell = layout_nets.cell (layout_nets.add_cell ("NETS"));
db::CellMapping cm = l2ndb.cell_mapping_into (layout_nets, top_cell);
l2ndb.build_all_nets (cm, layout_nets, l2ndb.create_layermap (layout_nets, 1000), "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
l2ndb.build_all_nets (cm, layout_nets, l2ndb.create_layermap (layout_nets, 1000), "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", 0);
std::string fn (tl::testdata ());
fn += "/net_tracer/";