diff options
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 1 | ||||
-rw-r--r-- | kernel/driver.cc | 17 | ||||
-rw-r--r-- | kernel/log.cc | 19 | ||||
-rw-r--r-- | kernel/log.h | 1 | ||||
-rw-r--r-- | misc/yosysjs/demo03.html | 103 | ||||
-rw-r--r-- | misc/yosysjs/yosysjs.js | 19 |
7 files changed, 156 insertions, 16 deletions
@@ -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 = diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 23cea27f1..f2bc9c573 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -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(); diff --git a/kernel/driver.cc b/kernel/driver.cc index d0ebdde77..dda27c6a6 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -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() diff --git a/kernel/log.cc b/kernel/log.cc index ada2cabb2..bf92daced 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -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(); } diff --git a/kernel/log.h b/kernel/log.h index fd35c7bf7..16ad7b6c9 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -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 index 000000000..720b82e90 --- /dev/null +++ b/misc/yosysjs/demo03.html @@ -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 <= 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"> </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('&', '&').replace('<', '<').replace('>', '>') + '</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> diff --git a/misc/yosysjs/yosysjs.js b/misc/yosysjs/yosysjs.js index 87c951183..a1181493e 100644 --- a/misc/yosysjs/yosysjs.js +++ b/misc/yosysjs/yosysjs.js @@ -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() |