Compare commits

...

35 Commits

Author SHA1 Message Date
Nikolay Puzanov
3aee2d2f38 Fix help message 2024-04-14 16:16:45 +03:00
Nikolay Puzanov
b84ec9a1c5 Remove clock from testbench input 2024-04-14 16:08:20 +03:00
Nikolay Puzanov
1e0bfb58cf Add support for verilator 5.018+ 2023-11-07 14:27:08 +03:00
Nikolay Puzanov
e67558de14 Enable dump in iverilog testbench template 2023-06-02 11:08:51 +03:00
Nikolay Puzanov
54f7e2be54 Enable trace of structs 2022-12-13 11:49:15 +03:00
Nikolay Puzanov
cc605cce85 Top module for all simulators must have an input clock signal 2022-12-09 10:21:40 +03:00
Nikolay Puzanov
2f9f5b6dd1 Disable Save hotkey (to prevent thoughtless use) 2022-12-09 10:13:03 +03:00
Nikolay Puzanov
cb8bc37dfe Disable ligatures 2022-12-09 09:23:07 +03:00
Nikolay Puzanov
1e12d5d3e2 Don't save unmodified code 2022-12-09 09:20:53 +03:00
Nikolay Puzanov
1bc6ec544d Save code only by Save button. Save always to new location 2022-12-09 09:07:13 +03:00
Nikolay Puzanov
d04282e1c7 Add simple scroll of long waveform 2022-12-08 19:06:08 +03:00
Nikolay Puzanov
664b7b1f5c Buttons can move to new line 2022-12-07 18:07:00 +03:00
Nikolay Puzanov
37b7a54d3b Visual improvements 2022-12-07 17:55:21 +03:00
Nikolay Puzanov
01c982fada Fix parsing canvas width 2022-12-07 17:54:50 +03:00
Nikolay Puzanov
931f4d8aa4 Fix signals sorting (put clock on the top) 2022-12-07 17:53:50 +03:00
Nikolay Puzanov
90905544d4 Upcase signal values 2022-12-07 17:53:17 +03:00
Nikolay Puzanov
ab5db7f6e8 Add waveforms 2022-12-07 17:00:51 +03:00
Nikolay Puzanov
e8ba09ecab Add VCD to SVG conversion functions 2022-12-06 20:06:26 +03:00
Nikolay Puzanov
daa744f8b2 Replace 'when not' to 'unless' 2022-12-05 20:26:04 +03:00
Nikolay Puzanov
c91003e34b Replace string-trim (left only trim) by string-trim-both 2022-12-04 19:53:56 +03:00
Nikolay Puzanov
53412381fb Optionally enable timestamp in save snippet uri 2022-12-04 12:09:32 +03:00
Nikolay Puzanov
536bde92df Allow to disable code sanitization 2022-12-04 11:29:25 +03:00
Nikolay Puzanov
b9cd29ad87 Fix Crtl-S hotkey 2022-12-04 11:29:10 +03:00
Nikolay Puzanov
c6c6744b22 Show execution time of compilation and simulation 2022-12-04 10:20:53 +03:00
Nikolay Puzanov
42f22147ea Limit dump file size for Icarus Verilog 2022-12-03 23:53:03 +03:00
Nikolay Puzanov
b4507004b8 Add latest Icarus Verilog and Verilator to Docker image 2022-12-03 19:31:39 +03:00
Nikolay Puzanov
74e76d8131 Add verilator build jobs option 2022-12-03 19:30:58 +03:00
Nikolay Puzanov
058191de55 Add Verilator support 2022-12-03 18:36:50 +03:00
Nikolay Puzanov
f61bb7b980 Prepare to add Verilator 2022-12-03 13:52:43 +03:00
Nikolay Puzanov
9939a226c8 Add help button 2022-12-03 13:32:09 +03:00
Nikolay Puzanov
185dcb350d Fix content type of binary response. Add favicon 2022-12-02 18:46:42 +03:00
Nikolay Puzanov
28d86fb98d Disable side-by-side layout on mobile phones 2022-12-02 16:13:39 +03:00
Nikolay Puzanov
680e9f3aa5 Add 'Save as new' button 2022-12-02 14:53:43 +03:00
Nikolay Puzanov
ec02787747 Change page design. Make page mobile friendly 2022-12-02 14:33:31 +03:00
Nikolay Puzanov
b87a7e0c97 Flush stdout after log string printing 2022-12-01 22:15:59 +03:00
10 changed files with 919 additions and 251 deletions

View File

@@ -10,4 +10,11 @@ module testbench;
initial begin initial begin
$finish; $finish;
end end
`ifdef DUMP
initial begin
$dumpfile("testbench.fst");
$dumpvars(0, testbench);
end
`endif
endmodule endmodule

View File

