kernel/mem: Add functions to emulate read port enable/init/reset signals.
[yosys.git] / kernel / yosys.cc
index 6009d6647baebfd7e04cd89ff566e000bcd8dad7..102f9e737e87e76634609a18cf4ca2f15effdf11 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  yosys -- Yosys Open SYnthesis Suite
  *
- *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
  *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
 #  include <unistd.h>
 #  include <dirent.h>
 #  include <sys/types.h>
-#  include <sys/wait.h>
 #  include <sys/stat.h>
+#  if !defined(YOSYS_DISABLE_SPAWN)
+#    include <sys/wait.h>
+#  endif
 #endif
 
 #if !defined(_WIN32) && defined(YOSYS_ENABLE_GLOB)
@@ -65,6 +67,7 @@
 #   define INIT_MODULE initlibyosys
        extern "C" void INIT_MODULE();
 #endif
+#include <signal.h>
 #endif
 
 #include <limits.h>
@@ -87,6 +90,12 @@ bool memhasher_active = false;
 uint32_t memhasher_rng = 123456;
 std::vector<void*> memhasher_store;
 
+std::string yosys_share_dirname;
+std::string yosys_abc_executable;
+
+void init_share_dirname();
+void init_abc_executable_name();
+
 void memhasher_on()
 {
 #if defined(__linux__) || defined(__FreeBSD__)
@@ -129,7 +138,7 @@ void yosys_banner()
        log(" |                                                                            |\n");
        log(" |  yosys -- Yosys Open SYnthesis Suite                                       |\n");
        log(" |                                                                            |\n");
-       log(" |  Copyright (C) 2012 - 2020  Claire Wolf <claire@symbioticeda.com>          |\n");
+       log(" |  Copyright (C) 2012 - 2020  Claire Xenia Wolf <claire@yosyshq.com>         |\n");
        log(" |                                                                            |\n");
        log(" |  Permission to use, copy, modify, and/or distribute this software for any  |\n");
        log(" |  purpose with or without fee is hereby granted, provided that the above    |\n");
@@ -336,16 +345,13 @@ bool patmatch(const char *pattern, const char *string)
        return false;
 }
 
