From 0f7b8b8d23b4f5ba6a4d0f37c821a8935cd0e508 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Fri, 2 Dec 2022 15:29:10 +0100 Subject: [PATCH] tcl: Don't exit repl on recoverable command errors --- kernel/driver.cc | 2 ++ kernel/yosys.cc | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index aa90802c9..a89c790d9 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -205,6 +205,7 @@ extern char yosys_path[PATH_MAX]; #ifdef YOSYS_ENABLE_TCL namespace Yosys { extern int yosys_tcl_iterp_init(Tcl_Interp *interp); + extern void yosys_tcl_activate_repl(); }; #endif @@ -584,6 +585,7 @@ int main(int argc, char **argv) if (run_tcl_shell) { #ifdef YOSYS_ENABLE_TCL + yosys_tcl_activate_repl(); Tcl_Main(argc, argv, yosys_tcl_iterp_init); #else log_error("Can't exectue TCL shell: this version of yosys is not built with TCL support enabled.\n"); diff --git a/kernel/yosys.cc b/kernel/yosys.cc index c75500997..9ece3a2c0 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -84,6 +84,7 @@ CellTypes yosys_celltypes; #ifdef YOSYS_ENABLE_TCL Tcl_Interp *yosys_tcl_interp = NULL; +bool yosys_tcl_repl_active = false; #endif std::set yosys_input_files, yosys_output_files; @@ -773,12 +774,36 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a yosys_get_design()->scratchpad_unset("result.json"); - if (args.size() == 1) { - Pass::call(yosys_get_design(), args[0]); - } else { - Pass::call(yosys_get_design(), args); + bool in_repl = yosys_tcl_repl_active; + bool restore_log_cmd_error_throw = log_cmd_error_throw; + + log_cmd_error_throw = true; + + try { + if (args.size() == 1) { + Pass::call(yosys_get_design(), args[0]); + } else { + Pass::call(yosys_get_design(), args); + } + } catch (log_cmd_error_exception) { + if (in_repl) { + auto design = yosys_get_design(); + while (design->selection_stack.size() > 1) + design->selection_stack.pop_back(); + log_reset_stack(); + } + Tcl_SetResult(interp, (char *)"Yosys command produced an error", TCL_STATIC); + + yosys_tcl_repl_active = in_repl; + log_cmd_error_throw = restore_log_cmd_error_throw; + return TCL_ERROR; + } catch (...) { + log_error("uncaught exception during Yosys command invoked from TCL\n"); } + yosys_tcl_repl_active = in_repl; + log_cmd_error_throw = restore_log_cmd_error_throw; + auto &scratchpad = yosys_get_design()->scratchpad; auto result = scratchpad.find("result.json"); if (result != scratchpad.end()) { @@ -805,6 +830,11 @@ int yosys_tcl_iterp_init(Tcl_Interp *interp) return TCL_OK ; } +void yosys_tcl_activate_repl() +{ + yosys_tcl_repl_active = true; +} + extern Tcl_Interp *yosys_get_tcl_interp() { if (yosys_tcl_interp == NULL) {