Added YosysJS wrapper
authorClifford Wolf <clifford@clifford.at>
Mon, 16 Feb 2015 11:41:48 +0000 (12:41 +0100)
committerClifford Wolf <clifford@clifford.at>
Mon, 16 Feb 2015 11:41:48 +0000 (12:41 +0100)
.gitignore
Makefile
kernel/driver.cc
misc/yosys.html [deleted file]
misc/yosysjs/demo01.html [new file with mode: 0644]
misc/yosysjs/demo02.html [new file with mode: 0644]
misc/yosysjs/yosysjs.js [new file with mode: 0644]

index 4334b3d84dc16ecf56da855e73f2d7ce33ad194a..2e937c73574ce431eb304a092d255253e24132b4 100644 (file)
@@ -15,7 +15,6 @@
 /yosys
 /yosys.exe
 /yosys.js
-/yosys.html
 /yosys-abc
 /yosys-abc.exe
 /yosys-config
index a7035008cf6afe66bb64daf0e47f049a828c3f91..a301df2fc531cc726dd17201479671973ac00e37 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -113,12 +113,18 @@ LDLIBS =
 EXE = .js
 
 TARGETS := $(filter-out yosys-config,$(TARGETS))
-EXTRA_TARGETS += yosys.html viz.js
+EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip
 
 viz.js:
        wget -O viz.js.part https://github.com/mdaines/viz.js/releases/download/0.0.3/viz.js
        mv viz.js.part viz.js
 
+yosysjs-$(YOSYS_VER).zip: yosys.js viz.js misc/yosysjs/*
+       rm -rf yosysjs-$(YOSYS_VER) yosysjs-$(YOSYS_VER).zip
+       mkdir -p yosysjs-$(YOSYS_VER)
+       cp viz.js misc/yosysjs/* yosys.js yosysjs-$(YOSYS_VER)/
+       zip -r yosysjs-$(YOSYS_VER).zip yosysjs-$(YOSYS_VER)
+
 yosys.html: misc/yosys.html
        $(P) cp misc/yosys.html yosys.html
 
index 6df7cf2e8eb96bc7e5d23edc74effd90d751173a..69a7b8e156357e54156f92a9e9f08ed4162c0c6b 100644 (file)
@@ -93,7 +93,9 @@ void run(const char *command)
 
 const char *prompt()
 {
-       return create_prompt(yosys_get_design(), 0);
+       const char *p = create_prompt(yosys_get_design(), 0);
+       while (*p == '\n') p++;
+       return p;
 }
 
 #else /* EMSCRIPTEN */
