add macro function support to openfpga shell and update unit test

This commit is contained in:
tangxifan 2020-01-22 19:30:36 -07:00
parent 558f0bb1bd
commit e983966a08
4 changed files with 59 additions and 1 deletions

View File

@ -61,6 +61,7 @@ class Shell {
STANDARD,
SHORT,
BUILTIN,
MACRO,
NUM_EXEC_FUNC_TYPES
};
public: /* Constructor */
@ -89,6 +90,7 @@ class Shell {
* 1. Standard function, including the data exchange <T> and commands
* 2. Short function, including only the data exchange <T>
* 3. Built-in function, including only the shell envoriment variables
* 4. Marco function, which directly call a macro function without command parsing
* Users just need to specify the function object and its type will be automatically inferred
*/
void set_command_execute_function(const ShellCommandId& cmd_id,
@ -97,6 +99,8 @@ class Shell {
std::function<void(T&)> exec_func);
void set_command_execute_function(const ShellCommandId& cmd_id,
std::function<void()> exec_func);
void set_command_execute_function(const ShellCommandId& cmd_id,
std::function<void(int, char**)> exec_func);
void set_command_dependency(const ShellCommandId& cmd_id,
const std::vector<ShellCommandId> cmd_dependency);
ShellCommandClassId add_command_class(const char* name);
@ -150,10 +154,12 @@ class Shell {
* 1. Standard function, including the data exchange <T> and commands
* 2. Short function, including only the data exchange <T>
* 3. Built-in function, including only the shell envoriment variables
* 4. Marco function, which directly call a macro function without command parsing
*/
vtr::vector<ShellCommandId, std::function<void(T&, const Command&, const CommandContext&)>> command_standard_execute_functions_;
vtr::vector<ShellCommandId, std::function<void(T&)>> command_short_execute_functions_;
vtr::vector<ShellCommandId, std::function<void()>> command_builtin_execute_functions_;
vtr::vector<ShellCommandId, std::function<void(int, char**)>> command_macro_execute_functions_;
/* Type of execute functions for each command.
* This is supposed to be an internal data ONLY

View File

@ -128,6 +128,7 @@ ShellCommandId Shell<T>::add_command(const Command& cmd, const char* descr) {
command_standard_execute_functions_.emplace_back();
command_short_execute_functions_.emplace_back();
command_builtin_execute_functions_.emplace_back();
command_macro_execute_functions_.emplace_back();
command_dependencies_.emplace_back();
/* Register the name in the name2id map */
@ -173,6 +174,14 @@ void Shell<T>::set_command_execute_function(const ShellCommandId& cmd_id,
command_builtin_execute_functions_[cmd_id] = exec_func;
}
template<class T>
void Shell<T>::set_command_execute_function(const ShellCommandId& cmd_id,
std::function<void(int, char**)> exec_func) {
VTR_ASSERT(true == valid_command_id(cmd_id));
command_execute_function_types_[cmd_id] = MACRO;
command_macro_execute_functions_[cmd_id] = exec_func;
}
template<class T>
void Shell<T>::set_command_dependency(const ShellCommandId& cmd_id,
const std::vector<ShellCommandId> dependent_cmds) {
@ -337,7 +346,28 @@ void Shell<T>::execute_command(const char* cmd_line,
/* TODO: Check the dependency graph to see if all the prequistics have been met */
/* Find the command! Parse the options */
/* Find the command! Parse the options
* Note:
* Macro command will not be parsed! It will be directly executed
*/
if (MACRO == command_execute_function_types_[cmd_id]) {
/* Convert the tokens from string to char */
char** argv = (char**)malloc(tokens.size() * sizeof(char*));
for (size_t itok = 0; itok < tokens.size(); ++itok) {
argv[itok] = (char*)malloc((tokens[itok].length() + 1) * sizeof(char));
strcpy(argv[itok], tokens[itok].c_str());
}
/* Execute the marco function */
command_macro_execute_functions_[cmd_id](tokens.size(), argv);
/* Free the argv */
for (size_t itok = 0; itok < tokens.size(); ++itok) {
free(argv[itok]);
}
free(argv);
/* Finish for macro command, return */
return;
}
if (false == parse_command(tokens, commands_[cmd_id], command_contexts_[cmd_id])) {
/* Echo the command */
print_command_options(commands_[cmd_id]);
@ -358,6 +388,7 @@ void Shell<T>::execute_command(const char* cmd_line,
case BUILTIN:
command_builtin_execute_functions_[cmd_id]();
break;
/* MACRO should be executed eariler in this function. It should not appear here */
default:
/* This is not allowed! Error out */
VTR_LOG("Invalid type of execute function for command '%s'!\n",

View File

@ -27,6 +27,15 @@ void shell_execute_print(ShellContext& context) {
VTR_LOG("a=%d\n", context.a);
}
static
void shell_execute_print_macro(int argc, char** argv) {
VTR_LOG("Number of arguments: %d\n", argc);
VTR_LOG("Detailed arguments:\n");
for (int iarg = 0; iarg < argc; ++iarg) {
VTR_LOG("\t[%d]: %s\n", iarg, argv[iarg]);
}
}
int main(int argc, char** argv) {
/* Create the command to launch shell in different modes */
Command start_cmd("test_shell");
@ -97,6 +106,15 @@ int main(int argc, char** argv) {
shell.set_command_class(shell_cmd_print_id, arith_cmd_class);
shell.set_command_execute_function(shell_cmd_print_id, shell_execute_print);
/* Create a macro command of 'print_macro'
* This function will print the value of an internal variable of ShellContext
*/
Command shell_cmd_print_macro("print_macro");
ShellCommandId shell_cmd_print_macro_id = shell.add_command(shell_cmd_print_macro, "A macro function to print arguments");
shell.set_command_class(shell_cmd_print_macro_id, arith_cmd_class);
shell.set_command_execute_function(shell_cmd_print_macro_id, shell_execute_print_macro);
/* Add a new class of commands */
ShellCommandClassId basic_cmd_class = shell.add_command_class("Basic");

View File

@ -6,4 +6,7 @@ set --value 5
print # Print out the value
# Test macro arguments
print_macro arch blif
exit # Finish