YosysJS stuff
authorClifford Wolf <clifford@clifford.at>
Thu, 19 Feb 2015 12:36:54 +0000 (13:36 +0100)
committerClifford Wolf <clifford@clifford.at>
Thu, 19 Feb 2015 12:36:54 +0000 (13:36 +0100)
Makefile
frontends/verilog/verilog_parser.y
kernel/driver.cc
kernel/log.cc
kernel/log.h
misc/yosysjs/demo03.html [new file with mode: 0644]
misc/yosysjs/yosysjs.js

index a301df2fc531cc726dd17201479671973ac00e37..405870b6420c45ca84d44d546d3aa50c73b8d9da 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -97,16 +97,10 @@ else ifeq ($(CONFIG),emcc)
 CXX = emcc
 CXXFLAGS := -std=c++11 $(filter-out -fPIC -ggdb,$(CXXFLAGS))
 EMCCFLAGS := -Os -Wno-warn-absolute-paths
-EMCCFLAGS += --memory-init-file 0 -s NO_EXIT_RUNTIME=1
-EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt']"
-EMCCFLAGS += --embed-file share
+EMCCFLAGS += --memory-init-file 0 --embed-file share -s NO_EXIT_RUNTIME=1
+EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt','_errmsg']"
+EMCCFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1
 # https://github.com/kripken/emscripten/blob/master/src/settings.js
-# EMCCFLAGS += -s ALLOW_MEMORY_GROWTH=1
-# EMCCFLAGS += -s DISABLE_EXCEPTION_CATCHING=0
-# EMCCFLAGS += -s AGGRESSIVE_VARIABLE_ELIMINATION=1
-# EMCCFLAGS += -s ASSERTIONS=2
-# EMCCFLAGS += -s SAFE_HEAP=1
-# EMCCFLAGS += -s RELOOP=0
 CXXFLAGS += $(EMCCFLAGS)
 LDFLAGS += $(EMCCFLAGS)
 LDLIBS =