@@ -3,10 +3,24 @@ FROM ubuntu:22.10
LABEL description="Verilog playground" LABEL description="Verilog playground"
# Prepare OS # Prepare OS
RUN sed -i 's/^# *deb-src/deb-src/g' /etc/apt/sources.list
RUN apt-get -y update \ RUN apt-get -y update \
&& apt-get -y install iverilog guile-3.0 locales git && apt-get -y install guile-3.0 locales git
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen \ RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen \
&& locale-gen && locale-gen
RUN apt-get build-dep -y iverilog verilator
# Build latest Icarus Veriolog
WORKDIR /build
RUN git clone --depth 1 https://github.com/steveicarus/iverilog.git
WORKDIR /build/iverilog
RUN sh ./autoconf.sh && ./configure --prefix=/usr && make -j2 && make install
# Build latest Verilator
WORKDIR /build
RUN git clone --depth 1 https://github.com/verilator/verilator.git
WORKDIR /build/verilator
RUN autoconf && ./configure --prefix=/usr && make -j2 && make install
# Environment # Environment
ENV GIT_SSL_NO_VERIFY=1 ENV GIT_SSL_NO_VERIFY=1
@@ -28,8 +42,10 @@ CMD [ "guile", "-e", "main", \
"--port=8080", \ "--port=8080", \
"--addr=0.0.0.0", \ "--addr=0.0.0.0", \
"--host=https://play.embddr.com", \ "--host=https://play.embddr.com", \
"--iverilog-exe=./iverilog", \ "--iverilog-wrap=./restrict", \
"--vvp-exe=./vvp", \ "--vvp-wrap=./restrict", \
"--verilator-sim-wrap=./restrict", \
"--verilator-build-jobs=2", \
"--max-len=10000", \ "--max-len=10000", \
"--work-base=play-work", \ "--work-base=play-work", \
"--stor-base=/verilog-playground-store", \ "--stor-base=/verilog-playground-store", \

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -2,57 +2,148 @@
<html> <html>
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Verilog Playground</title> <title>Verilog Playground</title>
<style type="text/css" media="screen"> <style type="text/css" media="screen">
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap'); @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap');
.container { * {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 5px;
box-sizing: border-box; box-sizing: border-box;
background: white; margin: 0;
padding: 0;
font-variant-ligatures: none;
}
body {
padding: 3px;
font-family: 'JetBrains Mono', monospace; font-family: 'JetBrains Mono', monospace;
font-size: 14px; font-size: 10pt;
} }
.panel { pre {
float: left; font-family: 'JetBrains Mono', monospace;
position: relative; font-size: 10pt;
height: 100%;
padding: 4px;
border: 1px solid #008899;
box-sizing: border-box;
} }
.ctrl-panel { width: 10%; } #buttons {
.editor { width: 45%; } color: white;
.log-panel { width: 45%; } background-color: #2d3d40;
#log {
width: 100%; width: 100%;
height: 100%; padding: 3px;
border: 0px;
font-size: inherit; font-size: inherit;
} }
#logdiv, #editor, #buttons {
border-width: 1px;
border-style: solid;
border-color: #505050;
}
button {
color: black;
background-color: #dbdbdb;
margin-left: 1px;
margin-right: 1px;
margin-top: 2px;
margin-bottom: 2px;
height: 25px;
}
button span.text { padding: 4px; }
#editor {
height: 75vh;
width: 100%;
}
#logdiv {
height: 100%;
width: 100%;
}
#logdiv {
position: relative;
overflow: scroll;
}
svg {
fill: none;
stroke: white;
stroke-width: 0;
shape-rendering: crispEdges;
}
svg text {
font-family: 'JetBrains Mono', monospace;
font-size: 10pt;
fill: white;
}
svg #wave-signals {
stroke: #00fcff;
stroke-width: 1;
}
svg #wave-clock {
stroke: #fffe9a;
font-size: 8pt;
stroke-width: 1;
}
svg #wave-signals text { font-size: 8pt; }
svg #wave-clock text { font-size: 8pt; }
svg #wave-delim {
stroke: #d0d0d0;
stroke-width: 2;
}
svg #wave-background { fill: #1e2426; }
@media (orientation: landscape) and (not (pointer: coarse)) {
body {
display: flex;
flex-flow: column;
height: 100vh;
}
#text { flex-grow: 1; }
#editor {
float: left;
width: 50%;
height: 100%;
}
#logdiv {
float: left;
width: 50%;
height: 100%;
}
#logdiv pre {
position: absolute;
height: 100%;
}
}
</style> </style>
</head> </head>
<body> <body>
<div class="container"> <div id="buttons">
<div class="panel ctrl-panel"> <button onclick="show_help()"><span class="text">?</span></button>
<button style="width:100%" onclick="save_code()">Save (ctrl+s)</button> <button onclick="save_code('%SAVECODEURI%')"><span class="text">Save</span></button>
<button style="width:100%" onclick="send_to_icarus()">Run Icarus Verilog</button> Sim:
</div> <button onclick="send_to_sim('%IVERILOGPOSTURI%')"><span class="text">Icarus</span></button>
<div class="panel editor" id="editor">@CODE@</div> <button onclick="send_to_sim('%VERILATORPOSTURI%')"><span class="text">Verilator</span></button>
<div class="panel log-panel">
<textarea id="log" readonly="readonly"></textarea>
</div>
</div> </div>
<div id="text">
<div id="editor">@CODE@</div>
<div id="logdiv"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ace.js" type="text/javascript" charset="utf-8"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ext-language_tools.js" type="text/javascript" charset="utf-8"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ext-language_tools.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
@@ -66,10 +157,11 @@
enableBasicAutocompletion : true, enableBasicAutocompletion : true,
enableLiveAutocompletion : true enableLiveAutocompletion : true
}); });
const log_area = document.getElementById('log'); const log_area = document.getElementById('logdiv');
function send_to_icarus() { function send_to_sim(uri) {
log_area.value = "Please wait..."; query = uri + "?width=" + log_area.clientWidth;
fetch('%IVERILOGPOSTURI%', log_area.innerHTML = "Please wait...";
fetch(query,
{ {
method: 'POST', method: 'POST',
headers: { headers: {
@@ -79,11 +171,11 @@
body: editor.getValue() body: editor.getValue()
}) })
.then((response) => response.text()) .then((response) => response.text())
.then((text) => { log_area.value = text; }); .then((text) => { log_area.innerHTML = text; });
}; };
function save_code() { function save_code(uri) {
fetch('%SAVECODEURI%', fetch(uri,
{ {
method: 'POST', method: 'POST',
headers: { headers: {
@@ -96,12 +188,9 @@
.then((text) => { window.location.href = text; }); .then((text) => { window.location.href = text; });
}; };
document.addEventListener('keydown', (e) => { function show_help() {
if (e.key.toLowerCase() === 's' && e.ctrlKey) { alert("%HELPSTRING%");
e.preventDefault(); };
save_code();
}
});
</script> </script>
</body> </body>

View File

@@ -1 +0,0 @@
run-restricted

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,12 @@
#!/usr/bin/env bash #!/usr/bin/env bash
exe=$(basename $0)
if [ -z "$DONOTUSEFIREJAIL" ]; then if [ -z "$DONOTUSEFIREJAIL" ]; then
exec firejail \ exec firejail \
--quiet --noprofile \ --quiet --noprofile \
--rlimit-cpu=5 \ --rlimit-cpu=5 \
--rlimit-as=250m \ --rlimit-as=250m \
--rlimit-fsize=250k \ --rlimit-fsize=250k \
"$exe" "$@" "$@"
else else
exec timeout -v -s INT 5 "$exe" "$@" exec timeout -v -s KILL 5 "$@"
fi fi

View File

@@ -0,0 +1,11 @@
`timescale 1ps/1ps
module __@TOPMODULE@__;
@TOPMODULE@ @TOPMODULE@ ();
initial begin
$dumpfile("@WORKDIR@/@TOPMODULE@.vcd");
$dumpvars(1, @TOPMODULE@);
$dumplimit(100000);
end
endmodule

View File

@@ -0,0 +1,43 @@
#include "verilated.h"
#include "verilated_vcd_c.h"
#include "V@TOPMODULE@.h"
#define DUMPFILE "@WORKDIR@/@TOPMODULE@.vcd"
int main(int argc, char** argv, char**) {
// Setup context, defaults, and parse command line
Verilated::debug(0);
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
contextp->traceEverOn(true);
contextp->commandArgs(argc, argv);
// Construct the Verilated model, from Vtop.h generated from Verilating
const std::unique_ptr<V@TOPMODULE@> topp{new V@TOPMODULE@{contextp.get()}};
VerilatedVcdC *vcd = new VerilatedVcdC;
topp->trace(vcd, 99);
vcd->open(DUMPFILE);
// Simulate until $finish
while (!contextp->gotFinish()) {
// Evaluate model
topp->eval();
vcd->dump(contextp->time());
// Advance time
if (!topp->eventsPending()) break;
contextp->time(topp->nextTimeSlot());
}
if (!contextp->gotFinish()) {
VL_DEBUG_IF(VL_PRINTF("+ Exiting without $finish; no events left\n"););
}
// Execute 'final' processes
topp->final();
// Print statistical summary report
contextp->statsPrintSummary();
vcd->close();
return 0;
}

View File

@@ -1 +0,0 @@
run-restricted