WIP: netlist browser - extended the net export scheme of build_net to support net annotation and flattening.

This commit is contained in:
Matthias Koefferlein 2019-05-03 23:33:37 +02:00
parent 062b74aad7
commit 2aaec56adb
18 changed files with 621 additions and 215 deletions

View File

@ -484,13 +484,13 @@ namespace
} }
template <class Tr> template <class Tr>
static bool deliver_shape (const db::PolygonRef &, StopOnFirst, const Tr &) static bool deliver_shape (const db::PolygonRef &, StopOnFirst, const Tr &, db::properties_id_type)
{ {
return false; return false;
} }
template <class Tr> template <class Tr>
static bool deliver_shape (const db::PolygonRef &pr, db::Region &region, const Tr &tr) static bool deliver_shape (const db::PolygonRef &pr, db::Region &region, const Tr &tr, db::properties_id_type /*propid*/)
{ {
if (pr.obj ().is_box ()) { if (pr.obj ().is_box ()) {
region.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr)); region.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
@ -501,27 +501,41 @@ static bool deliver_shape (const db::PolygonRef &pr, db::Region &region, const T
} }
template <class Tr> template <class Tr>
static bool deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr) static bool deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr, db::properties_id_type propid)
{ {
if (pr.obj ().is_box ()) { if (pr.obj ().is_box ()) {
shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr)); if (propid) {
shapes.insert (db::BoxWithProperties (pr.obj ().box ().transformed (pr.trans ()).transformed (tr), propid));
} else {
shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
}
} else { } else {
db::Layout *layout = shapes.layout (); db::Layout *layout = shapes.layout ();
if (layout) { if (layout) {
shapes.insert (db::PolygonRef (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ())); db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ());
if (propid) {
shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid));
} else {
shapes.insert (polygon_ref);
}
} else { } else {
shapes.insert (pr.obj ().transformed (pr.trans ()).transformed (tr)); db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr));
if (propid) {
shapes.insert (db::PolygonWithProperties (polygon, propid));
} else {
shapes.insert (polygon);
}
} }
} }
return true; return true;
} }
template <class To> 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) 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)
{ {
// deliver the net shapes // deliver the net shapes
for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) { for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
if (! deliver_shape (*rci, to, tr * rci.trans ())) { if (! deliver_shape (*rci, to, tr * rci.trans (), propid)) {
return false; return false;
} }
} }
@ -529,7 +543,7 @@ static bool deliver_shapes_of_net_recursive (const db::Netlist * /*nl*/, const d
} }
template <class To> 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) 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)
{ {
// NOTE: this scheme will deliver the shapes from the cell, including (!) // NOTE: this scheme will deliver the shapes from the cell, including (!)
// subcells that are purged // subcells that are purged
@ -546,7 +560,7 @@ static bool deliver_shapes_of_net_nonrecursive (const db::Netlist *nl, const db:
} else { } else {
if (! deliver_shape (*rci, to, tr * rci.trans ())) { if (! deliver_shape (*rci, to, tr * rci.trans (), propid)) {
return false; return false;
} }
prev_ci = cci; prev_ci = cci;
@ -560,17 +574,24 @@ static bool deliver_shapes_of_net_nonrecursive (const db::Netlist *nl, const db:
return true; return true;
} }
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const 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); unsigned int lid = layer_of (of_layer);
const db::Circuit *circuit = net.circuit (); const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0); tl_assert (circuit != 0);
if (! recursive) { deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), to, propid);
deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), to);
} else {
deliver_shapes_of_net_recursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), to);
}
} }
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const
@ -581,26 +602,22 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
std::auto_ptr<db::Region> res (new db::Region ()); std::auto_ptr<db::Region> res (new db::Region ());
if (! recursive) { 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_nonrecursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), *res);
} else {
deliver_shapes_of_net_recursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), *res);
}
return res.release (); return res.release ();
} }
void void
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const db::ICplxTrans &tr) const LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const db::ICplxTrans &tr) const
{ {
const db::Circuit *circuit = net.circuit (); const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0); tl_assert (circuit != 0);
build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, &net, net_cell_name_prefix, cell_name_prefix, device_cell_name_prefix, cmap, tr); build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, &net, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, cmap, tr);
} }
void void
LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const db::ICplxTrans &tr) const LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const db::ICplxTrans &tr) const
{ {
db::Cell *target_cell = &tc; db::Cell *target_cell = &tc;
@ -615,7 +632,7 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end () && !consider_cell; ++l) { for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end () && !consider_cell; ++l) {
if (l->second) { if (l->second) {
StopOnFirst sof; StopOnFirst sof;
consider_cell = !deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, 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);
} }
} }
@ -635,11 +652,11 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) { for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) { if (l->second) {
deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, target_cell->shapes (l->first)); 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);
} }
} }
if (! circuit_cell_name_prefix && ! device_cell_name_prefix) { if (hier_mode != BNH_SubcircuitCells && ! device_cell_name_prefix) {
return; return;
} }
@ -673,7 +690,7 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
db::cell_index_type target_ci = target.add_cell ((std::string (name_prefix) + cell_name).c_str ()); db::cell_index_type target_ci = target.add_cell ((std::string (name_prefix) + cell_name).c_str ());
cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), target_ci)).first; cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), target_ci)).first;
build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, 0, 0, circuit_cell_name_prefix, device_cell_name_prefix, cmap, tr_mag); build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, 0, 0, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cmap, tr_mag);
} else { } else {
cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), std::numeric_limits<db::cell_index_type>::max ())).first; cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), std::numeric_limits<db::cell_index_type>::max ())).first;
@ -690,8 +707,24 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
} }
} }
db::properties_id_type
LayoutToNetlist::make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const
{
if (! netname_prop.is_nil ()) {
db::property_names_id_type name_propnameid = ly.properties_repository ().prop_name_id (netname_prop);
db::PropertiesRepository::properties_set propset;
propset.insert (std::make_pair (name_propnameid, tl::Variant (net.expanded_name ())));
return ly.properties_repository ().properties_id (propset);
} else {
return 0;
}
}
void void
LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix) const LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const
{ {
if (! m_netlist_extracted) { if (! m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
@ -700,11 +733,13 @@ LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &ta
std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> cell_map; std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> cell_map;
double mag = internal_layout ()->dbu () / target.dbu (); double mag = internal_layout ()->dbu () / target.dbu ();
build_net_rec (net, target, target_cell, lmap, 0, cell_name_prefix, device_cell_name_prefix, cell_map, db::ICplxTrans (mag));
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, net);
build_net_rec (net, target, target_cell, lmap, 0, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, cell_map, db::ICplxTrans (mag));
} }
void void
LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
{ {
if (! m_netlist_extracted) { if (! m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet"))); throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
@ -727,15 +762,16 @@ LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
// exlude local nets in recursive mode // exlude local nets in recursive mode
if (circuit_cell_name_prefix && ! is_top_circuit && n->pin_count () > 0) { if (hier_mode != BNH_Disconnected && ! is_top_circuit && n->pin_count () > 0) {
continue; continue;
} }
build_net_rec (*n, target, target.cell (target_ci), lmap, net_cell_name_prefix, circuit_cell_name_prefix, device_cell_name_prefix, cell_map, db::ICplxTrans (mag)); 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_map, db::ICplxTrans (mag));
} }
if (circuit_cell_name_prefix) { if (hier_mode != BNH_Disconnected) {
// with recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will // with recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from // get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
@ -756,11 +792,13 @@ LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target
double dbu = target.dbu (); double dbu = target.dbu ();
db::ICplxTrans tr = db::ICplxTrans (mag) * (db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu)); db::ICplxTrans tr = db::ICplxTrans (mag) * (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) { if (net_cell_name_prefix) {
std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":"; std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":";
build_net_rec (*n, target, target.cell (target_ci), lmap, ncn.c_str (), circuit_cell_name_prefix, device_cell_name_prefix, cell_map, tr); 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_map, tr);
} else { } else {
build_net_rec (*n, target, target.cell (target_ci), lmap, net_cell_name_prefix, circuit_cell_name_prefix, device_cell_name_prefix, cell_map, tr); 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_map, tr);
} }
} }
@ -922,8 +960,8 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg
db::Region rgate, rmetal; db::Region rgate, rmetal;
deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (gate), db::ICplxTrans (), rgate); deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (gate), db::ICplxTrans (), rgate, 0);
deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (metal), db::ICplxTrans (), rmetal); deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (metal), db::ICplxTrans (), rmetal, 0);
double agate = rgate.area () * dbu * dbu; double agate = rgate.area () * dbu * dbu;
double ametal = rmetal.area () * dbu * dbu; double ametal = rmetal.area () * dbu * dbu;
@ -934,7 +972,7 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg
for (std::vector<std::pair<const db::Region *, double> >::const_iterator d = diodes.begin (); d != diodes.end () && ! skip; ++d) { for (std::vector<std::pair<const db::Region *, double> >::const_iterator d = diodes.begin (); d != diodes.end () && ! skip; ++d) {
db::Region rdiode; db::Region rdiode;
deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (*d->first), db::ICplxTrans (), rdiode); deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (*d->first), db::ICplxTrans (), rdiode, 0);
if (fabs (d->second) < db::epsilon) { if (fabs (d->second) < db::epsilon) {
if (rdiode.area () > 0) { if (rdiode.area () > 0) {

View File

@ -491,32 +491,64 @@ public:
* *
* This methods returns a new'd Region. It's the responsibility of the caller * This methods returns a new'd Region. It's the responsibility of the caller
* to delete this object. * to delete this object.
*
* propid is an optional properties ID which is attached to the shapes if not 0.
*/ */
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const; void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0) const;
/**
* @brief An enum describing the way the net hierarchy is mapped
*/
enum BuildNetHierarchyMode
{
/**
* @brief Flatten the net
* Collects all shapes of a net and puts that into the net cell or circuit cell
*/
BNH_Flatten = 0,
/**
* @brief Build a net hierarchy adding cells for each subcircuit on the net
* Uses the circuit_cell_prefix to build the subcircuit cell names
*/
BNH_SubcircuitCells = 1,
/**
* @brief No hierarchy
* Just output the shapes of the net belonging to the circuit cell.
* Connections are not indicated!
*/
BNH_Disconnected = 2
};
/** /**
* @brief Builds a net representation in the given layout and cell * @brief Builds a net representation in the given layout and cell
* *
* This method has two modes: recursive and top-level mode. In recursive mode, * This method puts the shapes of a net into the given target cell using a variety of options
* it will create a proper hierarchy below the given target cell to hold all subcircuits the * to represent the net name and the hierarchy of the net.
* net connects to. It will copy the net's parts from this subcircuits into these cells.
* *
* In top-level mode, only the shapes from the net inside it's circuit are copied to * If the netname_prop name is not nil, a property with the given name is created and assigned
* the given target cell. No other cells are created. * the net name.
* *
* Recursive mode is picked when a cell name prefix is given. The new cells will be * Net hierarchy is covered in three ways:
* named like cell_name_prefix + circuit name. * * No connection indicated (hier_mode == BNH_Disconnected: the net shapes are simply put into their
* respective circuits. The connections are not indicated.
* * Subnet hierarchy (hier_mode == BNH_SubcircuitCells): for each root net, a full hierarchy is built
* to accommodate the subnets (see build_net in recursive mode).
* * Flat (hier_mode == BNH_Flatten): each net is flattened and put into the circuit it
* belongs to.
* *
* If a device cell name prefix is given, cells will be produced for each device abstract * If a device cell name prefix is given, cells will be produced for each device abstract
* using a name like device_cell_name_prefix + device name. * using a name like device_cell_name_prefix + device name. Otherwise the device shapes are
* treated as part of the net.
* *
* @param target The target layout * @param target The target layout
* @param target_cell The target cell * @param target_cell The target cell
* @param lmap Target layer indexes (keys) and net regions (values) * @param lmap Target layer indexes (keys) and net regions (values)
* @param hier_mode See description of this method
* @param netname_prop An (optional) property name to which to attach the net name
* @param cell_name_prefix Chooses recursive mode if non-null * @param cell_name_prefix Chooses recursive mode if non-null
* @param device_cell_name_prefix See above * @param device_cell_name_prefix See above
*/ */
void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix) const; void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const;
/** /**
* @brief Builds a full hierarchical representation of the nets * @brief Builds a full hierarchical representation of the nets
@ -525,28 +557,37 @@ public:
* object to determine the target cell (create them with "cell_mapping_into" or "const_cell_mapping_into"). * object to determine the target cell (create them with "cell_mapping_into" or "const_cell_mapping_into").
* If no mapping is requested, the specific circuit it skipped. * If no mapping is requested, the specific circuit it skipped.
* *
* The method has two net annotation modes: * The method has three net annotation modes:
* * No annotation (net_cell_name_prefix == 0): the shapes will be put into the target cell simply * * No annotation (net_cell_name_prefix == 0 and netname_prop == nil): the shapes will be put
* into the target cell simply
* * Net name property (net_cell_name_prefix == 0 and netname_prop != nil): the shapes will be
* annotated with a property named with netname_prop and containing the net name string.
* * Individual subcells per net (net_cell_name_prefix != 0): for each net, a subcell is created * * Individual subcells per net (net_cell_name_prefix != 0): for each net, a subcell is created
* and the net shapes will be put there (name of the subcell = net_cell_name_prefix + net name). * and the net shapes will be put there (name of the subcell = net_cell_name_prefix + net name).
* (this mode can be combined with netname_prop too).
* *
* In addition, net hierarchy is covered in two ways: * In addition, net hierarchy is covered in three ways:
* * No connection indicated (circuit_cell_name_prefix == 0: the net shapes are simply put into their * * No connection indicated (hier_mode == BNH_Disconnected: the net shapes are simply put into their
* respective circuits. The connections are not indicated. * respective circuits. The connections are not indicated.
* * Subnet hierarchy (circuit_cell_name_prefix != 0): for each root net, a full hierarchy is built * * Subnet hierarchy (hier_mode == BNH_SubcircuitCells): for each root net, a full hierarchy is built
* to accommodate the subnets (see build_net in recursive mode). * to accommodate the subnets (see build_net in recursive mode).
* * Flat (hier_mode == BNH_Flatten): each net is flattened and put into the circuit it
* belongs to.
* *
* If a device cell name prefix is given, cells will be produced for each device abstract * If a device cell name prefix is given, cells will be produced for each device abstract
* using a name like device_cell_name_prefix + device name. * using a name like device_cell_name_prefix + device name. Otherwise the device shapes are
* treated as part of the net.
* *
* @param cmap The mapping of internal layout to target layout for the circuit mapping * @param cmap The mapping of internal layout to target layout for the circuit mapping
* @param target The target layout * @param target The target layout
* @param lmap Target layer indexes (keys) and net regions (values) * @param lmap Target layer indexes (keys) and net regions (values)
* @param hier_mode See description of this method
* @param netname_prop An (optional) property name to which to attach the net name
* @param circuit_cell_name_prefix See method description * @param circuit_cell_name_prefix See method description
* @param net_cell_name_prefix See method description * @param net_cell_name_prefix See method description
* @param device_cell_name_prefix See above * @param device_cell_name_prefix See above
*/ */
void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const; void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
/** /**
* @brief Finds the net by probing a specific location on the given layer * @brief Finds the net by probing a specific location on the given layer
@ -636,11 +677,12 @@ private:
void init (); void init ();
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<db::PolygonRef> &test_cluster, std::vector<db::InstElement> &rev_inst_path); size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<db::PolygonRef> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, 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, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, 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, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, 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, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const ICplxTrans &tr) const;
db::DeepLayer deep_layer_of (const db::Region &region) const; db::DeepLayer deep_layer_of (const db::Region &region) const;
void ensure_layout () const; void ensure_layout () const;
std::string make_new_name (const std::string &stem = std::string ()); std::string make_new_name (const std::string &stem = std::string ());
db::properties_id_type make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const;
}; };
} }

View File

@ -65,19 +65,34 @@ static db::Cell *l2n_internal_top_cell (db::LayoutToNetlist *l2n)
return const_cast<db::Cell *> (l2n->internal_top_cell ()); return const_cast<db::Cell *> (l2n->internal_top_cell ());
} }
static void build_net (const db::LayoutToNetlist *l2n, const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix) static int bnh_flatten ()
{
return int (db::LayoutToNetlist::BNH_Flatten);
}
static int bnh_disconnected ()
{
return int (db::LayoutToNetlist::BNH_Disconnected);
}
static int bnh_subcircuit_cells ()
{
return int (db::LayoutToNetlist::BNH_SubcircuitCells);
}
static void build_net (const db::LayoutToNetlist *l2n, const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, int hier_mode, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix)
{ {
std::string p = circuit_cell_name_prefix.to_string (); std::string p = circuit_cell_name_prefix.to_string ();
std::string dp = device_cell_name_prefix.to_string (); std::string dp = device_cell_name_prefix.to_string ();
l2n->build_net (net, target, target_cell, lmap, circuit_cell_name_prefix.is_nil () ? 0 : p.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ()); l2n->build_net (net, target, target_cell, lmap, netname_prop, (db::LayoutToNetlist::BuildNetHierarchyMode) hier_mode, circuit_cell_name_prefix.is_nil () ? 0 : p.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ());
} }
static void build_all_nets (const db::LayoutToNetlist *l2n, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &net_cell_name_prefix, const tl::Variant &circuit_cell_name_prefix, const tl::Variant &device_cell_name_prefix) static void build_all_nets (const db::LayoutToNetlist *l2n, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &net_cell_name_prefix, const tl::Variant &netname_prop, int 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 cp = circuit_cell_name_prefix.to_string ();
std::string np = net_cell_name_prefix.to_string (); std::string np = net_cell_name_prefix.to_string ();
std::string dp = device_cell_name_prefix.to_string (); std::string dp = device_cell_name_prefix.to_string ();
l2n->build_all_nets (cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), circuit_cell_name_prefix.is_nil () ? 0 : cp.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ()); l2n->build_all_nets (cmap, target, lmap, net_cell_name_prefix.is_nil () ? 0 : np.c_str (), netname_prop, (db::LayoutToNetlist::BuildNetHierarchyMode) hier_mode, circuit_cell_name_prefix.is_nil () ? 0 : cp.c_str (), device_cell_name_prefix.is_nil () ? 0 : dp.c_str ());
} }
static std::vector<std::string> l2n_layer_names (const db::LayoutToNetlist *l2n) static std::vector<std::string> l2n_layer_names (const db::LayoutToNetlist *l2n)
@ -349,66 +364,91 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"If 'recursive'' is true, the returned region will contain the shapes of\n" "If 'recursive'' is true, the returned region will contain the shapes of\n"
"all subcircuits too.\n" "all subcircuits too.\n"
) + ) +
gsi::method ("shapes_of_net", (void (db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, db::Shapes &) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), gsi::arg ("to"), gsi::method ("shapes_of_net", (void (db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, db::Shapes &, db::properties_id_type) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), gsi::arg ("to"), gsi::arg ("propid", db::properties_id_type (0), "0"),
"@brief Sends all shapes of a specific net and layer to the given Shapes container.\n" "@brief Sends all shapes of a specific net and layer to the given Shapes container.\n"
"If 'recursive'' is true, the returned region will contain the shapes of\n" "If 'recursive'' is true, the returned region will contain the shapes of\n"
"all subcircuits too.\n" "all subcircuits too.\n"
"\"prop_id\" is an optional properties ID. If given, this property set will be attached to the shapes."
) + ) +
gsi::method_ext ("build_net", &build_net, gsi::arg ("net"), gsi::arg ("target"), gsi::arg ("target_cell"), gsi::arg ("lmap"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"), gsi::constant ("BNH_Flatten", &bnh_flatten,
"@brief This constant tells \\build_net and \\build_all_nets to flatten the nets (used for the \"hier_mode\" parameter)."
) +
gsi::constant ("BNH_Disconnected", &bnh_disconnected,
"@brief This constant tells \\build_net and \\build_all_nets to produce local nets without connections to subcircuits (used for the \"hier_mode\" parameter)."
) +
gsi::constant ("BNH_SubcircuitCells", &bnh_subcircuit_cells,
"@brief This constant tells \\build_net and \\build_all_nets to produce a hierarchy of subcircuit cells per net (used for the \"hier_mode\" parameter)."
) +
gsi::method_ext ("build_net", &build_net, gsi::arg ("net"), gsi::arg ("target"), gsi::arg ("target_cell"), gsi::arg ("lmap"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", int (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 net representation in the given layout and cell\n" "@brief Builds a net representation in the given layout and cell\n"
"\n" "\n"
"This method has two modes: recursive and top-level mode. In recursive mode,\n" "This method puts the shapes of a net into the given target cell using a variety of options\n"
"it will create a proper hierarchy below the given target cell to hold all subcircuits the\n" "to represent the net name and the hierarchy of the net.\n"
"net connects to. It will copy the net's parts from this subcircuits into these cells.\n"
"\n" "\n"
"In top-level mode, only the shapes from the net inside it's circuit are copied to\n" "If the netname_prop name is not nil, a property with the given name is created and assigned\n"
"the given target cell. No other cells are created.\n" "the net name.\n"
"\n" "\n"
"Recursive mode is picked when a circuit cell name prefix is given. The new cells will be\n" "Net hierarchy is covered in three ways:\n"
"named like circuit_cell_name_prefix + circuit name.\n" "@ul\n"
"\n" " @li No connection indicated (hier_mode == \\BNH_Disconnected: the net shapes are simply put into their\n"
"If a device cell name prefix is given, device shapes will be output on device cells named\n" " respective circuits. The connections are not indicated. @/li\n"
"like device_cell_name_prefix + device name.\n" " @li Subnet hierarchy (hier_mode == \\BNH_SubcircuitCells): for each root net, a full hierarchy is built\n"
" to accommodate the subnets (see build_net in recursive mode). @/li\n"
" @li Flat (hier_mode == \\BNH_Flatten): each net is flattened and put into the circuit it\n"
" belongs to. @/li\n"
"@/ul\n"
"If a device cell name prefix is given, cells will be produced for each device abstract\n"
"using a name like device_cell_name_prefix + device name. Otherwise the device shapes are\n"
"treated as part of the net.\n"
"\n" "\n"
"@param target The target layout\n" "@param target The target layout\n"
"@param target_cell The target cell\n" "@param target_cell The target cell\n"
"@param lmap Target layer indexes (keys) and net regions (values)\n" "@param lmap Target layer indexes (keys) and net regions (values)\n"
"@param circuit_cell_name_prefix Chooses recursive mode if non-nil\n" "@param hier_mode See description of this method\n"
"@param device_cell_name_prefix If given, devices will be output as separate cells\n" "@param netname_prop An (optional) property name to which to attach the net name\n"
"@param cell_name_prefix Chooses recursive mode if non-null\n"
"@param device_cell_name_prefix See above\n"
) + ) +
gsi::method_ext ("build_all_nets", &build_all_nets, gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"), gsi::method_ext ("build_all_nets", &build_all_nets, gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", int (db::LayoutToNetlist::BNH_Flatten), "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
"@brief Builds a full hierarchical representation of the nets\n" "@brief Builds a full hierarchical representation of the nets\n"
"\n" "\n"
"This method copies all nets into cells corresponding to the circuits. It uses the cmap\n" "This method copies all nets into cells corresponding to the circuits. It uses the cmap\n"
"object to determine the target cell (create them with \\cell_mapping_into or \\const_cell_mapping_into.\n" "object to determine the target cell (create them with \"cell_mapping_into\" or \"const_cell_mapping_into\").\n"
"If no mapping is requested, the specific circuit it skipped.\n" "If no mapping is requested, the specific circuit it skipped.\n"
"\n" "\n"
"The method has two net annotation modes:\n" "The method has three net annotation modes:\n"
"\n"
"@ul\n" "@ul\n"
"@li 'No annotation'' (net_cell_name_prefix == 0): the shapes will be put into the target cell simply @/li\n" " @li No annotation (net_cell_name_prefix == nil and netname_prop == nil): the shapes will be put\n"
"@li Individual subcells per net (net_cell_name_prefix != 0): for each net, a subcell is created\n" " into the target cell simply. @/li\n"
" and the net shapes will be put there (name of the subcell = net_cell_name_prefix + net name). @/li\n" " @li Net name property (net_cell_name_prefix == nil and netname_prop != nil): the shapes will be\n"
" annotated with a property named with netname_prop and containing the net name string. @/li\n"
" @li Individual subcells per net (net_cell_name_prefix != 0): for each net, a subcell is created\n"
" and the net shapes will be put there (name of the subcell = net_cell_name_prefix + net name).\n"
" (this mode can be combined with netname_prop too). @/li\n"
"@/ul\n" "@/ul\n"
"\n" "\n"
"In addition, net hierarchy is covered in two ways:\n" "In addition, net hierarchy is covered in three ways:\n"
"\n"
"@ul\n" "@ul\n"
"@li No connection indicated (circuit_cell_name_prefix == 0: the net shapes are simply put into their\n" " @li No connection indicated (hier_mode == \\BNH_Disconnected: the net shapes are simply put into their\n"
" respective circuits. The connections are not indicated. @/li\n" " respective circuits. The connections are not indicated. @/li\n"
"@li Subnet hierarchy (circuit_cell_name_prefix != 0): for each root net, a full hierarchy is built\n" " @li Subnet hierarchy (hier_mode == \\BNH_SubcircuitCells): for each root net, a full hierarchy is built\n"
" to accommodate the subnets (see build_net in recursive mode). @/li\n" " to accommodate the subnets (see build_net in recursive mode). @/li\n"
" @li Flat (hier_mode == \\BNH_Flatten): each net is flattened and put into the circuit it\n"
" belongs to. @/li\n"
"@/ul\n" "@/ul\n"
"\n" "\n"
"If a device name prefix is given, device shapes will be output on device cells named\n" "If a device cell name prefix is given, cells will be produced for each device abstract\n"
"like device_name_prefix + device name.\n" "using a name like device_cell_name_prefix + device name. Otherwise the device shapes are\n"
"treated as part of the net.\n"
"\n" "\n"
"@param cmap The mapping of internal layout to target layout for the circuit mapping\n" "@param cmap The mapping of internal layout to target layout for the circuit mapping\n"
"@param target The target layout\n" "@param target The target layout\n"
"@param lmap Target layer indexes (keys) and net regions (values)\n" "@param lmap Target layer indexes (keys) and net regions (values)\n"
"@param net_cell_name_prefix See method description\n" "@param hier_mode See description of this method\n"
"@param netname_prop An (optional) property name to which to attach the net name\n"
"@param circuit_cell_name_prefix See method description\n" "@param circuit_cell_name_prefix See method description\n"
"@param device_cell_name_prefix If given, devices will be output as separate cells\n" "@param net_cell_name_prefix See method description\n"
"@param device_cell_name_prefix See above\n"
) + ) +
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"),
"@brief Finds the net by probing a specific location on the given layer\n" "@brief Finds the net by probing a specific location on the given layer\n"

View File

@ -81,7 +81,7 @@ TEST(1_ReaderBasic)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_by_name ("via1"); 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"); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_by_name ("metal2");
l2n.build_all_nets (cm, ly2, lmap, "NET_", 0, "DEVICE_"); l2n.build_all_nets (cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, "DEVICE_");
std::string au = tl::testsrc (); std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata"); au = tl::combine_path (au, "testdata");
@ -177,7 +177,7 @@ TEST(2_ReaderWithGlobalNets)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_by_name ("via1"); 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"); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_by_name ("metal2");
l2n.build_all_nets (cm, ly2, lmap, "NET_", "CIRCUIT_", "DEVICE_"); l2n.build_all_nets (cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testsrc (); std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata"); au = tl::combine_path (au, "testdata");

View File

@ -397,7 +397,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get (); lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get (); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, 0, 0, 0); l2n.build_all_nets (cm, ly2, lmap, 0, tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, 0);
std::string au = tl::testsrc (); std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata"); au = tl::combine_path (au, "testdata");
@ -424,7 +424,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get (); lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get (); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", 0, 0); l2n.build_all_nets (cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_Disconnected, 0, 0);
std::string au = tl::testsrc (); std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata"); au = tl::combine_path (au, "testdata");
@ -451,7 +451,7 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get (); lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get (); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, 0, "CIRCUIT_", 0); l2n.build_all_nets (cm, ly2, lmap, 0, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
std::string au = tl::testsrc (); std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata"); au = tl::combine_path (au, "testdata");
@ -478,7 +478,34 @@ TEST(1_BasicExtraction)
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get (); lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get (); lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", "CIRCUIT_", "DEVICE_"); l2n.build_all_nets (cm, ly2, lmap, 0, tl::Variant (42), db::LayoutToNetlist::BNH_Flatten, 0, 0);
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "device_extract_au1_rebuild_pf.gds");
db::compare_layouts (_this, ly2, au);
}
{
db::Layout ly2;
ly2.dbu (ly.dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = &rpsd;
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = &rnsd;
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = rpoly.get ();
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = rdiff_cont.get ();
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = rpoly_cont.get ();
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = rmetal1.get ();
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
std::string au = tl::testsrc (); std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata"); au = tl::combine_path (au, "testdata");

View File

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

View File

@ -101,4 +101,6 @@ unit_tests.depends += plugins $$MAIN_DEPENDS
RESOURCES += \ RESOURCES += \
laybasic/laybasic/layResources.qrc \ laybasic/laybasic/layResources.qrc \
laybasic/laybasic/layResources.qrc laybasic/laybasic/layResources.qrc \
plugins/streamers/lay/lay/layResources.qrc \
plugins/streamers/lay/lay/layResources.qrc

View File

@ -466,7 +466,7 @@ MainWindow::MainWindow (QApplication *app, lay::Plugin *plugin_parent, const cha
init_menu (); init_menu ();
lay::register_help_handler (this, SLOT (show_help (const QString &))); lay::register_help_handler (this, SLOT (show_help (const QString &)), SLOT (show_modal_help (const QString &)));
mp_assistant = new lay::HelpDialog (this); mp_assistant = new lay::HelpDialog (this);
@ -697,7 +697,7 @@ MainWindow::~MainWindow ()
} }
tl::DeferredMethodScheduler::instance ()->enable (false); tl::DeferredMethodScheduler::instance ()->enable (false);
lay::register_help_handler (0, 0); lay::register_help_handler (0, 0, 0);
// since the configuration actions unregister themselves, we need to do this before the main // since the configuration actions unregister themselves, we need to do this before the main
// window is gone: // window is gone:
@ -4783,6 +4783,12 @@ MainWindow::show_help (const QString &url)
show_assistant_url (tl::to_string (url), false); show_assistant_url (tl::to_string (url), false);
} }
void
MainWindow::show_modal_help (const QString &url)
{
show_assistant_url (tl::to_string (url), true);
}
void void
MainWindow::show_assistant_url (const std::string &url, bool modal) MainWindow::show_assistant_url (const std::string &url, bool modal)
{ {

View File

@ -832,11 +832,17 @@ public slots:
void cm_navigator_close (); void cm_navigator_close ();
/** /**
* @brief shows the given URL as a model help window * @brief shows the given URL as a non-modal help window
* Intended as a connection target for QLabel linkVisisted signals. * Intended as a connection target for QLabel linkVisisted signals.
*/ */
void show_help (const QString &url); void show_help (const QString &url);
/**
* @brief shows the given URL as a modal help window
* Intended as a connection target for QLabel linkVisisted signals.
*/
void show_modal_help (const QString &url);
/** /**
* @brief visibility of one of the dock widgets changed * @brief visibility of one of the dock widgets changed
*/ */

View File

@ -6,94 +6,45 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>531</width> <width>508</width>
<height>321</height> <height>454</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Export Net Options</string> <string>Export Net Options</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="7" column="2"> <item row="11" column="0" colspan="4">
<widget class="QLineEdit" name="device_cell_prefix"/> <spacer name="verticalSpacer_4">
</item> <property name="orientation">
<item row="6" column="0" colspan="3"> <enum>Qt::Vertical</enum>
<widget class="QCheckBox" name="produce_device_cells_cb">
<property name="text">
<string>Produce cells for devices</string>
</property> </property>
</widget> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item> </item>
<item row="2" column="0" colspan="3"> <item row="4" column="0" colspan="4">
<widget class="QCheckBox" name="produce_circuit_cells_cb"> <widget class="QCheckBox" name="produce_circuit_cells_cb">
<property name="text"> <property name="text">
<string>Produce cells for circuits</string> <string>Produce cells for circuits</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="2"> <item row="5" column="1">
<widget class="QLineEdit" name="circuit_cell_prefix"/> <widget class="QLabel" name="label_2">
</item>
<item row="3" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Net cell name prefix</string> <string>Cell name prefix</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2"> <item row="13" column="0" colspan="4">
<widget class="QLineEdit" name="net_cell_prefix"/>
</item>
<item row="8" column="1" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>If this options is selected, each device will be represented by one cell made from the device name and the given prefix. Otherwise, device parts are exported as shapes inside the net.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -106,21 +57,34 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="3" column="1"> <item row="14" column="0" colspan="4">
<widget class="QLabel" name="label_2"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="text"> <property name="standardButtons">
<string>Cell name prefix</string> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="5" column="2" colspan="2">
<widget class="QLabel" name="label_3"> <widget class="QLineEdit" name="circuit_cell_prefix"/>
</item>
<item row="8" column="0" colspan="4">
<widget class="QCheckBox" name="produce_device_cells_cb">
<property name="text"> <property name="text">
<string>Cell name prefix</string> <string>Produce cells for devices</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0" colspan="3"> <item row="6" column="1" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>If this option is selected, the subcircuits on a net are represented by individual cells. Otherwise the net is exported as a whole into a single cell (flattened).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4">
<spacer name="verticalSpacer_2"> <spacer name="verticalSpacer_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -136,17 +100,96 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="4" column="1" colspan="2"> <item row="0" column="0" colspan="4">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
<string>If this option is selected, the subcircuits on a net are represented by individual cells. Otherwise the net is exported as a whole into a single cell (flattened).</string> <string>This feature will export the nets to a new layout. This layout will contain the original hierarchy as far as required. Within each cell, that corresponds to a circuit, a cell is generated for each net. Each net has it's own hierarchy which can be tailored with the options below.</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0" colspan="3"> <item row="9" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Cell name prefix</string>
</property>
</widget>
</item>
<item row="1" column="2" colspan="2">
<widget class="QLineEdit" name="net_cell_prefix"/>
</item>
<item row="12" column="0" colspan="3">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Starting layer number for unknown layers</string>
</property>
</widget>
</item>
<item row="9" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="10" column="1" colspan="3">
<widget class="QLabel" name="label_4">
<property name="text">
<string>If this options is selected, each device will be represented by one cell made from the device name and the given prefix. Otherwise, device parts are exported as shapes inside the net.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="2" colspan="2">
<widget class="QLineEdit" name="device_cell_prefix"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Net cell name prefix</string>
</property>
</widget>
</item>
<item row="5" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="12" column="3">
<widget class="QLineEdit" name="layernum">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="7" column="0" colspan="4">
<spacer name="verticalSpacer_3"> <spacer name="verticalSpacer_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -162,8 +205,58 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="2" column="2" colspan="2">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="net_propname"/>
</item>
<item>
<widget class="QLabel" name="help_label">
<property name="text">
<string>&lt;html&gt;&lt;body&gt;(&lt;a href=&quot;int:/about/variant_notation.xml&quot;&gt;See here for the name notation&lt;/a&gt;)&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Net property name</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<tabstops>
<tabstop>net_cell_prefix</tabstop>
<tabstop>net_propname</tabstop>
<tabstop>produce_circuit_cells_cb</tabstop>
<tabstop>circuit_cell_prefix</tabstop>
<tabstop>produce_device_cells_cb</tabstop>
<tabstop>device_cell_prefix</tabstop>
<tabstop>layernum</tabstop>
</tabstops>
<resources/> <resources/>
<connections> <connections>
<connection> <connection>

View File

@ -22,6 +22,9 @@
#include "layNetExportDialog.h" #include "layNetExportDialog.h"
#include "layPlugin.h" #include "layPlugin.h"
#include "layQtTools.h"
#include "tlExceptions.h"
#include "ui_NetExportDialog.h" #include "ui_NetExportDialog.h"
@ -31,10 +34,12 @@ namespace lay
{ {
extern std::string cfg_l2ndb_net_cell_prefix; extern std::string cfg_l2ndb_net_cell_prefix;
extern std::string cfg_l2ndb_net_propname;
extern std::string cfg_l2ndb_circuit_cell_prefix; extern std::string cfg_l2ndb_circuit_cell_prefix;
extern std::string cfg_l2ndb_produce_circuit_cells; extern std::string cfg_l2ndb_produce_circuit_cells;
extern std::string cfg_l2ndb_device_cell_prefix; extern std::string cfg_l2ndb_device_cell_prefix;
extern std::string cfg_l2ndb_produce_device_cells; extern std::string cfg_l2ndb_produce_device_cells;
extern std::string cfg_l2ndb_start_layer_number;
NetExportDialog::NetExportDialog (QWidget *parent) NetExportDialog::NetExportDialog (QWidget *parent)
@ -42,6 +47,8 @@ NetExportDialog::NetExportDialog (QWidget *parent)
{ {
ui = new Ui::NetExportDialog (); ui = new Ui::NetExportDialog ();
ui->setupUi (this); ui->setupUi (this);
lay::activate_modal_help_links (ui->help_label);
} }
NetExportDialog::~NetExportDialog () NetExportDialog::~NetExportDialog ()
@ -62,6 +69,29 @@ NetExportDialog::net_prefix ()
return tl::to_string (ui->net_cell_prefix->text ()); return tl::to_string (ui->net_cell_prefix->text ());
} }
void
NetExportDialog::set_net_propname (const tl::Variant &net_propname)
{
if (net_propname.is_nil ()) {
ui->net_propname->setText (QString ());
} else {
ui->net_propname->setText (tl::to_qstring (net_propname.to_parsable_string ()));
}
}
tl::Variant
NetExportDialog::net_propname ()
{
std::string np = tl::to_string (ui->net_propname->text ());
tl::Extractor ex (np.c_str ());
tl::Variant v;
if (! ex.at_end ()) {
ex.read (v);
ex.expect_end ();
}
return v;
}
void void
NetExportDialog::set_produce_circuit_cells (bool f) NetExportDialog::set_produce_circuit_cells (bool f)
{ {
@ -112,6 +142,30 @@ NetExportDialog::device_cell_prefix ()
return tl::to_string (ui->device_cell_prefix->text ()); return tl::to_string (ui->device_cell_prefix->text ());
} }
void
NetExportDialog::set_start_layer_number (int ln)
{
ui->layernum->setText (tl::to_qstring (tl::to_string (ln)));
}
int
NetExportDialog::start_layer_number ()
{
int ln = 0;
tl::from_string (tl::to_string (ui->layernum->text ()), ln);
return ln;
}
void
NetExportDialog::accept ()
{
BEGIN_PROTECTED
start_layer_number ();
net_propname ();
QDialog::accept ();
END_PROTECTED
}
int int
NetExportDialog::exec (lay::PluginRoot *plugin_root) NetExportDialog::exec (lay::PluginRoot *plugin_root)
{ {
@ -119,6 +173,10 @@ NetExportDialog::exec (lay::PluginRoot *plugin_root)
plugin_root->config_get (cfg_l2ndb_net_cell_prefix, v); plugin_root->config_get (cfg_l2ndb_net_cell_prefix, v);
set_net_prefix (v); set_net_prefix (v);
tl::Variant var;
plugin_root->config_get (cfg_l2ndb_net_propname, var);
set_net_propname (var);
bool f = false; bool f = false;
plugin_root->config_get (cfg_l2ndb_produce_circuit_cells, f); plugin_root->config_get (cfg_l2ndb_produce_circuit_cells, f);
set_produce_circuit_cells (f); set_produce_circuit_cells (f);
@ -135,10 +193,16 @@ NetExportDialog::exec (lay::PluginRoot *plugin_root)
plugin_root->config_get (cfg_l2ndb_device_cell_prefix, v); plugin_root->config_get (cfg_l2ndb_device_cell_prefix, v);
set_device_cell_prefix (v); set_device_cell_prefix (v);
int ln = 0;
plugin_root->config_get (cfg_l2ndb_start_layer_number, ln);
set_start_layer_number (ln);
int ret = QDialog::exec (); int ret = QDialog::exec ();
if (ret) { if (ret) {
plugin_root->config_set (cfg_l2ndb_net_cell_prefix, net_prefix ()); plugin_root->config_set (cfg_l2ndb_net_cell_prefix, net_prefix ());
plugin_root->config_set (cfg_l2ndb_net_propname, net_propname ());
plugin_root->config_set (cfg_l2ndb_start_layer_number, tl::to_string (start_layer_number ()));
plugin_root->config_set (cfg_l2ndb_produce_circuit_cells, tl::to_string (produce_circuit_cells ())); plugin_root->config_set (cfg_l2ndb_produce_circuit_cells, tl::to_string (produce_circuit_cells ()));
plugin_root->config_set (cfg_l2ndb_circuit_cell_prefix, circuit_cell_prefix ()); plugin_root->config_set (cfg_l2ndb_circuit_cell_prefix, circuit_cell_prefix ());
plugin_root->config_set (cfg_l2ndb_produce_device_cells, tl::to_string (produce_device_cells ())); plugin_root->config_set (cfg_l2ndb_produce_device_cells, tl::to_string (produce_device_cells ()));

View File

@ -56,6 +56,9 @@ public:
void set_net_prefix (const std::string &net_prefix); void set_net_prefix (const std::string &net_prefix);
std::string net_prefix (); std::string net_prefix ();
void set_net_propname (const tl::Variant &net_propname);
tl::Variant net_propname ();
void set_produce_circuit_cells (bool f); void set_produce_circuit_cells (bool f);
bool produce_circuit_cells (); bool produce_circuit_cells ();
@ -68,8 +71,14 @@ public:
void set_device_cell_prefix (const std::string &net_prefix); void set_device_cell_prefix (const std::string &net_prefix);
std::string device_cell_prefix (); std::string device_cell_prefix ();
void set_start_layer_number (int ln);
int start_layer_number ();
int exec (lay::PluginRoot *mp_plugin_root); int exec (lay::PluginRoot *mp_plugin_root);
protected:
void accept ();
private: private:
Ui::NetExportDialog *ui; Ui::NetExportDialog *ui;
}; };

View File

@ -51,6 +51,8 @@ extern const std::string cfg_l2ndb_max_shapes_highlighted ("l2ndb-max-shapes-hig
extern const std::string cfg_l2ndb_show_all ("l2ndb-show-all"); extern const std::string cfg_l2ndb_show_all ("l2ndb-show-all");
extern const std::string cfg_l2ndb_window_state ("l2ndb-window-state"); extern const std::string cfg_l2ndb_window_state ("l2ndb-window-state");
extern const std::string cfg_l2ndb_net_cell_prefix ("l2ndb-net-cell-prefix"); extern const std::string cfg_l2ndb_net_cell_prefix ("l2ndb-net-cell-prefix");
extern const std::string cfg_l2ndb_net_propname ("l2ndb-net-propname");
extern const std::string cfg_l2ndb_start_layer_number ("l2ndb-start-layer-number");
extern const std::string cfg_l2ndb_circuit_cell_prefix ("l2ndb-circuit-cell-prefix"); extern const std::string cfg_l2ndb_circuit_cell_prefix ("l2ndb-circuit-cell-prefix");
extern const std::string cfg_l2ndb_produce_circuit_cells ("l2ndb-produce-circuit-cells"); extern const std::string cfg_l2ndb_produce_circuit_cells ("l2ndb-produce-circuit-cells");
extern const std::string cfg_l2ndb_device_cell_prefix ("l2ndb-device-cell-prefix"); extern const std::string cfg_l2ndb_device_cell_prefix ("l2ndb-device-cell-prefix");
@ -340,7 +342,9 @@ public:
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_marker_intensity, "50")); options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_marker_intensity, "50"));
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_show_all, "true")); options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_show_all, "true"));
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_window_state, "")); options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_window_state, ""));
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_net_propname, ""));
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_net_cell_prefix, "NET_")); options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_net_cell_prefix, "NET_"));
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_start_layer_number, "1000"));
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_produce_circuit_cells, "false")); options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_produce_circuit_cells, "false"));
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_circuit_cell_prefix, "CIRCUIT_")); options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_circuit_cell_prefix, "CIRCUIT_"));
options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_produce_device_cells, "false")); options.push_back (std::pair<std::string, std::string> (cfg_l2ndb_produce_device_cells, "false"));

View File

@ -31,6 +31,8 @@
#include "tlProgress.h" #include "tlProgress.h"
#include "dbLayoutToNetlist.h" #include "dbLayoutToNetlist.h"
#include "dbNetlistDeviceClasses.h" #include "dbNetlistDeviceClasses.h"
#include "dbCellMapping.h"
#include "dbLayerMapping.h"
#include <QUrl> #include <QUrl>
#include <QPainter> #include <QPainter>
@ -2490,15 +2492,6 @@ NetlistBrowserPage::clear_markers ()
mp_markers.clear (); mp_markers.clear ();
} }
void
NetlistBrowserPage::export_all ()
{
std::auto_ptr<lay::NetExportDialog> dialog (new lay::NetExportDialog (this));
if (dialog->exec (mp_plugin_root)) {
// @@@
}
}
void void
NetlistBrowserPage::export_selected () NetlistBrowserPage::export_selected ()
{ {
@ -2508,5 +2501,73 @@ NetlistBrowserPage::export_selected ()
} }
} }
void
NetlistBrowserPage::export_all ()
{
if (! mp_view || ! mp_database.get () || ! mp_database->internal_layout ()) {
return;
}
const db::Layout &source_layout = *mp_database->internal_layout ();
if (source_layout.begin_top_down () == source_layout.end_top_cells ()) {
// nothing to export
return;
}
const db::Cell &source_top = source_layout.cell (*source_layout.begin_top_down ());
std::auto_ptr<lay::NetExportDialog> dialog (new lay::NetExportDialog (this));
if (dialog->exec (mp_plugin_root)) {
// NOTE: mp_view and database might get reset to 0 in create_layout
lay::LayoutView *view = mp_view;
db::LayoutToNetlist *database = mp_database.get ();
unsigned int cv_index = view->create_layout (true);
db::Layout &target_layout = view->cellview (cv_index)->layout ();
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;
{
// create a layer mapping
std::set<unsigned int> layers_to_copy;
const db::Connectivity &conn = database->connectivity ();
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
layers_to_copy.insert (*layer);
}
int ln = dialog->start_layer_number ();
for (std::set<unsigned int>::const_iterator l = layers_to_copy.begin (); l != layers_to_copy.end (); ++l) {
const db::LayerProperties &lp = source_layout.get_properties (*l);
unsigned int tl;
if (! lp.is_null ()) {
tl = target_layout.insert_layer (lp);
} else {
tl = target_layout.insert_layer (db::LayerProperties (ln++, 0, database->name (*l)));
}
lm.insert (std::make_pair (tl, database->layer_by_index (*l)));
}
}
database->build_all_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,
dialog->produce_circuit_cells () ? dialog->circuit_cell_prefix ().c_str () : 0,
dialog->produce_device_cells () ? dialog->device_cell_prefix ().c_str () : 0);
view->zoom_fit ();
view->max_hier ();
view->add_missing_layers ();
view->select_cell (target_top_index, cv_index);
}
}
} }