index 23cea27f124f2dea1bc26998ffd8d60f07364f2b..f2bc9c57328ad97d46f91be3c7cbc465d79ebf32 100644 (file)
@@ -139,6 +139,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
 %%
 
 input: {
+       ast_stack.clear();
        ast_stack.push_back(current_ast);
 } design {
        ast_stack.pop_back();
index d0ebdde77e5c1004665da4f744a2970b67cb959a..dda27c6a6a9f01dbaf72ec1716effed1da9f6375 100644 (file)
@@ -78,6 +78,7 @@ USING_YOSYS_NAMESPACE
 
 extern "C" int main(int, char**);
 extern "C" void run(const char*);
+extern "C" const char *errmsg();
 extern "C" const char *prompt();
 
 int main(int, char**)
@@ -92,7 +93,21 @@ int main(int, char**)
 
 void run(const char *command)
 {
-       run_pass(command);
+       int selSize = GetSize(yosys_get_design()->selection_stack);
+       try {
+               log_last_error = "Internal error (see JavaScript console for details)";
+               run_pass(command);
+               log_last_error = "";
+       } catch (...) {
+               while (GetSize(yosys_get_design()->selection_stack) > selSize)
+                       yosys_get_design()->selection_stack.pop_back();
+               throw;
+       }
+}
+
+const char *errmsg()
+{
+       return log_last_error.c_str();
 }
 
 const char *prompt()
index ada2cabb222a924cb2a7e7b090f48cfe18737ecb..bf92dacedd441be16637dab8693e1d9fb6c44a67 100644 (file)
@@ -48,6 +48,7 @@ bool log_error_stderr = false;
 bool log_cmd_error_throw = false;
 bool log_quiet_warnings = false;
 int log_verbose_level;
+string log_last_error;
 
 vector<int> header_count;
 pool<RTLIL::IdString> log_id_cache;
@@ -173,6 +174,10 @@ void logv_warning(const char *format, va_list ap)
 
 void logv_error(const char *format, va_list ap)
 {
+#ifdef EMSCRIPTEN
+       auto backup_log_files = log_files;
+#endif
+
        if (log_errfile != NULL)
                log_files.push_back(log_errfile);
 
@@ -181,10 +186,16 @@ void logv_error(const char *format, va_list ap)
                        if (f == stdout)
                                f = stderr;
 
-       log("ERROR: ");
-       logv(format, ap);
+       log_last_error = vstringf(format, ap);
+       log("ERROR: %s", log_last_error.c_str());
        log_flush();
+
+#ifdef EMSCRIPTEN
+       log_files = backup_log_files;
+       throw 0;
+#else
        exit(1);
+#endif
 }
 
 void log(const char *format, ...)
@@ -224,8 +235,8 @@ void log_cmd_error(const char *format, ...)
        va_start(ap, format);
 
        if (log_cmd_error_throw) {
-               log("ERROR: ");
-               logv(format, ap);
+               log_last_error = vstringf(format, ap);
+               log("ERROR: %s", log_last_error.c_str());
                log_flush();
                throw log_cmd_error_exception();
        }
index fd35c7bf71ae02e37135bc6efbcb8f9361063c24..16ad7b6c9990cc3f9901b105ef71d48551aad18b 100644 (file)
@@ -50,6 +50,7 @@ extern bool log_error_stderr;
 extern bool log_cmd_error_throw;
 extern bool log_quiet_warnings;
 extern int log_verbose_level;
+extern string log_last_error;
 
 void logv(const char *format, va_list ap);
 void logv_header(const char *format, va_list ap);
diff --git a/misc/yosysjs/demo03.html b/misc/yosysjs/demo03.html
new file mode 100644 (file)
index 0000000..720b82e
--- /dev/null
@@ -0,0 +1,103 @@
+<html><head>
+<title>YosysJS Example Application #02</title>
+<script type="text/javascript" src="yosysjs.js"></script>
+<script src="http://wavedrom.com/skins/default.js" type="text/javascript"></script>
+<script src="http://wavedrom.com/WaveDrom.js" type="text/javascript"></script>
+<style type="text/css">
+.noedit { color: #666; }
+</style>
+<script id="golden_verilog" type="text/plain">
+module ref(input clk, reset, input [7:0] A, output reg [7:0] Y);
+       always @(posedge clk) begin
+               if (reset)
+                       Y <= 0;
+               else
+                       Y <= ((Y << 5) + Y) ^ A;
+       end
+endmodule
+</script>
+</head><body>
+       <div id="popup" style="position: fixed; left: 0; top: 0; width:100%; height:100%; text-align:center; z-index: 1000;
+               background-color: rgba(100, 100, 100, 0.5);"><div style="width:300px; margin: 200px auto; background-color: #88f;
+               border:3px dashed #000; padding:15px; text-align:center;"><span id="popupmsg">Loading...</span></div>
+       </div>
+       <h1>YosysJS Example Application #03</h1>
+       <b>Your mission:</b> Create a behavioral Verilog model for the following circuit:
+       <p/>
+       <svg id="schem" width="800"></svg>
+       <p/>
+       <pre id="code" style="width: 800px; border:2px solid #000; padding: 0.5em;"><span class="noedit">module top(input clk, reset, input [7:0] A, output reg [7:0] Y);
+  always @(posedge clock) begin</span><span class="edit" contenteditable="true">
+    Y &lt;= A | {4{reset}};
+  </span><span class="noedit">end
+endmodule</span></pre><p/>
+       <input type="button" value="Check Model" onclick="check_model()"> <span id="checkmessage"></span>
+       <p/>
+       <p id="wave">&nbsp;</p>
+       <script type="text/javascript">
+               function on_ys_ready() {
+                       ys.write_file('golden.v', document.getElementById('golden_verilog').textContent);
+                       ys.run('echo on; read_verilog golden.v; proc;;');
+                       ys.run('show -notitle -width -stretch');
+                       YosysJS.dot_into_svg(ys.read_file('show.dot'), 'schem');
+                       document.getElementById('popup').style.visibility = 'hidden';
+                       document.getElementById('popupmsg').textContent = 'Please wait..';
+               }
+               function check_model() {
+                       function work() {
+                               ys.remove_file('wave.json');
+                               ys.write_file('code.v', document.getElementById('code').textContent);
+                               ys.errmsg = '';
+                               ys.run('design -reset; read_verilog code.v; hierarchy -top top; proc; opt; flatten; hierarchy; ' +
+                                       'read_verilog golden.v; proc; miter -equiv -ignore_gold_x -make_outputs -flatten ref top miter; ' +
+                                       'hierarchy -top miter; clean -purge; sat -set-init-undef -seq 8 -dump_json wave.json -show-ports ' +
+                                       '-max_undef -prove trigger 0 miter');
+                               w = document.getElementById('wave')
+                               if (ys.errmsg) {
+                                       w.innerHTML = '<b><pre>ERROR: ' + ys.errmsg.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;') + '</pre></b>';
+                               } else {
+                                       wdata = ys.read_file('wave.json');
+                                       if (wdata) {
+                                               console.log(wdata)
+                                               wdata = JSON.parse(wdata);
+                                               function wsignal(signame, newname) {
+                                                       for (i = 0; i < wdata["signal"].length; i++)
+                                                               if (wdata["signal"][i].name == signame) {
+                                                                       if (newname)
+                                                                               wdata["signal"][i].name = newname;
+                                                                       return wdata["signal"][i];
+                                                               }
+                                                       return {};
+                                               }
+                                               wdata2 = {
+                                                       "signal" : [
+                                                               { name: 'clk', wave: 'P........' },
+                                                               wsignal("trigger"),
+                                                               {},
+                                                               [ "Inputs", wsignal("in_reset", "reset"), wsignal("in_A", "A") ],
+                                                               {},
+                                                               [ "Y Output", wsignal("gold_Y", "Ref"), wsignal("gate_Y", "UUT") ],
+                                                       ],
+                                                       "config" : wdata["config"]
+                                               };
+                                               wdata2 = JSON.stringify(wdata2)
+                                               console.log(wdata2)
+                                               w.innerHTML = '<b>The model did not pass verification:</b><p/>' +
+                                                               '<script type="WaveDrom">' + wdata2 + '<\/script>';
+                                               WaveDrom.ProcessAll();
+                                       } else {
+                                               w.innerHTML = '<b>Congratulations! The model did pass verification.</b><p/>';
+                                       }
+                               }
+                               document.getElementById('popup').style.visibility = 'hidden';
+                       }
+                       document.getElementById('popup').style.visibility = 'visible';
+                       window.setTimeout(work, 100);
+               }
+
+               YosysJS.load_viz();
+               var ys = YosysJS.create('', on_ys_ready);
+               ys.logprint = true;
+               ys.echo = true;
+       </script>
+</body></html>
index 87c951183e4c04d896a21a1e5cc56bb137dc27d7..a1181493e0becebc6ea9375ee510a3b666d82499 100644 (file)
@@ -45,6 +45,7 @@ var YosysJS = new function() {
                ys.verbose = false;
                ys.logprint = false;
                ys.echo = false;
+               ys.errmsg = "";
 
                if (typeof(reference_element) == 'string' && reference_element != "")
                        reference_element = document.getElementById(reference_element);
@@ -151,12 +152,20 @@ var YosysJS = new function() {
                                        ys.write("");
                                ys.write(ys.prompt() + cmd);
                        }
-                       mod.ccall('run', '', ['string'], [cmd]);
+                       try {
+                               mod.ccall('run', '', ['string'], [cmd]);
+                       } catch (e) {
+                               ys.errmsg = mod.ccall('errmsg', 'string', [], []);;
+                       }
                        return ys.print_buffer;
                }
 
                ys.read_file = function(filename) {
-                       return ys.window.FS.readFile(filename, {encoding: 'utf8'});
+                       try {
+                               return ys.window.FS.readFile(filename, {encoding: 'utf8'});
+                       } catch (e) {
+                               return "";
+                       }
                }
 
                ys.write_file = function(filename, text) {
@@ -167,6 +176,12 @@ var YosysJS = new function() {
                        return ys.window.FS.readdir(dirname);
                }
 
+               ys.remove_file = function(filename) {
+                       try {
+                               ys.window.FS.unlink(filename);
+                       } catch (e) { }
+               }
+
                doc.open()
                doc.write('<script type="text/javascript" src="' + this.url_prefix + 'yosys.js"></' + 'script>');
                doc.close()