summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/driver.cc65
-rw-r--r--kernel/register.cc78
-rw-r--r--kernel/register.h9
3 files changed, 114 insertions, 38 deletions
diff --git a/kernel/driver.cc b/kernel/driver.cc
index c49bf657..ae179675 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<std::string>, 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 fb70c80d..302a8f6c 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -23,8 +23,14 @@
#include <string.h>
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<std::string, Frontend*> frontend_register;
std::map<std::string, Pass*> pass_register;
std::map<std::string, Backend*> backend_register;
@@ -34,13 +40,36 @@ std::vector<std::string> 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<std::string> args, size_t argidx, RTLIL::Desig
void Pass::call(RTLIL::Design *design, std::string command)
{
std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> args, RTLIL::Design *design)
diff --git a/kernel/register.h b/kernel/register.h
index 713d468e..56350be3 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<std::string> 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<std::string> 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<std::string> args, RTLIL::Design *design);
virtual void execute(FILE *&f, std::string filename, std::vector<std::string> 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<std::string> args, RTLIL::Design *design);
virtual void execute(FILE *&f, std::string filename, std::vector<std::string> 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<std::string, Pass*> pass_register;
extern std::map<std::string, Frontend*> frontend_register;
extern std::map<std::string, Backend*> backend_register;