mirror of https://github.com/KLayout/klayout.git
Rework: unifying device extractor logger entries and LayoutToNetlist ones
This commit is contained in:
parent
a5bee51046
commit
1b4c81ac7b
|
|
@ -123,6 +123,7 @@ SOURCES = \
|
|||
gsiDeclDbLayoutUtils.cc \
|
||||
gsiDeclDbLayoutQuery.cc \
|
||||
gsiDeclDbLibrary.cc \
|
||||
gsiDeclDbLog.cc \
|
||||
gsiDeclDbManager.cc \
|
||||
gsiDeclDbMatrix.cc \
|
||||
gsiDeclDbMetaInfo.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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
||||
}
|
||||
|
|
@ -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 ());
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue