mirror of https://github.com/KLayout/klayout.git
WIP: introduced error messaging for device extractor.
This commit is contained in:
parent
411c18cdb4
commit
c665d6aceb
|
|
@ -29,6 +29,23 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// NetlistDeviceExtractorError implementation
|
||||
|
||||
NetlistDeviceExtractorError::NetlistDeviceExtractorError ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetlistDeviceExtractorError::NetlistDeviceExtractorError (const std::string &cell_name, const std::string &msg)
|
||||
: m_cell_name (cell_name), m_message (msg)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// NetlistDeviceExtractor implementation
|
||||
|
||||
NetlistDeviceExtractor::NetlistDeviceExtractor ()
|
||||
: mp_layout (0), m_cell_index (0), mp_circuit (0)
|
||||
{
|
||||
|
|
@ -219,4 +236,49 @@ void NetlistDeviceExtractor::define_terminal (Device *device, size_t terminal_id
|
|||
define_terminal (device, terminal_id, layer_index, db::Polygon (db::Box (point - dv, point + dv)));
|
||||
}
|
||||
|
||||
std::string NetlistDeviceExtractor::cell_name () const
|
||||
{
|
||||
if (layout ()) {
|
||||
return layout ()->cell_name (cell_index ());
|
||||
} else {
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
void NetlistDeviceExtractor::error (const std::string &msg)
|
||||
{
|
||||
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
|
||||
}
|
||||
|
||||
void NetlistDeviceExtractor::error (const std::string &msg, const db::Polygon &poly)
|
||||
{
|
||||
error (msg);
|
||||
m_errors.back ().set_geometry (db::Region (poly));
|
||||
}
|
||||
|
||||
void NetlistDeviceExtractor::error (const std::string &msg, const db::Region ®ion)
|
||||
{
|
||||
error (msg);
|
||||
m_errors.back ().set_geometry (region);
|
||||
}
|
||||
|
||||
void NetlistDeviceExtractor::error (const std::string &category_name, const std::string &category_description, const std::string &msg)
|
||||
{
|
||||
error (msg);
|
||||
m_errors.back ().set_category_name (category_name);
|
||||
m_errors.back ().set_category_description (category_description);
|
||||
}
|
||||
|
||||
void NetlistDeviceExtractor::error (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::Polygon &poly)
|
||||
{
|
||||
error (category_name, category_description, msg);
|
||||
m_errors.back ().set_geometry (db::Region (poly));
|
||||
}
|
||||
|
||||
void NetlistDeviceExtractor::error (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::Region ®ion)
|
||||
{
|
||||
error (category_name, category_description, msg);
|
||||
m_errors.back ().set_geometry (region);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,123 @@
|
|||
#include "dbLayout.h"
|
||||
#include "dbHierNetworkProcessor.h"
|
||||
#include "dbDeepShapeStore.h"
|
||||
#include "dbRegion.h"
|
||||
|
||||
#include "gsiObject.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief An error object for the netlist device extractor
|
||||
*
|
||||
* The device extractor will keep errors using objects of this kind.
|
||||
*/
|
||||
class DB_PUBLIC NetlistDeviceExtractorError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates an error
|
||||
*/
|
||||
NetlistDeviceExtractorError ();
|
||||
|
||||
/**
|
||||
* @brief Creates an error with a cell name and a message (the minimum information)
|
||||
*/
|
||||
NetlistDeviceExtractorError (const std::string &cell_name, const std::string &msg);
|
||||
|
||||
/**
|
||||
* @brief The category name of the error
|
||||
* Specifying the category name is optional. If a category is given, it will be used for
|
||||
* the report.
|
||||
*/
|
||||
const std::string &category_name () const
|
||||
{
|
||||
return m_category_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the category name
|
||||
*/
|
||||
void set_category_name (const std::string &s)
|
||||
{
|
||||
m_category_name = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The category description of the error
|
||||
* Specifying the category description is optional. If a category is given, this attribute will
|
||||
* be used for the category description.
|
||||
*/
|
||||
const std::string &category_description () const
|
||||
{
|
||||
return m_category_description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the category description
|
||||
*/
|
||||
void set_category_description (const std::string &s)
|
||||
{
|
||||
m_category_description = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the geometry for this error
|
||||
* Not all errors may specify a geometry.
|
||||
*/
|
||||
const db::Region &geometry () const
|
||||
{
|
||||
return m_geometry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the geometry
|
||||
*/
|
||||
void set_geometry (const db::Region &g)
|
||||
{
|
||||
m_geometry = g;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the message for this error
|
||||
*/
|
||||
const std::string &message () const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the message
|
||||
*/
|
||||
void set_message (const std::string &n)
|
||||
{
|
||||
m_message = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the cell name the error occured in
|
||||
*/
|
||||
const std::string &cell_name () const
|
||||
{
|
||||
return m_cell_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the cell name
|
||||
*/
|
||||
void set_cell_name (const std::string &n)
|
||||
{
|
||||
m_cell_name = n;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_cell_name;
|
||||
std::string m_message;
|
||||
db::Region m_geometry;
|
||||
std::string m_category_name, m_category_description;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements the device extraction for a specific setup
|
||||
*
|
||||
|
|
@ -44,6 +155,9 @@ class DB_PUBLIC NetlistDeviceExtractor
|
|||
: public gsi::ObjectBase
|
||||
{
|
||||
public:
|
||||
typedef std::list<db::NetlistDeviceExtractorError> error_list;
|
||||
typedef error_list::const_iterator error_iterator;
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
|
|
@ -92,6 +206,30 @@ public:
|
|||
*/
|
||||
void extract (DeepShapeStore &dss, const std::vector<DeepLayer> &layers, Netlist *netlist);
|
||||
|
||||
/**
|
||||
* @brief Gets the error iterator, begin
|
||||
*/
|
||||
error_iterator begin_errors ()
|
||||
{
|
||||
return m_errors.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the error iterator, end
|
||||
*/
|
||||
error_iterator end_errors ()
|
||||
{
|
||||
return m_errors.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true, if there are errors
|
||||
*/
|
||||
bool has_errors () const
|
||||
{
|
||||
return ! m_errors.empty ();
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Creates the device classes
|
||||
|
|
@ -186,6 +324,41 @@ protected:
|
|||
return m_cell_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issues an error with the given message
|
||||
*/
|
||||
void error (const std::string &msg);
|
||||
|
||||
/**
|
||||
* @brief Issues an error with the given message and error shape
|
||||
*/
|
||||
void error (const std::string &msg, const db::Polygon &poly);
|
||||
|
||||
/**
|
||||
* @brief Issues an error with the given message and error geometry
|
||||
*/
|
||||
void error (const std::string &msg, const db::Region ®ion);
|
||||
|
||||
/**
|
||||
* @brief Issues an error with the given category name, description and message
|
||||
*/
|
||||
void error (const std::string &category_name, const std::string &category_description, const std::string &msg);
|
||||
|
||||
/**
|
||||
* @brief Issues an error with the given category name, description and message and error shape
|
||||
*/
|
||||
void error (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::Polygon &poly);
|
||||
|
||||
/**
|
||||
* @brief Issues an error with the given category name, description and message and error geometry
|
||||
*/
|
||||
void error (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::Region ®ion);
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the current cell
|
||||
*/
|
||||
std::string cell_name () const;
|
||||
|
||||
private:
|
||||
tl::weak_ptr<db::Netlist> m_netlist;
|
||||
db::Layout *mp_layout;
|
||||
|
|
@ -195,6 +368,7 @@ private:
|
|||
std::vector<db::DeviceClass *> m_device_classes;
|
||||
std::vector<unsigned int> m_layers;
|
||||
unsigned int m_device_name_index;
|
||||
error_list m_errors;
|
||||
|
||||
/**
|
||||
* @brief Initializes the extractor
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 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 "dbNetlistDeviceExtractor.h"
|
||||
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
TEST(1_NetlistDeviceExtractorErrorBasic)
|
||||
{
|
||||
db::NetlistDeviceExtractorError error;
|
||||
|
||||
EXPECT_EQ (error.message (), "");
|
||||
error.set_message ("x");
|
||||
EXPECT_EQ (error.message (), "x");
|
||||
error.set_category_name ("cat");
|
||||
EXPECT_EQ (error.category_name (), "cat");
|
||||
error.set_category_description ("cdesc");
|
||||
EXPECT_EQ (error.category_description (), "cdesc");
|
||||
error.set_cell_name ("cell");
|
||||
EXPECT_EQ (error.cell_name (), "cell");
|
||||
error.set_geometry (db::Region (db::Box (0, 1, 2, 3)));
|
||||
EXPECT_EQ (error.geometry ().to_string (), "(0,1;0,3;2,3;2,1)");
|
||||
|
||||
error = db::NetlistDeviceExtractorError ("cell2", "msg2");
|
||||
EXPECT_EQ (error.cell_name (), "cell2");
|
||||
EXPECT_EQ (error.message (), "msg2");
|
||||
EXPECT_EQ (error.category_name (), "");
|
||||
EXPECT_EQ (error.category_description (), "");
|
||||
EXPECT_EQ (error.geometry ().to_string (), "");
|
||||
}
|
||||
|
||||
namespace {
|
||||
class DummyDeviceExtractor
|
||||
: public db::NetlistDeviceExtractor
|
||||
{
|
||||
public:
|
||||
DummyDeviceExtractor ()
|
||||
{
|
||||
error ("msg1");
|
||||
error ("msg2", db::Box (0, 1, 2, 3));
|
||||
error ("msg3", db::Region (db::Box (10, 11, 12, 13)));
|
||||
error ("cat1", "desc1", "msg1");
|
||||
error ("cat1", "desc1", "msg2", db::Box (0, 1, 2, 3));
|
||||
error ("cat1", "desc1", "msg3", db::Region (db::Box (10, 11, 12, 13)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static std::string error2string (const db::NetlistDeviceExtractorError &e)
|
||||
{
|
||||
return e.cell_name() + ":" + e.category_name () + ":" + e.category_description () + ":" +
|
||||
e.geometry ().to_string () + ":" + e.message ();
|
||||
}
|
||||
|
||||
TEST(2_NetlistDeviceExtractorErrors)
|
||||
{
|
||||
DummyDeviceExtractor dummy_ex;
|
||||
|
||||
EXPECT_EQ (dummy_ex.has_errors (), true);
|
||||
|
||||
std::vector<db::NetlistDeviceExtractorError> errors (dummy_ex.begin_errors (), dummy_ex.end_errors ());
|
||||
EXPECT_EQ (int (errors.size ()), 6);
|
||||
EXPECT_EQ (error2string (errors [0]), "::::msg1");
|
||||
EXPECT_EQ (error2string (errors [1]), ":::(0,1;0,3;2,3;2,1):msg2");
|
||||
EXPECT_EQ (error2string (errors [2]), ":::(10,11;10,13;12,13;12,11):msg3");
|
||||
EXPECT_EQ (error2string (errors [3]), ":cat1:desc1::msg1");
|
||||
EXPECT_EQ (error2string (errors [4]), ":cat1:desc1:(0,1;0,3;2,3;2,1):msg2");
|
||||
EXPECT_EQ (error2string (errors [5]), ":cat1:desc1:(10,11;10,13;12,13;12,11):msg3");
|
||||
}
|
||||
|
|
@ -161,30 +161,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void error (const std::string &msg)
|
||||
{
|
||||
// @@@ TODO: move this to device extractor
|
||||
tl::error << tr ("Error in cell '") << cell_name () << "': " << msg;
|
||||
}
|
||||
|
||||
void error (const std::string &msg, const db::Polygon &poly)
|
||||
{
|
||||
// @@@ TODO: move this to device extractor
|
||||
tl::error << tr ("Error in cell '") << cell_name () << "': " << msg << " (" << poly.to_string () << ")";
|
||||
}
|
||||
|
||||
void error (const std::string &msg, const db::Region ®ion)
|
||||
{
|
||||
// @@@ TODO: move this to device extractor
|
||||
tl::error << tr ("Error in cell '") << cell_name () << "': " << msg << " (" << region.to_string () << ")";
|
||||
}
|
||||
|
||||
std::string cell_name () const
|
||||
{
|
||||
// @@@ TODO: move this to device extractor
|
||||
return layout ()->cell_name (cell_index ());
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_debug_out;
|
||||
unsigned int m_ldiff, m_lgate;
|
||||
|
|
@ -363,7 +339,7 @@ static std::string netlist2string (const db::Netlist &nl)
|
|||
return res;
|
||||
}
|
||||
|
||||
TEST(1_DeviceAndNetExtraction)
|
||||
TEST(2_DeviceAndNetExtraction)
|
||||
{
|
||||
db::Layout ly;
|
||||
db::LayerMap lmap;
|
||||
|
|
@ -535,3 +511,92 @@ TEST(1_DeviceAndNetExtraction)
|
|||
|
||||
db::compare_layouts (_this, ly, au);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// An attempt to simplify things.
|
||||
|
||||
/*
|
||||
- layers: use db::Region, or wrapper?
|
||||
-> use regions, but test whether they are deep regions (?)
|
||||
|
||||
TODO:
|
||||
- netlist query functions such as net_by_name, device_by_name, circuit_by_name
|
||||
- terminal geometry (Polygon) for device, combined device geometry (all terminals)
|
||||
- error interface for device extraction
|
||||
// gets the device extraction errors
|
||||
// device_extraction_error_iterator begin_device_extraction_errors () const;
|
||||
// device_extraction_error_iterator end_device_extraction_errors () const;
|
||||
// bool has_device_extraction_errors () const;
|
||||
|
||||
- device extractor needs to declare the layers to allow passing them by name
|
||||
- netlist manipulation methods (i.e. flatten certain cells, purging etc.)
|
||||
*/
|
||||
|
||||
#include "tlGlobPattern.h"
|
||||
#include "dbHierNetworkProcessor.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class DB_PUBLIC LayoutToNetlist
|
||||
{
|
||||
public:
|
||||
// the iterator provides the hierarchical selection (enabling/disabling cells etc.)
|
||||
LayoutToNetlist (const db::RecursiveShapeIterator &iter);
|
||||
|
||||
// --- preparation
|
||||
|
||||
// returns a new'd region
|
||||
db::Region *make_layer (unsigned int layer_index);
|
||||
db::Region *make_text_layer (unsigned int layer_index);
|
||||
db::Region *make_polygon_layer (unsigned int layer_index);
|
||||
|
||||
// gets the internal layout and cell
|
||||
const db::Layout &internal_layout () const;
|
||||
const db::Cell &internal_top_cell () const;
|
||||
|
||||
// --- device extraction
|
||||
|
||||
// after this, the device extractor will have errors if some occured.
|
||||
void extract_devices (db::NetlistDeviceExtractor *extractor, const std::map<std::string, const db::Region *> &layers);
|
||||
|
||||
// --- net extraction
|
||||
|
||||
// define connectivity for the netlist extraction
|
||||
void connect (const db::Region &l);
|
||||
void connect (const db::Region &a, const db::Region &b);
|
||||
|
||||
// runs the netlist extraction
|
||||
void extract_netlist ();
|
||||
|
||||
// --- retrieval
|
||||
|
||||
// gets the internal layer index of the given region
|
||||
unsigned int layer_of (const db::Region ®ion) const;
|
||||
|
||||
// creates a cell mapping for copying the internal hierarchy to the given layout
|
||||
// CAUTION: may create new cells in "layout".
|
||||
db::CellMapping cell_mapping_into (db::Layout &layout, db::Cell &cell);
|
||||
|
||||
// creates a cell mapping for copying the internal hierarchy to the given layout
|
||||
// This version will not create new cells in the target layout.
|
||||
db::CellMapping const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell);
|
||||
|
||||
// gets the netlist extracted (0 if no extraction happened yet)
|
||||
db::Netlist *netlist () const;
|
||||
|
||||
// gets the hierarchical clusters of the nets (CAUTION: the layer indexes therein are
|
||||
// internal layer indexes), same for cell indexes.
|
||||
// -> NOT GSI
|
||||
const db::hier_clusters<db::PolygonRef> &net_clusters () const;
|
||||
|
||||
// copies the shapes of the given net from a given layer
|
||||
// (recursive true: include nets from subcircuits)
|
||||
db::Region shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ SOURCES = \
|
|||
dbHierNetworkProcessorTests.cc \
|
||||
dbNetlistPropertyTests.cc \
|
||||
dbNetlistTests.cc \
|
||||
dbNetlistExtractorTests.cc
|
||||
dbNetlistExtractorTests.cc \
|
||||
dbNetlistDeviceExtractorTests.cc
|
||||
|
||||
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
|
||||
DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC
|
||||
|
|
|
|||
Loading…
Reference in New Issue