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>
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_b;
@ -305,7 +305,9 @@ CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /
called_b.insert (cell_index_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));
new_cells.push_back (new_cell);
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, "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.
*/
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:
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 &
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;
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
// 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"
* 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

View File

@ -445,7 +445,7 @@ unsigned int LayoutToNetlist::layer_of (const db::Region &region) const
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;
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)
@ -563,11 +587,11 @@ static bool deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const T
return true;
}
template <class To>
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)
template <class To, class Shape>
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
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)) {
return false;
}
@ -575,56 +599,61 @@ static bool deliver_shapes_of_net_recursive (const db::Netlist * /*nl*/, const d
return true;
}
template <class To>
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)
template <class To, class Shape>
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 (!)
// subcells that are purged
// shortcut
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 (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (clusters, layer_id, ci, cid); !rci.at_end (); ) {
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)) {
for (typename std::map<unsigned int, To *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
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)) {
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;
}
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
{
unsigned int lid = layer_of (of_layer);
const db::Circuit *circuit = net.circuit ();
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
@ -634,8 +663,10 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
tl_assert (circuit != 0);
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 ();
}
@ -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 ();
if (! any_connections) {
bool consider_cell = any_connections;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end () && !consider_cell; ++l) {
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) {
StopOnFirst 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);
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;
@ -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) {
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) {
return;
}
@ -780,26 +815,53 @@ LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target
}
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) {
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;
double mag = internal_layout ()->dbu () / target.dbu ();
const db::Netlist *netlist = mp_netlist.get ();
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 ();
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) {
// 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;
}
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);
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) {
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);
if (net_cell_name_prefix) {
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 {
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);
/**
* @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.
* 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);
@ -601,7 +610,7 @@ public:
/**
* @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
@ -730,12 +739,14 @@ private:
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);
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 db::Region &region) 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, 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 ());
}
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)
{
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"
"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"
"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"
"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"),
"@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"),
"@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"
"object to determine the target cell (create them with \"cell_mapping_into\" or \"const_cell_mapping_into\").\n"
"If no mapping is requested, the specific circuit it skipped.\n"
"This method copies all nets into cells corresponding to the circuits. It uses the 'cmap'\n"
"object to determine the target cell (create it with \"cell_mapping_into\" or \"const_cell_mapping_into\").\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"
"The method has three net annotation modes:\n"
"@ul\n"
@ -427,6 +446,9 @@ 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"),
"@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"),
"@brief Finds the net by probing a specific location on the given layer\n"
"\n"

View File

@ -86,7 +86,164 @@ TEST(1_ReaderBasic)
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.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);
}

View File

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

View File

@ -76,7 +76,7 @@ NetlistBrowserDialog::NetlistBrowserDialog (lay::PluginRoot *root, lay::LayoutVi
{
Ui::NetlistBrowserDialog::setupUi (this);
browser_frame->set_plugin_root (root);
browser_page->set_plugin_root (root);
if (view ()) {
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
browser_frame->select_net (net);
browser_page->select_net (net);
}
void
@ -353,40 +353,9 @@ END_PROTECTED
void
NetlistBrowserDialog::export_clicked ()
{
BEGIN_PROTECTED
#if 0 // @@@
if (m_l2n_index >= int (view ()->num_rdbs ()) || m_l2n_index < 0) {
return;
if (m_l2n_index < int (view ()->num_l2ndbs ()) && m_l2n_index >= 0) {
browser_page->export_all ();
}
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
@ -431,9 +400,9 @@ BEGIN_PROTECTED
tl::log << tl::to_string (QObject::tr ("Loading file: ")) << l2ndb->filename ();
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 ());
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 (*)"));
#if 0 // TODO: would be good to have this:
// 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 ();
}
#else
@ -480,7 +449,7 @@ NetlistBrowserDialog::configure (const std::string &name, const std::string &val
{
bool need_update = false;
bool taken = true;
bool show_all = browser_frame->show_all ();
bool show_all = browser_page->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) {
browser_frame->set_max_shape_count (m_max_shape_count);
browser_frame->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_max_shape_count (m_max_shape_count);
browser_page->set_window (m_window, m_window_dim);
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;
}
@ -636,7 +605,7 @@ NetlistBrowserDialog::l2ndbs_changed ()
void
NetlistBrowserDialog::cellview_changed (int)
{
browser_frame->update_highlights ();
browser_page->update_highlights ();
}
void
@ -725,13 +694,13 @@ NetlistBrowserDialog::update_content ()
m_unload_all_action->setEnabled (l2ndb != 0);
m_reload_action->setEnabled (l2ndb != 0);
browser_frame->enable_updates (false); // Avoid building the internal lists several times ...
browser_frame->set_l2ndb (l2ndb);
browser_frame->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_frame->set_window (m_window, m_window_dim);
browser_frame->set_view (view (), m_cv_index);
browser_frame->enable_updates (true);
browser_page->enable_updates (false); // Avoid building the internal lists several times ...
browser_page->set_l2ndb (l2ndb);
browser_page->set_max_shape_count (m_max_shape_count);
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_page->set_window (m_window, m_window_dim);
browser_page->set_view (view (), m_cv_index);
browser_page->enable_updates (true);
if (l2ndb) {
// 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 ());
}
browser_frame->set_l2ndb (0);
browser_frame->set_view (0, 0);
browser_page->set_l2ndb (0);
browser_page->set_view (0, 0);
}
void

View File

@ -31,6 +31,7 @@
#include "layNetInfoDialog.h"
#include "layNetExportDialog.h"
#include "tlProgress.h"
#include "tlExceptions.h"
#include "dbLayoutToNetlist.h"
#include "dbNetlistDeviceClasses.h"
#include "dbCellMapping.h"
@ -1157,18 +1158,24 @@ NetlistBrowserPage::clear_markers ()
void
NetlistBrowserPage::export_selected ()
{
BEGIN_PROTECTED
std::vector<const db::Net *> nets = selected_nets ();
if (nets.empty ()) {
return;
}
export_nets (&nets);
END_PROTECTED
}
void
NetlistBrowserPage::export_all ()
{
BEGIN_PROTECTED
export_nets (0);
END_PROTECTED
}
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::CellMapping cm = database->cell_mapping_into (target_layout, target_layout.cell (target_top_index));
std::map<unsigned int, const db::Region *> lm = database->create_layermap (target_layout, dialog->start_layer_number ());
std::set<const db::Net *> net_set;
if (nets) {
net_set.insert (nets->begin (), nets->end ());
db::CellMapping cm;
if (! nets) {
cm = database->cell_mapping_into (target_layout, target_layout.cell (target_top_index));
} else {
cm = database->cell_mapping_into (target_layout, target_layout.cell (target_top_index), *nets);
}
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_propname (),
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.