diff --git a/misc/yosys.html b/misc/yosys.html
deleted file mode 100644 (file)
index 264a58f..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-<html><head>
-       <title>yosys.js example application</title>
-</head><body onload="document.getElementById('command').focus()">
-       <h1>yosys.js example application</h1>
-       <table width="100%"><tr><td><div id="tabs"></div></td><td align="right"><tt>[ <span onclick="load_example()">load example</span> ]</tt></td></tr></table>
-       <iframe id="viz" style="display: none"><script type="text/javascript" src="viz.js"></script></iframe>
-       <svg id="svg" style="display: none; position: absolute; padding: 10px; width: 100%; height: 80%;"></svg>
-       <div><textarea id="output" style="width: 100%" rows="30" cols="100"></textarea></div>
-       <div id="wait" style="display: block"><br/><b><span id="waitmsg">Loading...</span></b></div>
-       <div id="input" style="display: none"><form onsubmit="window.setTimeout(run_command); return false"><tt><span id="prompt">
-                       </span></tt><input id="command" type="text" onkeydown="history(event)" style="font-family: monospace; font-weight: bold;" size="100"></form></div>
-       <script type='text/javascript'>
-               var got_log_messages = false;
-               var history_log = [];
-               var history_index = 0;
-               var history_bak = "";
-
-               function history(ev) {
-                       if (ev.keyCode == 38) {
-                               el = document.getElementById('command');
-                               if (history_index == history_log.length)
-                                       history_bak = el.value
-                               if (history_index > 0)
-                                       el.value = history_log[--history_index];
-                       }
-                       if (ev.keyCode == 40) {
-                               if (history_index < history_log.length) {
-                                       el = document.getElementById('command');
-                                       if (++history_index < history_log.length)
-                                               el.value = history_log[history_index];
-                                       else
-                                               el.value = history_bak;
-                               }
-                       }
-               }
-
-               var Module = {
-                       print: (function() {
-                               var element = document.getElementById('output');
-                               if (element) element.value = ''; // clear browser cache
-                               return function(text) {
-                                       if (!got_log_messages) {
-                                               window.setTimeout(startup, 50);
-                                               got_log_messages = true;
-                                       }
-                                       if (element && typeof(text) != "number") {
-                                               element.value += text + "\n";
-                                               element.scrollTop = element.scrollHeight; // focus on bottom
-                                       }
-                               };
-                       })(),
-                       printErr: (function() {
-                               var element = document.getElementById('output');
-                               if (element) element.value = ''; // clear browser cache
-                               return function(text) {
-                                       if (element && typeof(text) != "number") {
-                                               console.log(text);
-                                               if (got_log_messages) {
-                                                       element.value += text + "\n";
-                                                       element.scrollTop = element.scrollHeight; // focus on bottom
-                                               }
-                                       }
-                               };
-                       })(),
-               };
-
-               var current_file = "";
-               var console_messages = "";
-               var svg_cache = { };
-
-               function update_tabs() {
-                       var f, html = "", flist = FS.readdir('.');
-                       if (current_file == "") {
-                               html += '<tt>[ <b>Console</b>';
-                       } else {
-                               html += '<tt>[ <span onclick="open_file(\'\')">Console</span>';
-                       }
-                       for (i in flist) {
-                               f = flist[i]
-                               if (f == "." || f == "..")
-                                       continue;
-                               if (current_file == f) {
-                                       html += ' | <b>' + f + '</b>';
-                               } else {
-                                       html += ' | <span onclick="open_file(\'' + f + '\')">' + f + '</span>';
-                               }
-                       }
-                       html += ' | <span onclick="open_file(prompt(\'Filename:\'))">new file</span> ]</tt>';
-                       document.getElementById('tabs').innerHTML = html;
-                       if (current_file == "" || /\.dot$/.test(current_file)) {
-                               var element = document.getElementById('output');
-                               element.readOnly = true;
-                               element.scrollTop = element.scrollHeight; // focus on bottom
-                               document.getElementById('command').focus();
-                       } else {
-                               document.getElementById('output').readOnly = false;
-                               document.getElementById('output').focus();
-                       }
-               }
-
-               function open_file(filename)
-               {
-                       if (current_file == "")
-                               console_messages = document.getElementById('output').value;
-                       else if (!/\.dot$/.test(current_file))
-                               FS.writeFile(current_file, document.getElementById('output').value, {encoding: 'utf8'});
-
-                       if (filename == "") {
-                               document.getElementById('output').value = console_messages;
-                       } else {
-                               try {
-                                       document.getElementById('output').value = FS.readFile(filename, {encoding: 'utf8'});
-                               } catch (e) {
-                                       document.getElementById('output').value = "";
-                                       FS.writeFile(filename, document.getElementById('output').value, {encoding: 'utf8'});
-                               }
-                       }
-
-                       if (/\.dot$/.test(filename)) {
-                               dot = document.getElementById('output').value;
-                               if (!(dot in svg_cache)) {
-                                       el = document.getElementById('viz');
-                                       svg_cache[dot] = el.contentWindow.Viz(dot, "svg");
-                               }
-                               document.getElementById('svg').innerHTML = svg_cache[dot];
-                               document.getElementById('svg').style.display = 'block';
-                               document.getElementById('output').value = '';
-                       } else {
-                               document.getElementById('svg').innerHTML = '';
-                               document.getElementById('svg').style.display = 'none';
-                       }
-
-                       current_file = filename;
-                       update_tabs()
-               }
-
-               function startup() {
-                       el = document.getElementById('viz');
-                       el.contentWindow.document.open();
-                       el.contentWindow.document.write('<script type="text/javascript" src="viz.js"></' + 'script>');
-                       el.contentWindow.document.close();
-
-                       document.getElementById('wait').style.display = 'none';
-                       document.getElementById('input').style.display = 'block';
-                       document.getElementById('waitmsg').textContent = 'Waiting for yosys.js...';
-                       document.getElementById('prompt').textContent = yosys_prompt();
-
-                       try { FS.mkdir('/work'); } catch (e) { }
-                       FS.chdir('/work');
-
-                       update_tabs();
-                       console.log('yosys.js loaded.');
-               }
-
-               function load_example() {
-                       open_file('')
-
-                       var txt = "";
-                       txt += "// a simple yosys.js example. run \"script example.ys\".\n";
-                       txt += "\n";
-                       txt += "module example(input clk, input rst, input inc, output reg [3:0] cnt);\n";
-                       txt += "  always @(posedge clk) begin\n";
-                       txt += "    if (rst)\n";
-                       txt += "      cnt <= 0;\n";
-                       txt += "    else if (inc)\n";
-                       txt += "      cnt <= cnt + 1;\n";
-                       txt += "  end\n";
-                       txt += "endmodule\n";
-                       txt += "\n";
-                       FS.writeFile('example.v', txt, {encoding: 'utf8'});
-
-                       var txt = "";
-                       txt += "# a simple yosys.js example. run \"script example.ys\".\n";
-                       txt += "\n";
-                       txt += "design -reset\n";
-                       txt += "read_verilog example.v\n";
-                       txt += "proc\n";
-                       txt += "opt\n";
-                       txt += "show\n";
-                       txt += "\n";
-                       FS.writeFile('example.ys', txt, {encoding: 'utf8'});
-
-                       open_file('example.ys')
-                       document.getElementById('command').focus();
-               }
-
-               function yosys_command(cmd) {
-                       Module.ccall('run', '', ['string'], [cmd])
-               }
-
-               function yosys_prompt() {
-                       return Module.ccall('prompt', 'string', [], [])
-               }
-
-               function run_command() {
-                       var cmd = document.getElementById('command').value;
-                       document.getElementById('command').value = '';
-                       if (history_log.length == 0 || history_log[history_log.length-1] != cmd)
-                               history_log.push(cmd);
-                       history_index = history_log.length;
-
-                       var show_dot_before = "";
-                       try { show_dot_before = FS.readFile('show.dot', { encoding: 'utf8' }); } catch (e) { }
-
-                       open_file('');
-                       Module.print(yosys_prompt() + cmd);
-
-                       document.getElementById('wait').style.display = 'block';
-                       document.getElementById('input').style.display = 'none';
-
-                       function run_command_bh() {
-                               try {
-                                       yosys_command(cmd);
-                               } catch (e) {
-                                       Module.print('Caught JavaScript exception. (see JavaScript console for details.)');
-                                       console.log(e);
-                               }
-
-                               document.getElementById('wait').style.display = 'none';
-                               document.getElementById('input').style.display = 'block';
-                               document.getElementById('prompt').textContent = yosys_prompt();
-
-                               var show_dot_after = "";
-                               try { show_dot_after = FS.readFile('show.dot', { encoding: 'utf8' }); } catch (e) { }
-
-                               if (show_dot_before != show_dot_after)
-                                       open_file('show.dot');
-
-                               update_tabs();
-                       }
-
-                       window.setTimeout(run_command_bh, 50);
-                       return false;
-               }
-       </script>
-       <script async type="text/javascript" src="yosys.js"></script>
-</body></html>
diff --git a/misc/yosysjs/demo01.html b/misc/yosysjs/demo01.html
new file mode 100644 (file)
index 0000000..e0ba024
--- /dev/null
@@ -0,0 +1,237 @@
+<html><head>
+       <title>YosysJS Example Application #01</title>
+</head><body onload="document.getElementById('command').focus()">
+       <h1>YosysJS Example Application #01</h1>
+       <table width="100%"><tr><td><div id="tabs"></div></td><td align="right"><tt>[ <span onclick="load_example()">load example</span> ]</tt></td></tr></table>
+       <iframe id="viz" style="display: none"><script type="text/javascript" src="viz.js"></script></iframe>
+       <svg id="svg" style="display: none; position: absolute; padding: 10px; width: 100%; height: 80%;"></svg>
+       <div><textarea id="output" style="width: 100%" rows="30" cols="100"></textarea></div>
+       <div id="wait" style="display: block"><br/><b><span id="waitmsg">Loading...</span></b></div>
+       <div id="input" style="display: none"><form onsubmit="window.setTimeout(run_command); return false"><tt><span id="prompt">
+                       </span></tt><input id="command" type="text" onkeydown="history(event)" style="font-family: monospace; font-weight: bold;" size="100"></form></div>
+       <script type='text/javascript'>
+               var got_log_messages = false;
+               var history_log = [];
+               var history_index = 0;
+               var history_bak = "";
+
+               function history(ev) {
+                       if (ev.keyCode == 38) {
+                               el = document.getElementById('command');
+                               if (history_index == history_log.length)
+                                       history_bak = el.value
+                               if (history_index > 0)
+                                       el.value = history_log[--history_index];
+                       }
+                       if (ev.keyCode == 40) {
+                               if (history_index < history_log.length) {
+                                       el = document.getElementById('command');
+                                       if (++history_index < history_log.length)
+                                               el.value = history_log[history_index];
+                                       else
+                                               el.value = history_bak;
+                               }
+                       }
+               }
+
+               var Module = {
+                       print: (function() {
+                               var element = document.getElementById('output');
+                               if (element) element.value = ''; // clear browser cache
+                               return function(text) {
+                                       if (!got_log_messages) {
+                                               window.setTimeout(startup, 50);
+                                               got_log_messages = true;
+                                       }
+                                       if (element && typeof(text) != "number") {
+                                               element.value += text + "\n";
+                                               element.scrollTop = element.scrollHeight; // focus on bottom
+                                       }
+                               };
+                       })(),
+                       printErr: (function() {
+                               var element = document.getElementById('output');
+                               if (element) element.value = ''; // clear browser cache
+                               return function(text) {
+                                       if (element && typeof(text) != "number") {
+                                               console.log(text);
+                                               if (got_log_messages) {
+                                                       element.value += text + "\n";
+                                                       element.scrollTop = element.scrollHeight; // focus on bottom
+                                               }
+                                       }
+                               };
+                       })(),
+               };
+
+               var current_file = "";
+               var console_messages = "";
+               var svg_cache = { };
+
+               function update_tabs() {
+                       var f, html = "", flist = FS.readdir('.');
+                       if (current_file == "") {
+                               html += '<tt>[ <b>Console</b>';
+                       } else {
+                               html += '<tt>[ <span onclick="open_file(\'\')">Console</span>';
+                       }
+                       for (i in flist) {
+                               f = flist[i]
+                               if (f == "." || f == "..")
+                                       continue;
+                               if (current_file == f) {
+                                       html += ' | <b>' + f + '</b>';
+                               } else {
+                                       html += ' | <span onclick="open_file(\'' + f + '\')">' + f + '</span>';
+                               }
+                       }
+                       html += ' | <span onclick="open_file(prompt(\'Filename:\'))">new file</span> ]</tt>';
+                       document.getElementById('tabs').innerHTML = html;
+                       if (current_file == "" || /\.dot$/.test(current_file)) {
+                               var element = document.getElementById('output');
+                               element.readOnly = true;
+                               element.scrollTop = element.scrollHeight; // focus on bottom
+                               document.getElementById('command').focus();
+                       } else {
+                               document.getElementById('output').readOnly = false;
+                               document.getElementById('output').focus();
+                       }
+               }
+
+               function open_file(filename)
+               {
+                       if (current_file == "")
+                               console_messages = document.getElementById('output').value;
+                       else if (!/\.dot$/.test(current_file))
+                               FS.writeFile(current_file, document.getElementById('output').value, {encoding: 'utf8'});
+
+                       if (filename == "") {
+                               document.getElementById('output').value = console_messages;
+                       } else {
+                               try {
+                                       document.getElementById('output').value = FS.readFile(filename, {encoding: 'utf8'});
+                               } catch (e) {
+                                       document.getElementById('output').value = "";
+                                       FS.writeFile(filename, document.getElementById('output').value, {encoding: 'utf8'});
+                               }
+                       }
+
+                       if (/\.dot$/.test(filename)) {
+                               dot = document.getElementById('output').value;
+                               if (!(dot in svg_cache)) {
+                                       el = document.getElementById('viz');
+                                       svg_cache[dot] = el.contentWindow.Viz(dot, "svg");
+                               }
+                               document.getElementById('svg').innerHTML = svg_cache[dot];
+                               document.getElementById('svg').style.display = 'block';
+                               document.getElementById('output').value = '';
+                       } else {
+                               document.getElementById('svg').innerHTML = '';
+                               document.getElementById('svg').style.display = 'none';
+                       }
+
+                       current_file = filename;
+                       update_tabs()
+               }
+
+               function startup() {
+                       el = document.getElementById('viz');
+                       el.contentWindow.document.open();
+                       el.contentWindow.document.write('<script type="text/javascript" src="viz.js"></' + 'script>');
+                       el.contentWindow.document.close();
+
+                       document.getElementById('wait').style.display = 'none';
+                       document.getElementById('input').style.display = 'block';
+                       document.getElementById('waitmsg').textContent = 'Waiting for yosys.js...';
+                       document.getElementById('prompt').textContent = yosys_prompt();
+
+                       try { FS.mkdir('/work'); } catch (e) { }
+                       FS.chdir('/work');
+
+                       update_tabs();
+                       console.log('yosys.js loaded.');
+               }
+
+               function load_example() {
+                       open_file('')
+
+                       var txt = "";
+                       txt += "// a simple yosys.js example. run \"script example.ys\".\n";
+                       txt += "\n";
+                       txt += "module example(input clk, input rst, input inc, output reg [3:0] cnt);\n";
+                       txt += "  always @(posedge clk) begin\n";
+                       txt += "    if (rst)\n";
+                       txt += "      cnt <= 0;\n";
+                       txt += "    else if (inc)\n";
+                       txt += "      cnt <= cnt + 1;\n";
+                       txt += "  end\n";
+                       txt += "endmodule\n";
+                       txt += "\n";
+                       FS.writeFile('example.v', txt, {encoding: 'utf8'});
+
+                       var txt = "";
+                       txt += "# a simple yosys.js example. run \"script example.ys\".\n";
+                       txt += "\n";
+                       txt += "design -reset\n";
+                       txt += "read_verilog example.v\n";
+                       txt += "proc\n";
+                       txt += "opt\n";
+                       txt += "show\n";
+                       txt += "\n";
+                       FS.writeFile('example.ys', txt, {encoding: 'utf8'});
+
+                       open_file('example.ys')
+                       document.getElementById('command').focus();
+               }
+
+               function yosys_command(cmd) {
+                       Module.ccall('run', '', ['string'], [cmd])
+               }
+
+               function yosys_prompt() {
+                       return Module.ccall('prompt', 'string', [], [])
+               }
+
+               function run_command() {
+                       var cmd = document.getElementById('command').value;
+                       document.getElementById('command').value = '';
+                       if (history_log.length == 0 || history_log[history_log.length-1] != cmd)
+                               history_log.push(cmd);
+                       history_index = history_log.length;
+
+                       var show_dot_before = "";
+                       try { show_dot_before = FS.readFile('show.dot', { encoding: 'utf8' }); } catch (e) { }
+
+                       open_file('');
+                       Module.print(yosys_prompt() + cmd);
+
+                       document.getElementById('wait').style.display = 'block';
+                       document.getElementById('input').style.display = 'none';
+
+                       function run_command_bh() {
+                               try {
+                                       yosys_command(cmd);
+                               } catch (e) {
+                                       Module.print('Caught JavaScript exception. (see JavaScript console for details.)');
+                                       console.log(e);
+                               }
+
+                               document.getElementById('wait').style.display = 'none';
+                               document.getElementById('input').style.display = 'block';
+                               document.getElementById('prompt').textContent = yosys_prompt();
+
+                               var show_dot_after = "";
+                               try { show_dot_after = FS.readFile('show.dot', { encoding: 'utf8' }); } catch (e) { }
+
+                               if (show_dot_before != show_dot_after)
+                                       open_file('show.dot');
+
+                               update_tabs();
+                       }
+
+                       window.setTimeout(run_command_bh, 50);
+                       return false;
+               }
+       </script>
+       <script async type="text/javascript" src="yosys.js"></script>
+</body></html>
diff --git a/misc/yosysjs/demo02.html b/misc/yosysjs/demo02.html
new file mode 100644 (file)
index 0000000..ec33198
--- /dev/null
@@ -0,0 +1,102 @@
+<html><head>
+       <title>YosysJS Example Application #02</title>
+       <script type="text/javascript" src="yosysjs.js"></script>
+</head><body>
+       <div id="popup" style="position: fixed; left: 0; top: 0; width:100%; height:100%; text-align:center; z-index: 1000;"><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 #02</h1>
+       <iframe id="ys" style="width: 800px; height: 100px;"></iframe><p/>
+       <textarea id="code" style="width: 800px; height: 300px;">
+// borrowed with some modifications from
+// http://www.ee.ed.ac.uk/~gerard/Teach/Verilog/manual/Example/lrgeEx2/cooley.html
+module up3down5(clock, data_in, up, down, carry_out, borrow_out, count_out, parity_out);
+
+input [8:0] data_in;
+input clock, up, down;
+
+output reg [8:0] count_out;
+output reg carry_out, borrow_out, parity_out;
+
+reg [9:0] cnt_up, cnt_dn;
+reg [8:0] count_nxt;
+
+always @(posedge clock)
+begin
+       cnt_dn = count_out - 3'b 101;
+       cnt_up = count_out + 2'b 11;
+
+       case ({up,down})
+               2'b 00 : count_nxt = data_in;
+               2'b 01 : count_nxt = cnt_dn;
+               2'b 10 : count_nxt = cnt_up;
+               2'b 11 : count_nxt = count_out;
+               default : count_nxt = 9'bX;
+       endcase
+
+       parity_out  &lt;= ^count_nxt;
+       carry_out   &lt;= up &amp; cnt_up[9];
+       borrow_out  &lt;= down &amp; cnt_dn[9];
+       count_out   &lt;= count_nxt;
+end
+
+endmodule
+       </textarea><p/>
+       <input type="button" value="Before Behavioral Synth" onclick="synth1()">
+       <input type="button" value="After Behavioral Synth" onclick="synth2()">
+       <input type="button" value="After RTL Synth" onclick="synth3()">
+       <input type="button" value="After Gate-Level Synth" onclick="synth4()"><p/>
+       <svg id="svg" width="800"></svg>
+       </td></tr></table>
+       <script type="text/javascript">
+               YosysJS.load_viz();
+               function on_ys_ready() {
+                       document.getElementById('popup').style.visibility = 'hidden';
+                       document.getElementById('popupmsg').textContent = 'Please wait..';
+               }
+               function synth1() {
+                       function work() {
+                               ys.write_file("input.v", document.getElementById('code').value);
+                               ys.run('design -reset; read_verilog input.v; show -stretch');
+                               YosysJS.dot_into_svg(ys.read_file('show.dot'), document.getElementById('svg'));
+                               document.getElementById('popup').style.visibility = 'hidden';
+                       }
+                       document.getElementById('popup').style.visibility = 'visible';
+                       window.setTimeout(work, 100);
+               }
+               function synth2() {
+                       function work() {
+                               ys.write_file("input.v", document.getElementById('code').value);
+                               ys.run('design -reset; read_verilog input.v; proc; opt_clean; show -stretch');
+                               YosysJS.dot_into_svg(ys.read_file('show.dot'), document.getElementById('svg'));
+                               document.getElementById('popup').style.visibility = 'hidden';
+                       }
+                       document.getElementById('popup').style.visibility = 'visible';
+                       window.setTimeout(work, 100);
+               }
+               function synth3() {
+                       function work() {
+                               ys.write_file("input.v", document.getElementById('code').value);
+                               ys.run('design -reset; read_verilog input.v; synth -run coarse; show -stretch');
+                               YosysJS.dot_into_svg(ys.read_file('show.dot'), document.getElementById('svg'));
+                               document.getElementById('popup').style.visibility = 'hidden';
+                       }
+                       document.getElementById('popup').style.visibility = 'visible';
+                       window.setTimeout(work, 100);
+               }
+               function synth4() {
+                       function work() {
+                               ys.write_file("input.v", document.getElementById('code').value);
+                               ys.run('design -reset; read_verilog input.v; synth -run coarse; synth -run fine; show -stretch');
+                               YosysJS.dot_into_svg(ys.read_file('show.dot'), document.getElementById('svg'));
+                               document.getElementById('popup').style.visibility = 'hidden';
+                       }
+                       document.getElementById('popup').style.visibility = 'visible';
+                       window.setTimeout(work, 100);
+               }
+               var ys = YosysJS.create('ys', on_ys_ready);
+               ys.verbose = true;
+               ys.echo = true;
+       </script>
+</body></html>
diff --git a/misc/yosysjs/yosysjs.js b/misc/yosysjs/yosysjs.js
new file mode 100644 (file)
index 0000000..ad6df34
--- /dev/null
@@ -0,0 +1,159 @@
+var YosysJS = new function() {
+       this.script_element = document.currentScript;
+       this.viz_element = undefined;
+
+       this.url_prefix = this.script_element.src.replace(/[^/]+$/, '')
+
+       this.load_viz = function() {
+               if (this.viz_element)
+                       return;
+
+               this.viz_element = document.createElement('iframe')
+               this.viz_element.style.display = 'none'
+               document.body.appendChild(this.viz_element);
+
+               this.viz_element.contentWindow.document.open()
+               this.viz_element.contentWindow.document.write('<script type="text/javascript" src="' + this.url_prefix + 'viz.js"></' + 'script>');
+               this.viz_element.contentWindow.document.close()
+       }
+
+       this.dot_to_svg = function(dot_text) {
+               return this.viz_element.contentWindow.Viz(dot_text, "svg");
+       }
+
+       this.dot_into_svg = function(dot_text, svg_element) {
+               svg_element.innerHTML = this.dot_to_svg(dot_text);
+               c = svg_element.firstChild;
+               while (c) {
+                       if (c.tagName == 'svg') {
+                               while (c.firstChild)
+                                       svg_element.appendChild(c.firstChild);
+                               svg_element.setAttribute('viewBox', c.getAttribute('viewBox'));
+                               // svg_element.removeChild(c);
+                               break;
+                       }
+                       c = c.nextSibling;
+               }
+       }
+
+       this.create = function(reference_element, on_ready) {
+               var ys = new Object();
+               ys.init_script = "";
+               ys.ready = false;
+               ys.verbose = false;
+               ys.echo = false;
+
+               if (typeof(reference_element) == 'string')
+                       reference_element = document.getElementById(reference_element);
+
+               if (reference_element) {
+                       if (reference_element.tagName == 'textarea')
+                               ys.init_script = reference_element.value;
+               
+                       if (reference_element.tagName == 'iframe') {
+                               ys.iframe_element = reference_element;
+                       } else {
+                               ys.iframe_element = document.createElement('iframe');
+                               ys.iframe_element.id = reference_element.id;
+                               for (i in reference_element.style)
+                                       ys.iframe_element.style[i] = reference_element.style[i];
+                               reference_element.parentNode.insertBefore(ys.iframe_element, reference_element);
+                               reference_element.parentNode.removeChild(reference_element);
+                       }
+               } else {
+                       ys.iframe_element = document.createElement('iframe');
+                       document.body.appendChild(ys.iframe_element);
+               }
+
+               var return_buffer = "";
+               var last_line_empty = false;
+
+               var win = ys.iframe_element.contentWindow;
+               var doc = ys.iframe_element.contentWindow.document;
+               var mod = ys.iframe_element.contentWindow.Module = {
+                       print: function(text) {
+                               return_buffer += text + "\n";
+                               if (ys.verbose) {
+                                       last_line_empty = text == "";
+                                       span = doc.createElement('span');
+                                       span.textContent = text + "\n";
+                                       span.style.fontFamily = 'monospace';
+                                       span.style.whiteSpace = 'pre';
+                                       doc.body.appendChild(span);
+                                       win.scrollTo(0, doc.body.scrollHeight)
+                               }
+                               ys.ready = true;
+                       },
+                       printErr: function(text) {
+                               return_buffer += text + "\n";
+                               last_line_empty = text == "";
+                               span = doc.createElement('span');
+                               span.textContent = text + "\n";
+                               span.style.fontFamily = 'monospace';
+                               span.style.whiteSpace = 'pre';
+                               span.style.color = 'red';
+                               doc.body.appendChild(span);
+                               win.scrollTo(0, doc.body.scrollHeight)
+                       },
+               };
+
+               ys.write = function(text) {
+                       last_line_empty = text == "";
+                       span = doc.createElement('span');
+                       span.textContent = text + "\n";
+                       span.style.fontFamily = 'monospace';
+                       span.style.whiteSpace = 'pre';
+                       doc.body.appendChild(span);
+                       win.scrollTo(0, doc.body.scrollHeight)
+               }
+
+               ys.prompt = function() {
+                       return mod.ccall('prompt', 'string', [], [])
+               }
+
+               ys.run = function(cmd) {
+                       return_buffer = "";
+                       if (ys.echo) {
+                               if (!last_line_empty)
+                                       ys.write("");
+                               ys.write(ys.prompt() + cmd);
+                       }
+                       mod.ccall('run', '', ['string'], [cmd]);
+                       return return_buffer;
+               }
+
+               ys.read_file = function(filename) {
+                       return win.FS.readFile(filename, {encoding: 'utf8'});
+               }
+
+               ys.write_file = function(filename, text) {
+                       return win.FS.writeFile(filename, text, {encoding: 'utf8'});
+               }
+
+               ys.read_dir = function(dirname) {
+                       return win.FS.readdir(dirname);
+               }
+
+               el = doc.createElement('script');
+               el.type = 'text/javascript';
+               el.src = this.url_prefix + 'yosys.js';
+               doc.head.appendChild(el);
+
+               if (on_ready || ys.init_script) {
+                       function check_ready() {
+                               if (ys.ready) {
+                                       if (ys.init_script) {
+                                               ys.write_file("/script.ys", ys.init_script);
+                                               ys.run("script /script.ys");
+                                       }
+                                       if (on_ready)
+                                               on_ready(ys);
+                               } else
+                                       window.setTimeout(check_ready, 100);
+                       }
+                       window.setTimeout(check_ready, 100);
+               }
+
+               return ys;
+       }
+}