WIP: introduced error messaging for device extractor.

This commit is contained in:
Matthias Koefferlein 2018-12-28 01:06:17 +01:00
parent 411c18cdb4
commit c665d6aceb
5 changed files with 416 additions and 26 deletions

View File

@ -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 &region)
{
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 &region)
{
error (category_name, category_description, msg);
m_errors.back ().set_geometry (region);
}
}

View File

@ -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 &region);
/**
* @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 &region);
/**
* @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

View File

@ -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");
}

View File

@ -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 &region)
{
// @@@ 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 &region) 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

View File

@ -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