Rework: unifying device extractor logger entries and LayoutToNetlist ones

This commit is contained in:
Matthias Koefferlein 2023-09-24 18:16:19 +02:00
parent a5bee51046
commit 1b4c81ac7b
22 changed files with 678 additions and 426 deletions

View File

@ -123,6 +123,7 @@ SOURCES = \
gsiDeclDbLayoutUtils.cc \
gsiDeclDbLayoutQuery.cc \
gsiDeclDbLibrary.cc \
gsiDeclDbLog.cc \
gsiDeclDbManager.cc \
gsiDeclDbMatrix.cc \
gsiDeclDbMetaInfo.cc \

View File

@ -242,13 +242,11 @@ void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, co
ensure_netlist ();
extractor.clear_errors ();
extractor.clear_log_entries ();
extractor.extract (dss (), m_layout_index, layers, *mp_netlist, m_net_clusters, m_device_scaling);
// transfer errors to log entries
for (auto e = extractor.begin_errors (); e != extractor.end_errors (); ++e) {
m_log_entries.push_back (db::LogEntryData (e->is_warning () ? db::Warning : db::Error, e->to_string ()));
}
m_log_entries.insert (m_log_entries.end (), extractor.begin_log_entries (), extractor.end_log_entries ());
}
void LayoutToNetlist::reset_extracted ()
@ -390,14 +388,14 @@ void LayoutToNetlist::check_extraction_errors ()
int max_errors = 10;
std::string errors;
for (auto l = m_log_entries.begin (); l != m_log_entries.end (); ++l) {
if (l->severity >= db::Error) {
if (l->severity () >= db::Error) {
errors += "\n";
if (++num_errors >= max_errors) {
errors += "...\n";
errors += tl::sprintf (tl::to_string (tr ("(list shortened after %d errrors, see log for all errors)")), max_errors);
break;
} else {
errors += l->msg;
errors += l->to_string ();
}
}
}
@ -467,16 +465,24 @@ void LayoutToNetlist::check_must_connect (const db::Circuit &c, const db::Net &a
if (c.begin_refs () != c.end_refs ()) {
if (a.begin_pins () == a.end_pins ()) {
error (tl::sprintf (tl::to_string (tr ("Must-connect net %s from circuit %s is not connected to outside")), a.expanded_name (), c.name ()));
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected to outside")), a.expanded_name ()));
error.set_cell_name (c.name ());
log_entry (error);
}
if (b.begin_pins () == b.end_pins ()) {
error (tl::sprintf (tl::to_string (tr ("Must-connect net %s from circuit %s is not connected to outside")), a.expanded_name (), c.name ()));
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected to outside")), a.expanded_name ()));
error.set_cell_name (c.name ());
log_entry (error);
}
} else {
if (a.expanded_name () == b.expanded_name ()) {
warn (tl::sprintf (tl::to_string (tr ("Must-connect nets %s from circuit %s must be connected further up in the hierarchy. This is an error at the chip top level.")), a.expanded_name (), c.name ()));
db::LogEntryData warn (db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s must be connected further up in the hierarchy. This is an error at the chip top level.")), a.expanded_name ()));
warn.set_cell_name (c.name ());
log_entry (warn);
} else {
warn (tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s from circuit %s must be connected further up in the hierarchy. This is an error at the chip top level.")), a.expanded_name (), b.expanded_name (), c.name ()));
db::LogEntryData warn (db::Warning, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s must be connected further up in the hierarchy. This is an error at the chip top level.")), a.expanded_name (), b.expanded_name ()));
warn.set_cell_name (c.name ());
log_entry (warn);
}
}
@ -487,16 +493,24 @@ void LayoutToNetlist::check_must_connect (const db::Circuit &c, const db::Net &a
const db::Net *net_a = sc.net_for_pin (a.begin_pins ()->pin_id ());
const db::Net *net_b = sc.net_for_pin (b.begin_pins ()->pin_id ());
if (net_a == 0) {
error (tl::sprintf (tl::to_string (tr ("Must-connect net %s from circuit %s is not connected at all %s")), a.expanded_name (), c.name (), subcircuit_to_string (sc)));
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected at all %s")), a.expanded_name (), subcircuit_to_string (sc)));
error.set_cell_name (c.name ());
log_entry (error);
}
if (net_b == 0) {
error (tl::sprintf (tl::to_string (tr ("Must-connect net %s from circuit %s is not connected at all %s")), b.expanded_name (), c.name (), subcircuit_to_string (sc)));
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect net %s is not connected at all %s")), b.expanded_name (), subcircuit_to_string (sc)));
error.set_cell_name (c.name ());
log_entry (error);
}
if (net_a && net_b && net_a != net_b) {
if (net_a->expanded_name () == net_b->expanded_name ()) {
error (tl::sprintf (tl::to_string (tr ("Must-connect nets %s from circuit %s are not connected %s")), a.expanded_name (), c.name (), subcircuit_to_string (sc)));
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect nets %s are not connected %s")), a.expanded_name (), subcircuit_to_string (sc)));
error.set_cell_name (c.name ());
log_entry (error);
} else {
error (tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s from circuit %s are not connected %s")), a.expanded_name (), b.expanded_name (), c.name (), subcircuit_to_string (sc)));
db::LogEntryData error (db::Error, tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s are not connected %s")), a.expanded_name (), b.expanded_name (), subcircuit_to_string (sc)));
error.set_cell_name (c.name ());
log_entry (error);
}
}
}
@ -541,32 +555,6 @@ void LayoutToNetlist::do_join_nets ()
}
}
void LayoutToNetlist::error (const std::string &msg)
{
if (m_log_entries.empty () || m_log_entries.back ().severity != db::Error || m_log_entries.back ().msg != msg) {
tl::error << msg;
m_log_entries.push_back (db::LogEntryData (db::Error, msg));
}
}
void LayoutToNetlist::warn (const std::string &msg)
{
if (m_log_entries.empty () || m_log_entries.back ().severity != db::Warning || m_log_entries.back ().msg != msg) {
tl::warn << msg;
m_log_entries.push_back (db::LogEntryData (db::Warning, msg));
}
}
void LayoutToNetlist::info (const std::string &msg)
{
if (m_log_entries.empty () || m_log_entries.back ().severity != db::Info || m_log_entries.back ().msg != msg) {
if (tl::verbosity () >= 10) {
tl::info << msg;
}
m_log_entries.push_back (db::LogEntryData (db::Info, msg));
}
}
void LayoutToNetlist::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{
if (! no_self) {

View File

@ -200,6 +200,22 @@ public:
return m_log_entries;
}
/**
* @brief Iterator for the log entries (begin)
*/
log_entries_type::const_iterator begin_log_entries () const
{
return m_log_entries.begin ();
}
/**
* @brief Iterator for the log entries (end)
*/
log_entries_type::const_iterator end_log_entries () const
{
return m_log_entries.end ();
}
/**
* @brief Clears the log entries
*/
@ -213,7 +229,9 @@ public:
*/
void log_entry (const db::LogEntryData &log_entry)
{
m_log_entries.push_back (log_entry);
if (m_log_entries.empty () || m_log_entries.back () != log_entry) {
m_log_entries.push_back (log_entry);
}
}
/**
@ -406,7 +424,8 @@ public:
* boolean operations for deriving layers. Other operations are applicable as long as they are
* capable of delivering hierarchical layers.
*
* If errors occur, the device extractor will contain theses errors.
* If errors occur, the device extractor will contain theses errors. They are also transferred
* to the LayoutToNetlist object.
*/
void extract_devices (db::NetlistDeviceExtractor &extractor, const std::map<std::string, db::ShapeCollection *> &layers);
@ -584,6 +603,9 @@ public:
*/
void extract_netlist ();
/**
* @brief Throws an exception if the extractor contains errors
*/
void check_extraction_errors ();
/**
@ -997,9 +1019,6 @@ private:
void join_nets_from_pattern (db::Circuit &c, const tl::GlobPattern &p);
void join_nets_from_pattern (db::Circuit &c, const std::set<std::string> &p);
void check_must_connect (const db::Circuit &c, const db::Net &a, const db::Net &b);
void error (const std::string &msg);
void warn (const std::string &msg);
void info (const std::string &msg);
// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);

View File

@ -61,6 +61,8 @@ namespace l2n_std_format
DB_PUBLIC std::string LongKeys::info_severity_key ("info");
DB_PUBLIC std::string LongKeys::warning_severity_key ("warning");
DB_PUBLIC std::string LongKeys::error_severity_key ("error");
DB_PUBLIC std::string LongKeys::cell_key ("cell");
DB_PUBLIC std::string LongKeys::cat_key ("cat");
// A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y
DB_PUBLIC std::string ShortKeys::version_key ("V");
@ -89,11 +91,13 @@ namespace l2n_std_format
DB_PUBLIC std::string ShortKeys::pin_key ("P");
DB_PUBLIC std::string ShortKeys::message_key ("H");
// I, W, E
// I, W, E, C, X
DB_PUBLIC std::string ShortKeys::info_severity_key ("I");
DB_PUBLIC std::string ShortKeys::warning_severity_key ("W");
DB_PUBLIC std::string ShortKeys::error_severity_key ("E");
DB_PUBLIC std::string ShortKeys::cell_key ("C");
DB_PUBLIC std::string ShortKeys::cat_key ("X");
}
}

View File

@ -144,7 +144,7 @@ namespace db
* coordinates are bottom/left and top/right
*
* [text]:
* text(<layer> [text] [coord]) - defines a rectangle [short key: J]
* text(<layer> <string> [coord]) - defines a label [short key: J]
*
* [coord]:
* <x> <y> - absolute coordinates
@ -182,15 +182,24 @@ namespace db
* scale(<mag>) - magnification (default is 1) [short key: S]
*
* [message-entry]:
* message([severity] [message|any]*) - message entry [short key: H]
* message([severity] [message|message-geometry|message-cell|message-category|any]*) - message entry [short key: H]
*
* [message]:
* description(<name>) - error description [short key: B]
* description(<name>) - message text [short key: B]
*
* [message-geometry]:
* polygon(<string>) - message geometry polygon in string-serialized form [short key: Q]
*
* [message-cell]:
* cell(<name>) - message cell [short key: C]
*
* [message-category]:
* cat(<name> <name>?) - message category with optional description [short key: X]
*
* [severity]:
* info | - [short key: I]
* warning | - [short key: W]
* error - [short key: E]
* info | - [short key: I]
* warning | - [short key: W]
* error - [short key: E]
*
* [any]:
* * |
@ -237,6 +246,8 @@ namespace l2n_std_format
static std::string info_severity_key;
static std::string warning_severity_key;
static std::string error_severity_key;
static std::string cell_key;
static std::string cat_key;
};
struct DB_PUBLIC LongKeys
@ -274,6 +285,8 @@ namespace l2n_std_format
static std::string info_severity_key;
static std::string warning_severity_key;
static std::string error_severity_key;
static std::string cell_key;
static std::string cat_key;
};
template <bool Short> struct DB_PUBLIC keys;

View File

@ -213,22 +213,78 @@ bool LayoutToNetlistStandardReader::read_severity (db::Severity &severity)
}
}
bool LayoutToNetlistStandardReader::read_message_cell (std::string &cell_name)
{
if (test (skeys::cell_key) || test (lkeys::cell_key)) {
Brace br (this);
read_word_or_quoted (cell_name);
br.done ();
return true;
} else {
return false;
}
}
bool LayoutToNetlistStandardReader::read_message_geometry (db::DPolygon &polygon)
{
if (test (skeys::polygon_key) || test (lkeys::polygon_key)) {
Brace br (this);
std::string s;
read_word_or_quoted (s);
tl::Extractor ex (s.c_str ());
ex.read (polygon);
br.done ();
return true;
} else {
return false;
}
}
bool LayoutToNetlistStandardReader::read_message_cat (std::string &category_name, std::string &category_description)
{
if (test (skeys::cat_key) || test (lkeys::cat_key)) {
Brace br (this);
read_word_or_quoted (category_name);
if (br) {
read_word_or_quoted (category_description);
}
br.done ();
return true;
} else {
return false;
}
}
void LayoutToNetlistStandardReader::read_message_entry (db::LogEntryData &data)
{
data.severity = db::NoSeverity;
data.msg.clear ();
Severity severity (db::NoSeverity);
std::string msg, cell_name, category_name, category_description;
db::DPolygon geometry;
Brace br (this);
while (br) {
if (read_severity (data.severity)) {
if (read_severity (severity)) {
// continue
} else if (read_message (data.msg)) {
} else if (read_message (msg)) {
// continue
} else if (read_message_cell (cell_name)) {
// continue
} else if (read_message_cat (category_name, category_description)) {
// continue
} else if (read_message_geometry (geometry)) {
// continue
} else {
skip_element ();
}
}
br.done ();
data.set_severity (severity);
data.set_message (msg);
data.set_cell_name (cell_name);
data.set_category_description (category_description);
data.set_category_name (category_name);
data.set_geometry (geometry);
}
void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)

View File

@ -163,6 +163,9 @@ private:
void read_geometries (db::NetlistObject *obj, Brace &br, db::LayoutToNetlist *l2n, db::local_cluster<NetShape> &lc, db::Cell &cell);
db::Point read_point ();
void read_message_entry (db::LogEntryData &data);
bool read_message_cell (std::string &cell_name);
bool read_message_geometry (db::DPolygon &polygon);
bool read_message_cat (std::string &category_name, std::string &category_description);
};
}

View File

@ -130,6 +130,41 @@ TokenizedOutput &TokenizedOutput::operator<< (const std::string &s)
// -------------------------------------------------------------------------------------------
static void write_point (TokenizedOutput &out, const db::Point &pt, db::Point &ref, bool relative)
{
if (relative) {
TokenizedOutput (out, std::string (), true) << tl::to_string (pt.x () - ref.x ()) << tl::to_string (pt.y () - ref.y ());
} else {
if (pt.x () == 0 || pt.x () != ref.x ()) {
out << tl::to_string (pt.x ());
} else {
out << "*";
}
if (pt.y () == 0 || pt.y () != ref.y ()) {
out << tl::to_string (pt.y ());
} else {
out << "*";
}
}
ref = pt;
}
template <class T, class Tr>
static void write_points (TokenizedOutput &out, const T &poly, const Tr &tr, db::Point &ref, bool relative)
{
for (typename T::polygon_contour_iterator c = poly.begin_hull (); c != poly.end_hull (); ++c) {
write_point (out, tr * *c, ref, relative);
}
}
// -------------------------------------------------------------------------------------------
namespace l2n_std_format
{
@ -166,6 +201,30 @@ std::string std_writer_impl<Keys>::severity_to_s (const db::Severity severity)
}
}
template <class Keys>
void std_writer_impl<Keys>::write_log_entry (TokenizedOutput &stream, const LogEntryData &le)
{
stream << severity_to_s (le.severity ());
stream << message_to_s (le.to_string ());
if (! le.cell_name ().empty ()) {
TokenizedOutput (stream, Keys::cell_key, true) << tl::to_word_or_quoted_string (le.cell_name ());
}
if (! le.category_name ().empty ()) {
TokenizedOutput o (stream, Keys::cat_key, true);
o << tl::to_word_or_quoted_string (le.category_name ());
if (! le.category_description ().empty ()) {
o << tl::to_word_or_quoted_string (le.category_description ());
}
}
if (le.geometry () != db::DPolygon ()) {
TokenizedOutput o (stream, Keys::polygon_key);
o << tl::to_word_or_quoted_string (le.geometry ().to_string ());
}
}
static std::string name_for_layer (const db::LayoutToNetlist *l2n, unsigned int l)
{
std::string n = l2n->name (l);
@ -346,8 +405,9 @@ void std_writer_impl<Keys>::write (bool nested, TokenizedOutput &stream, std::ma
if (! Keys::is_short ()) {
stream << endl << "# Log entries" << endl;
}
for (auto l = mp_l2n->log_entries ().begin (); l != mp_l2n->log_entries ().end (); ++l) {
TokenizedOutput (stream, Keys::message_key) << severity_to_s (l->severity) << message_to_s (l->msg);
for (auto l = mp_l2n->begin_log_entries (); l != mp_l2n->end_log_entries (); ++l) {
TokenizedOutput out (stream, Keys::message_key);
this->write_log_entry (out, *l);
m_progress.set (mp_stream->pos ());
}
}
@ -395,39 +455,6 @@ void std_writer_impl<Keys>::write (bool nested, TokenizedOutput &stream, std::ma
}
}
static void write_point (TokenizedOutput &out, const db::Point &pt, db::Point &ref, bool relative)
{
if (relative) {
TokenizedOutput (out, std::string (), true) << tl::to_string (pt.x () - ref.x ()) << tl::to_string (pt.y () - ref.y ());
} else {
if (pt.x () == 0 || pt.x () != ref.x ()) {
out << tl::to_string (pt.x ());
} else {
out << "*";
}
if (pt.y () == 0 || pt.y () != ref.y ()) {
out << tl::to_string (pt.y ());
} else {
out << "*";
}
}
ref = pt;
}
template <class T, class Tr>
static void write_points (TokenizedOutput &out, const T &poly, const Tr &tr, db::Point &ref, bool relative)
{
for (typename T::polygon_contour_iterator c = poly.begin_hull (); c != poly.end_hull (); ++c) {
write_point (out, tr * *c, ref, relative);
}
}
template <class Keys>
void std_writer_impl<Keys>::write (TokenizedOutput &stream, const db::Circuit &circuit, std::map<const db::Circuit *, std::map<const db::Net *, unsigned int> > *net2id_per_circuit)
{

View File

@ -44,6 +44,7 @@ class Net;
class Netlist;
class LayoutToNetlist;
class NetShape;
class LogEntryData;
/**
* @brief A helper class to produce token/list lines
@ -95,6 +96,7 @@ protected:
std::string severity_to_s (const db::Severity severity);
std::string message_to_s (const std::string &msg);
void write_log_entry (TokenizedOutput &stream, const LogEntryData &log_entry);
private:
tl::OutputStream *mp_stream;

View File

@ -155,6 +155,8 @@ void LayoutVsSchematicStandardReader::read_log_entry (db::NetlistCrossReference
}
br.done ();
// NOTE: this API does not use the full feature set of db::LogEntryData, so
// we do not use this object here.
xref->log_entry (severity, msg);
}

View File

@ -203,7 +203,8 @@ void std_writer_impl<Keys>::write (TokenizedOutput &stream, const db::NetlistCro
o << endl;
for (auto l = xref->other_log_entries ().begin (); l != xref->other_log_entries ().end (); ++l) {
TokenizedOutput (o, Keys::log_entry_key, true) << this->severity_to_s (l->severity) << this->message_to_s (l->msg);
TokenizedOutput to (o, Keys::log_entry_key, true);
this->write_log_entry (to, *l);
o << endl;
}
@ -224,7 +225,8 @@ void std_writer_impl<Keys>::write (TokenizedOutput &stream, const db::NetlistCro
o << endl;
for (auto l = pcd->log_entries.begin (); l != pcd->log_entries.end (); ++l) {
TokenizedOutput (o, Keys::log_entry_key, true) << this->severity_to_s (l->severity) << this->message_to_s (l->msg);
TokenizedOutput to (o, Keys::log_entry_key, true);
this->write_log_entry (to, *l);
o << endl;
}

View File

@ -22,10 +22,165 @@
#include "dbCommon.h"
#include "dbLog.h"
#include "tlThreads.h"
namespace db
{
// ------------------------------------------------------------------
// A string repository for keeping the memory footprint low for
// the log entries
class LogEntryStringRepository
{
public:
LogEntryStringRepository ()
{
// .. nothing yet ..
}
size_t id_for_string (const std::string &s)
{
if (s.empty ()) {
return 0;
}
tl::MutexLocker locker (&m_lock);
auto m = m_id_to_string.find (s);
if (m == m_id_to_string.end ()) {
m_strings.push_back (s);
size_t id = m_strings.size ();
m_id_to_string.insert (std::make_pair (s, id));
return id;
} else {
return m->second;
}
}
const std::string &string_for_id (size_t id) const
{
if (id == 0) {
static const std::string empty;
return empty;
}
tl::MutexLocker locker (&m_lock);
return m_strings [id - 1];
}
private:
mutable tl::Mutex m_lock;
std::vector<std::string> m_strings;
std::map<std::string, size_t> m_id_to_string;
};
static LogEntryStringRepository s_strings;
// ------------------------------------------------------------------
// LogEntryData implementation
LogEntryData::LogEntryData ()
: m_severity (NoSeverity), m_cell_name (0), m_message (0), m_category_name (0), m_category_description (0)
{
// .. nothing yet ..
}
LogEntryData::LogEntryData (Severity s, const std::string &msg)
: m_severity (s), m_cell_name (0), m_message (s_strings.id_for_string (msg)), m_category_name (0), m_category_description (0)
{
// .. nothing yet ..
}
LogEntryData::LogEntryData (Severity s, const std::string &cell_name, const std::string &msg)
: m_severity (s), m_cell_name (s_strings.id_for_string (cell_name)), m_message (s_strings.id_for_string (msg)), m_category_name (0), m_category_description (0)
{
// .. nothing yet ..
}
bool
LogEntryData::operator== (const LogEntryData &other) const
{
return m_severity == other.m_severity &&
m_message == other.m_message &&
m_cell_name == other.m_cell_name &&
m_geometry == other.m_geometry &&
m_category_name == other.m_category_name &&
m_category_description == other.m_category_description;
}
const std::string &
LogEntryData::category_name () const
{
return s_strings.string_for_id (m_category_name);
}
void
LogEntryData::set_category_name (const std::string &s)
{
m_category_name = s_strings.id_for_string (s);
}
const std::string &
LogEntryData::category_description () const
{
return s_strings.string_for_id (m_category_description);
}
void
LogEntryData::set_category_description (const std::string &s)
{
m_category_description = s_strings.id_for_string (s);
}
const std::string &
LogEntryData::message () const
{
return s_strings.string_for_id (m_message);
}
void
LogEntryData::set_message (const std::string &n)
{
m_message = s_strings.id_for_string (n);
}
const std::string &
LogEntryData::cell_name () const
{
return s_strings.string_for_id (m_cell_name);
}
void
LogEntryData::set_cell_name (const std::string &n)
{
m_cell_name = s_strings.id_for_string (n);
}
std::string
LogEntryData::to_string () const
{
std::string res;
if (m_category_name != 0) {
if (m_category_description != 0) {
res += "[" + category_name () + "] ";
} else {
res += "[" + category_description () + "] ";
}
}
res += message ();
if (m_cell_name != 0) {
res += tl::to_string (tr (", in cell: ")) + cell_name ();
}
if (! m_geometry.box ().empty ()) {
res += tl::to_string (tr (", shape: ")) + m_geometry.to_string ();
}
return res;
}
}

View File

@ -24,6 +24,7 @@
#define _HDR_dbLog
#include "dbCommon.h"
#include "dbPolygon.h"
#include <string>
@ -41,17 +42,137 @@ enum Severity {
};
/**
* @brief A class representing one log entry
* @brief A generic log entry
*
* This object can be used for collecting errors or warnings.
* It features a message and a severity level and optionally
* a polygon (for geometry marker), a category name and a category description.
*/
struct LogEntryData
class DB_PUBLIC LogEntryData
{
LogEntryData (Severity s, const std::string &m) : severity (s), msg (m) { }
LogEntryData () : severity (NoSeverity) { }
public:
typedef size_t string_id_type;
Severity severity;
std::string msg;
/**
* @brief Creates a log entry
*/
LogEntryData ();
/**
* @brief Creates a log entry with the severity and a message
*/
LogEntryData (Severity s, const std::string &msg);
/**
* @brief Creates an error with the severity, a cell name and a message
*/
LogEntryData (Severity s, const std::string &cell_name, const std::string &msg);
/**
* @brief Equality
*/
bool operator== (const LogEntryData &other) const;
/**
* @brief Inequality
*/
bool operator!= (const LogEntryData &other) const
{
return ! operator== (other);
}
/**
* @brief Sets the severity
*/
void set_severity (Severity severity)
{
m_severity = severity;
}
/**
* @brief Gets the severity
*/
Severity severity () const
{
return m_severity;
}
/**
* @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;
/**
* @brief Sets the category name
*/
void set_category_name (const std::string &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;
/**
* @brief Sets the category description
*/
void set_category_description (const std::string &s);
/**
* @brief Gets the geometry for this error
* Not all errors may specify a geometry. In this case, the polygon is empty.
*/
const db::DPolygon &geometry () const
{
return m_geometry;
}
/**
* @brief Sets the geometry
*/
void set_geometry (const db::DPolygon &g)
{
m_geometry = g;
}
/**
* @brief Gets the message for this error
*/
const std::string &message () const;
/**
* @brief Sets the message
*/
void set_message (const std::string &n);
/**
* @brief Gets the cell name the error occurred in
*/
const std::string &cell_name () const;
/**
* @brief Sets the cell name
*/
void set_cell_name (const std::string &n);
/**
* @brief Formats this message for printing
*/
std::string to_string () const;
private:
Severity m_severity;
string_id_type m_cell_name;
string_id_type m_message;
db::DPolygon m_geometry;
string_id_type m_category_name, m_category_description;
};
}
#endif

View File

@ -32,46 +32,6 @@
namespace db
{
// ----------------------------------------------------------------------------------------
// NetlistDeviceExtractorError implementation
NetlistDeviceExtractorError::NetlistDeviceExtractorError ()
: m_warning (false)
{
// .. nothing yet ..
}
NetlistDeviceExtractorError::NetlistDeviceExtractorError (const std::string &cell_name, const std::string &msg)
: m_warning (false), m_cell_name (cell_name), m_message (msg)
{
// .. nothing yet ..
}
std::string NetlistDeviceExtractorError::to_string () const
{
std::string res;
if (! m_category_name.empty ()) {
if (m_category_description.empty ()) {
res += "[" + m_category_name + "] ";
} else {
res += "[" + m_category_description + "] ";
}
}
res += m_message;
if (! m_cell_name.empty ()) {
res += tl::to_string (tr (", in cell: ")) + m_cell_name;
}
if (! m_geometry.box ().empty ()) {
res += tl::to_string (tr (", shape: ")) + m_geometry.to_string ();
}
return res;
}
// ----------------------------------------------------------------------------------------
// NetlistDeviceExtractor implementation
@ -587,89 +547,85 @@ std::string NetlistDeviceExtractor::cell_name () const
void NetlistDeviceExtractor::error (const std::string &msg)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_log_entries.push_back (db::LogEntryData (db::Error, cell_name (), msg));
if (tl::verbosity () >= 20) {
tl::error << m_errors.back ().to_string ();
tl::error << m_log_entries.back ().to_string ();
}
}
void NetlistDeviceExtractor::error (const std::string &msg, const db::DPolygon &poly)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_geometry (poly);
m_log_entries.push_back (db::LogEntryData (db::Error, cell_name (), msg));
m_log_entries.back ().set_geometry (poly);
if (tl::verbosity () >= 20) {
tl::error << m_errors.back ().to_string ();
tl::error << m_log_entries.back ().to_string ();
}
}
void NetlistDeviceExtractor::error (const std::string &category_name, const std::string &category_description, const std::string &msg)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_category_name (category_name);
m_errors.back ().set_category_description (category_description);
m_log_entries.push_back (db::LogEntryData (db::Error, cell_name (), msg));
m_log_entries.back ().set_category_name (category_name);
m_log_entries.back ().set_category_description (category_description);
if (tl::verbosity () >= 20) {
tl::error << m_errors.back ().to_string ();
tl::error << m_log_entries.back ().to_string ();
}
}
void NetlistDeviceExtractor::error (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::DPolygon &poly)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_category_name (category_name);
m_errors.back ().set_category_description (category_description);
m_errors.back ().set_geometry (poly);
m_log_entries.push_back (db::LogEntryData (db::Error, cell_name (), msg));
m_log_entries.back ().set_category_name (category_name);
m_log_entries.back ().set_category_description (category_description);
m_log_entries.back ().set_geometry (poly);
if (tl::verbosity () >= 20) {
tl::error << m_errors.back ().to_string ();
tl::error << m_log_entries.back ().to_string ();
}
}
void NetlistDeviceExtractor::warn (const std::string &msg)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_warning (true);
m_log_entries.push_back (db::LogEntryData (db::Warning, cell_name (), msg));
if (tl::verbosity () >= 20) {
tl::warn << m_errors.back ().to_string ();
tl::warn << m_log_entries.back ().to_string ();
}
}
void NetlistDeviceExtractor::warn (const std::string &msg, const db::DPolygon &poly)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_geometry (poly);
m_errors.back ().set_warning (true);
m_log_entries.push_back (db::LogEntryData (db::Warning, cell_name (), msg));
m_log_entries.back ().set_geometry (poly);
if (tl::verbosity () >= 20) {
tl::warn << m_errors.back ().to_string ();
tl::warn << m_log_entries.back ().to_string ();
}
}
void NetlistDeviceExtractor::warn (const std::string &category_name, const std::string &category_description, const std::string &msg)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_category_name (category_name);
m_errors.back ().set_category_description (category_description);
m_errors.back ().set_warning (true);
m_log_entries.push_back (db::LogEntryData (db::Warning, cell_name (), msg));
m_log_entries.back ().set_category_name (category_name);
m_log_entries.back ().set_category_description (category_description);
if (tl::verbosity () >= 20) {
tl::warn << m_errors.back ().to_string ();
tl::warn << m_log_entries.back ().to_string ();
}
}
void NetlistDeviceExtractor::warn (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::DPolygon &poly)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_category_name (category_name);
m_errors.back ().set_category_description (category_description);
m_errors.back ().set_geometry (poly);
m_errors.back ().set_warning (true);
m_log_entries.push_back (db::LogEntryData (db::Warning, cell_name (), msg));
m_log_entries.back ().set_category_name (category_name);
m_log_entries.back ().set_category_description (category_description);
m_log_entries.back ().set_geometry (poly);
if (tl::verbosity () >= 20) {
tl::warn << m_errors.back ().to_string ();
tl::warn << m_log_entries.back ().to_string ();
}
}

