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

View File

@ -143,11 +143,17 @@ 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;
/* 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;
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

View File

@ -272,7 +272,9 @@ void Shell<T>::run_interactive_mode(T& context, const bool& quiet_mode) {
}
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();
@ -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 */
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 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;
}
}
}
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 <class T>
@ -392,7 +405,7 @@ void Shell<T>::print_commands() const {
}
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 */
int exit_code = 0;
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 */
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 <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",
@ -431,7 +462,7 @@ void Shell<T>::exit() const {
VTR_LOG("\nThank you for using %s!\n",
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());
/* Echo the command help desk */
print_command_options(commands_[cmd_id]);
command_status_[cmd_id] = 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])) {
/* Echo the command */
print_command_options(commands_[cmd_id]);
command_status_[cmd_id] = 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 */
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");
@ -95,17 +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);
return 0;
openfpga_context,
start_cmd_context.option_enable(start_cmd, opt_batch_exec));
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;
}