Added emscripten (emcc) support to build system and some build fixes
authorClifford Wolf <clifford@clifford.at>
Fri, 22 Aug 2014 14:09:13 +0000 (16:09 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 22 Aug 2014 14:20:22 +0000 (16:20 +0200)
Makefile
frontends/ast/ast.cc
frontends/ast/dpicall.cc
kernel/celltypes.h
kernel/compatibility.cc
kernel/driver.cc
kernel/rtlil.cc
kernel/rtlil.h
kernel/yosys.cc
passes/cmds/plugin.cc
passes/cmds/show.cc

index 8d7f2f8dd6fca116997b5c8d092163a4a38d5a03..ca595d9cd1c362410aa28a6e0ee7f034802064a0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,11 +2,14 @@
 CONFIG := clang
 # CONFIG := gcc
 # CONFIG := gcc-4.6
+# CONFIG := emcc
 
 # features (the more the better)
 ENABLE_TCL := 1
 ENABLE_QT4 := 1
 ENABLE_ABC := 1
+ENABLE_PLUGINS := 1
+ENABLE_READLINE := 1
 ENABLE_VERIFIC := 0
 
 # other configuration flags
@@ -27,7 +30,7 @@ all: top-all
 
 CXXFLAGS = -Wall -Wextra -ggdb -I"$(shell pwd)" -MD -DYOSYS_SRC='"$(shell pwd)"' -D_YOSYS_ -fPIC -I${DESTDIR}/include
 LDFLAGS = -L${DESTDIR}/lib
-LDLIBS = -lstdc++ -lreadline -lm -lffi -ldl
+LDLIBS = -lstdc++ -lm
 QMAKE = qmake-qt4
 SED = sed
 
@@ -72,6 +75,22 @@ CXX = gcc-4.6
 CXXFLAGS += -std=gnu++0x -Os
 endif
 
+ifeq ($(CONFIG),emcc)
+CXX = emcc
+CXXFLAGS += -std=c++11 -Os -Wno-warn-absolute-paths
+CXXFLAGS := $(filter-out -ggdb,$(CXXFLAGS))
+endif
+
+ifeq ($(ENABLE_READLINE),1)
+CXXFLAGS += -DYOSYS_ENABLE_READLINE
+LDLIBS += -lreadline
+endif
+
+ifeq ($(ENABLE_PLUGINS),1)
+CXXFLAGS += -DYOSYS_ENABLE_PLUGINS
+LDLIBS += -lffi -ldl
+endif
+
 ifeq ($(ENABLE_TCL),1)
 TCL_VERSION ?= tcl8.5
 TCL_INCLUDE ?= /usr/include/$(TCL_VERSION)
@@ -290,6 +309,14 @@ config-gcc: clean
 config-gcc-4.6: clean
        echo 'CONFIG := gcc-4.6' > Makefile.conf
 
+config-emcc: clean
+       echo 'CONFIG := emcc' > Makefile.conf
+       echo 'ENABLE_TCL := 0' >> Makefile.conf
+       echo 'ENABLE_QT4 := 0' >> Makefile.conf
+       echo 'ENABLE_ABC := 0' >> Makefile.conf
+       echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
+       echo 'ENABLE_READLINE := 0' >> Makefile.conf
+
 config-gprof: clean
        echo 'CONFIG := gcc' > Makefile.conf
        echo 'ENABLE_GPROF := 1' >> Makefile.conf
index 2fc8f9835aef6ec15861973de69f5c4954be67c0..1e43875ae5aea73f9aa04d20fc5d0ad965e9b2c4 100644 (file)
@@ -844,7 +844,11 @@ RTLIL::Const AstNode::realAsConst(int width)
 {
        double v = round(realvalue);
        RTLIL::Const result;
+#ifdef EMSCRIPTEN
+       if (!isfinite(v)) {
+#else
        if (!std::isfinite(v)) {
+#endif
                result.bits = std::vector<RTLIL::State>(width, RTLIL::State::Sx);
        } else {
                bool is_negative = v < 0;
index b79bd59ebb89cbf96a4d4d27274a0098f99b0700..2eb104fa048fc69820471db4fd22bf2bf667fa68 100644 (file)
  *
  */
 
+#include "ast.h"
+
+#ifdef YOSYS_ENABLE_PLUGINS
+
 #include <dlfcn.h>
 #include <ffi.h>
-#include "ast.h"
 
 typedef void (*ffi_fptr) ();
 
@@ -126,3 +129,12 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname,
        return newNode;
 }
 
+#else /* YOSYS_ENABLE_PLUGINS */
+
+AST::AstNode *AST::dpi_call(const std::string&, const std::string &fname, const std::vector<std::string>&, const std::vector<AstNode*>&)
+{
+       log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname.c_str());
+}
+
+#endif /* YOSYS_ENABLE_PLUGINS */
+
index 8c2e9a48e54ee03a5dd1dfdb6e0b52f6125a8ae3..515da25ce2e11121b8f65c8f3a15e475b99c210a 100644 (file)
@@ -108,7 +108,7 @@ struct CellTypes
                for (auto type : std::vector<RTLIL::IdString>({"$mux", "$pmux"}))
                        setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
 
-               setup_type("$assert", {"\\A", "\\EN"}, {}, true);
+               setup_type("$assert", {"\\A", "\\EN"}, std::set<RTLIL::IdString>(), true);
        }
 
        void setup_internals_mem()
@@ -121,7 +121,7 @@ struct CellTypes
                setup_type("$dlatchsr", {"\\EN", "\\SET", "\\CLR", "\\D"}, {"\\Q"});
 
                setup_type("$memrd", {"\\CLK", "\\ADDR"}, {"\\DATA"});
-               setup_type("$memwr", {"\\CLK", "\\EN", "\\ADDR", "\\DATA"}, {});
+               setup_type("$memwr", {"\\CLK", "\\EN", "\\ADDR", "\\DATA"}, std::set<RTLIL::IdString>());
                setup_type("$mem", {"\\RD_CLK", "\\RD_ADDR", "\\WR_CLK", "\\WR_EN", "\\WR_ADDR", "\\WR_DATA"}, {"\\RD_DATA"});
 
                setup_type("$fsm", {"\\CLK", "\\ARST", "\\CTRL_IN"}, {"\\CTRL_OUT"});
index 2ef023eb3b3246905e7708fbeb43f7f113937a50..4c4cbd6de9f8e17aa2931739d8c2211e367c9d96 100644 (file)
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <errno.h>
 
-#if !(_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L)
+#if !(_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L || defined(EMSCRIPTEN))
 
 typedef struct memstream {
        off_t pos;
index 6bd60d7b56014a585a996a062526914325bd1274..e778e13897539fcb11210b6b3eb483fb8030c6f6 100644 (file)
 #include "kernel/yosys.h"
 #include "libs/sha1/sha1.h"
 
-#include <readline/readline.h>
-#include <readline/history.h>
+#ifdef YOSYS_ENABLE_READLINE
+#  include <readline/readline.h>
+#  include <readline/history.h>
+#endif
 
 #include <stdio.h>
 #include <string.h>
@@ -46,6 +48,7 @@ int main(int argc, char **argv)
        bool print_stats = true;
        bool call_abort = false;
 
+#ifdef YOSYS_ENABLE_READLINE
        int history_offset = 0;
        std::string history_file;
        if (getenv("HOME") != NULL) {
@@ -53,6 +56,7 @@ int main(int argc, char **argv)
                read_history(history_file.c_str());
                history_offset = where_history();
        }
+#endif
 
        int opt;
        while ((opt = getopt(argc, argv, "AQTVSm:f:Hh:b:o:p:l:qv:ts:c:")) != -1)
@@ -329,6 +333,7 @@ int main(int argc, char **argv)
        if (call_abort)
                abort();
 
+#ifdef YOSYS_ENABLE_READLINE
        if (!history_file.empty()) {
                if (history_offset > 0) {
                        history_truncate_file(history_file.c_str(), 100);
@@ -341,6 +346,7 @@ int main(int argc, char **argv)
        HIST_ENTRY **hist_list = history_list();
        if (hist_list != NULL)
                free(hist_list);
+#endif
 
        yosys_shutdown();
 
index 24cce6b8b211b26c485e841b693f07737909ab65..22bff7bdb3944acac1f509d45321e0f92a65fd04 100644 (file)
@@ -1605,6 +1605,10 @@ RTLIL::Memory::Memory()
        size = 0;
 }
 
+RTLIL::Cell::Cell() : module(nullptr)
+{
+}
+
 bool RTLIL::Cell::hasPort(RTLIL::IdString portname) const
 {
        return connections_.count(portname) != 0;
index 8b3306f6fac320d767bbbf7ee23ea03bdbe8e7e5..ebfe4ca296964a6c4c60c364ce26003035eb1314 100644 (file)
@@ -77,7 +77,7 @@ namespace RTLIL
                // the global id string cache
 
                struct char_ptr_cmp {
-                       bool operator()(const char *a, const char *b) {
+                       bool operator()(const char *a, const char *b) const {
                                for (int i = 0; a[i] || b[i]; i++)
                                        if (a[i] != b[i])
                                                return a[i] < b[i];
@@ -815,8 +815,7 @@ struct RTLIL::Cell
 protected:
        // use module->addCell() and module->remove() to create or destroy cells
        friend struct RTLIL::Module;
-       Cell() : module(nullptr) { };
-       ~Cell() { };
+       Cell();
 
 public:
        // do not simply copy cells
index ce24873142135398e760fe7b31e6326a33242eff..7b8173b6abf214b1caba04d8310b0e104acac8bf 100644 (file)
 
 #include "kernel/yosys.h"
 
-#include <readline/readline.h>
-#include <readline/history.h>
+#ifdef YOSYS_ENABLE_READLINE
+#  include <readline/readline.h>
+#  include <readline/history.h>
+#endif
 
 #include <dlfcn.h>
 #include <unistd.h>
 #include <limits.h>
+#include <errno.h>
 
 YOSYS_NAMESPACE_BEGIN
 
@@ -232,6 +235,11 @@ std::string proc_self_dirname ()
                buflen--;
        return std::string(path, buflen);
 }
+#elif defined(EMSCRIPTEN)
+std::string proc_self_dirname ()
+{
+       return "/";
+}
 #else
        #error Dont know how to determine process executable base path!
 #endif
@@ -416,6 +424,7 @@ void run_backend(std::string filename, std::string command, RTLIL::Design *desig
        Backend::backend_call(design, NULL, filename, command);
 }
 
+#ifdef YOSYS_ENABLE_READLINE
 static char *readline_cmd_generator(const char *text, int state)
 {
        static std::map<std::string, Pass*>::iterator it;
@@ -493,6 +502,7 @@ static char **readline_completion(const char *text, int start, int)
                return rl_completion_matches(text, readline_obj_generator);
        return NULL;
 }
+#endif
 
 void shell(RTLIL::Design *design)
 {
@@ -501,16 +511,25 @@ void shell(RTLIL::Design *design)
        recursion_counter++;
        log_cmd_error_throw = true;
 
+#ifdef YOSYS_ENABLE_READLINE
        rl_readline_name = "yosys";
        rl_attempted_completion_function = readline_completion;
        rl_basic_word_break_characters = " \t\n";
+#endif
 
        char *command = NULL;
+#ifdef YOSYS_ENABLE_READLINE
        while ((command = readline(create_prompt(design, recursion_counter))) != NULL)
+#else
+       char command_buffer[4096];
+       while ((command = fgets(command_buffer, 4096, stdin)) != NULL)
+#endif
        {
                if (command[strspn(command, " \t\r\n")] == 0)
                        continue;
+#ifdef YOSYS_ENABLE_READLINE
                add_history(command);
+#endif
 
                char *p = command + strspn(command, " \t\r\n");
                if (!strncmp(p, "exit", 4)) {
@@ -576,6 +595,7 @@ struct ShellPass : public Pass {
        }
 } ShellPass;
 
+#ifdef YOSYS_ENABLE_READLINE
 struct HistoryPass : public Pass {
        HistoryPass() : Pass("history", "show last interactive commands") { }
        virtual void help() {
@@ -593,6 +613,7 @@ struct HistoryPass : public Pass {
                        log("%s\n", (*list)->line);
        }
 } HistoryPass;
+#endif
 
 struct ScriptPass : public Pass {
        ScriptPass() : Pass("script", "execute commands from script file") { }
index c73684f1be5222fb693e161ec76fe73ee065d809..4e8234d165eb7ca3d643f5b74abe5a1701440293 100644 (file)
  */
 
 #include "kernel/yosys.h"
-#include <dlfcn.h>
+
+#ifdef YOSYS_ENABLE_PLUGINS
+#  include <dlfcn.h>
+#endif
 
 YOSYS_NAMESPACE_BEGIN
 
@@ -27,6 +30,7 @@ std::map<std::string, std::string> loaded_plugin_aliases;
 
 void load_plugin(std::string filename, std::vector<std::string> aliases)
 {
+#ifdef YOSYS_ENABLE_PLUGINS
        if (filename.find('/') == std::string::npos)
                filename = "./" + filename;
 
@@ -40,6 +44,9 @@ void load_plugin(std::string filename, std::vector<std::string> aliases)
 
        for (auto &alias : aliases)
                loaded_plugin_aliases[alias] = filename;
+#else
+       log_error("This version of yosys is built without plugin support.\n");
+#endif
 }
 
 struct PluginPass : public Pass {
index 4f6b811bcb5d21a663832e8f5ee6ab5f9f209224..fc6e972eef49e196c103aee2fee69101ea8a9d85 100644 (file)
 #include "kernel/log.h"
 #include <string.h>
 #include <dirent.h>
-#include <readline/readline.h>
+
+#ifdef YOSYS_ENABLE_READLINE
+#  include <readline/readline.h>
+#endif
 
 using RTLIL::id2cstr;
 
@@ -770,6 +773,7 @@ struct ShowPass : public Pass {
                }
 
                if (flag_pause) {
+               #ifdef YOSYS_ENABLE_READLINE
                        char *input = NULL;
                        while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != NULL) {
                                if (input[strspn(input, " \t\r\n")] == 0)
@@ -780,6 +784,9 @@ struct ShowPass : public Pass {
                                        break;
                                }
                        }
+               #else
+                       log_cmd_error("This version of yosys is built without readline support => 'show -pause' is not available.\n");
+               #endif
                }
 
                log_pop();