View File

@ -30,144 +30,13 @@
#include "dbDeepShapeStore.h"
#include "dbRegion.h"
#include "dbNetShape.h"
#include "dbLog.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 Sets a value indicating whether the error is only a warning
*/
void set_warning (bool f)
{
m_warning = f;
}
/**
* @brief Gets a value indicating whether the error is only a warning
*/
bool is_warning () const
{
return m_warning;
}
/**
* @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. In this case, the polygon is empty.
*/
const db::DPolygon &geometry () const
{
return m_geometry;
}
/**
* @brief Sets the geometry
*/
void set_geometry (const db::DPolygon &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 occurred 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;
}
/**
* @brief Formats this message for printing
*/
std::string to_string () const;
private:
bool m_warning;
std::string m_cell_name;
std::string m_message;
db::DPolygon m_geometry;
std::string m_category_name, m_category_description;
};
/**
* @brief Specifies a single layer from the device extractor
*/
@ -218,8 +87,8 @@ class DB_PUBLIC NetlistDeviceExtractor
: public gsi::ObjectBase, public tl::Object
{
public:
typedef std::list<db::NetlistDeviceExtractorError> error_list;
typedef error_list::const_iterator error_iterator;
typedef std::list<db::LogEntryData> log_entry_list;
typedef log_entry_list::const_iterator log_entry_iterator;
typedef std::vector<db::NetlistDeviceExtractorLayerDefinition> layer_definitions;
typedef layer_definitions::const_iterator layer_definitions_iterator;
typedef std::map<std::string, db::ShapeCollection *> input_layers;
@ -283,35 +152,27 @@ public:
void extract (DeepShapeStore &dss, unsigned int layout_index, const input_layers &layers, Netlist &netlist, hier_clusters_type &clusters, double device_scaling = 1.0);
/**
* @brief Clears the errors
* @brief Clears the log entries
*/
void clear_errors ()
void clear_log_entries ()
{
m_errors.clear ();
m_log_entries.clear ();
}
/**
* @brief Gets the error iterator, begin
* @brief Gets the log entry iterator, begin
*/
error_iterator begin_errors ()
log_entry_iterator begin_log_entries ()
{
return m_errors.begin ();
return m_log_entries.begin ();
}
/**
* @brief Gets the error iterator, end
* @brief Gets the log entry iterator, end
*/
error_iterator end_errors ()
log_entry_iterator end_log_entries ()
{
return m_errors.end ();
}
/**
* @brief Returns true, if there are errors
*/
bool has_errors () const
{
return ! m_errors.empty ();
return m_log_entries.end ();
}
/**
@ -617,7 +478,7 @@ private:
std::string m_name;
layer_definitions m_layer_definitions;
std::vector<unsigned int> m_layers;
error_list m_errors;
log_entry_list m_log_entries;
std::map<size_t, std::pair<db::Device *, geometry_per_terminal_type> > m_new_devices;
std::map<DeviceCellKey, std::pair<db::cell_index_type, db::DeviceAbstract *> > m_device_cells;

View File

@ -1839,7 +1839,7 @@ gsi::EnumIn<db::Edges, db::SpecialEdgeOrientationFilter::FilterType> decl_EdgesE
gsi::enum_const ("OrthoDiagonalEdges", db::SpecialEdgeOrientationFilter::OrthoDiagonal,
"@brief Diagonal or orthogonal edges are selected (0, 90, -45 and 45 degree)\n"
),
"@brief This enum specifies the the edge type for edge angle filters.\n"
"@brief This enum specifies the edge type for edge angle filters.\n"
"\n"
"This enum was introduced in version 0.28.\n"
);

View File

@ -712,7 +712,10 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"@brief Reads the extracted netlist from the file.\n"
"This method employs the native format of KLayout.\n"
) +
// @@@ Add API for logs
gsi::iterator ("each_log_entry|#each_error", &db::LayoutToNetlist::begin_log_entries, &db::LayoutToNetlist::end_log_entries,
"@brief Iterates over all log entries collected during device and netlist extraction.\n"
"This method has been introduced in version 0.28.13."
) +
gsi::method_ext ("antenna_check", &antenna_check, gsi::arg ("gate"), gsi::arg ("metal"), gsi::arg ("ratio"), gsi::arg ("diodes", std::vector<tl::Variant> (), "[]"), gsi::arg ("texts", (db::Texts *) 0, "nil"),
"@brief Runs an antenna check on the extracted clusters\n"
"\n"

117
src/db/db/gsiDeclDbLog.cc Normal file
View File

@ -0,0 +1,117 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2023 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 "gsiDecl.h"
#include "gsiEnums.h"
#include "dbLog.h"
namespace gsi
{
Class<db::LogEntryData> decl_dbNetlistDeviceExtractorError ("db", "LogEntryData",
gsi::method ("severity", &db::LogEntryData::severity,
"@brief Gets the severity attribute.\n"
) +
gsi::method ("severity=", &db::LogEntryData::set_severity, gsi::arg ("severity"),
"@brief Sets the severity attribute.\n"
) +
gsi::method ("message", &db::LogEntryData::message,
"@brief Gets the message text.\n"
) +
gsi::method ("message=", &db::LogEntryData::set_message, gsi::arg ("message"),
"@brief Sets the message text.\n"
) +
gsi::method ("cell_name", &db::LogEntryData::cell_name,
"@brief Gets the cell name.\n"
"See \\cell_name= for details about this attribute."
) +
gsi::method ("cell_name=", &db::LogEntryData::set_cell_name, gsi::arg ("cell_name"),
"@brief Sets the cell name.\n"
"The cell name is the name of the layout cell which was treated. This is "
"also the name of the circuit the device should have appeared in (it may be dropped because of this error). "
"If netlist hierarchy manipulation happens however, the circuit may not exist "
"any longer or may be renamed."
) +
gsi::method ("geometry", &db::LogEntryData::geometry,
"@brief Gets the geometry.\n"
"See \\geometry= for more details."
) +
gsi::method ("geometry=", &db::LogEntryData::set_geometry, gsi::arg ("polygon"),
"@brief Sets the geometry.\n"
"The geometry is optional. If given, a marker will be shown when selecting this error."
) +
gsi::method ("category_name", &db::LogEntryData::category_name,
"@brief Gets the category name.\n"
"See \\category_name= for more details."
) +
gsi::method ("category_name=", &db::LogEntryData::set_category_name, gsi::arg ("name"),
"@brief Sets the category name.\n"
"The category name is optional. If given, it specifies a formal category name. Errors with the same "
"category name are shown in that category. If in addition a category description is specified "
"(see \\category_description), this description will be displayed as the title of."
) +
gsi::method ("category_description", &db::LogEntryData::category_description,
"@brief Gets the category description.\n"
"See \\category_name= for details about categories."
) +
gsi::method ("category_description=", &db::LogEntryData::set_category_description, gsi::arg ("description"),
"@brief Sets the category description.\n"
"See \\category_name= for details about categories."
) +
gsi::method ("to_s", &db::LogEntryData::to_string,
"@brief Gets the string representation of this error or warning.\n"
"This method has been introduced in version 0.28.13."
),
"@brief A generic log entry\n"
"This class is used for example by the device extractor (see \\NetlistDeviceExtractor) to keep errors or warnings "
"that occurred during extraction of the devices.\n"
"\n"
"Other classes also make use of this object to store errors, warnings or information. "
"The log entry object features a severity (warning, error, info), a message, an optional "
"category name and description (good for filtering if needed) and an optional \\DPolygon object "
"for indicating some location or error marker."
"\n"
"The original class used to be \"NetlistDeviceExtractorError\" which had been introduced in version 0.26. "
"It was generalized and renamed in version 0.28.13 as it was basically not useful as a seperate class."
);
gsi::Enum<db::Severity> decl_Severity ("db", "Severity",
gsi::enum_const ("NoSeverity", db::NoSeverity,
"@brief Specifies no particular severity (default)\n"
) +
gsi::enum_const ("Warning", db::Warning,
"@brief Specifies warning severity (log with high priority, but do not stop)\n"
) +
gsi::enum_const ("Error", db::Error,
"@brief Specifies error severity (preferred action is stop)\n"
) +
gsi::enum_const ("Info", db::Info,
"@brief Specifies info severity (print if requested, otherwise silent)\n"
),
"@brief This enum specifies the severity level for log entries.\n"
"\n"
"This enum was introduced in version 0.28.13.\n"
);
gsi::ClassExt<db::LogEntryData> inject_SeverityEnum_into_LogEntryData (decl_Severity.defs ());
}

View File

@ -657,21 +657,7 @@ Class<db::NetlistComparer> decl_dbNetlistComparer ("db", "NetlistComparer",
"This class has been introduced in version 0.26."
);
gsi::EnumIn<GenericNetlistCompareLogger, db::Severity> decl_CompareLoggerSeverity ("db", "Severity",
gsi::enum_const ("NoSeverity", db::NoSeverity,
"@brief Unspecific severity\n"
) +
gsi::enum_const ("Info", db::Info,
"@brief Information only\n"
) +
gsi::enum_const ("Warning", db::Warning,
"@brief A warning\n"
) +
gsi::enum_const ("Error", db::Error,
"@brief An error\n"
),
"@brief This class represents the log severity level for \\GenericNetlistCompareLogger#log_entry.\n"
"This enum has been introduced in version 0.28."
);
extern gsi::Enum<db::Severity> decl_Severity;
gsi::ClassExt<GenericNetlistCompareLogger> inject_SeverityEnum_into_GenericNetlistCompareLogger (decl_Severity.defs ());
}

View File

@ -156,76 +156,6 @@ Class<DeviceClassFactoryImpl> decl_dbDeviceClassFactoryBase ("db", "DeviceClassF
"This class has been introduced in version 0.27.3.\n"
);
Class<db::NetlistDeviceExtractorError> decl_dbNetlistDeviceExtractorError ("db", "NetlistDeviceExtractorError",
gsi::method ("is_warning?|is_warning", &db::NetlistDeviceExtractorError::is_warning,
"@brief Gets a value indicating whether the error is a warning.\n"
"This predicate has been introduced in version 0.28.13."
) +
gsi::method ("warning=", &db::NetlistDeviceExtractorError::set_warning, gsi::arg ("flag"),
"@brief Sets a value indicating whether the error is a warning.\n"
"This predicate has been introduced in version 0.28.13."
) +
gsi::method ("message", &db::NetlistDeviceExtractorError::message,
"@brief Gets the message text.\n"
) +
gsi::method ("message=", &db::NetlistDeviceExtractorError::set_message, gsi::arg ("message"),
"@brief Sets the message text.\n"
) +
gsi::method ("cell_name", &db::NetlistDeviceExtractorError::cell_name,
"@brief Gets the cell name.\n"
"See \\cell_name= for details about this attribute."
) +
gsi::method ("cell_name=", &db::NetlistDeviceExtractorError::set_cell_name, gsi::arg ("cell_name"),
"@brief Sets the cell name.\n"
"The cell name is the name of the layout cell which was treated. This is "
"also the name of the circuit the device should have appeared in (it may be dropped because of this error). "
"If netlist hierarchy manipulation happens however, the circuit may not exist "
"any longer or may be renamed."
) +
gsi::method ("geometry", &db::NetlistDeviceExtractorError::geometry,
"@brief Gets the geometry.\n"
"See \\geometry= for more details."
) +
gsi::method ("geometry=", &db::NetlistDeviceExtractorError::set_geometry, gsi::arg ("polygon"),
"@brief Sets the geometry.\n"
"The geometry is optional. If given, a marker will be shown when selecting this error."
) +
gsi::method ("category_name", &db::NetlistDeviceExtractorError::category_name,
"@brief Gets the category name.\n"
"See \\category_name= for more details."
) +
gsi::method ("category_name=", &db::NetlistDeviceExtractorError::set_category_name, gsi::arg ("name"),
"@brief Sets the category name.\n"
"The category name is optional. If given, it specifies a formal category name. Errors with the same "
"category name are shown in that category. If in addition a category description is specified "
"(see \\category_description), this description will be displayed as the title of."
) +
gsi::method ("category_description", &db::NetlistDeviceExtractorError::category_description,
"@brief Gets the category description.\n"
"See \\category_name= for details about categories."
) +
gsi::method ("category_description=", &db::NetlistDeviceExtractorError::set_category_description, gsi::arg ("description"),
"@brief Sets the category description.\n"
"See \\category_name= for details about categories."
) +
gsi::method ("to_s", &db::NetlistDeviceExtractorError::to_string,
"@brief Gets the string representation of this error or warning.\n"
"This method has been introduced in version 0.28.13."
),
"@brief An error or a warning that occurred during device extraction\n"
"The device extractor will keep errors that occurred during extraction of the devices. "
"It does not by using this error class.\n"
"\n"
"An error is basically described by the cell/circuit it occurs in and the message. "
"In addition, a geometry may be attached forming a marker that can be shown when the error is selected. "
"The geometry is given as a \\DPolygon object. If no geometry is specified, this polygon is empty.\n"
"\n"
"For categorization of the errors, a category name and description may be specified. If given, the "
"errors will be shown in the specified category. The category description is optional.\n"
"\n"
"This class has been introduced in version 0.26. Warning mode has been added in version 0.28.13."
);
static const std::string &ld_name (const db::NetlistDeviceExtractorLayerDefinition *ld)
{
return ld->name;
@ -292,8 +222,10 @@ Class<db::NetlistDeviceExtractor> decl_dbNetlistDeviceExtractor ("db", "DeviceEx
gsi::iterator ("each_layer_definition", &db::NetlistDeviceExtractor::begin_layer_definitions, &db::NetlistDeviceExtractor::end_layer_definitions,
"@brief Iterates over all layer definitions."
) +
gsi::iterator ("each_error", &db::NetlistDeviceExtractor::begin_errors, &db::NetlistDeviceExtractor::end_errors,
"@brief Iterates over all errors collected in the device extractor."
gsi::iterator ("each_log_entry|#each_error", &db::NetlistDeviceExtractor::begin_log_entries, &db::NetlistDeviceExtractor::end_log_entries,
"@brief Iterates over all log entries collected in the device extractor."
"Starting with version 0.28.13, the preferred name of the method is 'each_log_entry' as "
"log entries have been generalized to become warnings too."
),
"@brief The base class for all device extractors.\n"
"This is an abstract base class for device extractors. See \\GenericDeviceExtractor for a generic "

View File

@ -33,7 +33,7 @@
TEST(1_NetlistDeviceExtractorErrorBasic)
{
db::NetlistDeviceExtractorError error;
db::LogEntryData error;
EXPECT_EQ (error.message (), "");
error.set_message ("x");
@ -47,12 +47,16 @@ TEST(1_NetlistDeviceExtractorErrorBasic)
error.set_geometry (db::DPolygon (db::DBox (0, 1, 2, 3)));
EXPECT_EQ (error.geometry ().to_string (), "(0,1;0,3;2,3;2,1)");
error = db::NetlistDeviceExtractorError ("cell2", "msg2");
error = db::LogEntryData (db::Error, "cell2", "msg2");
EXPECT_EQ (error.severity () == db::Error, true);
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 (), "()");
error.set_severity (db::Warning);
EXPECT_EQ (error.severity () == db::Warning, true);
}
namespace {
@ -71,7 +75,7 @@ namespace {
};
}
static std::string error2string (const db::NetlistDeviceExtractorError &e)
static std::string error2string (const db::LogEntryData &e)
{
return e.cell_name() + ":" + e.category_name () + ":" + e.category_description () + ":" +
e.geometry ().to_string () + ":" + e.message ();
@ -81,9 +85,9 @@ TEST(2_NetlistDeviceExtractorErrors)
{
DummyDeviceExtractor dummy_ex;
EXPECT_EQ (dummy_ex.has_errors (), true);
EXPECT_EQ (dummy_ex.begin_log_entries () != dummy_ex.end_log_entries (), true);
std::vector<db::NetlistDeviceExtractorError> errors (dummy_ex.begin_errors (), dummy_ex.end_errors ());
std::vector<db::LogEntryData> errors (dummy_ex.begin_log_entries (), dummy_ex.end_log_entries ());
EXPECT_EQ (int (errors.size ()), 4);
EXPECT_EQ (error2string (errors [0]), ":::():msg1");
EXPECT_EQ (error2string (errors [1]), ":::(0,1;0,3;2,3;2,1):msg2");

View File

@ -87,14 +87,14 @@ NetlistLogModel::NetlistLogModel (QWidget *parent, const db::NetlistCrossReferen
mp_lvsdb_messages = cross_ref ? &cross_ref->other_log_entries () : 0;
if (mp_lvsdb_messages) {
for (auto l = mp_lvsdb_messages->begin (); l != mp_lvsdb_messages->end (); ++l) {
m_max_severity = std::max (m_max_severity, l->severity);
m_max_severity = std::max (m_max_severity, l->severity ());
}
}
mp_l2n_messages = l2n ? &l2n->log_entries () : 0;
if (mp_l2n_messages) {
for (auto l = mp_l2n_messages->begin (); l != mp_l2n_messages->end (); ++l) {
m_max_severity = std::max (m_max_severity, l->severity);
m_max_severity = std::max (m_max_severity, l->severity ());
}
}
@ -104,7 +104,7 @@ NetlistLogModel::NetlistLogModel (QWidget *parent, const db::NetlistCrossReferen
const db::NetlistCrossReference::PerCircuitData *pcd = cross_ref->per_circuit_data_for (*i);
if (pcd && (i->first || i->second) && ! pcd->log_entries.empty ()) {
for (auto l = pcd->log_entries.begin (); l != pcd->log_entries.end (); ++l) {
m_max_severity = std::max (m_max_severity, l->severity);
m_max_severity = std::max (m_max_severity, l->severity ());
}
m_circuits.push_back (std::make_pair (*i, &pcd->log_entries));
}
@ -201,13 +201,13 @@ NetlistLogModel::data (const QModelIndex &index, int role) const
if (role == Qt::DecorationRole) {
if (le) {
return icon_for_severity (le->severity);
return icon_for_severity (le->severity ());
}
} else if (role == Qt::DisplayRole) {
if (le) {
return QVariant (tl::to_qstring (le->msg));
return QVariant (tl::to_qstring (le->to_string ()));
} else if (! index.parent ().isValid () && index.row () >= m_global_entries && index.row () < int (m_circuits.size ()) + m_global_entries) {
const std::pair<const db::Circuit *, const db::Circuit *> &cp = m_circuits [index.row () - m_global_entries].first;
if (! cp.first) {
@ -225,7 +225,7 @@ NetlistLogModel::data (const QModelIndex &index, int role) const
if (le) {
QFont f;
f.setBold (le->severity == db::Error);
f.setBold (le->severity () == db::Error);
return QVariant (f);
} else if (! index.parent ().isValid () && index.row () >= m_global_entries && index.row () < int (m_circuits.size ()) + m_global_entries) {
QFont f;
@ -237,9 +237,9 @@ NetlistLogModel::data (const QModelIndex &index, int role) const
if (! le) {
// ignore
} else if (le->severity == db::Error) {
} else if (le->severity () == db::Error) {
return QColor (255, 0, 0);
} else if (le->severity == db::Warning) {
} else if (le->severity () == db::Warning) {
return QColor (0, 0, 255);
}