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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return mp_netlist.get ();
|
||||
|
|
|
|||
|
|
@ -442,6 +442,15 @@ public:
|
|||
*/
|
||||
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)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -972,33 +972,6 @@ NetlistBrowserPage::clear_markers ()
|
|||
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
|
||||
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::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;
|
||||
if (nets) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
#include "tlLog.h"
|
||||
|
||||
// -O3 appears not to work properly for gcc 4.4.7 (RHEL 6)
|
||||
|
|
@ -187,6 +188,8 @@ NetTracerData::~NetTracerData ()
|
|||
delete l->second;
|
||||
}
|
||||
m_log_layers.clear ();
|
||||
|
||||
clean_l2n_regions ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -334,6 +337,54 @@ NetTracerData::requires_booleans (unsigned int from_layer) const
|
|||
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
|
||||
|
||||
|
|
@ -728,6 +779,59 @@ NetTracerLayerExpression::to_string () const
|
|||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "dbShapes.h"
|
||||
#include "dbShape.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbRegion.h"
|
||||
|
||||
#include "tlProgress.h"
|
||||
#include "tlFixedVector.h"
|
||||
|
|
@ -44,6 +45,7 @@ namespace db
|
|||
class RecursiveShapeIterator;
|
||||
class NetTracerLayerElement;
|
||||
class NetTracerData;
|
||||
class LayoutToNetlist;
|
||||
|
||||
/**
|
||||
* @brief A shape heap where intermediate shapes can be placed into
|
||||
|
|
@ -260,6 +262,43 @@ public:
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
|
@ -383,12 +422,18 @@ public:
|
|||
*/
|
||||
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:
|
||||
int m_a, m_b;
|
||||
NetTracerLayerExpression *mp_a, *mp_b;
|
||||
Operator m_op;
|
||||
|
||||
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 ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @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:
|
||||
unsigned int m_next_log_layer;
|
||||
std::vector <NetTracerConnection> m_connections;
|
||||
|
|
@ -580,9 +635,11 @@ private:
|
|||
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;
|
||||
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_layers (unsigned int a, unsigned int b);
|
||||
void clean_l2n_regions ();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -281,6 +281,25 @@ BEGIN_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 *
|
||||
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
|
||||
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;
|
||||
db::Point stop_point;
|
||||
|
|
@ -535,7 +547,7 @@ NetTracerDialog::menu_activated (const std::string &symbol)
|
|||
{
|
||||
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 ()) {
|
||||
show ();
|
||||
activateWindow ();
|
||||
|
|
@ -543,6 +555,21 @@ NetTracerDialog::menu_activated (const std::string &symbol)
|
|||
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 {
|
||||
lay::Browser::menu_activated (symbol);
|
||||
}
|
||||
|
|
@ -1630,6 +1657,19 @@ NetTracerDialog::clear_markers ()
|
|||
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 "dbTechnology.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
|
||||
#include "layNetTracerConfig.h"
|
||||
#include "layBrowser.h"
|
||||
|
|
@ -39,12 +40,14 @@
|
|||
namespace db
|
||||
{
|
||||
class NetTracerNet;
|
||||
class LayoutToNetlist;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class FileDialog;
|
||||
class CellView;
|
||||
|
||||
class NetTracerDialog
|
||||
: public lay::Browser,
|
||||
|
|
@ -114,6 +117,8 @@ private:
|
|||
void layer_list_changed (int index);
|
||||
void release_mouse ();
|
||||
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);
|
||||
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::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
|
||||
|
|
|
|||
|
|
@ -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 = \
|
||||
dbNetTracer.cc \
|
||||
dbTraceAllNets.cc
|
||||
|
||||
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
|
||||
|
|
|
|||
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