From e6c9872ea259ef76b9abd562176c6ec343debb48 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 25 Aug 2023 22:49:54 +0200 Subject: [PATCH] Bugfix: re-run of include-expanded DRC/LVS wasn't working Reworked include-expansion scheme for DRC/LVS such that include expansion is done by the interpreter, hence is also available for re-running the script from the marker/netlist browser. This also affects the D25 implementation. --- .../drc/built-in-macros/drc_interpreters.lym | 77 ++++++++++--------- .../lvs/built-in-macros/lvs_interpreters.lym | 77 ++++++++++--------- src/lym/lym/gsiDeclLymMacro.cc | 19 +++++ src/lym/lym/lymMacroInterpreter.cc | 24 +----- .../built-in-macros/d25_interpreters.lym | 77 ++++++++++--------- 5 files changed, 146 insertions(+), 128 deletions(-) diff --git a/src/drc/drc/built-in-macros/drc_interpreters.lym b/src/drc/drc/built-in-macros/drc_interpreters.lym index dbd8591dd..720b7e963 100644 --- a/src/drc/drc/built-in-macros/drc_interpreters.lym +++ b/src/drc/drc/built-in-macros/drc_interpreters.lym @@ -19,7 +19,7 @@ module DRC class DRCExecutable < RBA::Executable - def initialize(macro, generator, rdb_index = nil) + def initialize(macro, interpreter, generator, rdb_index = nil) @drc = DRCEngine::new @drc._rdb_index = rdb_index @@ -27,6 +27,8 @@ module DRC @macro = macro + @interpreter = interpreter + end def execute @@ -38,9 +40,11 @@ module DRC begin + encoded_file, expanded_text = @interpreter.include_expansion(@macro) + # No verbosity set in drc engine - we cannot use the engine's logger RBA::Logger::verbosity >= 10 && RBA::Logger::info("Running #{@macro.path}") - @drc.instance_eval(@macro.text, @macro.path) + @drc.instance_eval(expanded_text, encoded_file) rescue => ex @@ -66,13 +70,40 @@ module DRC end + # A recipe implementation allowing the DRC run to be redone + class DRCRecipe < RBA::Recipe + + def initialize(interpreter) + + super("drc", "DRC recipe") + + @interpreter = interpreter + + end + + def executable(params) + + script = params["script"] + if ! script + return + end + + macro = RBA::Macro::macro_by_path(script) + macro || raise("Can't find DRC script #{script} - unable to re-run") + + DRCExecutable::new(macro, @interpreter, self.generator("script" => script), params["rdb_index"]) + + end + + end + # A DSL implementation for a DRC language (XML format) class DRCInterpreter < RBA::MacroInterpreter # Constructor - def initialize(recipe) + def initialize - @recipe = recipe + @recipe = DRCRecipe::new(self) # Make the DSL use ruby syntax highlighting self.syntax_scheme = "ruby" @@ -97,7 +128,7 @@ module DRC # Implements the execute method def executable(macro) - DRCExecutable::new(macro, @recipe.generator("script" => macro.path)) + DRCExecutable::new(macro, self, @recipe.generator("script" => macro.path)) end end @@ -106,9 +137,9 @@ module DRC class DRCPlainTextInterpreter < RBA::MacroInterpreter # Constructor - def initialize(recipe) + def initialize - @recipe = recipe + @recipe = DRCRecipe::new(self) # Make the DSL use ruby syntax highlighting self.syntax_scheme = "ruby" @@ -124,40 +155,14 @@ module DRC # Implements the execute method def executable(macro) - DRCExecutable::new(macro, @recipe.generator("script" => macro.path)) + DRCExecutable::new(macro, self, @recipe.generator("script" => macro.path)) end end - # A recipe implementation allowing the DRC run to be redone - class DRCRecipe < RBA::Recipe - - def initialize - super("drc", "DRC recipe") - end - - def executable(params) - - script = params["script"] - if ! script - return - end - - macro = RBA::Macro::macro_by_path(script) - macro || raise("Can't find DRC script #{script} - unable to re-run") - - DRCExecutable::new(macro, self.generator("script" => script), params["rdb_index"]) - - end - - end - - # Register the recipe - drc_recipe = DRCRecipe::new - # Register the new interpreters - DRCInterpreter::new(drc_recipe) - DRCPlainTextInterpreter::new(drc_recipe) + DRCInterpreter::new + DRCPlainTextInterpreter::new # Creates a new macro category if RBA.constants.member?(:Application) && RBA::Application::instance diff --git a/src/lvs/lvs/built-in-macros/lvs_interpreters.lym b/src/lvs/lvs/built-in-macros/lvs_interpreters.lym index c99c21e98..2aaf6f1fa 100644 --- a/src/lvs/lvs/built-in-macros/lvs_interpreters.lym +++ b/src/lvs/lvs/built-in-macros/lvs_interpreters.lym @@ -19,7 +19,7 @@ module LVS class LVSExecutable < RBA::Executable - def initialize(macro, generator, l2ndb_index = nil) + def initialize(macro, interpreter, generator, l2ndb_index = nil) @lvs = LVSEngine::new @lvs._l2ndb_index = l2ndb_index @@ -27,6 +27,8 @@ module LVS @macro = macro + @interpreter = interpreter + end def execute @@ -38,9 +40,11 @@ module LVS begin + encoded_file, expanded_text = @interpreter.include_expansion(@macro) + # No verbosity set in lvs engine - we cannot use the engine's logger RBA::Logger::verbosity >= 10 && RBA::Logger::info("Running #{@macro.path}") - @lvs.instance_eval(@macro.text, @macro.path) + @lvs.instance_eval(expanded_text, encoded_file) rescue => ex @@ -66,13 +70,40 @@ module LVS end + # A recipe implementation allowing the LVS run to be redone + class LVSRecipe < RBA::Recipe + + def initialize(interpreter) + + super("lvs", "LVS recipe") + + @interpreter = interpreter + + end + + def executable(params) + + script = params["script"] + if ! script + return + end + + macro = RBA::Macro::macro_by_path(script) + macro || raise("Can't find LVS script #{script} - unable to re-run") + + LVSExecutable::new(macro, @interpreter, self.generator("script" => script), params["l2ndb_index"]) + + end + + end + # A DSL implementation for a LVS language (XML format) class LVSInterpreter < RBA::MacroInterpreter # Constructor - def initialize(recipe) + def initialize - @recipe = recipe + @recipe = LVSRecipe::new(self) # Make the DSL use ruby syntax highlighting self.syntax_scheme = "ruby" @@ -97,7 +128,7 @@ module LVS # Implements the execute method def executable(macro) - LVSExecutable::new(macro, @recipe.generator("script" => macro.path)) + LVSExecutable::new(macro, self, @recipe.generator("script" => macro.path)) end end @@ -106,9 +137,9 @@ module LVS class LVSPlainTextInterpreter < RBA::MacroInterpreter # Constructor - def initialize(recipe) + def initialize - @recipe = recipe + @recipe = LVSRecipe::new(self) # Make the DSL use ruby syntax highlighting self.syntax_scheme = "ruby" @@ -124,40 +155,14 @@ module LVS # Implements the execute method def executable(macro) - LVSExecutable::new(macro, @recipe.generator("script" => macro.path)) + LVSExecutable::new(macro, self, @recipe.generator("script" => macro.path)) end end - # A recipe implementation allowing the LVS run to be redone - class LVSRecipe < RBA::Recipe - - def initialize - super("lvs", "LVS recipe") - end - - def executable(params) - - script = params["script"] - if ! script - return - end - - macro = RBA::Macro::macro_by_path(script) - macro || raise("Can't find LVS script #{script} - unable to re-run") - - LVSExecutable::new(macro, self.generator("script" => script), params["l2ndb_index"]) - - end - - end - - # Register the recipe - lvs_recipe = LVSRecipe::new - # Register the new interpreters - LVSInterpreter::new(lvs_recipe) - LVSPlainTextInterpreter::new(lvs_recipe) + LVSInterpreter::new + LVSPlainTextInterpreter::new # Creates a new macro category if RBA.constants.member?(:Application) && RBA::Application::instance diff --git a/src/lym/lym/gsiDeclLymMacro.cc b/src/lym/lym/gsiDeclLymMacro.cc index 7d7ce3d63..28e1ac4d7 100644 --- a/src/lym/lym/gsiDeclLymMacro.cc +++ b/src/lym/lym/gsiDeclLymMacro.cc @@ -247,6 +247,18 @@ private: bool m_supports_include_expansion; }; +static std::vector +include_expansion (MacroInterpreterImpl *interp, lym::Macro *macro) +{ + std::vector res; + + auto sp = interp->include_expansion (macro); + res.push_back (sp.first); + res.push_back (sp.second); + + return res; +} + gsi::EnumIn decl_FormatEnum ("lay", "Format", gsi::enum_const ("PlainTextFormat", lym::Macro::PlainTextFormat, "@brief The macro has plain text format" @@ -298,6 +310,13 @@ Class decl_MacroInterpreter ("lay", "MacroInterpreter", gsi::method ("NoDebugger", &const_NoDebugger, "@brief Indicates no debugging for \\debugger_scheme\n" ) + + gsi::method_ext ("include_expansion", &include_expansion, gsi::arg ("macro"), + "@brief Provides include expansion as defined by the interpreter\n" + "The return value will be a two-element array with the encoded file path " + "and the include-expanded text.\n" + "\n" + "This method has been introduced in version 0.28.12." + ) + gsi::method ("register", &MacroInterpreterImpl::register_gsi, gsi::arg ("name"), "@brief Registers the macro interpreter\n" "@param name The interpreter name. This is an arbitrary string which should be unique.\n" diff --git a/src/lym/lym/lymMacroInterpreter.cc b/src/lym/lym/lymMacroInterpreter.cc index 8cb7a9f34..e080223f2 100644 --- a/src/lym/lym/lymMacroInterpreter.cc +++ b/src/lym/lym/lymMacroInterpreter.cc @@ -130,31 +130,15 @@ MacroInterpreter::execute_macro (const lym::Macro *macro) if (cls.current_name () == macro->dsl_interpreter ()) { - std::pair et = cls->include_expansion (macro); - if (et.first.empty () || et.first == macro->path ()) { - - std::unique_ptr eo (cls->executable (macro)); - if (eo.get ()) { - eo->do_execute (); - } - - } else { - - // provide a copy which takes the include-expanded version - lym::Macro tmp_macro; - tmp_macro.assign (*macro); - tmp_macro.set_text (et.second); - tmp_macro.set_file_path (et.first); - std::unique_ptr eo (cls->executable (&tmp_macro)); - if (eo.get ()) { - eo->do_execute (); - } - + std::unique_ptr eo (cls->executable (macro)); + if (eo.get ()) { + eo->do_execute (); } return; } + } throw tl::Exception (tl::to_string (tr ("No interpreter registered for DSL type '")) + macro->dsl_interpreter () + "'"); diff --git a/src/plugins/tools/view_25d/lay_plugin/built-in-macros/d25_interpreters.lym b/src/plugins/tools/view_25d/lay_plugin/built-in-macros/d25_interpreters.lym index 86d7d954d..fd8e1bca5 100644 --- a/src/plugins/tools/view_25d/lay_plugin/built-in-macros/d25_interpreters.lym +++ b/src/plugins/tools/view_25d/lay_plugin/built-in-macros/d25_interpreters.lym @@ -19,13 +19,15 @@ module D25 class D25Executable < RBA::Executable - def initialize(macro, generator) + def initialize(macro, interpreter, generator) @d25 = D25Engine::new @d25._generator = generator @macro = macro + @interpreter = interpreter + end def execute @@ -37,9 +39,11 @@ module D25 begin + encoded_file, expanded_text = @interpreter.include_expansion(@macro) + # No verbosity set in d25 engine - we cannot use the engine's logger RBA::Logger::verbosity >= 10 && RBA::Logger::info("Running #{@macro.path}") - @d25.instance_eval(@macro.text, @macro.path) + @d25.instance_eval(expanded_text, encoded_file) rescue => ex @@ -67,13 +71,40 @@ module D25 end + # A recipe implementation allowing the D25 run to be redone + class D25Recipe < RBA::Recipe + + def initialize(interpreter) + + super("d25", "D25 recipe") + + @interpreter = interpreter + + end + + def executable(params) + + script = params["script"] + if ! script + return + end + + macro = RBA::Macro::macro_by_path(script) + macro || raise("Can't find D25 script #{script} - unable to re-run") + + D25Executable::new(macro, @interpreter, self.generator("script" => script)) + + end + + end + # A DSL implementation for a D25 language (XML format) class D25Interpreter < RBA::MacroInterpreter # Constructor - def initialize(recipe) + def initialize - @recipe = recipe + @recipe = D25Recipe::new(self) # Make the DSL use ruby syntax highlighting self.syntax_scheme = "ruby" @@ -98,7 +129,7 @@ module D25 # Implements the execute method def executable(macro) - D25Executable::new(macro, @recipe.generator("script" => macro.path)) + D25Executable::new(macro, self, @recipe.generator("script" => macro.path)) end end @@ -107,9 +138,9 @@ module D25 class D25PlainTextInterpreter < RBA::MacroInterpreter # Constructor - def initialize(recipe) + def initialize - @recipe = recipe + @recipe = D25Recipe::new(self) # Make the DSL use ruby syntax highlighting self.syntax_scheme = "ruby" @@ -125,40 +156,14 @@ module D25 # Implements the execute method def executable(macro) - D25Executable::new(macro, @recipe.generator("script" => macro.path)) + D25Executable::new(macro, self, @recipe.generator("script" => macro.path)) end end - # A recipe implementation allowing the D25 run to be redone - class D25Recipe < RBA::Recipe - - def initialize - super("d25", "D25 recipe") - end - - def executable(params) - - script = params["script"] - if ! script - return - end - - macro = RBA::Macro::macro_by_path(script) - macro || raise("Can't find D25 script #{script} - unable to re-run") - - D25Executable::new(macro, self.generator("script" => script)) - - end - - end - - # Register the recipe - d25_recipe = D25Recipe::new - # Register the new interpreters - D25Interpreter::new(d25_recipe) - D25PlainTextInterpreter::new(d25_recipe) + D25Interpreter::new + D25PlainTextInterpreter::new # Creates a new macro category if RBA::Application::instance