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.
This commit is contained in:
Matthias Koefferlein 2023-08-25 22:49:54 +02:00
parent 304800e4c5
commit e6c9872ea2
5 changed files with 146 additions and 128 deletions

View File

@ -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

View File

@ -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

View File

@ -247,6 +247,18 @@ private:
bool m_supports_include_expansion;
};
static std::vector<std::string>
include_expansion (MacroInterpreterImpl *interp, lym::Macro *macro)
{
std::vector<std::string> res;
auto sp = interp->include_expansion (macro);
res.push_back (sp.first);
res.push_back (sp.second);
return res;
}
gsi::EnumIn<lym::Macro, lym::Macro::Format> decl_FormatEnum ("lay", "Format",
gsi::enum_const ("PlainTextFormat", lym::Macro::PlainTextFormat,
"@brief The macro has plain text format"
@ -298,6 +310,13 @@ Class<MacroInterpreterImpl> 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"

View File

@ -130,31 +130,15 @@ MacroInterpreter::execute_macro (const lym::Macro *macro)
if (cls.current_name () == macro->dsl_interpreter ()) {
std::pair<std::string, std::string> et = cls->include_expansion (macro);
if (et.first.empty () || et.first == macro->path ()) {
std::unique_ptr<tl::Executable> 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<tl::Executable> eo (cls->executable (&tmp_macro));
if (eo.get ()) {
eo->do_execute ();
}
std::unique_ptr<tl::Executable> 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 () + "'");

View File

@ -19,13 +19,15 @@ module D25
class D25Executable &lt; 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 &gt;= 10 &amp;&amp; RBA::Logger::info("Running #{@macro.path}")
@d25.instance_eval(@macro.text, @macro.path)
@d25.instance_eval(expanded_text, encoded_file)
rescue =&gt; ex
@ -67,13 +71,40 @@ module D25
end
# A recipe implementation allowing the D25 run to be redone
class D25Recipe &lt; 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 &lt; 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 &lt; 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 &lt; 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