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";
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();
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)
log_errfile = NULL;
log_files.clear();
+ Pass::done_register();
+
return 0;
}
#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;
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()
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);
}
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)
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)
{
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;
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;
{
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;
};
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;