+#if !defined(YOSYS_DISABLE_SPAWN)
 int run_command(const std::string &command, std::function<void(const std::string&)> process_line)
 {
        if (!process_line)
                return system(command.c_str());
 
-#ifdef EMSCRIPTEN
-       FILE *f = nullptr;
-#else
        FILE *f = popen(command.c_str(), "r");
-#endif
        if (f == nullptr)
                return -1;
 
@@ -368,10 +374,16 @@ int run_command(const std::string &command, std::function<void(const std::string
        return WEXITSTATUS(ret);
 #endif
 }
+#endif
 
 std::string make_temp_file(std::string template_str)
 {
-#ifdef _WIN32
+#if defined(__wasm)
+       size_t pos = template_str.rfind("XXXXXX");
+       log_assert(pos != std::string::npos);
+       static size_t index = 0;
+       template_str.replace(pos, 6, stringf("%06zu", index++));
+#elif defined(_WIN32)
        if (template_str.rfind("/tmp/", 0) == 0) {
 #  ifdef __MINGW32__
                char longpath[MAX_PATH + 1];
@@ -420,10 +432,14 @@ std::string make_temp_file(std::string template_str)
 
 std::string make_temp_dir(std::string template_str)
 {
-#ifdef _WIN32
+#if defined(_WIN32)
        template_str = make_temp_file(template_str);
        mkdir(template_str.c_str());
        return template_str;
+#elif defined(__wasm)
+       template_str = make_temp_file(template_str);
+       mkdir(template_str.c_str(), 0777);
+       return template_str;
 #else
 #  ifndef NDEBUG
        size_t pos = template_str.rfind("XXXXXX");
@@ -514,6 +530,8 @@ void yosys_setup()
        if(already_setup)
                return;
        already_setup = true;
+       init_share_dirname();
+       init_abc_executable_name();
 
 #define X(_id) RTLIL::ID::_id = "\\" # _id;
 #include "kernel/constids.inc"
@@ -523,6 +541,7 @@ void yosys_setup()
                PyImport_AppendInittab((char*)"libyosys", INIT_MODULE);
                Py_Initialize();
                PyRun_SimpleString("import sys");
+               signal(SIGINT, SIG_DFL);
        #endif
 
        Pass::init_register();
@@ -704,7 +723,7 @@ extern Tcl_Interp *yosys_get_tcl_interp()
 
 struct TclPass : public Pass {
        TclPass() : Pass("tcl", "execute a TCL script file") { }
-       void help() YS_OVERRIDE {
+       void help() override {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
                log("    tcl <filename> [args]\n");
@@ -721,7 +740,7 @@ struct TclPass : public Pass {
                log("the standard $argc and $argv variables.\n");
                log("\n");
        }
-       void execute(std::vector<std::string> args, RTLIL::Design *) YS_OVERRIDE {
+       void execute(std::vector<std::string> args, RTLIL::Design *) override {
                if (args.size() < 2)
                        log_cmd_error("Missing script file.\n");
 
@@ -780,7 +799,9 @@ std::string proc_self_dirname()
                path = (char *) realloc((void *) path, buflen);
        while (buflen > 0 && path[buflen-1] != '/')
                buflen--;
-       return std::string(path, buflen);
+       std::string str(path, buflen);
+       free(path);
+       return str;
 }
 #elif defined(_WIN32)
 std::string proc_self_dirname()
@@ -806,7 +827,7 @@ std::string proc_self_dirname()
                path += char(shortpath[i]);
        return path;
 }
-#elif defined(EMSCRIPTEN)
+#elif defined(EMSCRIPTEN) || defined(__wasm)
 std::string proc_self_dirname()
 {
        return "/";
@@ -815,39 +836,84 @@ std::string proc_self_dirname()
        #error "Don't know how to determine process executable base path!"
 #endif
 
-#ifdef EMSCRIPTEN
-std::string proc_share_dirname()
+#if defined(EMSCRIPTEN) || defined(__wasm)
+void init_share_dirname()
 {
-       return "/share/";
+       yosys_share_dirname = "/share/";
 }
 #else
-std::string proc_share_dirname()
+void init_share_dirname()
 {
        std::string proc_self_path = proc_self_dirname();
 #  if defined(_WIN32) && !defined(YOSYS_WIN32_UNIX_DIR)
        std::string proc_share_path = proc_self_path + "share\\";
-       if (check_file_exists(proc_share_path, true))
-               return proc_share_path;
+       if (check_file_exists(proc_share_path, true)) {
+               yosys_share_dirname = proc_share_path;
+               return;
+       }
        proc_share_path = proc_self_path + "..\\share\\";
-       if (check_file_exists(proc_share_path, true))
-               return proc_share_path;
+       if (check_file_exists(proc_share_path, true)) {
+               yosys_share_dirname = proc_share_path;
+               return;
+       }
 #  else
        std::string proc_share_path = proc_self_path + "share/";
-       if (check_file_exists(proc_share_path, true))
-               return proc_share_path;
-       proc_share_path = proc_self_path + "../share/yosys/";
-       if (check_file_exists(proc_share_path, true))
-               return proc_share_path;
+       if (check_file_exists(proc_share_path, true)) {
+               yosys_share_dirname = proc_share_path;
+               return;
+       }
+       proc_share_path = proc_self_path + "../share/" + proc_program_prefix()+ "yosys/";
+       if (check_file_exists(proc_share_path, true)) {
+               yosys_share_dirname = proc_share_path;
+               return;
+       }
 #    ifdef YOSYS_DATDIR
        proc_share_path = YOSYS_DATDIR "/";
-       if (check_file_exists(proc_share_path, true))
-               return proc_share_path;
+       if (check_file_exists(proc_share_path, true)) {
+               yosys_share_dirname = proc_share_path;
+               return;
+       }
 #    endif
 #  endif
-       log_error("proc_share_dirname: unable to determine share/ directory!\n");
 }
 #endif
 
+void init_abc_executable_name()
+{
+#ifdef ABCEXTERNAL
+       std::string exe_file;
+       if (std::getenv("ABC")) {
+               yosys_abc_executable = std::getenv("ABC");
+       } else {
+               yosys_abc_executable = ABCEXTERNAL;
+       }
+#else
+       yosys_abc_executable = proc_self_dirname() + proc_program_prefix()+ "yosys-abc";
+#endif
+#ifdef _WIN32
+#ifndef ABCEXTERNAL
+       if (!check_file_exists(yosys_abc_executable + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc.exe"))
+               yosys_abc_executable = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
+#endif
+#endif
+}
+
+std::string proc_share_dirname()
+{
+       if (yosys_share_dirname.empty())
+               log_error("init_share_dirname: unable to determine share/ directory!\n");
+       return yosys_share_dirname;
+}
+
+std::string proc_program_prefix()
+{
+       std::string program_prefix;
+#ifdef YOSYS_PROGRAM_PREFIX
+       program_prefix = YOSYS_PROGRAM_PREFIX;
+#endif
+       return program_prefix;
+}
+
 bool fgetline(FILE *f, std::string &buffer)
 {
        buffer = "";
@@ -890,7 +956,7 @@ static void handle_label(std::string &command, bool &from_to_active, const std::
        }
 }
 
-void run_frontend(std::string filename, std::string command, std::string *backend_command, std::string *from_to_label, RTLIL::Design *design)
+bool run_frontend(std::string filename, std::string command, RTLIL::Design *design, std::string *from_to_label)
 {
        if (design == nullptr)
                design = yosys_design;
@@ -900,11 +966,11 @@ void run_frontend(std::string filename, std::string command, std::string *backen
                if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".gz") == 0)
                        filename_trim.erase(filename_trim.size()-3);
                if (filename_trim.size() > 2 && filename_trim.compare(filename_trim.size()-2, std::string::npos, ".v") == 0)
-                       command = "verilog";
+                       command = " -vlog2k";
                else if (filename_trim.size() > 2 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".sv") == 0)
-                       command = "verilog -sv";
+                       command = " -sv";
                else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".vhd") == 0)
-                       command = "vhdl";
+                       command = " -vhdl";
                else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-5, std::string::npos, ".blif") == 0)
                        command = "blif";
                else if (filename_trim.size() > 5 && filename_trim.compare(filename_trim.size()-6, std::string::npos, ".eblif") == 0)
@@ -912,7 +978,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
                else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-5, std::string::npos, ".json") == 0)
                        command = "json";
                else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".il") == 0)
-                       command = "ilang";
+                       command = "rtlil";
                else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".ys") == 0)
                        command = "script";
                else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".tcl") == 0)
@@ -990,10 +1056,12 @@ void run_frontend(std::string filename, std::string command, std::string *backen
                if (filename != "-")
                        fclose(f);
 
-               if (backend_command != NULL && *backend_command == "auto")
-                       *backend_command = "";
+               return true;
+       }
 
-               return;
+       if (command == "tcl") {
+               Pass::call(design, vector<string>({command, filename}));
+               return true;
        }
 
        if (filename == "-") {
@@ -1002,16 +1070,15 @@ void run_frontend(std::string filename, std::string command, std::string *backen
                log("\n-- Parsing `%s' using frontend `%s' --\n", filename.c_str(), command.c_str());
        }
 
-       if (command == "tcl")
-               Pass::call(design, vector<string>({command, filename}));
-       else
+       if (command[0] == ' ') {
+               auto argv = split_tokens("read" + command);
+               argv.push_back(filename);
+               Pass::call(design, argv);
+       } else
                Frontend::frontend_call(design, NULL, filename, command);
-       design->check();
-}
 
-void run_frontend(std::string filename, std::string command, RTLIL::Design *design)
-{
-       run_frontend(filename, command, nullptr, nullptr, design);
+       design->check();
+       return false;
 }
 
 void run_pass(std::string command, RTLIL::Design *design)
@@ -1032,8 +1099,12 @@ void run_backend(std::string filename, std::string command, RTLIL::Design *desig
        if (command == "auto") {
                if (filename.size() > 2 && filename.compare(filename.size()-2, std::string::npos, ".v") == 0)
                        command = "verilog";
+               else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".sv") == 0)
+                       command = "verilog -sv";
                else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0)
-                       command = "ilang";
+                       command = "rtlil";
+               else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".cc") == 0)
+                       command = "cxxrtl";
                else if (filename.size() > 4 && filename.compare(filename.size()-4, std::string::npos, ".aig") == 0)
                        command = "aiger";
                else if (filename.size() > 5 && filename.compare(filename.size()-5, std::string::npos, ".blif") == 0)
@@ -1043,7 +1114,7 @@ void run_backend(std::string filename, std::string command, RTLIL::Design *desig
                else if (filename.size() > 5 && filename.compare(filename.size()-5, std::string::npos, ".json") == 0)
                        command = "json";
                else if (filename == "-")
-                       command = "ilang";
+                       command = "rtlil";
                else if (filename.empty())
                        return;
                else
@@ -1200,7 +1271,7 @@ void shell(RTLIL::Design *design)
 
 struct ShellPass : public Pass {
        ShellPass() : Pass("shell", "enter interactive command mode") { }
-       void help() YS_OVERRIDE {
+       void help() override {
                log("\n");
                log("    shell\n");
                log("\n");
@@ -1232,7 +1303,7 @@ struct ShellPass : public Pass {
                log("Press Ctrl-D or type 'exit' to leave the interactive shell.\n");
                log("\n");
        }
-       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
+       void execute(std::vector<std::string> args, RTLIL::Design *design) override {
                extra_args(args, 1, design, false);
                shell(design);
        }
@@ -1241,7 +1312,7 @@ struct ShellPass : public Pass {
 #if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE)
 struct HistoryPass : public Pass {
        HistoryPass() : Pass("history", "show last interactive commands") { }
-       void help() YS_OVERRIDE {
+       void help() override {
                log("\n");
                log("    history\n");
                log("\n");
@@ -1250,7 +1321,7 @@ struct HistoryPass : public Pass {
                log("from executed scripts.\n");
                log("\n");
        }
-       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
+       void execute(std::vector<std::string> args, RTLIL::Design *design) override {
                extra_args(args, 1, design, false);
 #ifdef YOSYS_ENABLE_READLINE
                for(HIST_ENTRY **list = history_list(); *list != NULL; list++)
@@ -1265,7 +1336,7 @@ struct HistoryPass : public Pass {
 
 struct ScriptCmdPass : public Pass {
        ScriptCmdPass() : Pass("script", "execute commands from file or wire") { }
-       void help() YS_OVERRIDE {
+       void help() override {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
                log("    script <filename> [<from_label>:<to_label>]\n");
@@ -1288,7 +1359,7 @@ struct ScriptCmdPass : public Pass {
                log("'-module' mode can be exited by using the 'cd' command.\n");
                log("\n");
        }
-       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+       void execute(std::vector<std::string> args, RTLIL::Design *design) override
        {
                bool scriptwire = false;
 
@@ -1321,7 +1392,7 @@ struct ScriptCmdPass : public Pass {
                else if (args.size() == 2)
                        run_frontend(args[1], "script", design);
                else if (args.size() == 3)
-                       run_frontend(args[1], "script", NULL, &args[2], design);
+                       run_frontend(args[1], "script", design, &args[2]);
                else
                        extra_args(args, 2, design, false);
        }