View File

@ -42,6 +42,7 @@ namespace lay
QObject *s_help_handler = 0; QObject *s_help_handler = 0;
const char *s_help_slot = 0; const char *s_help_slot = 0;
const char *s_modal_help_slot = 0;
void activate_help_links (QLabel *label) void activate_help_links (QLabel *label)
{ {
@ -50,10 +51,18 @@ void activate_help_links (QLabel *label)
} }
} }
void register_help_handler (QObject *object, const char *slot) void activate_modal_help_links (QLabel *label)
{
if (s_help_handler) {
QObject::connect (label, SIGNAL (linkActivated (const QString &)), s_help_handler, s_modal_help_slot);
}
}
void register_help_handler (QObject *object, const char *slot, const char *modal_slot)
{ {
s_help_handler = object; s_help_handler = object;
s_help_slot = slot; s_help_slot = slot;
s_modal_help_slot = modal_slot;
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------

View File

@ -53,9 +53,14 @@ LAYBASIC_PUBLIC void restore_dialog_state (QWidget *dialog, const std::string &s
LAYBASIC_PUBLIC void activate_help_links (QLabel *label); LAYBASIC_PUBLIC void activate_help_links (QLabel *label);
/** /**
* @brief Register the help handler (object and slot) * @brief A utility function connecting a label's linkActivated event with the help browser (modal help dialogs)
*/ */
LAYBASIC_PUBLIC void register_help_handler (QObject *object, const char *slot); LAYBASIC_PUBLIC void activate_modal_help_links (QLabel *label);
/**
* @brief Register the help handler (object and slots for non-modal and modal help dialogs)
*/
LAYBASIC_PUBLIC void register_help_handler (QObject *object, const char *slot, const char *modal_slot);
} // namespace lay } // namespace lay

View File

@ -113,7 +113,7 @@
<string>...</string> <string>...</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../lay/lay/layResources.qrc"> <iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/clear.png</normaloff>:/clear.png</iconset> <normaloff>:/clear.png</normaloff>:/clear.png</iconset>
</property> </property>
</widget> </widget>
@ -140,7 +140,7 @@
<string>...</string> <string>...</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../lay/lay/layResources.qrc"> <iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/down.png</normaloff>:/down.png</iconset> <normaloff>:/down.png</normaloff>:/down.png</iconset>
</property> </property>
</widget> </widget>
@ -167,7 +167,7 @@
<string>...</string> <string>...</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../lay/lay/layResources.qrc"> <iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/add.png</normaloff>:/add.png</iconset> <normaloff>:/add.png</normaloff>:/add.png</iconset>
</property> </property>
</widget> </widget>
@ -181,7 +181,7 @@
<string>...</string> <string>...</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../lay/lay/layResources.qrc"> <iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/up.png</normaloff>:/up.png</iconset> <normaloff>:/up.png</normaloff>:/up.png</iconset>
</property> </property>
</widget> </widget>
@ -270,7 +270,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -292,7 +292,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -318,7 +318,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -447,7 +447,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -493,7 +493,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -509,7 +509,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -525,7 +525,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -541,7 +541,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -585,7 +585,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -604,7 +604,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -641,7 +641,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/right.png</pixmap> <pixmap resource="../../../../lay/lay/layResources.qrc">:/right.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -774,7 +774,7 @@
<tabstop>read_all_cbx</tabstop> <tabstop>read_all_cbx</tabstop>
</tabstops> </tabstops>
<resources> <resources>
<include location="../../lay/lay/layResources.qrc"/> <include location="../../../../lay/lay/layResources.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>

Binary file not shown.