mirror of https://github.com/KLayout/klayout.git
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:
parent
0f666d528c
commit
ebd00c186b
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ unsigned int LayoutToNetlist::layer_of (const db::Region ®ion) 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ®ion) 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue