aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJannis Harder <me@jix.one>2022-12-02 15:29:10 +0100
committerJannis Harder <me@jix.one>2022-12-02 15:50:41 +0100
commit0f7b8b8d23b4f5ba6a4d0f37c821a8935cd0e508 (patch)
treeb7559dce9a6ffdf5e95c6349f9ff6c5e1861913e /kernel
parent5524d5185d0d10246fb5410025c39e458e1a9abb (diff)
downloadyosys-0f7b8b8d23b4f5ba6a4d0f37c821a8935cd0e508.tar.gz
yosys-0f7b8b8d23b4f5ba6a4d0f37c821a8935cd0e508.tar.bz2
yosys-0f7b8b8d23b4f5ba6a4d0f37c821a8935cd0e508.zip
tcl: Don't exit repl on recoverable command errors
Diffstat (limited to 'kernel')
-rw-r--r--kernel/driver.cc2
-rw-r--r--kernel/yosys.cc38
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<std::string> 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) {