From 8cac3291cbd76f309e355a49cbd2597a2874e9b8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 24 Jan 2021 14:33:58 -0700 Subject: [PATCH 1/5] [Tool] Add batch mode to openfpga shell execution --- libopenfpga/libopenfpgashell/src/shell.h | 4 +++- libopenfpga/libopenfpgashell/src/shell.tpp | 19 ++++++++++++++----- openfpga/src/main.cpp | 9 +++++++-- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/libopenfpga/libopenfpgashell/src/shell.h b/libopenfpga/libopenfpgashell/src/shell.h index 67dd4356d..26695b819 100644 --- a/libopenfpga/libopenfpgashell/src/shell.h +++ b/libopenfpga/libopenfpgashell/src/shell.h @@ -143,7 +143,9 @@ class Shell { /* Start the interactive mode, where users will type-in command by command */ void run_interactive_mode(T& context, const bool& quiet_mode = false); /* Start the script mode, where users provide a file which includes all the commands to run */ - void run_script_mode(const char* script_file_name, T& context); + void run_script_mode(const char* script_file_name, + T& context, + const bool& batch_mode = false); /* Print all the commands by their classes. This is actually the help desk */ void print_commands() const; /* Quit the shell */ diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp index 7c0ff7ce6..6e607f016 100644 --- a/libopenfpga/libopenfpgashell/src/shell.tpp +++ b/libopenfpga/libopenfpgashell/src/shell.tpp @@ -272,7 +272,9 @@ void Shell::run_interactive_mode(T& context, const bool& quiet_mode) { } template -void Shell::run_script_mode(const char* script_file_name, T& context) { +void Shell::run_script_mode(const char* script_file_name, + T& context, + const bool& batch_mode) { time_start_ = std::clock(); @@ -356,17 +358,24 @@ void Shell::run_script_mode(const char* script_file_name, T& context) { /* Empty the line ready to start a new line */ cmd_line.clear(); - /* Check the execution status of the command, if fatal error happened, we should abort immediately */ + /* Check the execution status of the command, + * if fatal error happened, we should abort immediately + */ if (CMD_EXEC_FATAL_ERROR == status) { - VTR_LOG("Fatal error occurred!\nAbort and enter interactive mode\n"); + VTR_LOG("Fatal error occurred!\n"); + /* If not in the batch mode, we will got to interactive mode */ + VTR_LOGV(batch_mode, "OpenFPGA Abort\n"); + VTR_LOGV(!batch_mode, "Enter interactive mode\n"); break; } } } fp.close(); - /* Return to interactive mode, stay tuned */ - run_interactive_mode(context, true); + /* If not in batch mode, switch to interactive mode, stay tuned */ + if (!batch_mode) { + run_interactive_mode(context, true); + } } template diff --git a/openfpga/src/main.cpp b/openfpga/src/main.cpp index d19b35944..083d5965d 100644 --- a/openfpga/src/main.cpp +++ b/openfpga/src/main.cpp @@ -29,9 +29,10 @@ int main(int argc, char** argv) { /* Create the command to launch shell in different modes */ openfpga::Command start_cmd("OpenFPGA"); - /* Add two options: + /* Add options: * '--interactive', -i': launch the interactive mode * '--file', -f': launch the script mode + * '--batch_execution': execute the script in batch mode. Will exit immediately when fatal errors occurred */ openfpga::CommandOptionId opt_interactive = start_cmd.add_option("interactive", false, "Launch OpenFPGA in interactive mode"); start_cmd.set_option_short_name(opt_interactive, "i"); @@ -40,6 +41,9 @@ int main(int argc, char** argv) { start_cmd.set_option_require_value(opt_script_mode, openfpga::OPT_STRING); start_cmd.set_option_short_name(opt_script_mode, "f"); + openfpga::CommandOptionId opt_batch_exec = start_cmd.add_option("batch_execution", false, "Launch OpenFPGA in batch mode when running scripts"); + start_cmd.set_option_short_name(opt_batch_exec, "batch"); + openfpga::CommandOptionId opt_help = start_cmd.add_option("help", false, "Help desk"); start_cmd.set_option_short_name(opt_help, "h"); @@ -100,7 +104,8 @@ int main(int argc, char** argv) { if (true == start_cmd_context.option_enable(start_cmd, opt_script_mode)) { shell.run_script_mode(start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(), - openfpga_context); + openfpga_context, + start_cmd_context.option_enable(start_cmd, opt_batch_exec)); return 0; } /* Reach here there is something wrong, show the help desk */ From fd0e73a9bb634d1b8ea502a12dd9fcd54f19bae0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 24 Jan 2021 14:48:27 -0700 Subject: [PATCH 2/5] [Tool] Enhance return code for openfpga shell --- libopenfpga/libopenfpgashell/src/shell.h | 4 ++ libopenfpga/libopenfpgashell/src/shell.tpp | 50 +++++++++++++++------- openfpga/src/main.cpp | 9 ++-- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/libopenfpga/libopenfpgashell/src/shell.h b/libopenfpga/libopenfpgashell/src/shell.h index 26695b819..ffcb6f1e3 100644 --- a/libopenfpga/libopenfpgashell/src/shell.h +++ b/libopenfpga/libopenfpgashell/src/shell.h @@ -148,6 +148,10 @@ class Shell { const bool& batch_mode = false); /* Print all the commands by their classes. This is actually the help desk */ void print_commands() const; + /* Find the exit code (assume quit shell now) */ + int exit_code() const; + /* Show statistics of errors during command execution */ + int execution_errors() const; /* Quit the shell */ void exit() const; private: /* Private executors */ diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp index 6e607f016..eaa1e84c3 100644 --- a/libopenfpga/libopenfpgashell/src/shell.tpp +++ b/libopenfpga/libopenfpgashell/src/shell.tpp @@ -401,7 +401,7 @@ void Shell::print_commands() const { } template -void Shell::exit() const { +int Shell::exit_code() const { /* Check all the command status, if we see fatal errors or minor errors, we drop an error code */ int exit_code = 0; for (const int& status : command_status_) { @@ -412,23 +412,41 @@ void Shell::exit() const { } } + return exit_code; +} + +template +int Shell::execution_errors() const { /* Show error message if we detect any errors */ int num_err = 0; - if (0 != exit_code) { - VTR_LOG("\n"); - for (const ShellCommandId& cmd : commands()) { - if (command_status_[cmd] == CMD_EXEC_FATAL_ERROR) { - VTR_LOG_ERROR("Command '%s' execution has fatal errors\n", - commands_[cmd].name().c_str()); - num_err++; - } - - if (command_status_[cmd] == CMD_EXEC_MINOR_ERROR) { - VTR_LOG_ERROR("Command '%s' execution has minor errors\n", - commands_[cmd].name().c_str()); - num_err++; - } + + for (const ShellCommandId& cmd : commands()) { + if (command_status_[cmd] == CMD_EXEC_FATAL_ERROR) { + VTR_LOG_ERROR("Command '%s' execution has fatal errors\n", + commands_[cmd].name().c_str()); + num_err++; } + + if (command_status_[cmd] == CMD_EXEC_MINOR_ERROR) { + VTR_LOG_ERROR("Command '%s' execution has minor errors\n", + commands_[cmd].name().c_str()); + num_err++; + } + } + + return num_err; +} + +template +void Shell::exit() const { + /* Check all the command status, if we see fatal errors or minor errors, we drop an error code */ + int shell_exit_code = exit_code(); + + /* Show error message if we detect any errors */ + int num_err = 0; + if (0 != shell_exit_code) { + VTR_LOG("\n"); + num_err = execution_errors(); } VTR_LOG("\nFinish execution with %d errors\n", @@ -440,7 +458,7 @@ void Shell::exit() const { VTR_LOG("\nThank you for using %s!\n", name().c_str()); - std::exit(exit_code); + std::exit(shell_exit_code); } /************************************************************************ diff --git a/openfpga/src/main.cpp b/openfpga/src/main.cpp index 083d5965d..3c2372c2a 100644 --- a/openfpga/src/main.cpp +++ b/openfpga/src/main.cpp @@ -99,18 +99,21 @@ int main(int argc, char** argv) { if (true == start_cmd_context.option_enable(start_cmd, opt_interactive)) { shell.run_interactive_mode(openfpga_context); - return 0; + return shell.exit_code(); } if (true == start_cmd_context.option_enable(start_cmd, opt_script_mode)) { shell.run_script_mode(start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(), openfpga_context, start_cmd_context.option_enable(start_cmd, opt_batch_exec)); - return 0; + return shell.exit_code(); } /* Reach here there is something wrong, show the help desk */ openfpga::print_command_options(start_cmd); } - return 0; + /* Reach here, it means shell execution has critical errors. + * Return a code with fatal errors + */ + return 1; } From e18c533657ed0a37291259ea0f309d7511088523 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 24 Jan 2021 14:48:56 -0700 Subject: [PATCH 3/5] [Doc] Add new openfpga shell command to documentation --- .../source/manual/openfpga_shell/launch_openfpga_shell.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/source/manual/openfpga_shell/launch_openfpga_shell.rst b/docs/source/manual/openfpga_shell/launch_openfpga_shell.rst index 3ef6e9fb5..f03819fe6 100644 --- a/docs/source/manual/openfpga_shell/launch_openfpga_shell.rst +++ b/docs/source/manual/openfpga_shell/launch_openfpga_shell.rst @@ -15,6 +15,13 @@ To launch OpenFPGA shell, users can choose two modes. Launch OpenFPGA in script mode where users write commands in scripts and FPGA will execute them +.. option:: --batch_execution or -batch + + Execute OpenFPGA script in batch mode. This option is only valid for script mode. + + - If in batch mode, OpenFPGA will abort immediately when fatal errors occurred. + - If not in batch mode, OpenFPGA will enter interactive mode when fatal errors occurred. + .. option:: --help or -h Show the help desk From a8158322ef4b43758888d52f1b2b230caac3b85f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 24 Jan 2021 17:25:03 -0700 Subject: [PATCH 4/5] [Tool] Bug fix in setting command execution status in OpenFPGA shell --- libopenfpga/libopenfpgashell/src/shell.tpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp index eaa1e84c3..c58143c0c 100644 --- a/libopenfpga/libopenfpgashell/src/shell.tpp +++ b/libopenfpga/libopenfpgashell/src/shell.tpp @@ -487,6 +487,7 @@ int Shell::execute_command(const char* cmd_line, commands_[dep_cmd].name().c_str(), commands_[cmd_id].name().c_str()); /* Echo the command help desk */ print_command_options(commands_[cmd_id]); + command_status_[cmd_id] = CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR; } } @@ -521,6 +522,7 @@ int Shell::execute_command(const char* cmd_line, if (false == parse_command(tokens, commands_[cmd_id], command_contexts_[cmd_id])) { /* Echo the command */ print_command_options(commands_[cmd_id]); + command_status_[cmd_id] = CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR; } From 3b7762ef85adb783d7471710c40d1ca952f95799 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 24 Jan 2021 17:44:51 -0700 Subject: [PATCH 5/5] [Lib] Now try to call undefined command will cause a error code to return --- libopenfpga/libopenfpgashell/src/shell.h | 2 +- libopenfpga/libopenfpgashell/src/shell.tpp | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libopenfpga/libopenfpgashell/src/shell.h b/libopenfpga/libopenfpgashell/src/shell.h index ffcb6f1e3..7f8e3a142 100644 --- a/libopenfpga/libopenfpgashell/src/shell.h +++ b/libopenfpga/libopenfpgashell/src/shell.h @@ -153,7 +153,7 @@ class Shell { /* Show statistics of errors during command execution */ int execution_errors() const; /* Quit the shell */ - void exit() const; + void exit(const int& init_err = 0) const; private: /* Private executors */ /* Execute a command, the command line is the user's input to launch a command * The common_context is the data structure to exchange data between commands diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp index c58143c0c..3b608f135 100644 --- a/libopenfpga/libopenfpgashell/src/shell.tpp +++ b/libopenfpga/libopenfpgashell/src/shell.tpp @@ -363,8 +363,12 @@ void Shell::run_script_mode(const char* script_file_name, */ if (CMD_EXEC_FATAL_ERROR == status) { VTR_LOG("Fatal error occurred!\n"); - /* If not in the batch mode, we will got to interactive mode */ + /* If in the batch mode, we will exit with errors */ VTR_LOGV(batch_mode, "OpenFPGA Abort\n"); + if (batch_mode) { + exit(CMD_EXEC_FATAL_ERROR); + } + /* If not in the batch mode, we will got to interactive mode */ VTR_LOGV(!batch_mode, "Enter interactive mode\n"); break; } @@ -438,15 +442,15 @@ int Shell::execution_errors() const { } template -void Shell::exit() const { +void Shell::exit(const int& init_err) const { /* Check all the command status, if we see fatal errors or minor errors, we drop an error code */ - int shell_exit_code = exit_code(); + int shell_exit_code = exit_code() | init_err; /* Show error message if we detect any errors */ - int num_err = 0; - if (0 != shell_exit_code) { + int num_err = init_err; + if (CMD_EXEC_SUCCESS != shell_exit_code) { VTR_LOG("\n"); - num_err = execution_errors(); + num_err += execution_errors(); } VTR_LOG("\nFinish execution with %d errors\n",