diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index bb7399b35..b30dfb26a 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -1148,7 +1148,7 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg } -void db::LayoutToNetlist::save (const std::string &path, bool short_format) +void LayoutToNetlist::save (const std::string &path, bool short_format) { tl::OutputStream stream (path); db::LayoutToNetlistStandardWriter writer (stream, short_format); @@ -1156,7 +1156,7 @@ void db::LayoutToNetlist::save (const std::string &path, bool short_format) writer.write (this); } -void db::LayoutToNetlist::load (const std::string &path) +void LayoutToNetlist::load (const std::string &path) { tl::InputStream stream (path); db::LayoutToNetlistStandardReader reader (stream); @@ -1165,7 +1165,7 @@ void db::LayoutToNetlist::load (const std::string &path) reader.read (this); } -db::LayoutToNetlist *db::LayoutToNetlist::create_from_file (const std::string &path) +db::LayoutToNetlist *LayoutToNetlist::create_from_file (const std::string &path) { std::auto_ptr db; @@ -1189,4 +1189,9 @@ db::LayoutToNetlist *db::LayoutToNetlist::create_from_file (const std::string &p return db.release (); } +void LayoutToNetlist::set_generator (const std::string &g) +{ + m_generator = g; +} + } diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index e2287a301..3b31ddff3 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -254,6 +254,19 @@ public: */ std::string name (unsigned int) const; + /** + * @brief Sets the generator string + */ + void set_generator (const std::string &g); + + /** + * @brief Gets the generator string + */ + const std::string &generator () const + { + return m_generator; + } + /** * @brief Returns true, if the region is a persisted region * Persisted regions have a name and are kept inside the LayoutToNetlist @@ -730,6 +743,7 @@ private: bool m_is_flat; double m_device_scaling; db::DeepLayer m_dummy_layer; + std::string m_generator; struct CellReuseTableKey { diff --git a/src/db/db/dbLayoutVsSchematic.cc b/src/db/db/dbLayoutVsSchematic.cc index e6c092795..fc054d6f5 100644 --- a/src/db/db/dbLayoutVsSchematic.cc +++ b/src/db/db/dbLayoutVsSchematic.cc @@ -86,7 +86,7 @@ db::NetlistCrossReference *LayoutVsSchematic::make_cross_ref () } -void db::LayoutVsSchematic::save (const std::string &path, bool short_format) +void LayoutVsSchematic::save (const std::string &path, bool short_format) { tl::OutputStream stream (path); db::LayoutVsSchematicStandardWriter writer (stream, short_format); @@ -94,7 +94,7 @@ void db::LayoutVsSchematic::save (const std::string &path, bool short_format) writer.write (this); } -void db::LayoutVsSchematic::load (const std::string &path) +void LayoutVsSchematic::load (const std::string &path) { tl::InputStream stream (path); db::LayoutVsSchematicStandardReader reader (stream); diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 499bc4041..9222cee38 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -2138,14 +2138,14 @@ NetlistComparer::unmatched_circuits (db::Netlist *a, db::Netlist *b, std::vector for (db::Netlist::circuit_iterator i = a->begin_circuits (); i != a->end_circuits (); ++i) { size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ()); - if (cat && i->begin_refs () != i->end_refs ()) { + if (cat) { cat2circuits[cat].first = i.operator-> (); } } for (db::Netlist::circuit_iterator i = b->begin_circuits (); i != b->end_circuits (); ++i) { size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ()); - if (cat && i->begin_refs () != i->end_refs ()) { + if (cat) { cat2circuits[cat].second = i.operator-> (); } } diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index 02ba6b3c9..c8256b0c7 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -169,6 +169,13 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "The database unit is mandatory because the physical parameter extraction " "for devices requires this unit for translation of layout to physical dimensions.\n" ) + + gsi::method ("generator", &db::LayoutToNetlist::generator, + "@brief Gets the generator string.\n" + "The generator is the script that created this database.\n" + ) + + gsi::method ("generator=", &db::LayoutToNetlist::set_generator, gsi::arg ("generator"), + "@brief Sets the generator string.\n" + ) + gsi::method ("dss", (db::DeepShapeStore &(db::LayoutToNetlist::*) ()) &db::LayoutToNetlist::dss, "@brief Gets a reference to the internal DSS object.\n" ) + diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 2b5d4b559..f229dafb1 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1106,7 +1106,7 @@ Class decl_dbCircuit ("db", "Circuit", "@brief Iterates over the parent circuits of this circuit\n" "Child circuits are the ones that are referencing this circuit via subcircuits." ) + - gsi::method ("has_refs", &db::Circuit::has_refs, + gsi::method ("has_refs?", &db::Circuit::has_refs, "@brief Returns a value indicating whether the circuit has references\n" "A circuit has references if there is at least one subcircuit referring to it." ) + @@ -1379,13 +1379,13 @@ Class decl_dbNetlist ("db", "Netlist", gsi::method ("remove", &db::Netlist::remove_circuit, gsi::arg ("circuit"), "@brief Removes the given circuit object from the netlist\n" "After the circuit has been removed, the object becomes invalid and cannot be used further. " - "A circuit with references (see \\has_refs) should not be removed as the " + "A circuit with references (see \\has_refs?) should not be removed as the " "subcircuits calling it would afterwards point to nothing." ) + gsi::method ("purge_circuit", &db::Netlist::purge_circuit, gsi::arg ("circuit"), "@brief Removes the given circuit object and all child circuits which are not used otherwise from the netlist\n" "After the circuit has been removed, the object becomes invalid and cannot be used further. " - "A circuit with references (see \\has_refs) should not be removed as the " + "A circuit with references (see \\has_refs?) should not be removed as the " "subcircuits calling it would afterwards point to nothing." ) + gsi::method ("flatten_circuit", &db::Netlist::flatten_circuit, gsi::arg ("circuit"), diff --git a/src/db/db/gsiDeclDbNetlistCompare.cc b/src/db/db/gsiDeclDbNetlistCompare.cc index 0afaf06de..900df9d78 100644 --- a/src/db/db/gsiDeclDbNetlistCompare.cc +++ b/src/db/db/gsiDeclDbNetlistCompare.cc @@ -541,12 +541,10 @@ Class decl_dbNetlistComparer ("db", "NetlistComparer", gsi::method_ext ("unmatched_circuits_a", &unmatched_circuits_a, gsi::arg ("a"), gsi::arg ("b"), "@brief Returns a list of circuits in A for which there is not corresponding circuit in B\n" "This list can be used to flatten these circuits so they do not participate in the compare process.\n" - "Top level circuits are not included as they cannot be flattened.\n" ) + gsi::method_ext ("unmatched_circuits_b", &unmatched_circuits_b, gsi::arg ("a"), gsi::arg ("b"), "@brief Returns a list of circuits in B for which there is not corresponding circuit in A\n" "This list can be used to flatten these circuits so they do not participate in the compare process.\n" - "Top level circuits are not included as they cannot be flattened.\n" ) + gsi::method ("compare", (bool (db::NetlistComparer::*) (const db::Netlist *, const db::Netlist *) const) &db::NetlistComparer::compare, gsi::arg ("netlist_a"), gsi::arg ("netlist_b"), "@brief Compares two netlists.\n" diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb index 400acd91b..0763d6e54 100644 --- a/src/drc/drc/built-in-macros/_drc_netter.rb +++ b/src/drc/drc/built-in-macros/_drc_netter.rb @@ -407,6 +407,8 @@ module DRC @l2n = RBA::LayoutToNetlist::new(layout.top_cell.name, layout.dbu) end + @l2n.generator = $0 + end def register_layer(data) diff --git a/src/drc/drc/built-in-macros/drc_interpreters.lym b/src/drc/drc/built-in-macros/drc_interpreters.lym index 3445c815a..5818c23d7 100644 --- a/src/drc/drc/built-in-macros/drc_interpreters.lym +++ b/src/drc/drc/built-in-macros/drc_interpreters.lym @@ -74,6 +74,7 @@ module DRC # Implements the execute method def execute(macro) + $0 = macro.path DRC::execute_drc(macro) end diff --git a/src/klayout.pro b/src/klayout.pro index fbf20df44..bf978a92d 100644 --- a/src/klayout.pro +++ b/src/klayout.pro @@ -89,12 +89,12 @@ plugins.depends += lib rdb db plugins.depends += lay ant - laybasic.depends += rdb + lym.depends += gsi $$LANG_DEPENDS + laybasic.depends += rdb lym ant.depends += laybasic img.depends += laybasic edt.depends += laybasic - lym.depends += gsi $$LANG_DEPENDS - lay.depends += laybasic ant img edt lym + lay.depends += laybasic ant img edt klayout_main.depends += plugins $$MAIN_DEPENDS } diff --git a/src/laybasic/laybasic/NetlistBrowserPage.ui b/src/laybasic/laybasic/NetlistBrowserPage.ui index 84373f842..e341345cd 100644 --- a/src/laybasic/laybasic/NetlistBrowserPage.ui +++ b/src/laybasic/laybasic/NetlistBrowserPage.ui @@ -132,6 +132,20 @@ + + + + ... + + + + :/run.png:/run.png + + + true + + + diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index ee0474460..c078a9e38 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -30,6 +30,7 @@ #include "layMarker.h" #include "layNetInfoDialog.h" #include "layNetExportDialog.h" +#include "lymMacro.h" #include "tlProgress.h" #include "tlExceptions.h" #include "dbLayoutToNetlist.h" @@ -124,6 +125,7 @@ NetlistBrowserPage::NetlistBrowserPage (QWidget * /*parent*/) m_update_needed (true), mp_info_dialog (0), dm_update_highlights (this, &NetlistBrowserPage::update_highlights), + dm_rerun_macro (this, &NetlistBrowserPage::rerun_macro), m_cell_context_cache (0) { Ui::NetlistBrowserPage::setupUi (this); @@ -188,6 +190,7 @@ NetlistBrowserPage::NetlistBrowserPage (QWidget * /*parent*/) connect (m_show_all_action, SIGNAL (triggered ()), this, SLOT (show_all_clicked ())); connect (info_button, SIGNAL (pressed ()), this, SLOT (info_button_pressed ())); + connect (rerun_button, SIGNAL (pressed ()), this, SLOT (rerun_button_pressed ())); connect (find_button, SIGNAL (pressed ()), this, SLOT (find_button_pressed ())); connect (forward, SIGNAL (clicked ()), this, SLOT (navigate_forward ())); connect (backward, SIGNAL (clicked ()), this, SLOT (navigate_back ())); @@ -585,6 +588,27 @@ NetlistBrowserPage::navigate_forward () } } +void +NetlistBrowserPage::rerun_button_pressed () +{ + // NOTE: we use deferred execution, because otherwise the button won't get repainted properly + dm_rerun_macro (); +} + +void +NetlistBrowserPage::rerun_macro () +{ + if (! mp_database->generator ().empty ()) { + + lym::Macro *generator = lym::MacroCollection::root ().find_macro (mp_database->generator ()); + if (! generator) { + throw tl::Exception (tl::sprintf (tl::to_string (tr ("Cannot find generator script: %s")), mp_database->generator())); + } else { + generator->run (); + } + + } +} void NetlistBrowserPage::info_button_pressed () { @@ -741,6 +765,13 @@ NetlistBrowserPage::set_db (db::LayoutToNetlist *l2ndb) db::LayoutVsSchematic *lvsdb = dynamic_cast (l2ndb); mp_database.reset (l2ndb); + rerun_button->setEnabled (mp_database.get () && ! mp_database->generator ().empty ()); + if (rerun_button->isEnabled ()) { + rerun_button->setToolTip (tl::to_qstring (tl::to_string (tr ("Run ")) + mp_database->generator ())); + } else { + rerun_button->setToolTip (QString ()); + } + show_netlist->setVisible (lvsdb != 0); show_xref->setVisible (lvsdb != 0); diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h index 2bde27cec..1440a13b0 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.h +++ b/src/laybasic/laybasic/layNetlistBrowserPage.h @@ -169,6 +169,7 @@ public slots: private slots: void show_all_clicked (); void info_button_pressed (); + void rerun_button_pressed (); void find_button_pressed (); void anchor_clicked (const QString &url); void navigate_back (); @@ -212,6 +213,7 @@ private: std::vector m_current_circuits; lay::NetInfoDialog *mp_info_dialog; tl::DeferredMethod dm_update_highlights; + tl::DeferredMethod dm_rerun_macro; db::ContextCache m_cell_context_cache; void set_db (db::LayoutToNetlist *l2ndb); @@ -233,6 +235,7 @@ private: bool produce_highlights_for_subcircuit (const db::SubCircuit *subcircuit, size_t &n_markers, const std::vector &tv); bool produce_highlights_for_circuit (const db::Circuit *circuit, size_t &n_markers, const std::vector &tv); void configure_marker (lay::Marker *marker, bool with_fill); + void rerun_macro (); void export_nets (const std::vector *nets); }; diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index 5d59bd3af..443343ce1 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -275,9 +275,9 @@ HEADERS = \ layNetlistBrowserTreeModel.h \ layLibrariesView.h -INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC -DEPENDPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC -LIBS += -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_db -lklayout_rdb +INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC +DEPENDPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC +LIBS += -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_db -lklayout_rdb -lklayout_lym INCLUDEPATH += $$QTBASIC_INC DEPENDPATH += $$QTBASIC_INC diff --git a/src/lvs/lvs/built-in-macros/_lvs_netter.rb b/src/lvs/lvs/built-in-macros/_lvs_netter.rb index 3e68b3d1c..a0b0b2cf8 100644 --- a/src/lvs/lvs/built-in-macros/_lvs_netter.rb +++ b/src/lvs/lvs/built-in-macros/_lvs_netter.rb @@ -61,6 +61,8 @@ module LVS @lvs = RBA::LayoutVsSchematic::new(cell.name, layout.dbu) end + @lvs.generator = $0 + @l2n = @lvs @comparer = RBA::NetlistComparer::new @@ -117,8 +119,16 @@ module LVS nl = _ensure_two_netlists + unmatched_a = @comparer.unmatched_circuits_a(*nl) + + # check whether we're about to flatten away the internal top cell - that's bad + top_cell = l2n_data.internal_top_cell.name + if unmatched_a.find { |c| c.name == top_cell } + raise("Can't find a schematic counterpart for the top cell #{top_cell} - use 'same_circuit' to establish a correspondence") + end + # flatten layout cells for which there is no corresponding schematic circuit - @comparer.unmatched_circuits_a(*nl).each do |c| + unmatched_a.each do |c| @engine.info("Flatten layout cell (no schematic): #{c.name}") nl[0].flatten_circuit(c) end diff --git a/src/lvs/lvs/built-in-macros/lvs_interpreters.lym b/src/lvs/lvs/built-in-macros/lvs_interpreters.lym index 24a1d0d84..b72af993b 100644 --- a/src/lvs/lvs/built-in-macros/lvs_interpreters.lym +++ b/src/lvs/lvs/built-in-macros/lvs_interpreters.lym @@ -80,6 +80,7 @@ module LVS # Implements the execute method def execute(macro) + $0 = macro.path LVS::execute_lvs(macro) end