From 1b4c81ac7b5154114cee2210500e050796b7bd24 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 24 Sep 2023 18:16:19 +0200 Subject: [PATCH] Rework: unifying device extractor logger entries and LayoutToNetlist ones --- src/db/db/db.pro | 1 + src/db/db/dbLayoutToNetlist.cc | 68 +++----- src/db/db/dbLayoutToNetlist.h | 29 ++- src/db/db/dbLayoutToNetlistFormatDefs.cc | 6 +- src/db/db/dbLayoutToNetlistFormatDefs.h | 25 ++- src/db/db/dbLayoutToNetlistReader.cc | 64 ++++++- src/db/db/dbLayoutToNetlistReader.h | 3 + src/db/db/dbLayoutToNetlistWriter.cc | 97 ++++++---- src/db/db/dbLayoutToNetlistWriter.h | 2 + src/db/db/dbLayoutVsSchematicReader.cc | 2 + src/db/db/dbLayoutVsSchematicWriter.cc | 6 +- src/db/db/dbLog.cc | 155 ++++++++++++++++ src/db/db/dbLog.h | 133 +++++++++++++- src/db/db/dbNetlistDeviceExtractor.cc | 100 +++-------- src/db/db/dbNetlistDeviceExtractor.h | 165 ++---------------- src/db/db/gsiDeclDbEdges.cc | 2 +- src/db/db/gsiDeclDbLayoutToNetlist.cc | 5 +- src/db/db/gsiDeclDbLog.cc | 117 +++++++++++++ src/db/db/gsiDeclDbNetlistCompare.cc | 18 +- src/db/db/gsiDeclDbNetlistDeviceExtractor.cc | 76 +------- .../dbNetlistDeviceExtractorTests.cc | 14 +- src/layui/layui/layNetlistLogModel.cc | 16 +- 22 files changed, 678 insertions(+), 426 deletions(-) create mode 100644 src/db/db/gsiDeclDbLog.cc diff --git a/src/db/db/db.pro b/src/db/db/db.pro index ac7f6ec76..3b5aa2b4e 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -123,6 +123,7 @@ SOURCES = \ gsiDeclDbLayoutUtils.cc \ gsiDeclDbLayoutQuery.cc \ gsiDeclDbLibrary.cc \ + gsiDeclDbLog.cc \ gsiDeclDbManager.cc \ gsiDeclDbMatrix.cc \ gsiDeclDbMetaInfo.cc \ diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index c0b3d965b..d70d3c04b 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -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) { diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index eaa149907..be1bb68c0 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -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 &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 &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); diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.cc b/src/db/db/dbLayoutToNetlistFormatDefs.cc index c317ac857..3c54a06d8 100644 --- a/src/db/db/dbLayoutToNetlistFormatDefs.cc +++ b/src/db/db/dbLayoutToNetlistFormatDefs.cc @@ -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"); } } diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.h b/src/db/db/dbLayoutToNetlistFormatDefs.h index ea09112ff..8f5ec1d7c 100644 --- a/src/db/db/dbLayoutToNetlistFormatDefs.h +++ b/src/db/db/dbLayoutToNetlistFormatDefs.h @@ -144,7 +144,7 @@ namespace db * coordinates are bottom/left and top/right * * [text]: - * text( [text] [coord]) - defines a rectangle [short key: J] + * text( [coord]) - defines a label [short key: J] * * [coord]: * - absolute coordinates @@ -182,15 +182,24 @@ namespace db * scale() - 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() - error description [short key: B] + * description() - message text [short key: B] + * + * [message-geometry]: + * polygon() - message geometry polygon in string-serialized form [short key: Q] + * + * [message-cell]: + * cell() - message cell [short key: C] + * + * [message-category]: + * cat( ?) - 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 struct DB_PUBLIC keys; diff --git a/src/db/db/dbLayoutToNetlistReader.cc b/src/db/db/dbLayoutToNetlistReader.cc index 5d44b714c..365e9d828 100644 --- a/src/db/db/dbLayoutToNetlistReader.cc +++ b/src/db/db/dbLayoutToNetlistReader.cc @@ -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) diff --git a/src/db/db/dbLayoutToNetlistReader.h b/src/db/db/dbLayoutToNetlistReader.h index 367e5c4e6..fcb8eb245 100644 --- a/src/db/db/dbLayoutToNetlistReader.h +++ b/src/db/db/dbLayoutToNetlistReader.h @@ -163,6 +163,9 @@ private: void read_geometries (db::NetlistObject *obj, Brace &br, db::LayoutToNetlist *l2n, db::local_cluster &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); }; } diff --git a/src/db/db/dbLayoutToNetlistWriter.cc b/src/db/db/dbLayoutToNetlistWriter.cc index 86e254a2f..3b2c2754c 100644 --- a/src/db/db/dbLayoutToNetlistWriter.cc +++ b/src/db/db/dbLayoutToNetlistWriter.cc @@ -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 +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::severity_to_s (const db::Severity severity) } } +template +void std_writer_impl::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::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::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 -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 void std_writer_impl::write (TokenizedOutput &stream, const db::Circuit &circuit, std::map > *net2id_per_circuit) { diff --git a/src/db/db/dbLayoutToNetlistWriter.h b/src/db/db/dbLayoutToNetlistWriter.h index 25c175f9f..26434e06b 100644 --- a/src/db/db/dbLayoutToNetlistWriter.h +++ b/src/db/db/dbLayoutToNetlistWriter.h @@ -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; diff --git a/src/db/db/dbLayoutVsSchematicReader.cc b/src/db/db/dbLayoutVsSchematicReader.cc index 1101d1d56..f486a19eb 100644 --- a/src/db/db/dbLayoutVsSchematicReader.cc +++ b/src/db/db/dbLayoutVsSchematicReader.cc @@ -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); } diff --git a/src/db/db/dbLayoutVsSchematicWriter.cc b/src/db/db/dbLayoutVsSchematicWriter.cc index 9060c5a99..f51bd291f 100644 --- a/src/db/db/dbLayoutVsSchematicWriter.cc +++ b/src/db/db/dbLayoutVsSchematicWriter.cc @@ -203,7 +203,8 @@ void std_writer_impl::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::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; } diff --git a/src/db/db/dbLog.cc b/src/db/db/dbLog.cc index b777f6c94..3d423a50b 100644 --- a/src/db/db/dbLog.cc +++ b/src/db/db/dbLog.cc @@ -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 m_strings; + std::map 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; +} } diff --git a/src/db/db/dbLog.h b/src/db/db/dbLog.h index d9aea2650..985558b6d 100644 --- a/src/db/db/dbLog.h +++ b/src/db/db/dbLog.h @@ -24,6 +24,7 @@ #define _HDR_dbLog #include "dbCommon.h" +#include "dbPolygon.h" #include @@ -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 diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index 04b39e4ff..581861ac7 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -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 (); } } diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index b3b6bbed8..d12369f7d 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -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 error_list; - typedef error_list::const_iterator error_iterator; + typedef std::list log_entry_list; + typedef log_entry_list::const_iterator log_entry_iterator; typedef std::vector layer_definitions; typedef layer_definitions::const_iterator layer_definitions_iterator; typedef std::map 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 m_layers; - error_list m_errors; + log_entry_list m_log_entries; std::map > m_new_devices; std::map > m_device_cells; diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 2994880b9..f1abfe620 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -1839,7 +1839,7 @@ gsi::EnumIn 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" ); diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index dfaa7046a..59915bdfe 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -712,7 +712,10 @@ Class 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 (), "[]"), gsi::arg ("texts", (db::Texts *) 0, "nil"), "@brief Runs an antenna check on the extracted clusters\n" "\n" diff --git a/src/db/db/gsiDeclDbLog.cc b/src/db/db/gsiDeclDbLog.cc new file mode 100644 index 000000000..621c8e848 --- /dev/null +++ b/src/db/db/gsiDeclDbLog.cc @@ -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 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 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 inject_SeverityEnum_into_LogEntryData (decl_Severity.defs ()); + +} diff --git a/src/db/db/gsiDeclDbNetlistCompare.cc b/src/db/db/gsiDeclDbNetlistCompare.cc index ed61e975a..f138cdfb8 100644 --- a/src/db/db/gsiDeclDbNetlistCompare.cc +++ b/src/db/db/gsiDeclDbNetlistCompare.cc @@ -657,21 +657,7 @@ Class decl_dbNetlistComparer ("db", "NetlistComparer", "This class has been introduced in version 0.26." ); -gsi::EnumIn 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 decl_Severity; +gsi::ClassExt inject_SeverityEnum_into_GenericNetlistCompareLogger (decl_Severity.defs ()); } diff --git a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc index 05b67a8e3..c7a214dca 100644 --- a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc +++ b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc @@ -156,76 +156,6 @@ Class decl_dbDeviceClassFactoryBase ("db", "DeviceClassF "This class has been introduced in version 0.27.3.\n" ); -Class 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 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 " diff --git a/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc b/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc index a3d4ac867..e810c286b 100644 --- a/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistDeviceExtractorTests.cc @@ -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 errors (dummy_ex.begin_errors (), dummy_ex.end_errors ()); + std::vector 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"); diff --git a/src/layui/layui/layNetlistLogModel.cc b/src/layui/layui/layNetlistLogModel.cc index c89ef2c22..387ccbc6c 100644 --- a/src/layui/layui/layNetlistLogModel.cc +++ b/src/layui/layui/layNetlistLogModel.cc @@ -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 &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); }