mirror of https://github.com/KLayout/klayout.git
L2N log entries with net references
* Log entries on the L2N object can now have net references
(by expanded name) and the nets will be highlighted
when the log entry is selected in the netlist browser
For an application see drcSimpleTests:147.
* New function ("db") in evaluate_nets
* BUGFIX: proper computation of transformations for multiple
selections of nets in netlist browser
This commit is contained in:
parent
7b002a1815
commit
38ddffc645
|
|
@ -188,7 +188,7 @@ namespace db
|
||||||
* scale(<mag>) - magnification (default is 1) [short key: S]
|
* scale(<mag>) - magnification (default is 1) [short key: S]
|
||||||
*
|
*
|
||||||
* [message-entry]:
|
* [message-entry]:
|
||||||
* message([severity] [message|message-geometry|message-cell|message-category|any]*) - message entry [short key: H]
|
* message([severity] [message|message-geometry|message-cell|message-category|message-net|any]*) - message entry [short key: H]
|
||||||
*
|
*
|
||||||
* [message]:
|
* [message]:
|
||||||
* description(<name>) - message text [short key: B]
|
* description(<name>) - message text [short key: B]
|
||||||
|
|
@ -199,6 +199,9 @@ namespace db
|
||||||
* [message-cell]:
|
* [message-cell]:
|
||||||
* cell(<name>) - message cell [short key: C]
|
* cell(<name>) - message cell [short key: C]
|
||||||
*
|
*
|
||||||
|
* [message-net]:
|
||||||
|
* net(<name>) - message net name [short key: N]
|
||||||
|
*
|
||||||
* [message-category]:
|
* [message-category]:
|
||||||
* cat(<name> <name>?) - message category with optional description [short key: X]
|
* cat(<name> <name>?) - message category with optional description [short key: X]
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,18 @@ bool LayoutToNetlistStandardReader::read_message_cell (std::string &cell_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LayoutToNetlistStandardReader::read_message_net (std::string &net_name)
|
||||||
|
{
|
||||||
|
if (test (skeys::net_key) || test (lkeys::net_key)) {
|
||||||
|
Brace br (this);
|
||||||
|
read_word_or_quoted (net_name);
|
||||||
|
br.done ();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool LayoutToNetlistStandardReader::read_message_geometry (db::DPolygon &polygon)
|
bool LayoutToNetlistStandardReader::read_message_geometry (db::DPolygon &polygon)
|
||||||
{
|
{
|
||||||
if (test (skeys::polygon_key) || test (lkeys::polygon_key)) {
|
if (test (skeys::polygon_key) || test (lkeys::polygon_key)) {
|
||||||
|
|
@ -258,7 +270,7 @@ bool LayoutToNetlistStandardReader::read_message_cat (std::string &category_name
|
||||||
void LayoutToNetlistStandardReader::read_message_entry (db::LogEntryData &data)
|
void LayoutToNetlistStandardReader::read_message_entry (db::LogEntryData &data)
|
||||||
{
|
{
|
||||||
Severity severity (db::NoSeverity);
|
Severity severity (db::NoSeverity);
|
||||||
std::string msg, cell_name, category_name, category_description;
|
std::string msg, cell_name, net_name, category_name, category_description;
|
||||||
db::DPolygon geometry;
|
db::DPolygon geometry;
|
||||||
|
|
||||||
Brace br (this);
|
Brace br (this);
|
||||||
|
|
@ -269,6 +281,8 @@ void LayoutToNetlistStandardReader::read_message_entry (db::LogEntryData &data)
|
||||||
// continue
|
// continue
|
||||||
} else if (read_message_cell (cell_name)) {
|
} else if (read_message_cell (cell_name)) {
|
||||||
// continue
|
// continue
|
||||||
|
} else if (read_message_net (net_name)) {
|
||||||
|
// continue
|
||||||
} else if (read_message_cat (category_name, category_description)) {
|
} else if (read_message_cat (category_name, category_description)) {
|
||||||
// continue
|
// continue
|
||||||
} else if (read_message_geometry (geometry)) {
|
} else if (read_message_geometry (geometry)) {
|
||||||
|
|
@ -282,6 +296,7 @@ void LayoutToNetlistStandardReader::read_message_entry (db::LogEntryData &data)
|
||||||
data.set_severity (severity);
|
data.set_severity (severity);
|
||||||
data.set_message (msg);
|
data.set_message (msg);
|
||||||
data.set_cell_name (cell_name);
|
data.set_cell_name (cell_name);
|
||||||
|
data.set_net_name (net_name);
|
||||||
data.set_category_description (category_description);
|
data.set_category_description (category_description);
|
||||||
data.set_category_name (category_name);
|
data.set_category_name (category_name);
|
||||||
data.set_geometry (geometry);
|
data.set_geometry (geometry);
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,7 @@ private:
|
||||||
db::Point read_point ();
|
db::Point read_point ();
|
||||||
void read_message_entry (db::LogEntryData &data);
|
void read_message_entry (db::LogEntryData &data);
|
||||||
bool read_message_cell (std::string &cell_name);
|
bool read_message_cell (std::string &cell_name);
|
||||||
|
bool read_message_net (std::string &net_name);
|
||||||
bool read_message_geometry (db::DPolygon &polygon);
|
bool read_message_geometry (db::DPolygon &polygon);
|
||||||
bool read_message_cat (std::string &category_name, std::string &category_description);
|
bool read_message_cat (std::string &category_name, std::string &category_description);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,10 @@ void std_writer_impl<Keys>::write_log_entry (TokenizedOutput &stream, const LogE
|
||||||
TokenizedOutput (stream, Keys::cell_key, true) << tl::to_word_or_quoted_string (le.cell_name ());
|
TokenizedOutput (stream, Keys::cell_key, true) << tl::to_word_or_quoted_string (le.cell_name ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! le.net_name ().empty ()) {
|
||||||
|
TokenizedOutput (stream, Keys::net_key, true) << tl::to_word_or_quoted_string (le.net_name ());
|
||||||
|
}
|
||||||
|
|
||||||
if (! le.category_name ().empty ()) {
|
if (! le.category_name ().empty ()) {
|
||||||
TokenizedOutput o (stream, Keys::cat_key, true);
|
TokenizedOutput o (stream, Keys::cat_key, true);
|
||||||
o << tl::to_word_or_quoted_string (le.category_name ());
|
o << tl::to_word_or_quoted_string (le.category_name ());
|
||||||
|
|
|
||||||
|
|
@ -81,19 +81,25 @@ static LogEntryStringRepository s_strings;
|
||||||
// LogEntryData implementation
|
// LogEntryData implementation
|
||||||
|
|
||||||
LogEntryData::LogEntryData ()
|
LogEntryData::LogEntryData ()
|
||||||
: m_severity (NoSeverity), m_cell_name (0), m_message (0), m_category_name (0), m_category_description (0)
|
: m_severity (NoSeverity), m_cell_name (0), m_net_name (0), m_message (0), m_category_name (0), m_category_description (0)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
LogEntryData::LogEntryData (Severity s, const std::string &msg)
|
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)
|
: m_severity (s), m_cell_name (0), m_net_name (0), m_message (s_strings.id_for_string (msg)), m_category_name (0), m_category_description (0)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
LogEntryData::LogEntryData (Severity s, const std::string &cell_name, const std::string &msg)
|
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)
|
: m_severity (s), m_cell_name (s_strings.id_for_string (cell_name)), m_net_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 &net_name, const std::string &msg)
|
||||||
|
: m_severity (s), m_cell_name (s_strings.id_for_string (cell_name)), m_net_name (s_strings.id_for_string (net_name)), m_message (s_strings.id_for_string (msg)), m_category_name (0), m_category_description (0)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
@ -104,6 +110,7 @@ LogEntryData::operator== (const LogEntryData &other) const
|
||||||
return m_severity == other.m_severity &&
|
return m_severity == other.m_severity &&
|
||||||
m_message == other.m_message &&
|
m_message == other.m_message &&
|
||||||
m_cell_name == other.m_cell_name &&
|
m_cell_name == other.m_cell_name &&
|
||||||
|
m_net_name == other.m_net_name &&
|
||||||
m_geometry == other.m_geometry &&
|
m_geometry == other.m_geometry &&
|
||||||
m_category_name == other.m_category_name &&
|
m_category_name == other.m_category_name &&
|
||||||
m_category_description == other.m_category_description;
|
m_category_description == other.m_category_description;
|
||||||
|
|
@ -157,6 +164,18 @@ LogEntryData::set_cell_name (const std::string &n)
|
||||||
m_cell_name = s_strings.id_for_string (n);
|
m_cell_name = s_strings.id_for_string (n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &
|
||||||
|
LogEntryData::net_name () const
|
||||||
|
{
|
||||||
|
return s_strings.string_for_id (m_net_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LogEntryData::set_net_name (const std::string &n)
|
||||||
|
{
|
||||||
|
m_net_name = s_strings.id_for_string (n);
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
LogEntryData::to_string (bool with_geometry) const
|
LogEntryData::to_string (bool with_geometry) const
|
||||||
{
|
{
|
||||||
|
|
@ -179,10 +198,24 @@ LogEntryData::to_string (bool with_geometry) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cell_name != 0) {
|
if (m_net_name != 0) {
|
||||||
res += tl::to_string (tr ("In cell "));
|
if (m_cell_name != 0) {
|
||||||
res += cell_name ();
|
res += tl::to_string (tr ("In net "));
|
||||||
res += ": ";
|
res += net_name ();
|
||||||
|
res += tl::to_string (tr (" in circuit "));
|
||||||
|
res += cell_name ();
|
||||||
|
res += ": ";
|
||||||
|
} else {
|
||||||
|
res += tl::to_string (tr ("In net "));
|
||||||
|
res += net_name ();
|
||||||
|
res += ": ";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (m_cell_name != 0) {
|
||||||
|
res += tl::to_string (tr ("In cell "));
|
||||||
|
res += cell_name ();
|
||||||
|
res += ": ";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res += msg;
|
res += msg;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,11 @@ public:
|
||||||
*/
|
*/
|
||||||
LogEntryData (Severity s, const std::string &cell_name, const std::string &msg);
|
LogEntryData (Severity s, const std::string &cell_name, const std::string &msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates an error with the severity, a cell (circuit) name, a net name and a message
|
||||||
|
*/
|
||||||
|
LogEntryData (Severity s, const std::string &cell_name, const std::string &net_name, const std::string &msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Equality
|
* @brief Equality
|
||||||
*/
|
*/
|
||||||
|
|
@ -158,6 +163,16 @@ public:
|
||||||
*/
|
*/
|
||||||
void set_cell_name (const std::string &n);
|
void set_cell_name (const std::string &n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the net name the error occurred in
|
||||||
|
*/
|
||||||
|
const std::string &net_name () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the net name
|
||||||
|
*/
|
||||||
|
void set_net_name (const std::string &n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Formats this message for printing
|
* @brief Formats this message for printing
|
||||||
*/
|
*/
|
||||||
|
|
@ -166,6 +181,7 @@ public:
|
||||||
private:
|
private:
|
||||||
Severity m_severity;
|
Severity m_severity;
|
||||||
string_id_type m_cell_name;
|
string_id_type m_cell_name;
|
||||||
|
string_id_type m_net_name;
|
||||||
string_id_type m_message;
|
string_id_type m_message;
|
||||||
db::DPolygon m_geometry;
|
db::DPolygon m_geometry;
|
||||||
string_id_type m_category_name, m_category_description;
|
string_id_type m_category_name, m_category_description;
|
||||||
|
|
|
||||||
|
|
@ -492,6 +492,28 @@ private:
|
||||||
MeasureNetEval *mp_eval;
|
MeasureNetEval *mp_eval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NetDbFunction
|
||||||
|
: public tl::EvalFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetDbFunction (MeasureNetEval *eval)
|
||||||
|
: mp_eval (eval)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void execute (const tl::ExpressionParserContext &context, tl::Variant &out, const std::vector<tl::Variant> &args, const std::map<std::string, tl::Variant> * /*kwargs*/) const
|
||||||
|
{
|
||||||
|
if (args.size () != 0) {
|
||||||
|
throw tl::EvalError (tl::to_string (tr ("'db' function does not take any argument")), context);
|
||||||
|
}
|
||||||
|
out = mp_eval->db_func ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MeasureNetEval *mp_eval;
|
||||||
|
};
|
||||||
|
|
||||||
class NetFunction
|
class NetFunction
|
||||||
: public tl::EvalFunction
|
: public tl::EvalFunction
|
||||||
{
|
{
|
||||||
|
|
@ -558,7 +580,7 @@ private:
|
||||||
MeasureNetEval *mp_eval;
|
MeasureNetEval *mp_eval;
|
||||||
};
|
};
|
||||||
|
|
||||||
MeasureNetEval::MeasureNetEval (const db::LayoutToNetlist *l2n, double dbu)
|
MeasureNetEval::MeasureNetEval (LayoutToNetlist *l2n, double dbu)
|
||||||
: tl::Eval (), mp_l2n (l2n), m_dbu (dbu)
|
: tl::Eval (), mp_l2n (l2n), m_dbu (dbu)
|
||||||
{
|
{
|
||||||
m_copy_merge = false;
|
m_copy_merge = false;
|
||||||
|
|
@ -588,6 +610,7 @@ MeasureNetEval::init ()
|
||||||
define_function ("area", new NetAreaFunction (this));
|
define_function ("area", new NetAreaFunction (this));
|
||||||
define_function ("perimeter", new NetPerimeterFunction (this));
|
define_function ("perimeter", new NetPerimeterFunction (this));
|
||||||
define_function ("net", new NetFunction (this));
|
define_function ("net", new NetFunction (this));
|
||||||
|
define_function ("db", new NetDbFunction (this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -701,4 +724,10 @@ MeasureNetEval::net_func () const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tl::Variant
|
||||||
|
MeasureNetEval::db_func () const
|
||||||
|
{
|
||||||
|
return tl::Variant::make_variant_ref (mp_l2n);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ class DB_PUBLIC MeasureNetEval
|
||||||
: public tl::Eval
|
: public tl::Eval
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MeasureNetEval (const db::LayoutToNetlist *l2n, double dbu);
|
MeasureNetEval (db::LayoutToNetlist *l2n, double dbu);
|
||||||
|
|
||||||
void set_primary_layer (unsigned int layer_index);
|
void set_primary_layer (unsigned int layer_index);
|
||||||
void set_secondary_layer (const std::string &name, unsigned int layer_index);
|
void set_secondary_layer (const std::string &name, unsigned int layer_index);
|
||||||
|
|
@ -144,6 +144,7 @@ private:
|
||||||
friend class NetAreaFunction;
|
friend class NetAreaFunction;
|
||||||
friend class NetPerimeterFunction;
|
friend class NetPerimeterFunction;
|
||||||
friend class NetFunction;
|
friend class NetFunction;
|
||||||
|
friend class NetDbFunction;
|
||||||
friend class NetSkipFunction;
|
friend class NetSkipFunction;
|
||||||
friend class NetCopyFunction;
|
friend class NetCopyFunction;
|
||||||
|
|
||||||
|
|
@ -153,7 +154,7 @@ private:
|
||||||
double area, perimeter;
|
double area, perimeter;
|
||||||
};
|
};
|
||||||
|
|
||||||
const db::LayoutToNetlist *mp_l2n;
|
db::LayoutToNetlist *mp_l2n;
|
||||||
double m_dbu;
|
double m_dbu;
|
||||||
std::vector<unsigned int> m_layers;
|
std::vector<unsigned int> m_layers;
|
||||||
mutable std::vector<unsigned int> m_copy_layers;
|
mutable std::vector<unsigned int> m_copy_layers;
|
||||||
|
|
@ -173,6 +174,7 @@ private:
|
||||||
tl::Variant perimeter_func (int layer_index) const;
|
tl::Variant perimeter_func (int layer_index) const;
|
||||||
void copy_func (const std::vector<unsigned int> &layer_indexes, bool merge, size_t max_polygons) const;
|
void copy_func (const std::vector<unsigned int> &layer_indexes, bool merge, size_t max_polygons) const;
|
||||||
tl::Variant net_func () const;
|
tl::Variant net_func () const;
|
||||||
|
tl::Variant db_func () const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1251,6 +1251,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
||||||
"@li 'skip' or 'skip(flag)': will skip the primary shapes of that net when called with a true value or without one. See also 'copy'. @/li\n"
|
"@li 'skip' or 'skip(flag)': will skip the primary shapes of that net when called with a true value or without one. See also 'copy'. @/li\n"
|
||||||
"@li 'copy(...)': see below for details @/li\n"
|
"@li 'copy(...)': see below for details @/li\n"
|
||||||
"@li 'net': the \\Net object of the current net @/li\n"
|
"@li 'net': the \\Net object of the current net @/li\n"
|
||||||
|
"@li 'db': the \\LayoutToDatabase object the netlist lives in @/li\n"
|
||||||
"@/ul\n"
|
"@/ul\n"
|
||||||
"\n"
|
"\n"
|
||||||
"If given, the 'dbu' argument gives the database unit to use for converting shape dimensions into micrometer units. "
|
"If given, the 'dbu' argument gives the database unit to use for converting shape dimensions into micrometer units. "
|
||||||
|
|
@ -1294,7 +1295,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
||||||
"where the second expression establishes 'skip' as the default and conditionally executes 'copy',\n"
|
"where the second expression establishes 'skip' as the default and conditionally executes 'copy',\n"
|
||||||
"overriding 'skip'.\n"
|
"overriding 'skip'.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The 'copy' function was added and the 'skip' argument was made optional in version 0.30.6."
|
"The 'copy' and 'db' functions were added and the 'skip' argument was made optional in version 0.30.6."
|
||||||
) +
|
) +
|
||||||
// test API
|
// test API
|
||||||
gsi::method ("make_soft_connection_diodes=", &db::LayoutToNetlist::set_make_soft_connection_diodes, gsi::arg ("flag"), "@hide") +
|
gsi::method ("make_soft_connection_diodes=", &db::LayoutToNetlist::set_make_soft_connection_diodes, gsi::arg ("flag"), "@hide") +
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,53 @@
|
||||||
#include "gsiDecl.h"
|
#include "gsiDecl.h"
|
||||||
#include "gsiEnums.h"
|
#include "gsiEnums.h"
|
||||||
#include "dbLog.h"
|
#include "dbLog.h"
|
||||||
|
#include "dbNet.h"
|
||||||
|
#include "dbCircuit.h"
|
||||||
|
|
||||||
namespace gsi
|
namespace gsi
|
||||||
{
|
{
|
||||||
|
|
||||||
|
db::LogEntryData *new_le1 (db::Severity severity, const std::string &msg)
|
||||||
|
{
|
||||||
|
return new db::LogEntryData (severity, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
db::LogEntryData *new_le2 (db::Severity severity, const std::string &cell_name, const std::string &msg)
|
||||||
|
{
|
||||||
|
return new db::LogEntryData (severity, cell_name, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
db::LogEntryData *new_le3 (db::Severity severity, const std::string &cell_name, const std::string &net_name, const std::string &msg)
|
||||||
|
{
|
||||||
|
return new db::LogEntryData (severity, cell_name, net_name, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
db::LogEntryData *new_le4 (db::Severity severity, const db::Net *net, const std::string &msg)
|
||||||
|
{
|
||||||
|
if (! net || ! net->circuit ()) {
|
||||||
|
return new db::LogEntryData (severity, msg);
|
||||||
|
} else {
|
||||||
|
return new db::LogEntryData (severity, net->circuit ()->name (), net->expanded_name (), msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Class<db::LogEntryData> decl_dbNetlistDeviceExtractorError ("db", "LogEntryData",
|
Class<db::LogEntryData> decl_dbNetlistDeviceExtractorError ("db", "LogEntryData",
|
||||||
|
gsi::constructor ("new", &new_le1, gsi::arg ("severity"), gsi::arg ("msg"),
|
||||||
|
"@brief Creates a new LogEntry object with the given severity and message\n"
|
||||||
|
"This convenience constructor has been added in version 0.30.6\n"
|
||||||
|
) +
|
||||||
|
gsi::constructor ("new", &new_le2, gsi::arg ("severity"), gsi::arg ("cell_name"), gsi::arg ("msg"),
|
||||||
|
"@brief Creates a new LogEntry object with the given severity, cell or circuit name and message\n"
|
||||||
|
"This convenience constructor has been added in version 0.30.6\n"
|
||||||
|
) +
|
||||||
|
gsi::constructor ("new", &new_le3, gsi::arg ("severity"), gsi::arg ("cell_name"), gsi::arg ("new_name"), gsi::arg ("msg"),
|
||||||
|
"@brief Creates a new LogEntry object with the given severity, cell or circuit name, net name and message\n"
|
||||||
|
"This convenience constructor has been added in version 0.30.6\n"
|
||||||
|
) +
|
||||||
|
gsi::constructor ("new", &new_le4, gsi::arg ("severity"), gsi::arg ("net"), gsi::arg ("msg"),
|
||||||
|
"@brief Creates a new LogEntry object with the given severity and message and circuit and net name taken from the given \\Net object\n"
|
||||||
|
"This convenience constructor has been added in version 0.30.6\n"
|
||||||
|
) +
|
||||||
gsi::method ("severity", &db::LogEntryData::severity,
|
gsi::method ("severity", &db::LogEntryData::severity,
|
||||||
"@brief Gets the severity attribute.\n"
|
"@brief Gets the severity attribute.\n"
|
||||||
) +
|
) +
|
||||||
|
|
@ -51,6 +93,21 @@ Class<db::LogEntryData> decl_dbNetlistDeviceExtractorError ("db", "LogEntryData"
|
||||||
"warning generated during device extraction, the cell name is "
|
"warning generated during device extraction, the cell name is "
|
||||||
"the circuit the device should have appeared in."
|
"the circuit the device should have appeared in."
|
||||||
) +
|
) +
|
||||||
|
gsi::method ("net_name", &db::LogEntryData::net_name,
|
||||||
|
"@brief Gets the net name.\n"
|
||||||
|
"See \\net_name= for details about this attribute."
|
||||||
|
"\n"
|
||||||
|
"The net_name attribute has been introduced in version 0.30.6.\n"
|
||||||
|
) +
|
||||||
|
gsi::method ("net_name=", &db::LogEntryData::set_net_name, gsi::arg ("net_name"),
|
||||||
|
"@brief Sets the net name.\n"
|
||||||
|
"The net (or circuit) name specifies the net the "
|
||||||
|
"log entry is related to.\n"
|
||||||
|
"\n"
|
||||||
|
"By convention, the net name is the expanded net name (see \\Net#expanded_name).\n"
|
||||||
|
"\n"
|
||||||
|
"The net_name attribute has been introduced in version 0.30.6.\n"
|
||||||
|
) +
|
||||||
gsi::method ("geometry", &db::LogEntryData::geometry,
|
gsi::method ("geometry", &db::LogEntryData::geometry,
|
||||||
"@brief Gets the geometry.\n"
|
"@brief Gets the geometry.\n"
|
||||||
"See \\geometry= for more details."
|
"See \\geometry= for more details."
|
||||||
|
|
|
||||||
|
|
@ -807,6 +807,7 @@ module DRC
|
||||||
#
|
#
|
||||||
# @ul
|
# @ul
|
||||||
# @li "net" - the RBA::Net object of the current net @/li
|
# @li "net" - the RBA::Net object of the current net @/li
|
||||||
|
# @li "db" - the RBA::LayoutToNetlist object the netlist lives in @/li
|
||||||
# @li "skip" or "skip(flag)" - if called with a 'true' argument (the default), the primary layer's shapes are not copied for this net @/li
|
# @li "skip" or "skip(flag)" - if called with a 'true' argument (the default), the primary layer's shapes are not copied for this net @/li
|
||||||
# @li "copy(...)" - configures polygon output in a more elaborate way than "skip" (see below) @/li
|
# @li "copy(...)" - configures polygon output in a more elaborate way than "skip" (see below) @/li
|
||||||
# @li "put(name, value)" - places the value as a property with name 'name' (this must be a string) on the output shapes @/li
|
# @li "put(name, value)" - places the value as a property with name 'name' (this must be a string) on the output shapes @/li
|
||||||
|
|
|
||||||
|
|
@ -2076,3 +2076,35 @@ TEST(146d_edges_and_corners)
|
||||||
run_test (_this, "146", true);
|
run_test (_this, "146", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(147_MeasureNetsWithL2N)
|
||||||
|
{
|
||||||
|
std::string rs = tl::testdata ();
|
||||||
|
rs += "/drc/drcSimpleTests_147.drc";
|
||||||
|
|
||||||
|
std::string input = tl::testdata ();
|
||||||
|
input += "/drc/drcSimpleTests_147.gds";
|
||||||
|
|
||||||
|
std::string au_output = tl::testdata ();
|
||||||
|
au_output += "/drc/drcSimpleTests_au147.l2n";
|
||||||
|
|
||||||
|
std::string output = this->tmp_file ("tmp.l2n");
|
||||||
|
|
||||||
|
{
|
||||||
|
// Set some variables
|
||||||
|
lym::Macro config;
|
||||||
|
config.set_text (tl::sprintf (
|
||||||
|
"$drc_test_source = '%s'\n"
|
||||||
|
"$drc_test_target = '%s'\n"
|
||||||
|
, input, output)
|
||||||
|
);
|
||||||
|
config.set_interpreter (lym::Macro::Ruby);
|
||||||
|
EXPECT_EQ (config.run (), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lym::Macro drc;
|
||||||
|
drc.load_from (rs);
|
||||||
|
EXPECT_EQ (drc.run (), 0);
|
||||||
|
|
||||||
|
compare_text_files (output, au_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,24 @@ struct test_arg_func<gsi::VariantType>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct test_arg_func<gsi::StringType>
|
||||||
|
{
|
||||||
|
void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType & /*atype*/, bool /*loose*/, bool /*object_substitution*/)
|
||||||
|
{
|
||||||
|
*ret = arg.is_a_string ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct test_arg_func<gsi::ByteArrayType>
|
||||||
|
{
|
||||||
|
void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType & /*atype*/, bool /*loose*/, bool /*object_substitution*/)
|
||||||
|
{
|
||||||
|
*ret = arg.is_a_bytearray ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct test_arg_func<gsi::ObjectType>
|
struct test_arg_func<gsi::ObjectType>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -816,15 +816,31 @@ NetlistBrowserPage::log_selection_changed ()
|
||||||
|
|
||||||
QModelIndexList selection = log_view->selectionModel ()->selectedIndexes ();
|
QModelIndexList selection = log_view->selectionModel ()->selectedIndexes ();
|
||||||
for (QModelIndexList::const_iterator i = selection.begin (); i != selection.end (); ++i) {
|
for (QModelIndexList::const_iterator i = selection.begin (); i != selection.end (); ++i) {
|
||||||
if (i->column () == 0) {
|
|
||||||
const db::LogEntryData *le = model->log_entry (*i);
|
if (i->column () != 0) {
|
||||||
if (le && le->geometry () != db::DPolygon () && ! le->cell_name ().empty ()) {
|
continue;
|
||||||
const db::Circuit *c = mp_database->netlist ()->circuit_by_name (le->cell_name ());
|
}
|
||||||
if (c) {
|
|
||||||
m_markers.push_back (std::make_pair (c, le->geometry ()));
|
const db::LogEntryData *le = model->log_entry (*i);
|
||||||
}
|
|
||||||
|
const db::Circuit *c = 0;
|
||||||
|
if (le && ! le->cell_name ().empty ()) {
|
||||||
|
c = mp_database->netlist ()->circuit_by_name (le->cell_name ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// highlight geometries
|
||||||
|
if (c && le->geometry () != db::DPolygon ()) {
|
||||||
|
m_markers.push_back (std::make_pair (c, le->geometry ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// highlight nets
|
||||||
|
if (c && ! le->net_name ().empty ()) {
|
||||||
|
const db::Net *net = c->net_by_name (le->net_name ());
|
||||||
|
if (net) {
|
||||||
|
m_net_markers.push_back (std::make_pair (c, net));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_highlights ();
|
update_highlights ();
|
||||||
|
|
@ -1291,6 +1307,7 @@ NetlistBrowserPage::clear_highlights ()
|
||||||
m_current_path = lay::NetlistObjectsPath ();
|
m_current_path = lay::NetlistObjectsPath ();
|
||||||
m_selected_paths.clear ();
|
m_selected_paths.clear ();
|
||||||
m_markers.clear ();
|
m_markers.clear ();
|
||||||
|
m_net_markers.clear ();
|
||||||
|
|
||||||
update_highlights ();
|
update_highlights ();
|
||||||
}
|
}
|
||||||
|
|
@ -1350,6 +1367,31 @@ bbox_for_circuit (const db::Layout *layout, const db::Circuit *circuit)
|
||||||
return layout->cell (circuit->cell_index ()).bbox ();
|
return layout->cell (circuit->cell_index ()).bbox ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static db::Box
|
||||||
|
bbox_for_net (const db::LayoutToNetlist *db, const db::Circuit *circuit, const db::Net *net)
|
||||||
|
{
|
||||||
|
db::Box bbox;
|
||||||
|
|
||||||
|
db::cell_index_type cell_index = circuit->cell_index ();
|
||||||
|
size_t cluster_id = net->cluster_id ();
|
||||||
|
|
||||||
|
const db::Connectivity &conn = db->connectivity ();
|
||||||
|
for (db::Connectivity::all_layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
|
||||||
|
|
||||||
|
db::Box layer_bbox;
|
||||||
|
db::recursive_cluster_shape_iterator<db::NetShape> shapes (db->net_clusters (), *layer, cell_index, cluster_id);
|
||||||
|
while (! shapes.at_end ()) {
|
||||||
|
layer_bbox += shapes->bbox ().transformed (shapes.trans ());
|
||||||
|
++shapes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bbox += layer_bbox;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetlistBrowserPage::adjust_view ()
|
NetlistBrowserPage::adjust_view ()
|
||||||
{
|
{
|
||||||
|
|
@ -1425,22 +1467,7 @@ NetlistBrowserPage::adjust_view ()
|
||||||
|
|
||||||
} else if (net) {
|
} else if (net) {
|
||||||
|
|
||||||
db::cell_index_type cell_index = net->circuit ()->cell_index ();
|
ebox += bbox_for_net (mp_database.get (), circuit, net);
|
||||||
size_t cluster_id = net->cluster_id ();
|
|
||||||
|
|
||||||
const db::Connectivity &conn = mp_database->connectivity ();
|
|
||||||
for (db::Connectivity::all_layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
|
|
||||||
|
|
||||||
db::Box layer_bbox;
|
|
||||||
db::recursive_cluster_shape_iterator<db::NetShape> shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id);
|
|
||||||
while (! shapes.at_end ()) {
|
|
||||||
layer_bbox += shapes->bbox ().transformed (shapes.trans ());
|
|
||||||
++shapes;
|
|
||||||
}
|
|
||||||
|
|
||||||
ebox += layer_bbox;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (circuit) {
|
} else if (circuit) {
|
||||||
ebox += bbox_for_circuit (layout, circuit);
|
ebox += bbox_for_circuit (layout, circuit);
|
||||||
|
|
@ -1461,6 +1488,17 @@ NetlistBrowserPage::adjust_view ()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add net markers boxes
|
||||||
|
|
||||||
|
for (auto marker = m_net_markers.begin (); marker != m_net_markers.end (); ++marker) {
|
||||||
|
|
||||||
|
std::pair<bool, db::DCplxTrans> tr = trans_for (marker->first, *layout, *cell, m_cell_context_cache, cv.context_dtrans ());
|
||||||
|
if (tr.first) {
|
||||||
|
bbox += tr.second * db::CplxTrans (layout->dbu ()) * bbox_for_net (mp_database.get (), marker->first, marker->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (! bbox.empty ()) {
|
if (! bbox.empty ()) {
|
||||||
|
|
||||||
std::vector<db::DCplxTrans> tv = mp_view->cv_transform_variants (m_cv_index);
|
std::vector<db::DCplxTrans> tv = mp_view->cv_transform_variants (m_cv_index);
|
||||||
|
|
@ -1739,26 +1777,52 @@ NetlistBrowserPage::update_highlights ()
|
||||||
// a map of display properties vs. layer properties
|
// a map of display properties vs. layer properties
|
||||||
|
|
||||||
// correct DBU differences between the storage layout and the original layout
|
// correct DBU differences between the storage layout and the original layout
|
||||||
for (std::vector<db::DCplxTrans>::iterator t = tv.begin (); t != tv.end (); ++t) {
|
std::vector<db::DCplxTrans> tvt = tv;
|
||||||
|
for (std::vector<db::DCplxTrans>::iterator t = tvt.begin (); t != tvt.end (); ++t) {
|
||||||
*t = *t * trans * db::DCplxTrans (layout->dbu () / original_layout.dbu ());
|
*t = *t * trans * db::DCplxTrans (layout->dbu () / original_layout.dbu ());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path->net.first) {
|
if (path->net.first) {
|
||||||
if (produce_highlights_for_net (path->net.first, n_markers, display_by_lp, tv)) {
|
if (produce_highlights_for_net (path->net.first, n_markers, display_by_lp, tvt)) {
|
||||||
not_all_shapes_are_shown = true;
|
not_all_shapes_are_shown = true;
|
||||||
}
|
}
|
||||||
} else if (path->device.first) {
|
} else if (path->device.first) {
|
||||||
if (produce_highlights_for_device (path->device.first, n_markers, tv)) {
|
if (produce_highlights_for_device (path->device.first, n_markers, tvt)) {
|
||||||
not_all_shapes_are_shown = true;
|
not_all_shapes_are_shown = true;
|
||||||
}
|
}
|
||||||
} else if (circuit) {
|
} else if (circuit) {
|
||||||
if (produce_highlights_for_circuit (circuit, n_markers, tv)) {
|
if (produce_highlights_for_circuit (circuit, n_markers, tvt)) {
|
||||||
not_all_shapes_are_shown = true;
|
not_all_shapes_are_shown = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto marker = m_net_markers.begin (); marker != m_net_markers.end (); ++marker) {
|
||||||
|
|
||||||
|
// computes the transformation supplied by the path
|
||||||
|
|
||||||
|
std::pair<bool, db::DCplxTrans> tr = trans_for (marker->first, *layout, *cell, m_cell_context_cache, cv.context_dtrans ());
|
||||||
|
if (! tr.first) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
db::DCplxTrans trans = tr.second;
|
||||||
|
|
||||||
|
// a map of display properties vs. layer properties
|
||||||
|
|
||||||
|
// correct DBU differences between the storage layout and the original layout
|
||||||
|
std::vector<db::DCplxTrans> tvt = tv;
|
||||||
|
for (std::vector<db::DCplxTrans>::iterator t = tvt.begin (); t != tvt.end (); ++t) {
|
||||||
|
*t = *t * trans * db::DCplxTrans (layout->dbu () / original_layout.dbu ());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (produce_highlights_for_net (marker->second, n_markers, display_by_lp, tvt)) {
|
||||||
|
not_all_shapes_are_shown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for (auto marker = m_markers.begin (); marker != m_markers.end (); ++marker) {
|
for (auto marker = m_markers.begin (); marker != m_markers.end (); ++marker) {
|
||||||
|
|
||||||
// computes the transformation supplied by the path
|
// computes the transformation supplied by the path
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,7 @@ private:
|
||||||
lay::NetlistObjectsPath m_current_path;
|
lay::NetlistObjectsPath m_current_path;
|
||||||
std::vector<lay::NetlistObjectsPath> m_selected_paths;
|
std::vector<lay::NetlistObjectsPath> m_selected_paths;
|
||||||
std::vector<std::pair<const db::Circuit *, db::DPolygon> > m_markers;
|
std::vector<std::pair<const db::Circuit *, db::DPolygon> > m_markers;
|
||||||
|
std::vector<std::pair<const db::Circuit *, const db::Net *> > m_net_markers;
|
||||||
lay::NetInfoDialog *mp_info_dialog;
|
lay::NetInfoDialog *mp_info_dialog;
|
||||||
tl::DeferredMethod<NetlistBrowserPage> dm_update_highlights;
|
tl::DeferredMethod<NetlistBrowserPage> dm_update_highlights;
|
||||||
tl::DeferredMethod<NetlistBrowserPage> dm_rerun_macro;
|
tl::DeferredMethod<NetlistBrowserPage> dm_rerun_macro;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
source $drc_test_source
|
||||||
|
report_netlist $drc_test_target
|
||||||
|
|
||||||
|
deep
|
||||||
|
|
||||||
|
l1 = input(1, 0)
|
||||||
|
l2 = input(2, 0)
|
||||||
|
l3 = input(3, 0)
|
||||||
|
l4 = input(4, 0)
|
||||||
|
l5 = input(5, 0)
|
||||||
|
|
||||||
|
connect(l1, l2)
|
||||||
|
connect(l2, l3)
|
||||||
|
connect(l3, l4)
|
||||||
|
connect(l4, l5)
|
||||||
|
|
||||||
|
l1.output(1, 0)
|
||||||
|
l2.output(2, 0)
|
||||||
|
l3.output(3, 0)
|
||||||
|
l4.output(4, 0)
|
||||||
|
l5.output(5, 0)
|
||||||
|
|
||||||
|
netlist
|
||||||
|
|
||||||
|
sec = { "l2" => l2, "l3" => l3, "l4" => l4, "l5" => l5 }
|
||||||
|
|
||||||
|
script = <<"END"
|
||||||
|
skip;
|
||||||
|
var ar=area(l5)/area;
|
||||||
|
db.add_log_entry(LogEntryData.new(Severity.Info, net, 'AR='+to_s(ar)))
|
||||||
|
END
|
||||||
|
|
||||||
|
evaluate_nets(l1, sec, script, { "n" => "NET1" })
|
||||||
|
|
||||||
|
netlist
|
||||||
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,74 @@
|
||||||
|
#%l2n-klayout
|
||||||
|
W(TOP)
|
||||||
|
U(0.001)
|
||||||
|
L(l1 '1/0')
|
||||||
|
L(l2 '2/0')
|
||||||
|
L(l3 '3/0')
|
||||||
|
L(l4 '4/0')
|
||||||
|
L(l5 '5/0')
|
||||||
|
C(l1 l1 l2)
|
||||||
|
C(l2 l1 l2 l3)
|
||||||
|
C(l3 l2 l3 l4)
|
||||||
|
C(l4 l3 l4 l5)
|
||||||
|
C(l5 l4 l5)
|
||||||
|
H(I B('AR=5') C(B) N(NET1))
|
||||||
|
H(I B('AR=0') C(B) N($4))
|
||||||
|
H(I B('AR=9.875') C(TOP) N($1))
|
||||||
|
H(I B('AR=9.5') C(TOP) N($I2))
|
||||||
|
X(A
|
||||||
|
R((0 0) (38000 12000))
|
||||||
|
N(1 I(NET2)
|
||||||
|
R(l1 (0 8000) (4000 4000))
|
||||||
|
R(l2 (-3000 -3000) (2000 2000))
|
||||||
|
R(l3 (-3000 -11000) (4000 12000))
|
||||||
|
R(l4 (-3000 -11000) (2000 2000))
|
||||||
|
R(l5 (-3000 -3000) (38000 4000))
|
||||||
|
R(l5 (-22000 -2000) (0 0))
|
||||||
|
)
|
||||||
|
P(1 I(NET2))
|
||||||
|
)
|
||||||
|
X(B
|
||||||
|
R((-8000 -14000) (48000 34000))
|
||||||
|
N(1 I(NET1)
|
||||||
|
R(l1 (12000 8000) (4000 4000))
|
||||||
|
R(l1 (-10000 -14000) (4000 4000))
|
||||||
|
R(l2 (3000 7000) (2000 2000))
|
||||||
|
R(l2 (-8000 -12000) (2000 2000))
|
||||||
|
R(l3 (3000 -3000) (4000 14000))
|
||||||
|
R(l3 (-10000 -14000) (10000 4000))
|
||||||
|
R(l4 (-3000 -3000) (2000 2000))
|
||||||
|
R(l5 (-3000 -15000) (4000 16000))
|
||||||
|
R(l5 (14000 -16000) (10000 4000))
|
||||||
|
R(l5 (-6000 -2000) (0 0))
|
||||||
|
)
|
||||||
|
N(2 I($2)
|
||||||
|
R(l3 (25000 -5000) (4000 7000))
|
||||||
|
R(l4 (-3000 -3000) (2000 2000))
|
||||||
|
R(l5 (-3000 -3000) (15000 4000))
|
||||||
|
)
|
||||||
|
N(3 I($4)
|
||||||
|
R(l1 (25000 -5000) (4000 18000))
|
||||||
|
)
|
||||||
|
N(4 I($5)
|
||||||
|
R(l3 (25000 6000) (4000 7000))
|
||||||
|
)
|
||||||
|
N(5 I($6)
|
||||||
|
R(l5 (25000 6000) (15000 4000))
|
||||||
|
)
|
||||||
|
N(6 I(NET2)
|
||||||
|
R(l5 (16000 18000) (0 0))
|
||||||
|
)
|
||||||
|
P(6 I(NET2))
|
||||||
|
X(1 A Y(-8000 -14000) P(0 1))
|
||||||
|
X(2 A M Y(-8000 20000) P(0 6))
|
||||||
|
)
|
||||||
|
X(TOP
|
||||||
|
R((-18000 -51000) (58000 108000))
|
||||||
|
N(1 I($1)
|
||||||
|
R(l5 (0 16000) (4000 11000))
|
||||||
|
)
|
||||||
|
N(2 I($I2))
|
||||||
|
X(1 B Y(0 0) P(0 1))
|
||||||
|
X(2 B O(180) Y(22000 43000) P(0 1))
|
||||||
|
X(3 B O(180) Y(22000 -31000) P(0 2))
|
||||||
|
)
|
||||||
|
|
@ -35,6 +35,11 @@ class DBLog_TestClass < TestBase
|
||||||
|
|
||||||
le = RBA::LogEntryData::new
|
le = RBA::LogEntryData::new
|
||||||
|
|
||||||
|
le.severity = RBA::LogEntryData::Error
|
||||||
|
assert_equal(le.severity.to_s, "Error")
|
||||||
|
le.severity = RBA::LogEntryData::NoSeverity
|
||||||
|
assert_equal(le.severity.to_s, "NoSeverity")
|
||||||
|
|
||||||
le.message = "message"
|
le.message = "message"
|
||||||
assert_equal(le.message, "message")
|
assert_equal(le.message, "message")
|
||||||
|
|
||||||
|
|
@ -52,6 +57,44 @@ class DBLog_TestClass < TestBase
|
||||||
|
|
||||||
assert_equal(le.to_s, "[the answer] In cell TOP: message, shape: (1,2;1,4;3,4;3,2)")
|
assert_equal(le.to_s, "[the answer] In cell TOP: message, shape: (1,2;1,4;3,4;3,2)")
|
||||||
|
|
||||||
|
le.net_name = "NET"
|
||||||
|
assert_equal(le.net_name, "NET")
|
||||||
|
|
||||||
|
assert_equal(le.to_s, "[the answer] In net NET in circuit TOP: message, shape: (1,2;1,4;3,4;3,2)")
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_2_LogConstructors
|
||||||
|
|
||||||
|
le = RBA::LogEntryData::new(RBA::LogEntryData::Error, "a message")
|
||||||
|
assert_equal(le.to_s, "a message")
|
||||||
|
|
||||||
|
assert_equal(le.severity.to_s, "Error")
|
||||||
|
|
||||||
|
le = RBA::LogEntryData::new(RBA::LogEntryData::Info, "CELL", "a message")
|
||||||
|
assert_equal(le.to_s, "In cell CELL: a message")
|
||||||
|
|
||||||
|
assert_equal(le.severity.to_s, "Info")
|
||||||
|
|
||||||
|
le = RBA::LogEntryData::new(RBA::LogEntryData::Warning, "CELL", "NET", "a message")
|
||||||
|
assert_equal(le.to_s, "In net NET in circuit CELL: a message")
|
||||||
|
|
||||||
|
assert_equal(le.severity.to_s, "Warning")
|
||||||
|
|
||||||
|
# Create a LogEntry from a Net object:
|
||||||
|
|
||||||
|
nl = RBA::Netlist::new
|
||||||
|
c = RBA::Circuit::new
|
||||||
|
c.name = "CIRCUIT"
|
||||||
|
nl.add(c)
|
||||||
|
# NOTE: no explicit name, but ID 0
|
||||||
|
net = c.create_net
|
||||||
|
|
||||||
|
le = RBA::LogEntryData::new(RBA::LogEntryData::Error, net, "a message")
|
||||||
|
assert_equal(le.to_s, "In net $0 in circuit CIRCUIT: a message")
|
||||||
|
|
||||||
|
assert_equal(le.severity.to_s, "Error")
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue