Merge pull request #184 from lnis-uofu/openfpga_shell_batch

Support batch mode when executing OpenFPGA commands
This commit is contained in:
ganeshgore 2021-01-24 21:07:18 -07:00 committed by GitHub
commit df9df7c93c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 28 deletions

View File

@ -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 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 .. option:: --help or -h
Show the help desk Show the help desk

View File

@ -143,11 +143,17 @@ class Shell {
/* Start the interactive mode, where users will type-in command by command */ /* Start the interactive mode, where users will type-in command by command */
void run_interactive_mode(T& context, const bool& quiet_mode = false); 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 */ /* 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 */ /* Print all the commands by their classes. This is actually the help desk */
void print_commands() const; 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 */ /* Quit the shell */
void exit() const; void exit(const int& init_err = 0) const;
private: /* Private executors */ private: /* Private executors */
/* Execute a command, the command line is the user's input to launch a command /* 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 * The common_context is the data structure to exchange data between commands

View File

@ -272,7 +272,9 @@ void Shell<T>::run_interactive_mode(T& context, const bool& quiet_mode) {
} }
template <class T> template <class T>
void Shell<T>::run_script_mode(const char* script_file_name, T& context) { void Shell<T>::run_script_mode(const char* script_file_name,
T& context,
const bool& batch_mode) {
time_start_ = std::clock(); time_start_ = std::clock();
@ -356,17 +358,28 @@ void Shell<T>::run_script_mode(const char* script_file_name, T& context) {
/* Empty the line ready to start a new line */ /* Empty the line ready to start a new line */
cmd_line.clear(); 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) { if (CMD_EXEC_FATAL_ERROR == status) {
VTR_LOG("Fatal error occurred!\nAbort and enter interactive mode\n"); VTR_LOG("Fatal error occurred!\n");
/* 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; break;
} }
} }
} }
fp.close(); fp.close();
/* Return to interactive mode, stay tuned */ /* If not in batch mode, switch to interactive mode, stay tuned */
run_interactive_mode(context, true); if (!batch_mode) {
run_interactive_mode(context, true);
}
} }
template <class T> template <class T>
@ -392,7 +405,7 @@ void Shell<T>::print_commands() const {
} }
template <class T> template <class T>
void Shell<T>::exit() const { int Shell<T>::exit_code() const {
/* Check all the command status, if we see fatal errors or minor errors, we drop an error code */ /* Check all the command status, if we see fatal errors or minor errors, we drop an error code */
int exit_code = 0; int exit_code = 0;
for (const int& status : command_status_) { for (const int& status : command_status_) {
@ -403,23 +416,41 @@ void Shell<T>::exit() const {
} }
} }
return exit_code;
}
template <class T>
int Shell<T>::execution_errors() const {
/* Show error message if we detect any errors */ /* Show error message if we detect any errors */
int num_err = 0; int num_err = 0;
if (0 != exit_code) {
VTR_LOG("\n"); for (const ShellCommandId& cmd : commands()) {
for (const ShellCommandId& cmd : commands()) { if (command_status_[cmd] == CMD_EXEC_FATAL_ERROR) {
if (command_status_[cmd] == CMD_EXEC_FATAL_ERROR) { VTR_LOG_ERROR("Command '%s' execution has fatal errors\n",
VTR_LOG_ERROR("Command '%s' execution has fatal errors\n", commands_[cmd].name().c_str());
commands_[cmd].name().c_str()); num_err++;
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++;
}
} }
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 <class T>
void Shell<T>::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() | init_err;
/* Show error message if we detect any errors */
int num_err = init_err;
if (CMD_EXEC_SUCCESS != shell_exit_code) {
VTR_LOG("\n");
num_err += execution_errors();
} }
VTR_LOG("\nFinish execution with %d errors\n", VTR_LOG("\nFinish execution with %d errors\n",
@ -431,7 +462,7 @@ void Shell<T>::exit() const {
VTR_LOG("\nThank you for using %s!\n", VTR_LOG("\nThank you for using %s!\n",
name().c_str()); name().c_str());
std::exit(exit_code); std::exit(shell_exit_code);
} }
/************************************************************************ /************************************************************************
@ -460,6 +491,7 @@ int Shell<T>::execute_command(const char* cmd_line,
commands_[dep_cmd].name().c_str(), commands_[cmd_id].name().c_str()); commands_[dep_cmd].name().c_str(), commands_[cmd_id].name().c_str());
/* Echo the command help desk */ /* Echo the command help desk */
print_command_options(commands_[cmd_id]); print_command_options(commands_[cmd_id]);
command_status_[cmd_id] = CMD_EXEC_FATAL_ERROR;
return CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR;
} }
} }
@ -494,6 +526,7 @@ int Shell<T>::execute_command(const char* cmd_line,
if (false == parse_command(tokens, commands_[cmd_id], command_contexts_[cmd_id])) { if (false == parse_command(tokens, commands_[cmd_id], command_contexts_[cmd_id])) {
/* Echo the command */ /* Echo the command */
print_command_options(commands_[cmd_id]); print_command_options(commands_[cmd_id]);
command_status_[cmd_id] = CMD_EXEC_FATAL_ERROR;
return CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR;
} }

View File

@ -29,9 +29,10 @@ int main(int argc, char** argv) {
/* Create the command to launch shell in different modes */ /* Create the command to launch shell in different modes */
openfpga::Command start_cmd("OpenFPGA"); openfpga::Command start_cmd("OpenFPGA");
/* Add two options: /* Add options:
* '--interactive', -i': launch the interactive mode * '--interactive', -i': launch the interactive mode
* '--file', -f': launch the script 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"); openfpga::CommandOptionId opt_interactive = start_cmd.add_option("interactive", false, "Launch OpenFPGA in interactive mode");
start_cmd.set_option_short_name(opt_interactive, "i"); 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_require_value(opt_script_mode, openfpga::OPT_STRING);
start_cmd.set_option_short_name(opt_script_mode, "f"); 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"); openfpga::CommandOptionId opt_help = start_cmd.add_option("help", false, "Help desk");
start_cmd.set_option_short_name(opt_help, "h"); start_cmd.set_option_short_name(opt_help, "h");
@ -95,17 +99,21 @@ int main(int argc, char** argv) {
if (true == start_cmd_context.option_enable(start_cmd, opt_interactive)) { if (true == start_cmd_context.option_enable(start_cmd, opt_interactive)) {
shell.run_interactive_mode(openfpga_context); shell.run_interactive_mode(openfpga_context);
return 0; return shell.exit_code();
} }
if (true == start_cmd_context.option_enable(start_cmd, opt_script_mode)) { 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(), shell.run_script_mode(start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(),
openfpga_context); openfpga_context,
return 0; start_cmd_context.option_enable(start_cmd, opt_batch_exec));
return shell.exit_code();
} }
/* Reach here there is something wrong, show the help desk */ /* Reach here there is something wrong, show the help desk */
openfpga::print_command_options(start_cmd); 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;
} }