Compare commits
35 Commits
6a9959f98d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3aee2d2f38 | ||
|
|
b84ec9a1c5 | ||
|
|
1e0bfb58cf | ||
|
|
e67558de14 | ||
|
|
54f7e2be54 | ||
|
|
cc605cce85 | ||
|
|
2f9f5b6dd1 | ||
|
|
cb8bc37dfe | ||
|
|
1e12d5d3e2 | ||
|
|
1bc6ec544d | ||
|
|
d04282e1c7 | ||
|
|
664b7b1f5c | ||
|
|
37b7a54d3b | ||
|
|
01c982fada | ||
|
|
931f4d8aa4 | ||
|
|
90905544d4 | ||
|
|
ab5db7f6e8 | ||
|
|
e8ba09ecab | ||
|
|
daa744f8b2 | ||
|
|
c91003e34b | ||
|
|
53412381fb | ||
|
|
536bde92df | ||
|
|
b9cd29ad87 | ||
|
|
c6c6744b22 | ||
|
|
42f22147ea | ||
|
|
b4507004b8 | ||
|
|
74e76d8131 | ||
|
|
058191de55 | ||
|
|
f61bb7b980 | ||
|
|
9939a226c8 | ||
|
|
185dcb350d | ||
|
|
28d86fb98d | ||
|
|
680e9f3aa5 | ||
|
|
ec02787747 | ||
|
|
b87a7e0c97 |
@@ -10,4 +10,11 @@ module testbench;
|
||||
initial begin
|
||||
$finish;
|
||||
end
|
||||
|
||||
`ifdef DUMP
|
||||
initial begin
|
||||
$dumpfile("testbench.fst");
|
||||
$dumpvars(0, testbench);
|
||||
end
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
@@ -3,10 +3,24 @@ FROM ubuntu:22.10
|
||||
LABEL description="Verilog playground"
|
||||
|
||||
# Prepare OS
|
||||
RUN sed -i 's/^# *deb-src/deb-src/g' /etc/apt/sources.list
|
||||
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 \
|
||||
&& 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
|
||||
ENV GIT_SSL_NO_VERIFY=1
|
||||
@@ -28,8 +42,10 @@ CMD [ "guile", "-e", "main", \
|
||||
"--port=8080", \
|
||||
"--addr=0.0.0.0", \
|
||||
"--host=https://play.embddr.com", \
|
||||
"--iverilog-exe=./iverilog", \
|
||||
"--vvp-exe=./vvp", \
|
||||
"--iverilog-wrap=./restrict", \
|
||||
"--vvp-wrap=./restrict", \
|
||||
"--verilator-sim-wrap=./restrict", \
|
||||
"--verilator-build-jobs=2", \
|
||||
"--max-len=10000", \
|
||||
"--work-base=play-work", \
|
||||
"--stor-base=/verilog-playground-store", \
|
||||
|
||||
BIN
_web_server/server/favicon.png
Normal file
BIN
_web_server/server/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -2,57 +2,148 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<title>Verilog Playground</title>
|
||||
<style type="text/css" media="screen">
|
||||
@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;
|
||||
background: white;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-variant-ligatures: none;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 3px;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 14px;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.panel {
|
||||
float: left;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding: 4px;
|
||||
border: 1px solid #008899;
|
||||
box-sizing: border-box;
|
||||
pre {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.ctrl-panel { width: 10%; }
|
||||
.editor { width: 45%; }
|
||||
.log-panel { width: 45%; }
|
||||
|
||||
#log {
|
||||
#buttons {
|
||||
color: white;
|
||||
background-color: #2d3d40;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0px;
|
||||
padding: 3px;
|
||||
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>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="panel ctrl-panel">
|
||||
<button style="width:100%" onclick="save_code()">Save (ctrl+s)</button>
|
||||
<button style="width:100%" onclick="send_to_icarus()">Run Icarus Verilog</button>
|
||||
</div>
|
||||
<div class="panel editor" id="editor">@CODE@</div>
|
||||
<div class="panel log-panel">
|
||||
<textarea id="log" readonly="readonly"></textarea>
|
||||
</div>
|
||||
<div id="buttons">
|
||||
<button onclick="show_help()"><span class="text">?</span></button>
|
||||
<button onclick="save_code('%SAVECODEURI%')"><span class="text">Save</span></button>
|
||||
Sim:
|
||||
<button onclick="send_to_sim('%IVERILOGPOSTURI%')"><span class="text">Icarus</span></button>
|
||||
<button onclick="send_to_sim('%VERILATORPOSTURI%')"><span class="text">Verilator</span></button>
|
||||
</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/ext-language_tools.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
@@ -66,10 +157,11 @@
|
||||
enableBasicAutocompletion : true,
|
||||
enableLiveAutocompletion : true
|
||||
});
|
||||
const log_area = document.getElementById('log');
|
||||
function send_to_icarus() {
|
||||
log_area.value = "Please wait...";
|
||||
fetch('%IVERILOGPOSTURI%',
|
||||
const log_area = document.getElementById('logdiv');
|
||||
function send_to_sim(uri) {
|
||||
query = uri + "?width=" + log_area.clientWidth;
|
||||
log_area.innerHTML = "Please wait...";
|
||||
fetch(query,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -79,11 +171,11 @@
|
||||
body: editor.getValue()
|
||||
})
|
||||
.then((response) => response.text())
|
||||
.then((text) => { log_area.value = text; });
|
||||
.then((text) => { log_area.innerHTML = text; });
|
||||
};
|
||||
|
||||
function save_code() {
|
||||
fetch('%SAVECODEURI%',
|
||||
function save_code(uri) {
|
||||
fetch(uri,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -96,12 +188,9 @@
|
||||
.then((text) => { window.location.href = text; });
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key.toLowerCase() === 's' && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
save_code();
|
||||
}
|
||||
});
|
||||
function show_help() {
|
||||
alert("%HELPSTRING%");
|
||||
};
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
run-restricted
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
exe=$(basename $0)
|
||||
|
||||
if [ -z "$DONOTUSEFIREJAIL" ]; then
|
||||
exec firejail \
|
||||
--quiet --noprofile \
|
||||
--rlimit-cpu=5 \
|
||||
--rlimit-as=250m \
|
||||
--rlimit-fsize=250k \
|
||||
"$exe" "$@"
|
||||
"$@"
|
||||
else
|
||||
exec timeout -v -s INT 5 "$exe" "$@"
|
||||
exec timeout -v -s KILL 5 "$@"
|
||||
fi
|
||||
11
_web_server/server/top_iverilog.sv
Normal file
11
_web_server/server/top_iverilog.sv
Normal 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
|
||||
43
_web_server/server/top_verilator.cpp
Normal file
43
_web_server/server/top_verilator.cpp
Normal 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;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
run-restricted
|
||||
Reference in New Issue
Block a user