mirror of https://github.com/KLayout/klayout.git
Integration of netlist extractor with net tracer plugin (-> "trace all nets")
This commit is contained in:
parent
a48f190bcb
commit
30fdb0089b
|
|
@ -465,6 +465,36 @@ db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layo
|
||||||
return cm;
|
return cm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<unsigned int, const db::Region *>
|
||||||
|
LayoutToNetlist::create_layermap (db::Layout &target_layout, int ln) const
|
||||||
|
{
|
||||||
|
std::map<unsigned int, const db::Region *> lm;
|
||||||
|
if (! internal_layout ()) {
|
||||||
|
return lm;
|
||||||
|
}
|
||||||
|
|
||||||
|
const db::Layout &source_layout = *internal_layout ();
|
||||||
|
|
||||||
|
std::set<unsigned int> layers_to_copy;
|
||||||
|
const db::Connectivity &conn = connectivity ();
|
||||||
|
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
|
||||||
|
layers_to_copy.insert (*layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, name (*l)));
|
||||||
|
}
|
||||||
|
lm.insert (std::make_pair (tl, const_cast<LayoutToNetlist *> (this)->layer_by_index (*l)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return lm;
|
||||||
|
}
|
||||||
|
|
||||||
db::Netlist *LayoutToNetlist::netlist () const
|
db::Netlist *LayoutToNetlist::netlist () const
|
||||||
{
|
{
|
||||||
return mp_netlist.get ();
|
return mp_netlist.get ();
|
||||||
|
|
|
||||||
|
|
@ -442,6 +442,15 @@ public:
|
||||||
*/
|
*/
|
||||||
db::CellMapping const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell);
|
db::CellMapping const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a layer mapping for build_nets etc.
|
||||||
|
* This method will create new layers inside the target layout corresponding to the
|
||||||
|
* original layers as kept inside the LayoutToNetlist database.
|
||||||
|
* It will return a layer mapping table suitable for use with build_all_nets, build_nets etc.
|
||||||
|
* Layers without original layer information will be given layer numbers ln, ln+1 etc.
|
||||||
|
*/
|
||||||
|
std::map<unsigned int, const db::Region *> create_layermap (db::Layout &target_layout, int ln) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief gets the netlist extracted (0 if no extraction happened yet)
|
* @brief gets the netlist extracted (0 if no extraction happened yet)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -972,33 +972,6 @@ NetlistBrowserPage::clear_markers ()
|
||||||
mp_markers.clear ();
|
mp_markers.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<unsigned int, const db::Region *>
|
|
||||||
create_layermap (const db::LayoutToNetlist *database, db::Layout &target_layout, int ln)
|
|
||||||
{
|
|
||||||
std::map<unsigned int, const db::Region *> lm;
|
|
||||||
|
|
||||||
const db::Layout &source_layout = *database->internal_layout ();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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, (const_cast<db::LayoutToNetlist *> (database))->layer_by_index (*l)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return lm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
NetlistBrowserPage::export_selected ()
|
NetlistBrowserPage::export_selected ()
|
||||||
{
|
{
|
||||||
|
|
@ -1044,7 +1017,7 @@ NetlistBrowserPage::export_nets (const std::vector<const db::Net *> *nets)
|
||||||
db::cell_index_type target_top_index = target_layout.add_cell (source_layout.cell_name (source_top.cell_index ()));
|
db::cell_index_type target_top_index = target_layout.add_cell (source_layout.cell_name (source_top.cell_index ()));
|
||||||
|
|
||||||
db::CellMapping cm = database->cell_mapping_into (target_layout, target_layout.cell (target_top_index));
|
db::CellMapping cm = database->cell_mapping_into (target_layout, target_layout.cell (target_top_index));
|
||||||
std::map<unsigned int, const db::Region *> lm = create_layermap (database, target_layout, dialog->start_layer_number ());
|
std::map<unsigned int, const db::Region *> lm = database->create_layermap (target_layout, dialog->start_layer_number ());
|
||||||
|
|
||||||
std::set<const db::Net *> net_set;
|
std::set<const db::Net *> net_set;
|
||||||
if (nets) {
|
if (nets) {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include "dbRecursiveShapeIterator.h"
|
#include "dbRecursiveShapeIterator.h"
|
||||||
#include "dbPolygonTools.h"
|
#include "dbPolygonTools.h"
|
||||||
#include "dbShapeProcessor.h"
|
#include "dbShapeProcessor.h"
|
||||||
|
#include "dbLayoutToNetlist.h"
|
||||||
#include "tlLog.h"
|
#include "tlLog.h"
|
||||||
|
|
||||||
// -O3 appears not to work properly for gcc 4.4.7 (RHEL 6)
|
// -O3 appears not to work properly for gcc 4.4.7 (RHEL 6)
|
||||||
|
|
@ -187,6 +188,8 @@ NetTracerData::~NetTracerData ()
|
||||||
delete l->second;
|
delete l->second;
|
||||||
}
|
}
|
||||||
m_log_layers.clear ();
|
m_log_layers.clear ();
|
||||||
|
|
||||||
|
clean_l2n_regions ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -334,6 +337,54 @@ NetTracerData::requires_booleans (unsigned int from_layer) const
|
||||||
return r->second;
|
return r->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetTracerData::clean_l2n_regions ()
|
||||||
|
{
|
||||||
|
m_l2n_regions.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetTracerData::configure_l2n (db::LayoutToNetlist &l2n)
|
||||||
|
{
|
||||||
|
clean_l2n_regions ();
|
||||||
|
|
||||||
|
// take names from symbols
|
||||||
|
std::map<unsigned int, std::string> layer_to_symbol;
|
||||||
|
for (std::map<std::string, unsigned int>::const_iterator s = m_symbols.begin (); s != m_symbols.end (); ++s) {
|
||||||
|
layer_to_symbol.insert (std::make_pair (s->second, s->first));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map <unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> > regions_per_org_layer;
|
||||||
|
|
||||||
|
// first fetch all the alias expressions
|
||||||
|
for (std::map <unsigned int, NetTracerLayerExpression *>::const_iterator l = m_log_layers.begin (); l != m_log_layers.end (); ++l) {
|
||||||
|
if (l->second->is_alias ()) {
|
||||||
|
tl::shared_ptr<NetTracerLayerExpression::RegionHolder> rh = l->second->make_l2n_region (l2n, regions_per_org_layer, layer_to_symbol [l->first]);
|
||||||
|
m_l2n_regions [l->first] = rh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then compute all the symbolic expressions
|
||||||
|
for (std::map <unsigned int, NetTracerLayerExpression *>::const_iterator l = m_log_layers.begin (); l != m_log_layers.end (); ++l) {
|
||||||
|
if (! l->second->is_alias ()) {
|
||||||
|
tl::shared_ptr<NetTracerLayerExpression::RegionHolder> rh = l->second->make_l2n_region (l2n, regions_per_org_layer, layer_to_symbol [l->first]);
|
||||||
|
m_l2n_regions [l->first] = rh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make all connections (intra and inter-layer)
|
||||||
|
for (std::map<unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> >::const_iterator r = m_l2n_regions.begin (); r != m_l2n_regions.end (); ++r) {
|
||||||
|
l2n.connect (*r->second->get ());
|
||||||
|
const std::set<unsigned int> &connections_to = log_connections (r->first);
|
||||||
|
for (std::set<unsigned int>::const_iterator c = connections_to.begin (); c != connections_to.end (); ++c) {
|
||||||
|
std::map<unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> >::const_iterator rc = m_l2n_regions.find (*c);
|
||||||
|
if (rc != m_l2n_regions.end ()) {
|
||||||
|
l2n.connect (*r->second->get (), *rc->second->get ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
// NetTracerLayerExpression implementation
|
// NetTracerLayerExpression implementation
|
||||||
|
|
||||||
|
|
@ -728,6 +779,59 @@ NetTracerLayerExpression::to_string () const
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tl::shared_ptr<NetTracerLayerExpression::RegionHolder>
|
||||||
|
NetTracerLayerExpression::make_l2n_region_for_org (db::LayoutToNetlist &l2n, std::map <unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> > ®ion_cache, int org_index, const std::string &name)
|
||||||
|
{
|
||||||
|
std::map <unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> >::iterator r = region_cache.find ((unsigned int) org_index);
|
||||||
|
if (r != region_cache.end ()) {
|
||||||
|
return r->second;
|
||||||
|
} else {
|
||||||
|
tl::shared_ptr<NetTracerLayerExpression::RegionHolder> rh (new NetTracerLayerExpression::RegionHolder (l2n.make_layer ((unsigned int) org_index, name)));
|
||||||
|
region_cache.insert (std::make_pair ((unsigned int) org_index, rh));
|
||||||
|
return rh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tl::shared_ptr<NetTracerLayerExpression::RegionHolder>
|
||||||
|
NetTracerLayerExpression::make_l2n_region (db::LayoutToNetlist &l2n, std::map <unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> > ®ion_cache, const std::string &name)
|
||||||
|
{
|
||||||
|
tl::shared_ptr<NetTracerLayerExpression::RegionHolder> rha;
|
||||||
|
if (mp_a) {
|
||||||
|
rha = mp_a->make_l2n_region (l2n, region_cache, m_op == OPNone ? name : std::string ());
|
||||||
|
} else {
|
||||||
|
rha = make_l2n_region_for_org (l2n, region_cache, m_a, m_op == OPNone ? name : std::string ());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_op == OPNone) {
|
||||||
|
return rha;
|
||||||
|
}
|
||||||
|
|
||||||
|
tl::shared_ptr<NetTracerLayerExpression::RegionHolder> rhb;
|
||||||
|
if (mp_b) {
|
||||||
|
rhb = mp_b->make_l2n_region (l2n, region_cache, std::string ());
|
||||||
|
} else {
|
||||||
|
rhb = make_l2n_region_for_org (l2n, region_cache, m_b, std::string ());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::auto_ptr<db::Region> res (new db::Region (*rha->get ()));
|
||||||
|
|
||||||
|
if (m_op == OPAnd) {
|
||||||
|
*res &= *rhb->get ();
|
||||||
|
} else if (m_op == OPXor) {
|
||||||
|
*res ^= *rhb->get ();
|
||||||
|
} else if (m_op == OPOr) {
|
||||||
|
*res += *rhb->get ();
|
||||||
|
} else if (m_op == OPNot) {
|
||||||
|
*res -= *rhb->get ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! name.empty ()) {
|
||||||
|
l2n.register_layer (*res, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tl::shared_ptr<NetTracerLayerExpression::RegionHolder> (new NetTracerLayerExpression::RegionHolder (res.release ()));
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
// NetTracer implementation
|
// NetTracer implementation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "dbShapes.h"
|
#include "dbShapes.h"
|
||||||
#include "dbShape.h"
|
#include "dbShape.h"
|
||||||
#include "dbEdgeProcessor.h"
|
#include "dbEdgeProcessor.h"
|
||||||
|
#include "dbRegion.h"
|
||||||
|
|
||||||
#include "tlProgress.h"
|
#include "tlProgress.h"
|
||||||
#include "tlFixedVector.h"
|
#include "tlFixedVector.h"
|
||||||
|
|
@ -44,6 +45,7 @@ namespace db
|
||||||
class RecursiveShapeIterator;
|
class RecursiveShapeIterator;
|
||||||
class NetTracerLayerElement;
|
class NetTracerLayerElement;
|
||||||
class NetTracerData;
|
class NetTracerData;
|
||||||
|
class LayoutToNetlist;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A shape heap where intermediate shapes can be placed into
|
* @brief A shape heap where intermediate shapes can be placed into
|
||||||
|
|
@ -260,6 +262,43 @@ public:
|
||||||
*/
|
*/
|
||||||
enum Operator { OPNone, OPOr, OPNot, OPAnd, OPXor };
|
enum Operator { OPNone, OPOr, OPNot, OPAnd, OPXor };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A helper class wrapping a Region with a tl::Object
|
||||||
|
* This way we can use tl::shared_ptr<RegionHolder> to manage the
|
||||||
|
* region's lifetime.
|
||||||
|
*/
|
||||||
|
class RegionHolder
|
||||||
|
: public tl::Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RegionHolder ()
|
||||||
|
: mp_region (0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
RegionHolder (db::Region *region)
|
||||||
|
: mp_region (region)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~RegionHolder ()
|
||||||
|
{
|
||||||
|
delete mp_region;
|
||||||
|
mp_region = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
db::Region *get ()
|
||||||
|
{
|
||||||
|
return mp_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
const db::Region *get () const
|
||||||
|
{
|
||||||
|
return mp_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
db::Region *mp_region;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Default Constructor
|
* @brief Default Constructor
|
||||||
*/
|
*/
|
||||||
|
|
@ -383,12 +422,18 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string to_string () const;
|
std::string to_string () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a corresponding region inside a LayoutToNetlist object
|
||||||
|
*/
|
||||||
|
tl::shared_ptr<RegionHolder> make_l2n_region (db::LayoutToNetlist &l2n, std::map<unsigned int, tl::shared_ptr<RegionHolder> > ®ion_cache, const std::string &name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_a, m_b;
|
int m_a, m_b;
|
||||||
NetTracerLayerExpression *mp_a, *mp_b;
|
NetTracerLayerExpression *mp_a, *mp_b;
|
||||||
Operator m_op;
|
Operator m_op;
|
||||||
|
|
||||||
void collect_original_layers (std::set<unsigned int> &l) const;
|
void collect_original_layers (std::set<unsigned int> &l) const;
|
||||||
|
tl::shared_ptr<NetTracerLayerExpression::RegionHolder> make_l2n_region_for_org (db::LayoutToNetlist &l2n, std::map <unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> > ®ion_cache, int org_index, const std::string &name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -571,6 +616,16 @@ public:
|
||||||
return m_connections.empty ();
|
return m_connections.empty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepares the connectivity for a LayoutToNetlist object
|
||||||
|
*
|
||||||
|
* This method will provide the necessary regions for LayoutToNetlist,
|
||||||
|
* perform the boolean operations if required and set up the connectivity
|
||||||
|
* accordingly. The LayoutToNetlist object then is ready for netlist
|
||||||
|
* extraction.
|
||||||
|
*/
|
||||||
|
void configure_l2n (db::LayoutToNetlist &l2n);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int m_next_log_layer;
|
unsigned int m_next_log_layer;
|
||||||
std::vector <NetTracerConnection> m_connections;
|
std::vector <NetTracerConnection> m_connections;
|
||||||
|
|
@ -580,9 +635,11 @@ private:
|
||||||
mutable std::map <unsigned int, NetTracerLayerExpression *> m_log_layers;
|
mutable std::map <unsigned int, NetTracerLayerExpression *> m_log_layers;
|
||||||
mutable std::map <unsigned int, std::pair <std::set <unsigned int>, std::set <unsigned int> > > m_requires_booleans;
|
mutable std::map <unsigned int, std::pair <std::set <unsigned int>, std::set <unsigned int> > > m_requires_booleans;
|
||||||
std::map <std::string, unsigned int> m_symbols;
|
std::map <std::string, unsigned int> m_symbols;
|
||||||
|
std::map <unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> > m_l2n_regions;
|
||||||
|
|
||||||
void add_layer_pair (unsigned int a, unsigned int b);
|
void add_layer_pair (unsigned int a, unsigned int b);
|
||||||
void add_layers (unsigned int a, unsigned int b);
|
void add_layers (unsigned int a, unsigned int b);
|
||||||
|
void clean_l2n_regions ();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,25 @@ BEGIN_PROTECTED
|
||||||
END_PROTECTED
|
END_PROTECTED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NetTracerDialog::get_net_tracer_setup (const lay::CellView &cv, db::NetTracerData &data)
|
||||||
|
{
|
||||||
|
// fetch the net tracer data from the technology and apply to the current layout
|
||||||
|
const db::Technology *tech = cv->technology ();
|
||||||
|
if (! tech) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const db::NetTracerTechnologyComponent *tech_component = dynamic_cast <const db::NetTracerTechnologyComponent *> (tech->component_by_name (db::net_tracer_component_name ()));
|
||||||
|
if (! tech_component) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the net tracer environment
|
||||||
|
data = tech_component->get_tracer_data (cv->layout ());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
db::NetTracerNet *
|
db::NetTracerNet *
|
||||||
NetTracerDialog::do_trace (const db::DBox &start_search_box, const db::DBox &stop_search_box, bool trace_path)
|
NetTracerDialog::do_trace (const db::DBox &start_search_box, const db::DBox &stop_search_box, bool trace_path)
|
||||||
{
|
{
|
||||||
|
|
@ -331,18 +350,11 @@ NetTracerDialog::do_trace (const db::DBox &start_search_box, const db::DBox &sto
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch the net tracer data from the technology and apply to the current layout
|
|
||||||
const db::Technology *tech = cv->technology ();
|
|
||||||
if (! tech) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const db::NetTracerTechnologyComponent *tech_component = dynamic_cast <const db::NetTracerTechnologyComponent *> (tech->component_by_name (db::net_tracer_component_name ()));
|
|
||||||
if (! tech_component) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up the net tracer environment
|
// Set up the net tracer environment
|
||||||
db::NetTracerData tracer_data = tech_component->get_tracer_data (cv->layout ());
|
db::NetTracerData tracer_data;
|
||||||
|
if (! get_net_tracer_setup (cv, tracer_data)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int stop_layer = 0;
|
unsigned int stop_layer = 0;
|
||||||
db::Point stop_point;
|
db::Point stop_point;
|
||||||
|
|
@ -535,7 +547,7 @@ NetTracerDialog::menu_activated (const std::string &symbol)
|
||||||
{
|
{
|
||||||
if (symbol == "lay::net_trace") {
|
if (symbol == "lay::net_trace") {
|
||||||
|
|
||||||
lay::CellView cv = view ()->cellview (view ()->active_cellview_index ());
|
const lay::CellView &cv = view ()->cellview (view ()->active_cellview_index ());
|
||||||
if (cv.is_valid ()) {
|
if (cv.is_valid ()) {
|
||||||
show ();
|
show ();
|
||||||
activateWindow ();
|
activateWindow ();
|
||||||
|
|
@ -543,6 +555,21 @@ NetTracerDialog::menu_activated (const std::string &symbol)
|
||||||
activate ();
|
activate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (symbol == "lay::edit_layer_stack") {
|
||||||
|
|
||||||
|
layer_stack_clicked ();
|
||||||
|
|
||||||
|
} else if (symbol == "lay::trace_all_nets") {
|
||||||
|
|
||||||
|
const lay::CellView &cv = view ()->cellview (view ()->active_cellview_index ());
|
||||||
|
if (cv.is_valid ()) {
|
||||||
|
db::RecursiveShapeIterator si (cv->layout (), *cv.cell (), std::vector<unsigned int> ());
|
||||||
|
std::auto_ptr <db::LayoutToNetlist> l2ndb (new db::LayoutToNetlist (si));
|
||||||
|
trace_all_nets (l2ndb.get (), cv);
|
||||||
|
unsigned int l2ndb_index = view ()->add_l2ndb (l2ndb.release ());
|
||||||
|
view ()->open_l2ndb_browser (l2ndb_index, view ()->index_of_cellview (&cv));
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
lay::Browser::menu_activated (symbol);
|
lay::Browser::menu_activated (symbol);
|
||||||
}
|
}
|
||||||
|
|
@ -1630,6 +1657,19 @@ NetTracerDialog::clear_markers ()
|
||||||
mp_markers.clear ();
|
mp_markers.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv)
|
||||||
|
{
|
||||||
|
db::NetTracerData tracer_data;
|
||||||
|
if (! get_net_tracer_setup (cv, tracer_data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracer_data.configure_l2n (*l2ndb);
|
||||||
|
|
||||||
|
l2ndb->extract_netlist ();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include "dbNetTracer.h"
|
#include "dbNetTracer.h"
|
||||||
#include "dbTechnology.h"
|
#include "dbTechnology.h"
|
||||||
|
#include "dbLayoutToNetlist.h"
|
||||||
|
|
||||||
#include "layNetTracerConfig.h"
|
#include "layNetTracerConfig.h"
|
||||||
#include "layBrowser.h"
|
#include "layBrowser.h"
|
||||||
|
|
@ -39,12 +40,14 @@
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
class NetTracerNet;
|
class NetTracerNet;
|
||||||
|
class LayoutToNetlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace lay
|
namespace lay
|
||||||
{
|
{
|
||||||
|
|
||||||
class FileDialog;
|
class FileDialog;
|
||||||
|
class CellView;
|
||||||
|
|
||||||
class NetTracerDialog
|
class NetTracerDialog
|
||||||
: public lay::Browser,
|
: public lay::Browser,
|
||||||
|
|
@ -114,6 +117,8 @@ private:
|
||||||
void layer_list_changed (int index);
|
void layer_list_changed (int index);
|
||||||
void release_mouse ();
|
void release_mouse ();
|
||||||
db::NetTracerNet *do_trace (const db::DBox &start_search_box, const db::DBox &stop_search_box, bool trace_path);
|
db::NetTracerNet *do_trace (const db::DBox &start_search_box, const db::DBox &stop_search_box, bool trace_path);
|
||||||
|
bool get_net_tracer_setup (const lay::CellView &cv, db::NetTracerData &data);
|
||||||
|
void trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,8 @@ public:
|
||||||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||||
menu_entries.push_back (lay::MenuEntry ("net_trace_group", "tools_menu.end"));
|
menu_entries.push_back (lay::MenuEntry ("net_trace_group", "tools_menu.end"));
|
||||||
menu_entries.push_back (lay::MenuEntry ("lay::net_trace", "net_trace", "tools_menu.end", tl::to_string (QObject::tr ("Trace Net"))));
|
menu_entries.push_back (lay::MenuEntry ("lay::net_trace", "net_trace", "tools_menu.end", tl::to_string (QObject::tr ("Trace Net"))));
|
||||||
|
menu_entries.push_back (lay::MenuEntry ("lay::trace_all_nets", "trace_all_nets", "tools_menu.end", tl::to_string (QObject::tr ("Trace All Nets"))));
|
||||||
|
menu_entries.push_back (lay::MenuEntry ("lay::edit_layer_stack", "edit_layer_stack", "tools_menu.end", tl::to_string (QObject::tr ("Edit Layer Stack"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual lay::Plugin *create_plugin (db::Manager * /*manager*/, lay::PluginRoot *root, lay::LayoutView *view) const
|
virtual lay::Plugin *create_plugin (db::Manager * /*manager*/, lay::PluginRoot *root, lay::LayoutView *view) const
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,230 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2019 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "tlUnitTest.h"
|
||||||
|
|
||||||
|
#include "dbNetTracerIO.h"
|
||||||
|
#include "dbNetTracer.h"
|
||||||
|
#include "dbRecursiveShapeIterator.h"
|
||||||
|
#include "dbLayoutDiff.h"
|
||||||
|
#include "dbLayoutToNetlist.h"
|
||||||
|
#include "dbTestSupport.h"
|
||||||
|
#include "dbWriter.h"
|
||||||
|
#include "dbReader.h"
|
||||||
|
|
||||||
|
static db::NetTracerConnectionInfo connection (const std::string &a, const std::string &v, const std::string &b)
|
||||||
|
{
|
||||||
|
return db::NetTracerConnectionInfo (db::NetTracerLayerExpressionInfo::compile (a),
|
||||||
|
db::NetTracerLayerExpressionInfo::compile (v),
|
||||||
|
db::NetTracerLayerExpressionInfo::compile (b));
|
||||||
|
}
|
||||||
|
|
||||||
|
static db::NetTracerConnectionInfo connection (const std::string &a, const std::string &b)
|
||||||
|
{
|
||||||
|
return db::NetTracerConnectionInfo (db::NetTracerLayerExpressionInfo::compile (a),
|
||||||
|
db::NetTracerLayerExpressionInfo::compile (b));
|
||||||
|
}
|
||||||
|
|
||||||
|
static db::NetTracerSymbolInfo symbol (const std::string &s, const std::string &e)
|
||||||
|
{
|
||||||
|
return db::NetTracerSymbolInfo (s, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracerTechnologyComponent &tc, const std::string &file_au)
|
||||||
|
{
|
||||||
|
db::Manager m;
|
||||||
|
|
||||||
|
db::Layout layout_org (&m);
|
||||||
|
{
|
||||||
|
std::string fn (tl::testsrc ());
|
||||||
|
fn += "/testdata/net_tracer/";
|
||||||
|
fn += file;
|
||||||
|
tl::InputStream stream (fn);
|
||||||
|
db::Reader reader (stream);
|
||||||
|
reader.read (layout_org);
|
||||||
|
}
|
||||||
|
|
||||||
|
const db::Cell &cell = layout_org.cell (*layout_org.begin_top_down ());
|
||||||
|
|
||||||
|
db::RecursiveShapeIterator si (layout_org, cell, std::vector<unsigned int> ());
|
||||||
|
db::LayoutToNetlist l2ndb (si);
|
||||||
|
|
||||||
|
db::NetTracerData tracer_data = tc.get_tracer_data (layout_org);
|
||||||
|
tracer_data.configure_l2n (l2ndb);
|
||||||
|
|
||||||
|
l2ndb.extract_netlist ();
|
||||||
|
|
||||||
|
db::Layout layout_nets;
|
||||||
|
db::Cell &top_cell = layout_nets.cell (layout_nets.add_cell ("NETS"));
|
||||||
|
db::CellMapping cm = l2ndb.cell_mapping_into (layout_nets, top_cell);
|
||||||
|
|
||||||
|
l2ndb.build_all_nets (cm, layout_nets, l2ndb.create_layermap (layout_nets, 1000), "NET_", tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
|
||||||
|
|
||||||
|
std::string fn (tl::testsrc ());
|
||||||
|
fn += "/testdata/net_tracer/";
|
||||||
|
fn += file_au;
|
||||||
|
|
||||||
|
CHECKPOINT ();
|
||||||
|
db::compare_layouts (_this, layout_nets, fn, db::WriteOAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(1)
|
||||||
|
{
|
||||||
|
std::string file = "t1.oas.gz";
|
||||||
|
std::string file_au = "t1_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(1c)
|
||||||
|
{
|
||||||
|
std::string file = "t1.oas.gz";
|
||||||
|
std::string file_au = "t1_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add_symbol (symbol ("a", "1/0"));
|
||||||
|
tc.add_symbol (symbol ("c", "cc"));
|
||||||
|
tc.add_symbol (symbol ("cc", "3/0"));
|
||||||
|
tc.add (connection ("a", "2/0", "cc"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(1d)
|
||||||
|
{
|
||||||
|
std::string file = "t1.oas.gz";
|
||||||
|
std::string file_au = "t1d_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1/0", "10/0", "11/0"));
|
||||||
|
|
||||||
|
// some layers are non-existing
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(4)
|
||||||
|
{
|
||||||
|
std::string file = "t4.oas.gz";
|
||||||
|
std::string file_au = "t4_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(4b)
|
||||||
|
{
|
||||||
|
std::string file = "t4.oas.gz";
|
||||||
|
std::string file_au = "t4b_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1/0", "3/0"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(5)
|
||||||
|
{
|
||||||
|
std::string file = "t5.oas.gz";
|
||||||
|
std::string file_au = "t5_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1/0*10/0", "2/0", "3/0"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(5b)
|
||||||
|
{
|
||||||
|
std::string file = "t5.oas.gz";
|
||||||
|
std::string file_au = "t5b_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1/0", "2/0*10/0", "3/0"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(5c)
|
||||||
|
{
|
||||||
|
std::string file = "t5.oas.gz";
|
||||||
|
std::string file_au = "t5c_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1/0", "2/0-11/0", "3/0"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(5d)
|
||||||
|
{
|
||||||
|
std::string file = "t5.oas.gz";
|
||||||
|
std::string file_au = "t5d_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1/0-12/0", "2/0", "3/0-12/0"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(5f)
|
||||||
|
{
|
||||||
|
std::string file = "t5.oas.gz";
|
||||||
|
std::string file_au = "t5f_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add_symbol (symbol ("x", "3-14"));
|
||||||
|
tc.add (connection ("10-13", "x"));
|
||||||
|
tc.add (connection ("x", "2", "1+13"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(6)
|
||||||
|
{
|
||||||
|
std::string file = "t6.oas.gz";
|
||||||
|
std::string file_au = "t6_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("1-10", "2", "3"));
|
||||||
|
tc.add (connection ("3", "4", "5"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(7)
|
||||||
|
{
|
||||||
|
std::string file = "t7.oas.gz";
|
||||||
|
std::string file_au = "t7_all_nets.oas.gz";
|
||||||
|
|
||||||
|
db::NetTracerTechnologyComponent tc;
|
||||||
|
tc.add (connection ("15", "14", "2-7"));
|
||||||
|
tc.add (connection ("15", "14", "7"));
|
||||||
|
|
||||||
|
run_test (_this, file, tc, file_au);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -7,6 +7,7 @@ include($$PWD/../../../../lib_ut.pri)
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
dbNetTracer.cc \
|
dbNetTracer.cc \
|
||||||
|
dbTraceAllNets.cc
|
||||||
|
|
||||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||||
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
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