diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.h b/src/db/db/dbLayoutToNetlistFormatDefs.h index bea7dbd60..a9d18e078 100644 --- a/src/db/db/dbLayoutToNetlistFormatDefs.h +++ b/src/db/db/dbLayoutToNetlistFormatDefs.h @@ -188,7 +188,7 @@ namespace db * scale() - magnification (default is 1) [short key: S] * * [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]: * description() - message text [short key: B] @@ -199,6 +199,9 @@ namespace db * [message-cell]: * cell() - message cell [short key: C] * + * [message-net]: + * net() - message net name [short key: N] + * * [message-category]: * cat( ?) - message category with optional description [short key: X] * diff --git a/src/db/db/dbLayoutToNetlistReader.cc b/src/db/db/dbLayoutToNetlistReader.cc index 43b3850bd..3e65a1f38 100644 --- a/src/db/db/dbLayoutToNetlistReader.cc +++ b/src/db/db/dbLayoutToNetlistReader.cc @@ -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) { 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) { 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; Brace br (this); @@ -269,6 +281,8 @@ void LayoutToNetlistStandardReader::read_message_entry (db::LogEntryData &data) // continue } else if (read_message_cell (cell_name)) { // continue + } else if (read_message_net (net_name)) { + // continue } else if (read_message_cat (category_name, category_description)) { // continue } else if (read_message_geometry (geometry)) { @@ -282,6 +296,7 @@ void LayoutToNetlistStandardReader::read_message_entry (db::LogEntryData &data) data.set_severity (severity); data.set_message (msg); data.set_cell_name (cell_name); + data.set_net_name (net_name); data.set_category_description (category_description); data.set_category_name (category_name); data.set_geometry (geometry); diff --git a/src/db/db/dbLayoutToNetlistReader.h b/src/db/db/dbLayoutToNetlistReader.h index bc1230f66..cbfd57fff 100644 --- a/src/db/db/dbLayoutToNetlistReader.h +++ b/src/db/db/dbLayoutToNetlistReader.h @@ -164,6 +164,7 @@ private: db::Point read_point (); void read_message_entry (db::LogEntryData &data); 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_cat (std::string &category_name, std::string &category_description); }; diff --git a/src/db/db/dbLayoutToNetlistWriter.cc b/src/db/db/dbLayoutToNetlistWriter.cc index 0b734b7a0..35a250182 100644 --- a/src/db/db/dbLayoutToNetlistWriter.cc +++ b/src/db/db/dbLayoutToNetlistWriter.cc @@ -211,6 +211,10 @@ void std_writer_impl::write_log_entry (TokenizedOutput &stream, const LogE 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 ()) { TokenizedOutput o (stream, Keys::cat_key, true); o << tl::to_word_or_quoted_string (le.category_name ()); diff --git a/src/db/db/dbLog.cc b/src/db/db/dbLog.cc index 0a3c80fb5..58284d535 100644 --- a/src/db/db/dbLog.cc +++ b/src/db/db/dbLog.cc @@ -81,19 +81,25 @@ 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) + : m_severity (NoSeverity), m_cell_name (0), m_net_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) + : 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 .. } 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 .. } @@ -104,6 +110,7 @@ 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_net_name == other.m_net_name && m_geometry == other.m_geometry && m_category_name == other.m_category_name && 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); } +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 LogEntryData::to_string (bool with_geometry) const { @@ -179,10 +198,24 @@ LogEntryData::to_string (bool with_geometry) const } } - if (m_cell_name != 0) { - res += tl::to_string (tr ("In cell ")); - res += cell_name (); - res += ": "; + if (m_net_name != 0) { + if (m_cell_name != 0) { + res += tl::to_string (tr ("In net ")); + 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; diff --git a/src/db/db/dbLog.h b/src/db/db/dbLog.h index 85e60a587..d26009d28 100644 --- a/src/db/db/dbLog.h +++ b/src/db/db/dbLog.h @@ -68,6 +68,11 @@ public: */ 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 */ @@ -158,6 +163,16 @@ public: */ 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 */ @@ -166,6 +181,7 @@ public: private: Severity m_severity; string_id_type m_cell_name; + string_id_type m_net_name; string_id_type m_message; db::DPolygon m_geometry; string_id_type m_category_name, m_category_description; diff --git a/src/db/db/dbMeasureEval.cc b/src/db/db/dbMeasureEval.cc index 7bb2d45cc..d826868fc 100644 --- a/src/db/db/dbMeasureEval.cc +++ b/src/db/db/dbMeasureEval.cc @@ -492,6 +492,28 @@ private: 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 &args, const std::map * /*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 : public tl::EvalFunction { @@ -558,7 +580,7 @@ private: 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) { m_copy_merge = false; @@ -588,6 +610,7 @@ MeasureNetEval::init () define_function ("area", new NetAreaFunction (this)); define_function ("perimeter", new NetPerimeterFunction (this)); define_function ("net", new NetFunction (this)); + define_function ("db", new NetDbFunction (this)); } void @@ -701,4 +724,10 @@ MeasureNetEval::net_func () const } } +tl::Variant +MeasureNetEval::db_func () const +{ + return tl::Variant::make_variant_ref (mp_l2n); +} + } diff --git a/src/db/db/dbMeasureEval.h b/src/db/db/dbMeasureEval.h index 882d422fc..328891e90 100644 --- a/src/db/db/dbMeasureEval.h +++ b/src/db/db/dbMeasureEval.h @@ -122,7 +122,7 @@ class DB_PUBLIC MeasureNetEval : public tl::Eval { public: - MeasureNetEval (const db::LayoutToNetlist *l2n, double dbu); + MeasureNetEval (db::LayoutToNetlist *l2n, double dbu); void set_primary_layer (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 NetPerimeterFunction; friend class NetFunction; + friend class NetDbFunction; friend class NetSkipFunction; friend class NetCopyFunction; @@ -153,7 +154,7 @@ private: double area, perimeter; }; - const db::LayoutToNetlist *mp_l2n; + db::LayoutToNetlist *mp_l2n; double m_dbu; std::vector m_layers; mutable std::vector m_copy_layers; @@ -173,6 +174,7 @@ private: tl::Variant perimeter_func (int layer_index) const; void copy_func (const std::vector &layer_indexes, bool merge, size_t max_polygons) const; tl::Variant net_func () const; + tl::Variant db_func () const; }; } diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index 506e7dc32..36453908d 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -1251,6 +1251,7 @@ Class 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 'copy(...)': see below for details @/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" "\n" "If given, the 'dbu' argument gives the database unit to use for converting shape dimensions into micrometer units. " @@ -1294,7 +1295,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "where the second expression establishes 'skip' as the default and conditionally executes 'copy',\n" "overriding 'skip'.\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 gsi::method ("make_soft_connection_diodes=", &db::LayoutToNetlist::set_make_soft_connection_diodes, gsi::arg ("flag"), "@hide") + diff --git a/src/db/db/gsiDeclDbLog.cc b/src/db/db/gsiDeclDbLog.cc index 8c26282a8..171854868 100644 --- a/src/db/db/gsiDeclDbLog.cc +++ b/src/db/db/gsiDeclDbLog.cc @@ -23,11 +23,53 @@ #include "gsiDecl.h" #include "gsiEnums.h" #include "dbLog.h" +#include "dbNet.h" +#include "dbCircuit.h" 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 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, "@brief Gets the severity attribute.\n" ) + @@ -51,6 +93,21 @@ Class decl_dbNetlistDeviceExtractorError ("db", "LogEntryData" "warning generated during device extraction, the cell name is " "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, "@brief Gets the geometry.\n" "See \\geometry= for more details." diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb index efb9853ee..e5ec8f0a2 100644 --- a/src/drc/drc/built-in-macros/_drc_netter.rb +++ b/src/drc/drc/built-in-macros/_drc_netter.rb @@ -807,6 +807,7 @@ module DRC # # @ul # @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 "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 diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 6ccccb378..80199b2fb 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -2076,3 +2076,35 @@ TEST(146d_edges_and_corners) 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); +} + diff --git a/src/gsi/gsi/gsiVariantArgs.cc b/src/gsi/gsi/gsiVariantArgs.cc index 5e1b4ffb7..d8e565f33 100644 --- a/src/gsi/gsi/gsiVariantArgs.cc +++ b/src/gsi/gsi/gsiVariantArgs.cc @@ -75,6 +75,24 @@ struct test_arg_func } }; +template <> +struct test_arg_func +{ + 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 +{ + void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType & /*atype*/, bool /*loose*/, bool /*object_substitution*/) + { + *ret = arg.is_a_bytearray (); + } +}; + template <> struct test_arg_func { diff --git a/src/layui/layui/layNetlistBrowserPage.cc b/src/layui/layui/layNetlistBrowserPage.cc index ce725e086..b16dbf2e3 100644 --- a/src/layui/layui/layNetlistBrowserPage.cc +++ b/src/layui/layui/layNetlistBrowserPage.cc @@ -816,15 +816,31 @@ NetlistBrowserPage::log_selection_changed () QModelIndexList selection = log_view->selectionModel ()->selectedIndexes (); for (QModelIndexList::const_iterator i = selection.begin (); i != selection.end (); ++i) { - if (i->column () == 0) { - const db::LogEntryData *le = model->log_entry (*i); - if (le && le->geometry () != db::DPolygon () && ! le->cell_name ().empty ()) { - 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 ())); - } + + if (i->column () != 0) { + continue; + } + + 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 (); @@ -1291,6 +1307,7 @@ NetlistBrowserPage::clear_highlights () m_current_path = lay::NetlistObjectsPath (); m_selected_paths.clear (); m_markers.clear (); + m_net_markers.clear (); update_highlights (); } @@ -1350,6 +1367,31 @@ bbox_for_circuit (const db::Layout *layout, const db::Circuit *circuit) 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 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 NetlistBrowserPage::adjust_view () { @@ -1425,22 +1467,7 @@ NetlistBrowserPage::adjust_view () } else if (net) { - db::cell_index_type cell_index = net->circuit ()->cell_index (); - 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 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; - - } + ebox += bbox_for_net (mp_database.get (), circuit, net); } else if (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 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 ()) { std::vector tv = mp_view->cv_transform_variants (m_cv_index); @@ -1739,26 +1777,52 @@ NetlistBrowserPage::update_highlights () // a map of display properties vs. layer properties // correct DBU differences between the storage layout and the original layout - for (std::vector::iterator t = tv.begin (); t != tv.end (); ++t) { + std::vector tvt = tv; + for (std::vector::iterator t = tvt.begin (); t != tvt.end (); ++t) { *t = *t * trans * db::DCplxTrans (layout->dbu () / original_layout.dbu ()); } 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; } } 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; } } 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; } } } + for (auto marker = m_net_markers.begin (); marker != m_net_markers.end (); ++marker) { + + // computes the transformation supplied by the path + + std::pair 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 tvt = tv; + for (std::vector::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) { // computes the transformation supplied by the path diff --git a/src/layui/layui/layNetlistBrowserPage.h b/src/layui/layui/layNetlistBrowserPage.h index c9012e83f..b0345934b 100644 --- a/src/layui/layui/layNetlistBrowserPage.h +++ b/src/layui/layui/layNetlistBrowserPage.h @@ -246,6 +246,7 @@ private: lay::NetlistObjectsPath m_current_path; std::vector m_selected_paths; std::vector > m_markers; + std::vector > m_net_markers; lay::NetInfoDialog *mp_info_dialog; tl::DeferredMethod dm_update_highlights; tl::DeferredMethod dm_rerun_macro; diff --git a/testdata/drc/drcSimpleTests_147.drc b/testdata/drc/drcSimpleTests_147.drc new file mode 100644 index 000000000..1751e29c0 --- /dev/null +++ b/testdata/drc/drcSimpleTests_147.drc @@ -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 + diff --git a/testdata/drc/drcSimpleTests_147.gds b/testdata/drc/drcSimpleTests_147.gds new file mode 100644 index 000000000..ea9956148 Binary files /dev/null and b/testdata/drc/drcSimpleTests_147.gds differ diff --git a/testdata/drc/drcSimpleTests_au147.l2n b/testdata/drc/drcSimpleTests_au147.l2n new file mode 100644 index 000000000..6107261a6 --- /dev/null +++ b/testdata/drc/drcSimpleTests_au147.l2n @@ -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)) +) diff --git a/testdata/ruby/dbLogTest.rb b/testdata/ruby/dbLogTest.rb index 795e6eb49..7bbfa6ad1 100644 --- a/testdata/ruby/dbLogTest.rb +++ b/testdata/ruby/dbLogTest.rb @@ -35,6 +35,11 @@ class DBLog_TestClass < TestBase 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" 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)") + 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