Enhancements for net export feature

- some refactoring
- better performance (was slow because layer iteration
  was done outside of loop and recursive cluster iterator)
- with selected nets, only the required hierarchy is
  produced. For this a new argument is added to
  LayoutToNetlist::create_cell_mapping (nets) which
  allows selecting the nets for which a cell mapping
  is requested
This commit is contained in:
Matthias Koefferlein 2019-06-12 22:55:24 +02:00
parent 0f666d528c
commit ebd00c186b
17 changed files with 369 additions and 133 deletions

View File

@ -295,7 +295,7 @@ CellMapping::create_from_names (const db::Layout &layout_a, db::cell_index_type
} }
std::vector<db::cell_index_type> std::vector<db::cell_index_type>
CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells) CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells)
{ {
std::vector<db::cell_index_type> new_cells; std::vector<db::cell_index_type> new_cells;
std::vector<db::cell_index_type> new_cells_b; std::vector<db::cell_index_type> new_cells_b;
@ -305,7 +305,9 @@ CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /
called_b.insert (cell_index_b); called_b.insert (cell_index_b);
for (std::set<db::cell_index_type>::const_iterator b = called_b.begin (); b != called_b.end (); ++b) { for (std::set<db::cell_index_type>::const_iterator b = called_b.begin (); b != called_b.end (); ++b) {
if (m_b2a_mapping.find (*b) == m_b2a_mapping.end () && (! exclude_cells || exclude_cells->find (*b) == exclude_cells->end ())) { if (m_b2a_mapping.find (*b) == m_b2a_mapping.end ()
&& (! exclude_cells || exclude_cells->find (*b) == exclude_cells->end ())
&& (! include_cells || include_cells->find (*b) != include_cells->end ())) {
db::cell_index_type new_cell = layout_a.add_cell (layout_b.cell_name (*b)); db::cell_index_type new_cell = layout_a.add_cell (layout_b.cell_name (*b));
new_cells.push_back (new_cell); new_cells.push_back (new_cell);
new_cells_b.push_back (*b); new_cells_b.push_back (*b);

View File

@ -190,9 +190,12 @@ public:
* *
* If given, "exclude_cells" can specify a list of cells not to map. * If given, "exclude_cells" can specify a list of cells not to map.
* *
* If given, "include_cells" can specify a list of cells which are included in the
* cell tree to create. Cells not in the "include_cells" list are ignored.
*
* The returned vector lists the new cells. * The returned vector lists the new cells.
*/ */
std::vector<db::cell_index_type> create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0); std::vector<db::cell_index_type> create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0);
private: private:
void extract_unique (std::map <db::cell_index_type, std::vector<db::cell_index_type> >::const_iterator cand, void extract_unique (std::map <db::cell_index_type, std::vector<db::cell_index_type> >::const_iterator cand,

View File

@ -713,7 +713,7 @@ DeepShapeStore::issue_variants (unsigned int layout_index, const std::map<db::ce
} }
const db::CellMapping & const db::CellMapping &
DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set<db::cell_index_type> *excluded_cells) DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set<db::cell_index_type> *excluded_cells, const std::set<db::cell_index_type> *included_cells)
{ {
const db::Layout *source_layout = &m_layouts [layout_index]->layout; const db::Layout *source_layout = &m_layouts [layout_index]->layout;
if (source_layout->begin_top_down () == source_layout->end_top_cells ()) { if (source_layout->begin_top_down () == source_layout->end_top_cells ()) {
@ -774,7 +774,7 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
// Add new cells for the variants and (possible) devices which are cells added during the device // Add new cells for the variants and (possible) devices which are cells added during the device
// extraction process // extraction process
cm->second.create_missing_mapping (*into_layout, into_cell, *source_layout, source_top, excluded_cells); cm->second.create_missing_mapping (*into_layout, into_cell, *source_layout, source_top, excluded_cells, included_cells);
} }

View File

@ -375,9 +375,11 @@ public:
* "layout_index" is the layout to return to it's original. "into_layout" is the original layout, "into_cell" * "layout_index" is the layout to return to it's original. "into_layout" is the original layout, "into_cell"
* the original cell. * the original cell.
* *
* "excluded_cells" - if not 0 - will exclude the given cells (and flatten them). * "excluded_cells" - if not 0 - will exclude the given cells
*
* "included_cells" - if not 0 - will only include the given cells in the cell mapping
*/ */
const db::CellMapping &cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set<db::cell_index_type> *excluded_cells = 0); const db::CellMapping &cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set<db::cell_index_type> *excluded_cells = 0, const std::set<db::cell_index_type> *included_cells = 0);
/** /**
* @brief Create cell variants from the given variant collector * @brief Create cell variants from the given variant collector

View File

@ -445,7 +445,7 @@ unsigned int LayoutToNetlist::layer_of (const db::Region &region) const
return deep_layer_of (region).layer (); return deep_layer_of (region).layer ();
} }
db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells) db::CellMapping LayoutToNetlist::make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells)
{ {
std::set<db::cell_index_type> device_cells; std::set<db::cell_index_type> device_cells;
if (! with_device_cells && mp_netlist.get ()) { if (! with_device_cells && mp_netlist.get ()) {
@ -454,7 +454,31 @@ db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell
} }
} }
return dss ().cell_mapping_to_original (m_layout_index, &layout, cell.cell_index (), &device_cells); std::set<db::cell_index_type> net_cells;
if (nets) {
// Compute the "included cell" list for cell_mapping_to_original: these are all cells which
// are required to represent the net hierarchically.
for (std::vector<const db::Net *>::const_iterator n = nets->begin (); n != nets->end (); ++n) {
const db::Net *net = *n;
db::cell_index_type net_cell = net->circuit ()->cell_index ();
if (net_cells.find (net_cell) == net_cells.end ()) {
net_cells.insert (net_cell);
internal_layout()->cell (net_cell).collect_caller_cells (net_cells);
}
}
}
return dss ().cell_mapping_to_original (m_layout_index, &layout, cell.cell_index (), &device_cells, nets ? &net_cells : 0);
}
db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> &nets, bool with_device_cells)
{
return make_cell_mapping_into (layout, cell, &nets, with_device_cells);
}
db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells)
{
return make_cell_mapping_into (layout, cell, 0, with_device_cells);
} }
db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell) db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell)
@ -563,11 +587,11 @@ static bool deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const T
return true; return true;
} }
template <class To> template <class To, class Shape>
static bool deliver_shapes_of_net_recursive (const db::Netlist * /*nl*/, const db::hier_clusters<db::PolygonRef> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to, db::properties_id_type propid) static bool deliver_shapes_of_net_recursive (const db::Netlist * /*nl*/, const db::hier_clusters<Shape> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to, db::properties_id_type propid)
{ {
// deliver the net shapes // deliver the net shapes
for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) { for (db::recursive_cluster_shape_iterator<Shape> rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
if (! deliver_shape (*rci, to, tr * rci.trans (), propid)) { if (! deliver_shape (*rci, to, tr * rci.trans (), propid)) {
return false; return false;
} }
@ -575,56 +599,61 @@ static bool deliver_shapes_of_net_recursive (const db::Netlist * /*nl*/, const d
return true; return true;
} }
template <class To> template <class To, class Shape>
static bool deliver_shapes_of_net_nonrecursive (const db::Netlist *nl, const db::hier_clusters<db::PolygonRef> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to, db::properties_id_type propid) static bool deliver_shapes_of_net (bool recursive, const db::Netlist *nl, const db::hier_clusters<Shape> &clusters, db::cell_index_type ci, size_t cid, const std::map<unsigned int, To *> &lmap, const db::ICplxTrans &tr, db::properties_id_type propid)
{ {
// NOTE: this scheme will deliver the shapes from the cell, including (!) // shortcut
// subcells that are purged if (lmap.empty ()) {
return true;
}
db::cell_index_type prev_ci = ci; const db::connected_clusters<Shape> &cc = clusters.clusters_per_cell (ci);
const db::local_cluster<Shape> &lc = cc.cluster_by_id (cid);
// deliver the net shapes for (typename std::map<unsigned int, To *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (clusters, layer_id, ci, cid); !rci.at_end (); ) { for (typename db::local_cluster<Shape>::shape_iterator s = lc.begin (l->first); ! s.at_end (); ++s) {
if (! deliver_shape (*s, *l->second, tr, propid)) {
db::cell_index_type cci = rci.cell_index ();
if (cci != prev_ci && cci != ci && (! nl || nl->circuit_by_cell_index (cci) || nl->device_abstract_by_cell_index (cci))) {
rci.skip_cell ();
} else {
if (! deliver_shape (*rci, to, tr * rci.trans (), propid)) {
return false; return false;
} }
prev_ci = cci;
++rci;
} }
}
const typename db::connected_clusters<Shape>::connections_type &conn = cc.connections_for_cluster (cid);
for (typename db::connected_clusters<Shape>::connections_type::const_iterator c = conn.begin (); c != conn.end (); ) {
db::cell_index_type cci = c->inst_cell_index ();
if (! recursive && (! nl || nl->circuit_by_cell_index (cci) || nl->device_abstract_by_cell_index (cci))) {
// skip this cell in non-recursive mode (and all following instances of the same cell too)
typename db::connected_clusters<Shape>::connections_type::const_iterator cc = c;
while (++cc != conn.end ()) {
if (cc->inst_cell_index () != cci) {
break;
}
}
c = cc;
continue;
}
if (! deliver_shapes_of_net (recursive, nl, clusters, cci, c->id (), lmap, tr * c->inst_trans (), propid)) {
return false;
}
++c;
} }
return true; return true;
} }
template <class To>
static bool deliver_shapes_of_net (bool recursive, const db::Netlist *nl, const db::hier_clusters<db::PolygonRef> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to, db::properties_id_type propid)
{
if (recursive) {
return deliver_shapes_of_net_recursive (nl, clusters, ci, cid, layer_id, tr, to, propid);
} else {
return deliver_shapes_of_net_nonrecursive (nl, clusters, ci, cid, layer_id, tr, to, propid);
}
}
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid) const void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid) const
{ {
unsigned int lid = layer_of (of_layer); unsigned int lid = layer_of (of_layer);
const db::Circuit *circuit = net.circuit (); const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0); tl_assert (circuit != 0);
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), to, propid); std::map<unsigned int, db::Shapes *> lmap;
lmap [lid] = &to;
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), propid);
} }
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const
@ -634,8 +663,10 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
tl_assert (circuit != 0); tl_assert (circuit != 0);
std::auto_ptr<db::Region> res (new db::Region ()); std::auto_ptr<db::Region> res (new db::Region ());
std::map<unsigned int, db::Region *> lmap;
lmap [lid] = res.get ();
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), *res, 0); deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), 0);
return res.release (); return res.release ();
} }
@ -661,14 +692,15 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
bool any_connections = circuit_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty (); bool any_connections = circuit_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
if (! any_connections) { if (! any_connections) {
bool consider_cell = any_connections; StopOnFirst sof;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end () && !consider_cell; ++l) { 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) { if (l->second) {
StopOnFirst sof; sof_lmap.insert (std::make_pair (layer_of (*l->second), &sof));
consider_cell = !deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, sof, 0);
} }
} }
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) { if (! consider_cell) {
// shortcut if cell is empty -> no net cell will be produced // shortcut if cell is empty -> no net cell will be produced
return; return;
@ -683,12 +715,15 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
} }
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) { for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) { if (l->second) {
deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, target_cell->shapes (l->first), netname_propid); 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) { if (hier_mode != BNH_SubcircuitCells && ! device_cell_name_prefix) {
return; return;
} }
@ -780,26 +815,53 @@ LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target
} }
void void
LayoutToNetlist::build_nets (const std::set<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, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const 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);
}
}
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, 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) { if (! m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); 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 ());
}
cell_reuse_table_type cell_reuse_table; cell_reuse_table_type cell_reuse_table;
double mag = internal_layout ()->dbu () / target.dbu ();
const db::Netlist *netlist = mp_netlist.get (); const db::Netlist *netlist = mp_netlist.get ();
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) { for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
if (! cmap.has_mapping (c->cell_index ())) {
continue;
}
bool is_top_circuit = c->begin_parents () == c->end_parents (); bool is_top_circuit = c->begin_parents () == c->end_parents ();
db::cell_index_type target_ci = cmap.cell_mapping (c->cell_index ());
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
// exlude local nets in recursive mode except if they are explicitly selected // exlude local nets in recursive mode except if they are explicitly selected
@ -807,9 +869,9 @@ LayoutToNetlist::build_nets (const std::set<const db::Net *> *nets, const db::Ce
continue; continue;
} }
if (! nets || nets->find (n.operator-> ()) != nets->end ()) { if (! nets || net_set.find (n.operator-> ()) != net_set.end ()) {
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n); db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n);
build_net_rec (*n, target, target.cell (target_ci), lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans (mag)); 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 ());
} }
} }
@ -835,15 +897,15 @@ LayoutToNetlist::build_nets (const std::set<const db::Net *> *nets, const db::Ce
if (n) { if (n) {
double dbu = target.dbu (); double dbu = target.dbu ();
db::ICplxTrans tr = db::ICplxTrans (mag) * (db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu)); db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n); db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n);
if (net_cell_name_prefix) { if (net_cell_name_prefix) {
std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":"; std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":";
build_net_rec (*n, target, target.cell (target_ci), lmap, ncn.c_str (), netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr); 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 { } else {
build_net_rec (*n, target, target.cell (target_ci), lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr); 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);
} }
} }

View File

@ -435,10 +435,19 @@ public:
*/ */
db::CellMapping cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells = false); db::CellMapping cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells = false);
/**
* @brief Creates a cell mapping for copying shapes from the internal layout to the given target layout for a given list of nets
* This version will only create cells which are required to represent the given nets.
* If 'with_device_cells' is true, cells will be produced for devices. These are cells not corresponding to circuits, so they are disabled normally.
* Use this option, if you want to access device terminal shapes per device.
* CAUTION: This function may create new cells in "layout".
*/
db::CellMapping cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> &nets, bool with_device_cells = false);
/** /**
* @brief Creates a cell mapping for copying shapes from the internal layout to the given target layout. * @brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.
* This version will not create new cells in the target layout. * This version will not create new cells in the target layout.
* If the required cells do not exist there yet, flatting will happen. * If the required cells do not exist there yet, flattening will happen.
*/ */
db::CellMapping const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell); db::CellMapping const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell);
@ -601,7 +610,7 @@ public:
/** /**
* @brief Like build_all_nets, but with the ability to select some nets * @brief Like build_all_nets, but with the ability to select some nets
*/ */
void build_nets (const std::set<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, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const; void build_nets (const std::vector<const Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
/** /**
* @brief Finds the net by probing a specific location on the given layer * @brief Finds the net by probing a specific location on the given layer
@ -730,12 +739,14 @@ private:
void init (); void init ();
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<db::PolygonRef> &test_cluster, std::vector<db::InstElement> &rev_inst_path); size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<db::PolygonRef> &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 (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; 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 db::Region &region) const; db::DeepLayer deep_layer_of (const db::Region &region) const;
void ensure_layout () const; void ensure_layout () const;
std::string make_new_name (const std::string &stem = std::string ()); std::string make_new_name (const std::string &stem = std::string ());
db::properties_id_type make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const; db::properties_id_type make_netname_propid (db::Layout &ly, 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);
}; };
} }

View File

@ -81,6 +81,14 @@ static void build_all_nets (const db::LayoutToNetlist *l2n, const db::CellMappin
l2n->build_all_nets (cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), 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 (), 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)
{
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 (), 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) static std::vector<std::string> l2n_layer_names (const db::LayoutToNetlist *l2n)
{ {
std::vector<std::string> ln; std::vector<std::string> ln;
@ -331,11 +339,21 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"This method is required to derive the internal layer index - for example for\n" "This method is required to derive the internal layer index - for example for\n"
"investigating the cluster tree.\n" "investigating the cluster tree.\n"
) + ) +
gsi::method ("cell_mapping_into", &db::LayoutToNetlist::cell_mapping_into, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("with_device_cells", false), gsi::method ("cell_mapping_into", (db::CellMapping (db::LayoutToNetlist::*) (db::Layout &, db::Cell &, bool)) &db::LayoutToNetlist::cell_mapping_into, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("with_device_cells", false),
"@brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.\n" "@brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.\n"
"If 'with_device_cells' is true, cells will be produced for devices. These are cells not corresponding to circuits, so they are disabled normally.\n" "If 'with_device_cells' is true, cells will be produced for devices. These are cells not corresponding to circuits, so they are disabled normally.\n"
"Use this option, if you want to access device terminal shapes per device.\n" "Use this option, if you want to access device terminal shapes per device.\n"
"CAUTION: this function may create new cells in 'layout'.\n" "\n"
"CAUTION: this function may create new cells in 'layout'. Use \\const_cell_mapping_into if you want to use the target layout's hierarchy and not modify it.\n"
) +
gsi::method ("cell_mapping_into", (db::CellMapping (db::LayoutToNetlist::*) (db::Layout &, db::Cell &, const std::vector<const db::Net *> &, bool)) &db::LayoutToNetlist::cell_mapping_into, gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("nets"), gsi::arg ("with_device_cells", false),
"@brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.\n"
"This version will only create cells which are required to represent the nets from the 'nets' argument.\n"
"\n"
"If 'with_device_cells' is true, cells will be produced for devices. These are cells not corresponding to circuits, so they are disabled normally.\n"
"Use this option, if you want to access device terminal shapes per device.\n"
"\n"
"CAUTION: this function may create new cells in 'layout'. Use \\const_cell_mapping_into if you want to use the target layout's hierarchy and not modify it.\n"
) + ) +
gsi::method ("const_cell_mapping_into", &db::LayoutToNetlist::const_cell_mapping_into, gsi::arg ("layout"), gsi::arg ("cell"), gsi::method ("const_cell_mapping_into", &db::LayoutToNetlist::const_cell_mapping_into, gsi::arg ("layout"), gsi::arg ("cell"),
"@brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.\n" "@brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.\n"
@ -389,9 +407,10 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
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::LayoutToNetlist::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" "@brief Builds a full hierarchical representation of the nets\n"
"\n" "\n"
"This method copies all nets into cells corresponding to the circuits. It uses the cmap\n" "This method copies all nets into cells corresponding to the circuits. It uses the 'cmap'\n"
"object to determine the target cell (create them with \"cell_mapping_into\" or \"const_cell_mapping_into\").\n" "object to determine the target cell (create it with \"cell_mapping_into\" or \"const_cell_mapping_into\").\n"
"If no mapping is requested, the specific circuit it skipped.\n" "If no mapping is provided for a specific circuit cell, the nets are copied into the next mapped parent as "
"many times as the circuit cell appears there (circuit flattening).\n"
"\n" "\n"
"The method has three net annotation modes:\n" "The method has three net annotation modes:\n"
"@ul\n" "@ul\n"
@ -427,6 +446,9 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"@param net_cell_name_prefix See method description\n" "@param net_cell_name_prefix See method description\n"
"@param device_cell_name_prefix See above\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"),
"@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 &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"),
"@brief Finds the net by probing a specific location on the given layer\n" "@brief Finds the net by probing a specific location on the given layer\n"
"\n" "\n"

View File

@ -86,7 +86,164 @@ TEST(1_ReaderBasic)
std::string au = tl::testsrc (); std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata"); au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo"); au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_reader_au.gds"); au = tl::combine_path (au, "l2n_reader_au_1.gds");
db::compare_layouts (_this, ly2, au);
}
{
db::Layout ly2;
ly2.dbu (l2n.internal_layout ()->dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_by_name ("psd");
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_by_name ("nsd");
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_by_name ("poly");
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_by_name ("diff_cont");
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_by_name ("poly_cont");
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_by_name ("metal1");
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");
std::vector<const db::Net *> nets;
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, "DEVICE_");
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_reader_au_1b.gds");
db::compare_layouts (_this, ly2, au);
}
{
db::Layout ly2;
ly2.dbu (l2n.internal_layout ()->dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_by_name ("psd");
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_by_name ("nsd");
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_by_name ("poly");
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_by_name ("diff_cont");
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_by_name ("poly_cont");
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_by_name ("metal1");
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");
std::vector<const db::Net *> nets;
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_Flatten, 0, "DEVICE_");
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_reader_au_1c.gds");
db::compare_layouts (_this, ly2, au);
}
{
db::Layout ly2;
ly2.dbu (l2n.internal_layout ()->dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_by_name ("psd");
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_by_name ("nsd");
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_by_name ("poly");
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_by_name ("diff_cont");
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_by_name ("poly_cont");
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_by_name ("metal1");
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");
std::vector<const db::Net *> nets;
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_reader_au_1d.gds");
db::compare_layouts (_this, ly2, au);
}
{
db::Layout ly2;
ly2.dbu (l2n.internal_layout ()->dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_by_name ("psd");
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_by_name ("nsd");
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_by_name ("poly");
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_by_name ("diff_cont");
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_by_name ("poly_cont");
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_by_name ("metal1");
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");
std::vector<const db::Net *> nets;
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
nets.push_back (l2n.netlist ()->circuit_by_name ("INV2")->net_by_name ("IN"));
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_reader_au_1e.gds");
db::compare_layouts (_this, ly2, au);
}
{
db::Layout ly2;
ly2.dbu (l2n.internal_layout ()->dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_by_name ("psd");
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_by_name ("nsd");
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_by_name ("poly");
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_by_name ("diff_cont");
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_by_name ("poly_cont");
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_by_name ("metal1");
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");
std::vector<const db::Net *> nets;
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
nets.push_back (l2n.netlist ()->circuit_by_name ("INV2")->net_by_name ("IN"));
db::CellMapping cm = l2n.const_cell_mapping_into (ly2, top2);
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_reader_au_1f.gds");
db::compare_layouts (_this, ly2, au); db::compare_layouts (_this, ly2, au);
} }

View File

@ -172,7 +172,7 @@
<item> <item>
<widget class="QStackedWidget" name="central_stack"> <widget class="QStackedWidget" name="central_stack">
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="page"> <widget class="QWidget" name="page">
<layout class="QVBoxLayout"> <layout class="QVBoxLayout">
@ -192,7 +192,7 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="lay::NetlistBrowserPage" name="browser_frame"> <widget class="lay::NetlistBrowserPage" name="browser_page">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Ignored"> <sizepolicy hsizetype="Ignored" vsizetype="Ignored">
<horstretch>0</horstretch> <horstretch>0</horstretch>

View File

@ -76,7 +76,7 @@ NetlistBrowserDialog::NetlistBrowserDialog (lay::PluginRoot *root, lay::LayoutVi
{ {
Ui::NetlistBrowserDialog::setupUi (this); Ui::NetlistBrowserDialog::setupUi (this);
browser_frame->set_plugin_root (root); browser_page->set_plugin_root (root);
if (view ()) { if (view ()) {
view ()->cellviews_changed_event.add (this, &NetlistBrowserDialog::cellviews_changed); view ()->cellviews_changed_event.add (this, &NetlistBrowserDialog::cellviews_changed);
@ -282,7 +282,7 @@ NetlistBrowserDialog::probe_net (const db::DPoint &p, bool trace_path)
} }
// select the net if one was found // select the net if one was found
browser_frame->select_net (net); browser_page->select_net (net);
} }
void void
@ -353,40 +353,9 @@ END_PROTECTED
void void
NetlistBrowserDialog::export_clicked () NetlistBrowserDialog::export_clicked ()
{ {
BEGIN_PROTECTED if (m_l2n_index < int (view ()->num_l2ndbs ()) && m_l2n_index >= 0) {
browser_page->export_all ();
#if 0 // @@@
if (m_l2n_index >= int (view ()->num_rdbs ()) || m_l2n_index < 0) {
return;
} }
const rdb::Database *rdb = view ()->get_rdb (m_l2n_index);
if (! rdb) {
return;
}
const lay::CellView &cv = view ()->cellview (m_cv_index);
if (! cv.is_valid ()) {
return;
}
try {
view ()->manager ()->transaction (tl::to_string (QObject::tr ("Export Net")));
// ....
view ()->manager ()->commit ();
view ()->update_content ();
} catch (...) {
view ()->manager ()->commit ();
view ()->update_content ();
throw;
}
#endif
END_PROTECTED
} }
void void
@ -431,9 +400,9 @@ BEGIN_PROTECTED
tl::log << tl::to_string (QObject::tr ("Loading file: ")) << l2ndb->filename (); tl::log << tl::to_string (QObject::tr ("Loading file: ")) << l2ndb->filename ();
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Loading"))); tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Loading")));
browser_frame->set_l2ndb (0); browser_page->set_l2ndb (0);
l2ndb->load (l2ndb->filename ()); l2ndb->load (l2ndb->filename ());
browser_frame->set_l2ndb (l2ndb); browser_page->set_l2ndb (l2ndb);
} }
@ -450,7 +419,7 @@ BEGIN_PROTECTED
std::string fmts = tl::to_string (QObject::tr ("All files (*)")); std::string fmts = tl::to_string (QObject::tr ("All files (*)"));
#if 0 // TODO: would be good to have this: #if 0 // TODO: would be good to have this:
// collect the formats available ... // collect the formats available ...
for (tl::Registrar<rdb::FormatDeclaration>::iterator rdr = tl::Registrar<rdb::FormatDeclaration>::begin (); rdr != tl::Registrar<rdb::FormatDeclaration>::end (); ++rdr) { for (tl::Registrar<db::NetlistFormatDeclaration>::iterator rdr = tl::Registrar<db::NetlistFormatDeclaration>::begin (); rdr != tl::Registrar<db::NetlistFormatDeclaration>::end (); ++rdr) {
fmts += ";;" + rdr->file_format (); fmts += ";;" + rdr->file_format ();
} }
#else #else
@ -480,7 +449,7 @@ NetlistBrowserDialog::configure (const std::string &name, const std::string &val
{ {
bool need_update = false; bool need_update = false;
bool taken = true; bool taken = true;
bool show_all = browser_frame->show_all (); bool show_all = browser_page->show_all ();
if (name == cfg_l2ndb_show_all) { if (name == cfg_l2ndb_show_all) {
@ -577,12 +546,12 @@ NetlistBrowserDialog::configure (const std::string &name, const std::string &val
} }
if (active () && need_update) { if (active () && need_update) {
browser_frame->set_max_shape_count (m_max_shape_count); browser_page->set_max_shape_count (m_max_shape_count);
browser_frame->set_window (m_window, m_window_dim); browser_page->set_window (m_window, m_window_dim);
browser_frame->set_highlight_style (m_marker_color, m_marker_line_width, m_marker_vertex_size, m_marker_halo, m_marker_dither_pattern, m_marker_intensity, m_use_original_colors, m_auto_color_enabled ? &m_auto_colors : 0); browser_page->set_highlight_style (m_marker_color, m_marker_line_width, m_marker_vertex_size, m_marker_halo, m_marker_dither_pattern, m_marker_intensity, m_use_original_colors, m_auto_color_enabled ? &m_auto_colors : 0);
} }
browser_frame->show_all (show_all); browser_page->show_all (show_all);
return taken; return taken;
} }
@ -636,7 +605,7 @@ NetlistBrowserDialog::l2ndbs_changed ()
void void
NetlistBrowserDialog::cellview_changed (int) NetlistBrowserDialog::cellview_changed (int)
{ {
browser_frame->update_highlights (); browser_page->update_highlights ();
} }
void void
@ -725,13 +694,13 @@ NetlistBrowserDialog::update_content ()
m_unload_all_action->setEnabled (l2ndb != 0); m_unload_all_action->setEnabled (l2ndb != 0);
m_reload_action->setEnabled (l2ndb != 0); m_reload_action->setEnabled (l2ndb != 0);
browser_frame->enable_updates (false); // Avoid building the internal lists several times ... browser_page->enable_updates (false); // Avoid building the internal lists several times ...
browser_frame->set_l2ndb (l2ndb); browser_page->set_l2ndb (l2ndb);
browser_frame->set_max_shape_count (m_max_shape_count); browser_page->set_max_shape_count (m_max_shape_count);
browser_frame->set_highlight_style (m_marker_color, m_marker_line_width, m_marker_vertex_size, m_marker_halo, m_marker_dither_pattern, m_marker_intensity, m_use_original_colors, m_auto_color_enabled ? &m_auto_colors : 0); browser_page->set_highlight_style (m_marker_color, m_marker_line_width, m_marker_vertex_size, m_marker_halo, m_marker_dither_pattern, m_marker_intensity, m_use_original_colors, m_auto_color_enabled ? &m_auto_colors : 0);
browser_frame->set_window (m_window, m_window_dim); browser_page->set_window (m_window, m_window_dim);
browser_frame->set_view (view (), m_cv_index); browser_page->set_view (view (), m_cv_index);
browser_frame->enable_updates (true); browser_page->enable_updates (true);
if (l2ndb) { if (l2ndb) {
// Note: it appears to be required to show the browser page after it has been configured. // Note: it appears to be required to show the browser page after it has been configured.
@ -769,8 +738,8 @@ NetlistBrowserDialog::deactivated ()
lay::PluginRoot::instance ()->config_set (cfg_l2ndb_window_state, lay::save_dialog_state (this, false /*don't store the section sizes*/).c_str ()); lay::PluginRoot::instance ()->config_set (cfg_l2ndb_window_state, lay::save_dialog_state (this, false /*don't store the section sizes*/).c_str ());
} }
browser_frame->set_l2ndb (0); browser_page->set_l2ndb (0);
browser_frame->set_view (0, 0); browser_page->set_view (0, 0);
} }
void void

View File

@ -31,6 +31,7 @@
#include "layNetInfoDialog.h" #include "layNetInfoDialog.h"
#include "layNetExportDialog.h" #include "layNetExportDialog.h"
#include "tlProgress.h" #include "tlProgress.h"
#include "tlExceptions.h"
#include "dbLayoutToNetlist.h" #include "dbLayoutToNetlist.h"
#include "dbNetlistDeviceClasses.h" #include "dbNetlistDeviceClasses.h"
#include "dbCellMapping.h" #include "dbCellMapping.h"
@ -1157,18 +1158,24 @@ NetlistBrowserPage::clear_markers ()
void void
NetlistBrowserPage::export_selected () NetlistBrowserPage::export_selected ()
{ {
BEGIN_PROTECTED
std::vector<const db::Net *> nets = selected_nets (); std::vector<const db::Net *> nets = selected_nets ();
if (nets.empty ()) { if (nets.empty ()) {
return; return;
} }
export_nets (&nets); export_nets (&nets);
END_PROTECTED
} }
void void
NetlistBrowserPage::export_all () NetlistBrowserPage::export_all ()
{ {
BEGIN_PROTECTED
export_nets (0); export_nets (0);
END_PROTECTED
} }
void void
@ -1198,15 +1205,16 @@ NetlistBrowserPage::export_nets (const std::vector<const db::Net *> *nets)
db::cell_index_type target_top_index = target_layout.add_cell (source_layout.cell_name (source_top.cell_index ())); db::cell_index_type target_top_index = target_layout.add_cell (source_layout.cell_name (source_top.cell_index ()));
db::CellMapping cm = database->cell_mapping_into (target_layout, target_layout.cell (target_top_index)); db::CellMapping cm;
std::map<unsigned int, const db::Region *> lm = database->create_layermap (target_layout, dialog->start_layer_number ()); if (! nets) {
cm = database->cell_mapping_into (target_layout, target_layout.cell (target_top_index));
std::set<const db::Net *> net_set; } else {
if (nets) { cm = database->cell_mapping_into (target_layout, target_layout.cell (target_top_index), *nets);
net_set.insert (nets->begin (), nets->end ());
} }
database->build_nets (nets ? &net_set : 0, cm, target_layout, lm, std::map<unsigned int, const db::Region *> lm = database->create_layermap (target_layout, dialog->start_layer_number ());
database->build_nets (nets, cm, target_layout, lm,
dialog->net_prefix ().empty () ? 0 : dialog->net_prefix ().c_str (), dialog->net_prefix ().empty () ? 0 : dialog->net_prefix ().c_str (),
dialog->net_propname (), dialog->net_propname (),
dialog->produce_circuit_cells () ? db::LayoutToNetlist::BNH_SubcircuitCells : db::LayoutToNetlist::BNH_Flatten, dialog->produce_circuit_cells () ? db::LayoutToNetlist::BNH_SubcircuitCells : db::LayoutToNetlist::BNH_Flatten,

BIN
testdata/algo/l2n_reader_au_1b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/l2n_reader_au_1c.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/l2n_reader_au_1d.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/l2n_reader_au_1e.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/l2n_reader_au_1f.gds vendored Normal file

Binary file not shown.