From ae731369ddb8838302b5d9a3fa32689c44ab7934 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 6 Jan 2013 13:50:30 +0100 Subject: [PATCH] Improvements in command shell - Added 'shell' command (run interactive shell from synth script) - Added support for ; as cmd seperator as in "proc; opt" - Fixed c++ static initialization order problem with pass register --- kernel/driver.cc | 65 +++++++++++++++++++++++--------------- kernel/register.cc | 78 ++++++++++++++++++++++++++++++++++++++-------- kernel/register.h | 9 ++++++ 3 files changed, 114 insertions(+), 38 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index c49bf6575..ae1796757 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -140,6 +140,40 @@ static const char *create_prompt(RTLIL::Design *design) return buffer; } +static void shell(RTLIL::Design *design) +{ + log_cmd_error_throw = true; + + rl_readline_name = "yosys"; + rl_attempted_completion_function = readline_completion; + + char *command = NULL; + while ((command = readline(create_prompt(design))) != NULL) + { + if (command[strspn(command, " \t\r\n")] == 0) + continue; + add_history(command); + + try { + assert(design->selection_stack.size() == 1); + Pass::call(design, command); + } catch (int) { + while (design->selection_stack.size() > 1) + design->selection_stack.pop_back(); + log_reset_stack(); + } + } + + log_cmd_error_throw = false; +} + +struct ShellPass : public Pass { + ShellPass() : Pass("shell") { } + virtual void execute(std::vector, RTLIL::Design *design) { + shell(design); + } +} ShellPass; + int main(int argc, char **argv) { std::string frontend_command = "auto"; @@ -149,6 +183,8 @@ int main(int argc, char **argv) std::string scriptfile = ""; bool got_output_filename = false; + Pass::init_register(); + RTLIL::Design *design = new RTLIL::Design; design->selection_stack.push_back(RTLIL::Selection()); log_push(); @@ -196,33 +232,10 @@ int main(int argc, char **argv) if (log_errfile == NULL) log_files.push_back(stderr); - if (optind == argc && passes_commands.size() == 0 && scriptfile.empty()) - { - log_cmd_error_throw = true; - - rl_readline_name = "yosys"; - rl_attempted_completion_function = readline_completion; - - char *command = NULL; - while ((command = readline(create_prompt(design))) != NULL) - { - if (command[strspn(command, " \t\r\n")] == 0) - continue; - add_history(command); - - try { - assert(design->selection_stack.size() == 1); - Pass::call(design, command); - } catch (int) { - while (design->selection_stack.size() > 1) - design->selection_stack.pop_back(); - log_reset_stack(); - } - } - + if (optind == argc && passes_commands.size() == 0 && scriptfile.empty()) { if (!got_output_filename) backend_command = ""; - log_cmd_error_throw = false; + shell(design); } while (optind < argc) @@ -248,6 +261,8 @@ int main(int argc, char **argv) log_errfile = NULL; log_files.clear(); + Pass::done_register(); + return 0; } diff --git a/kernel/register.cc b/kernel/register.cc index fb70c80d9..302a8f6c3 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -23,8 +23,14 @@ #include using namespace REGISTER_INTERN; +#define MAX_REG_COUNT 1000 + +namespace REGISTER_INTERN +{ + int raw_register_count = 0; + bool raw_register_done = false; + Pass *raw_register_array[MAX_REG_COUNT]; -namespace REGISTER_INTERN { std::map frontend_register; std::map pass_register; std::map backend_register; @@ -34,13 +40,36 @@ std::vector Frontend::next_args; Pass::Pass(std::string name) : pass_name(name) { - assert(pass_register.count(name) == 0); - pass_register[name] = this; + assert(!raw_register_done); + assert(raw_register_count < MAX_REG_COUNT); + raw_register_array[raw_register_count++] = this; +} + +void Pass::run_register() +{ + assert(pass_register.count(pass_name) == 0); + pass_register[pass_name] = this; +} + +void Pass::init_register() +{ + if (raw_register_done) + done_register(); + while (raw_register_count > 0) + raw_register_array[--raw_register_count]->run_register(); + raw_register_done = true; +} + +void Pass::done_register() +{ + frontend_register.clear(); + pass_register.clear(); + backend_register.clear(); + raw_register_done = false; } Pass::~Pass() { - pass_register.erase(pass_name); } void Pass::help() @@ -92,9 +121,20 @@ void Pass::extra_args(std::vector args, size_t argidx, RTLIL::Desig void Pass::call(RTLIL::Design *design, std::string command) { std::vector args; - char *s = strdup(command.c_str()); - for (char *p = strtok(s, " \t\r\n"); p; p = strtok(NULL, " \t\r\n")) - args.push_back(p); + char *s = strdup(command.c_str()), *saveptr; + for (char *p = strtok_r(s, " \t\r\n", &saveptr); p; p = strtok_r(NULL, " \t\r\n", &saveptr)) { + std::string str = p; + int strsz = str.size(); + if (strsz > 0 && str[strsz-1] == ';') { + while (strsz > 0 && str[strsz-1] == ';') + strsz--; + if (strsz > 0) + args.push_back(str.substr(0, strsz)); + call(design, args); + args.clear(); + } else + args.push_back(str); + } free(s); call(design, args); } @@ -114,13 +154,19 @@ void Pass::call(RTLIL::Design *design, std::vector args) Frontend::Frontend(std::string name) : Pass("read_"+name), frontend_name(name) { - assert(frontend_register.count(name) == 0); - frontend_register[name] = this; +} + +void Frontend::run_register() +{ + assert(pass_register.count(pass_name) == 0); + pass_register[pass_name] = this; + + assert(frontend_register.count(frontend_name) == 0); + frontend_register[frontend_name] = this; } Frontend::~Frontend() { - frontend_register.erase(frontend_name); } void Frontend::execute(std::vector args, RTLIL::Design *design) @@ -200,13 +246,19 @@ void Frontend::frontend_call(RTLIL::Design *design, FILE *f, std::string filenam Backend::Backend(std::string name) : Pass("write_"+name), backend_name(name) { - assert(backend_register.count(name) == 0); - backend_register[name] = this; +} + +void Backend::run_register() +{ + assert(pass_register.count(pass_name) == 0); + pass_register[pass_name] = this; + + assert(backend_register.count(backend_name) == 0); + backend_register[backend_name] = this; } Backend::~Backend() { - backend_register.erase(backend_name); } void Backend::execute(std::vector args, RTLIL::Design *design) diff --git a/kernel/register.h b/kernel/register.h index 713d468e3..56350be34 100644 --- a/kernel/register.h +++ b/kernel/register.h @@ -30,6 +30,7 @@ struct Pass { std::string pass_name; Pass(std::string name); + virtual void run_register(); virtual ~Pass(); virtual void help(); virtual void execute(std::vector args, RTLIL::Design *design) = 0; @@ -40,12 +41,16 @@ struct Pass static void call(RTLIL::Design *design, std::string command); static void call(RTLIL::Design *design, std::vector args); + + static void init_register(); + static void done_register(); }; struct Frontend : Pass { std::string frontend_name; Frontend(std::string name); + virtual void run_register(); virtual ~Frontend(); virtual void execute(std::vector args, RTLIL::Design *design); virtual void execute(FILE *&f, std::string filename, std::vector args, RTLIL::Design *design) = 0; @@ -61,6 +66,7 @@ struct Backend : Pass { std::string backend_name; Backend(std::string name); + virtual void run_register(); virtual ~Backend(); virtual void execute(std::vector args, RTLIL::Design *design); virtual void execute(FILE *&f, std::string filename, std::vector args, RTLIL::Design *design) = 0; @@ -72,6 +78,9 @@ struct Backend : Pass }; namespace REGISTER_INTERN { + extern int raw_register_count; + extern bool raw_register_done; + extern Pass *raw_register_array[]; extern std::map pass_register; extern std::map frontend_register; extern std::map backend_register; -- 2.30.2