Add Verilator support

This commit is contained in:
Nikolay Puzanov 2022-12-03 18:36:50 +03:00
parent f61bb7b980
commit 058191de55
7 changed files with 295 additions and 140 deletions

View File

@ -98,7 +98,8 @@
<button onclick="save_code('%SAVECODEURI%')"><span class="text">Save (ctrl-s)</span></button> <button onclick="save_code('%SAVECODEURI%')"><span class="text">Save (ctrl-s)</span></button>
<button onclick="save_code('%SAVEASURI%')"><span class="text">Save as new</span></button> <button onclick="save_code('%SAVEASURI%')"><span class="text">Save as new</span></button>
Sim: Sim:
<button onclick="send_to_icarus()"><span class="text">Icarus</span></button> <button onclick="send_to_sim('%IVERILOGPOSTURI%')"><span class="text">Icarus</span></button>
<button onclick="send_to_sim('%VERILATORPOSTURI%')"><span class="text">Verilator</span></button>
<!-- button><span class="text">Verilator</span></button --> <!-- button><span class="text">Verilator</span></button -->
</div> </div>
@ -123,9 +124,9 @@
enableLiveAutocompletion : true enableLiveAutocompletion : true
}); });
const log_area = document.getElementById('log'); const log_area = document.getElementById('log');
function send_to_icarus() { function send_to_sim(uri) {
log_area.innerHTML = "Please wait..."; log_area.innerHTML = "Please wait...";
fetch('%IVERILOGPOSTURI%', fetch(uri,
{ {
method: 'POST', method: 'POST',
headers: { headers: {

View File

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

View File

@ -24,22 +24,17 @@
(define INDEX-FILE "index.html") (define INDEX-FILE "index.html")
(define DELETE-WORK-DIR #t) (define DELETE-WORK-DIR #t)
(define DEFAULT-CODE (define TOP-MODULE "testbench")
(string-append
"`timescale 10ps/10ps\n\n"
"module test;\n"
" initial begin\n"
" $display(\"Hello world!\");\n"
" $finish();\n"
" end\n"
"endmodule\n"))
(define SIM-SV-FILE "testbench.sv")
(define SIM-VC-FILE "testbench.vc")
(define SIM-EXE-FILE "testbench.out")
(define SNIPPET-FILE "code.sv") (define SNIPPET-FILE "code.sv")
(define IVERILOG-METATOP-FILE "top_iverilog.sv")
(define VERILATOR-CPP-FILE "top_verilator.cpp")
(define IVERILOG-EXE "iverilog")
(define VVP-EXE "vvp")
(define VERILATR-EXE "verilator")
(define URI-IVERILOG "iverilog") (define URI-IVERILOG "iverilog")
(define URI-VERILATOR "verilator")
(define URI-SAVE-CODE "save") (define URI-SAVE-CODE "save")
(define URI-SAVEAS-CODE "saveas") (define URI-SAVEAS-CODE "saveas")
@ -50,6 +45,16 @@
(define LOG-LEVEL LOG-VERBOSE) (define LOG-LEVEL LOG-VERBOSE)
(define DEFAULT-CODE
(string-append
"`timescale 1ps/1ps\n\n"
(format "module ~a (input clock);\n" TOP-MODULE)
" initial begin\n"
" $display(\"Hello world!\");\n"
" $finish();\n"
" end\n"
"endmodule\n"))
(define (multistring . strings) (define (multistring . strings)
(apply string-append (apply string-append
(insert-between strings "\n"))) (insert-between strings "\n")))
@ -235,21 +240,6 @@
(code (regexp-substitute/global #f "\\$dump[a-z]*" code 'pre "$error" 'post))) (code (regexp-substitute/global #f "\\$dump[a-z]*" code 'pre "$error" 'post)))
code)) code))
;;;
;;; Get module name
;;;
(define (module-name code)
(let ((rx (make-regexp
"(^|\\s)module\\s*(\\s|(#\\(.*\\)\\s*))[a-zA-Z0-9_]+")))
(let loop ((pos 0)
(modname #f))
(let ((m (regexp-exec rx code pos)))
(if m
(loop (match:end m) (match:substring m))
(if modname
(match:substring (string-match "[a-zA-Z0-9_]+$" modname))
#f))))))
;;; ;;;
;;; Concatenate path elements and remove duplicate slashes ;;; Concatenate path elements and remove duplicate slashes
;;; ;;;
@ -267,52 +257,86 @@
(map string-trim-both paths)) (map string-trim-both paths))
"/"))))) "/")))))
;;; (define (wrap-exe exe wrapper)
;;; Create dump module (format "~a~a" (if wrapper (format "~a " wrapper) "") exe))
;;;
(define (create-dump-module path modname top)
(define (-> . fmt) (display (apply format fmt)) (newline))
(let ((filename (path+ path (format "~a.v" modname))))
(with-output-to-file filename
(lambda ()
(-> "`timescale 1ps/1ps")
(-> "module ~a();" modname)
(-> " initial begin")
(-> " $dumpfile(\"~a/~a.vcd\");" path modname)
(-> " $dumpvars(0, ~a);" top)
(-> " end")
(-> "endmodule")))
filename))
;;; ;;;
;;; Make workdir with sources and command file ;;; Make workdir with sources and command file. Common part
;;; Returns work directory path string ;;; Returns work directory path string, verilog file name
;;; and command file name.
;;; ;;;
(define (make-sim-workdir simulator code top base) (define* (make-sim-workdir code base top)
(let* ((work-dir (mkdtemp (path+ base (format "work-~a-XXXXXX" (current-time))))) (let* ((work-dir (mkdtemp (path+ base (format "work-~a-XXXXXX" (current-time)))))
(verilog-file (path+ work-dir SIM-SV-FILE)) (verilog-file (path+ work-dir (format "~a.sv" top)))
(command-file (path+ work-dir SIM-VC-FILE)) (command-file (path+ work-dir (format "~a.vc" top))))
(dump-file (create-dump-module work-dir "dump" top)))
(with-output-to-file verilog-file (cut display code)) (with-output-to-file verilog-file (cut display code))
(with-output-to-file command-file (values work-dir verilog-file command-file)))
(lambda ()
(cond ;;;
((eq? simulator 'iverilog) ;;; Create workdir for Icarus Verilog
;;; Returns directory path
;;;
(define* (make-iverilog-workdir code metatop base top)
(let-values (((work-dir verilog-file command-file)
(make-sim-workdir code base top)))
(let ((metatop-file (path+ work-dir (format "__~a__.sv" top))))
(with-output-to-file metatop-file
(cut display (substitute metatop "@~a@"
`((WORKDIR ,work-dir)
(TOPMODULE ,top)))))
(with-output-to-file command-file
(lambda ()
(println "~a" verilog-file) (println "~a" verilog-file)
(println "~a" dump-file) (println "~a" metatop-file)
(println "+define+TESTBENCH") (println "+define+TESTBENCH")
(println "+timescale+1ps/1ps"))))) (println "+timescale+1ps/1ps"))))
work-dir))
;;;
;;; Create workdir for Verilator
;;; Returns directory path
;;;
(define* (make-verilator-workdir code cpp base top)
(let-values (((work-dir verilog-file command-file)
(make-sim-workdir code base top)))
(let ((cpp-file (path+ work-dir (format "~a.cpp" top))))
(with-output-to-file cpp-file
(cut display (substitute cpp "@~a@" `((WORKDIR ,work-dir)
(TOPMODULE ,top)))))
(with-output-to-file command-file
(lambda ()
(println "+define+TESTBENCH")
(println "--timescale 1ps/1ps")
(println "--top-module ~a" top)
(println "--Mdir ~a" (path+ work-dir top))
(println "-cc")
(println "-O2")
(println "-o ~a" top)
(println "--exe")
(println "--build")
(println "-sv")
(println "-Wno-WIDTH")
(println "+1800-2017ext+sv")
(println "--timing")
(println "--trace")
(println "--quiet-exit")
(println "~a" verilog-file)
(println "~a.cpp" top))))
work-dir)) work-dir))
;;; ;;;
;;; Compile sources and execute simulation with Icarus Verilog ;;; Compile sources and execute simulation with Icarus Verilog
;;; Returns (values status log) ;;; Returns (values status log)
;;; ;;;
(define (exec-sim-iverilog work-dir vvp-exe iverilog-exe) (define (exec-sim-iverilog top work-dir iverilog-wrap vvp-wrap)
(let ((exe-file (path+ work-dir SIM-EXE-FILE)) (let ((command-file (path+ work-dir (format "~a.vc" top)))
(command-file (path+ work-dir SIM-VC-FILE))) (exe-file (path+ work-dir (format "~a.out" top))))
;; Compile ;; Compile
(let ((cmdline (format "~a -g2012 -o ~a -c~a" iverilog-exe exe-file command-file))) (let ((cmdline (format "~a -g2012 -s __~a__ -o ~a -c~a"
(wrap-exe IVERILOG-EXE iverilog-wrap)
top exe-file command-file)))
(let-values (((status out) (let-values (((status out)
(system-to-string cmdline))) (system-to-string cmdline)))
(let ((compile-log (let ((compile-log
@ -321,13 +345,79 @@
(values status compile-log) (values status compile-log)
;; Execute ;; Execute
(let ((cmdline (format "~a -N ~a" vvp-exe exe-file))) (let ((cmdline (format "~a -N ~a" (wrap-exe VVP-EXE vvp-wrap) exe-file)))
(let-values (((status out) (let-values (((status out)
(system-to-string cmdline))) (system-to-string cmdline)))
(let ((execution-log (let ((execution-log
(exe-log-pretty cmdline status out))) (exe-log-pretty cmdline status out)))
(values status (string-append compile-log execution-log))))))))))) (values status (string-append compile-log execution-log)))))))))))
;;;
;;; Compile sources and execute simulation with Verilator
;;; Returns (values status log)
;;;
(define (exec-sim-verilator top work-dir verilator-wrap verilator-sim-wrap)
;; Compile
(let* ((command-file (path+ work-dir (format "~a.vc" top)))
(cmdline (format "~a -f ~a"
(wrap-exe VERILATR-EXE verilator-wrap)
command-file)))
(let-values (((status out)
(system-to-string cmdline)))
(let ((compile-log
(exe-log-pretty cmdline status out)))
(if (not (zero? status))
(values status compile-log)
;; Execute
(let ((cmdline (wrap-exe (path+ work-dir (format "~a/~a" top top))
verilator-sim-wrap)))
(let-values (((status out)
(system-to-string cmdline)))
(let ((execution-log
(exe-log-pretty cmdline status out)))
(values status (string-append compile-log execution-log))))))))))
;;;
;;; Execute simulation
;;;
(define* (exec-sim simulator code base top #:key
(vvp-wrap "") (iverilog-wrap "") (metatop "")
(verilator-wrap "") (verilator-sim-wrap "") (verilator-cpp ""))
(let-values
(((work-dir status log)
(cond
;; Run Icarus Verilog
((eq? simulator 'iverilog)
(let ((work-dir (make-iverilog-workdir code metatop base top)))
(let-values (((status log)
(exec-sim-iverilog top work-dir iverilog-wrap vvp-wrap)))
(values work-dir status log))))
;; Run Verilator
((eq? simulator 'verilator)
(let ((work-dir (make-verilator-workdir code verilator-cpp base top)))
(let-values (((status log)
(exec-sim-verilator top work-dir verilator-wrap verilator-sim-wrap)))
(values work-dir status log))))
;; Inknown simulator
(else
(values #f #f #f)))))
(if (not work-dir)
("ERROR: Unknown simulator")
(begin
;; Delete work dir
(when DELETE-WORK-DIR
(delete-recursive work-dir))
;; Return log
(string-append
log
(format "-----------------\nSimulation complete~a\n"
(if (zero? status) " succesfully"" with errors")))))))
;;; ;;;
;;; Get app version ;;; Get app version
;;; ;;;
@ -340,38 +430,6 @@
(car out) (car out)
"Unknown"))) "Unknown")))
;;;
;;; Execute simulation
;;;
(define* (exec-sim simulator code base
#:key
(vvp-exe "vvp")
(iverilog-exe "iverilog"))
(let ((top (module-name code)))
(if (not top)
"Error: No module declaration\n"
(let ((work-dir (make-sim-workdir simulator code top base)))
(let-values
(((status log)
(cond
((eq? simulator 'iverilog)
(exec-sim-iverilog work-dir vvp-exe iverilog-exe))
(else
(values -1 "No simulator found!\n")))))
;; Delete work dir
(when DELETE-WORK-DIR
(delete-recursive work-dir))
;; Return log
(string-append
log
(format "-----------------\nSimulation complete~a\n"
(if (zero? status)
" succesfully"
" with errors"))))))))
;;; ;;;
;;; Get storage dir from URI ;;; Get storage dir from URI
;;; ;;;
@ -428,40 +486,43 @@
(define (make-page-handler host root index-file (define (make-page-handler host root index-file
work-base stor-base work-base stor-base
max-code-size max-code-size
vvp-exe iverilog-exe iverilog-wrap vvp-wrap
verilator-exe) verilator-wrap verilator-sim-wrap)
(let* ((root-path (split-and-decode-uri-path root)) (let* ((root-path (split-and-decode-uri-path root))
(root (encode-and-join-uri-path root-path)) (root (encode-and-join-uri-path root-path))
(iverilog-path (append root-path `(,URI-IVERILOG))) (iverilog-path (append root-path `(,URI-IVERILOG)))
(verilator-path (append root-path `(,URI-VERILATOR)))
(savecode-path (append root-path `(,URI-SAVE-CODE))) (savecode-path (append root-path `(,URI-SAVE-CODE)))
(saveas-path (append root-path `(,URI-SAVEAS-CODE))) (saveas-path (append root-path `(,URI-SAVEAS-CODE)))
(iverilog-post-uri (encode-and-join-uri-path iverilog-path))
(savecode-post-uri (encode-and-join-uri-path savecode-path))
(saveas-post-uri (encode-and-join-uri-path saveas-path))
(index-html (index-html
(read-template-text (read-template-text
index-file index-file
`(("IVERILOGPOSTURI" ,iverilog-post-uri) `(("IVERILOGPOSTURI" ,(encode-and-join-uri-path iverilog-path))
("SAVECODEURI" ,savecode-post-uri) ("VERILATORPOSTURI" ,(encode-and-join-uri-path verilator-path))
("SAVEASURI" ,saveas-post-uri) ("SAVECODEURI" ,(encode-and-join-uri-path savecode-path))
("SAVEASURI" ,(encode-and-join-uri-path saveas-path))
("HELPSTRING", ("HELPSTRING",
(string-concatenate (string-concatenate
(insert-between (insert-between
`("Verilog Playground by Punzik (c) 2022" `("Verilog Playground by Punzik (c) 2022"
"" ""
,(format "Icarus: ~a" ,(format "Icarus: ~a"
(app-version iverilog-exe "-V")) (app-version (wrap-exe IVERILOG-EXE iverilog-wrap) "-V"))
,(format "Verilator: ~a" ,(format "Verilator: ~a"
(app-version verilator-exe)) (app-version (wrap-exe VERILATR-EXE verilator-wrap)))
"" ""
"Rules:" "Rules:"
"0. Don't fool around ;)" "0. Don't fool around ;)"
"1. (TODO) The top module must be named 'testbench'." "1. The top module must be named 'testbench'."
"2. (TODO) The top module for the Verilator must have an input clock signal." "2. The top module for the Verilator must have an input clock signal."
"3. Code size should not exceed 10000 characters." "3. Code size should not exceed 10000 characters."
"4. Code execution time no longer than 5 seconds.") "4. Code execution time no longer than 5 seconds.")
"\\n"))))))) "\\n"))))))
(iverilog-metatop
(call-with-input-file IVERILOG-METATOP-FILE get-string-all))
(verilator-cpp
(call-with-input-file VERILATOR-CPP-FILE get-string-all)))
(lambda (request request-body) (lambda (request request-body)
(let (;; Requested resource path (let (;; Requested resource path
@ -551,8 +612,27 @@
(exec-sim 'iverilog (exec-sim 'iverilog
(sanitize-verilog code) (sanitize-verilog code)
work-base work-base
#:vvp-exe vvp-exe TOP-MODULE
#:iverilog-exe iverilog-exe) #:metatop iverilog-metatop
#:vvp-wrap vvp-wrap
#:iverilog-wrap iverilog-wrap)
#:content-type 'text/plain))
;; Run verilator simulation
((equal? path verilator-path)
(logger LOG-DBG "Request verilator simulation")
(when ref-stor-dir
(save-to-storage (path+ stor-base ref-stor-dir) code))
(make-response
(exec-sim 'verilator
(sanitize-verilog code)
work-base
TOP-MODULE
#:verilator-wrap verilator-wrap
#:verilator-sim-wrap verilator-sim-wrap
#:verilator-cpp verilator-cpp)
#:content-type 'text/plain)) #:content-type 'text/plain))
;; Save snippet ;; Save snippet
@ -606,21 +686,27 @@
(-> "Start Verilog playground WEB server") (-> "Start Verilog playground WEB server")
(-> "") (-> "")
(-> "Options:") (-> "Options:")
(-> " -a, --addr ADDR Listen on ADDR address. Default: 127.0.0.1") (-> " -a, --addr ADDR Listen on ADDR address. Default: 127.0.0.1")
(-> " -p, --port PORT Listen on PORT port. Default: 8080") (-> " -p, --port PORT Listen on PORT port. Default: 8080")
(-> " -s, --host URL Run on URL hostname. Default: http://127.0.0.1:8080") (-> " -s, --host URL Run on URL hostname. Default: http://127.0.0.1:8080")
(-> " -r, --root URN Service location root. Default: ''") (-> " -r, --root URN Service location root. Default: ''")
(-> " --ivverilog-exe PATH Set Icarus Verilog compiler executable. Default: iverilog") (-> " --iverilog-wrap PATH Icarus compiler wrapper.")
(-> " --vvp-exe PATH Set Icarus Verilog interpreter executable. Default: vvp") (-> " --vvp-wrap PATH Icarus Verilog interpreter wrapper.")
(-> " --verilator-exe PATH Set Icarus Verilog interpreter executable. Default: verilator") (-> " --verilator-wrap PATH Verilator compiler wrapper.")
(-> " --max-len LEN Set maximum code size in symbols. Default: 0 (infinite)") (-> " --verilator-sim-wrap PATH Verilator simulation executable wrapper.")
(-> " --work-base PATH Set work base path. Default: ./") (-> " --max-len LEN Set maximum code size in symbols. Default: 0 (infinite)")
(-> " --stor-base PATH Set snippets storage path. Default: ./") (-> " --work-base PATH Set work base path. Default: ./")
(-> " --log-level LEVEL Set log level from 0 (quiet) to 10 (verbose). Default: 1./") (-> " --stor-base PATH Set snippets storage path. Default: ./")
(-> " -h, --help Print this message and exit") (-> " --log-level LEVEL Set log level from 0 (quiet) to 10 (verbose). Default: 1./")
(-> " -h, --help Print this message and exit")
(-> "") (-> "")
(-> "Source code and issue tracker: <https://github.com/punzik/>"))))) (-> "Source code and issue tracker: <https://github.com/punzik/>")))))
(define (string-trim-if-string str)
(if (string? str)
(string-trim str)
str))
(define (main args) (define (main args)
(debug-disable 'backtrace) (debug-disable 'backtrace)
(let-values (let-values
@ -630,9 +716,10 @@
'(("port" #\p) required) '(("port" #\p) required)
'(("host" #\s) required) '(("host" #\s) required)
'(("root" #\r) required) '(("root" #\r) required)
'(("vvp-exe") required) '(("vvp-wrap") required)
'(("iverilog-exe") required) '(("iverilog-wrap") required)
'(("verilator-exe") required) '(("verilator-wrap") required)
'(("verilator-sim-wrap") required)
'(("max-len") required) '(("max-len") required)
'(("work-base") required) '(("work-base") required)
'(("stor-base") required) '(("stor-base") required)
@ -643,9 +730,10 @@
(port (string->number (string-trim (or (option-get opts "port") "8080")))) (port (string->number (string-trim (or (option-get opts "port") "8080"))))
(host (string-trim (or (option-get opts "host") "http://127.0.0.1:8080"))) (host (string-trim (or (option-get opts "host") "http://127.0.0.1:8080")))
(root (string-trim (or (option-get opts "root") ""))) (root (string-trim (or (option-get opts "root") "")))
(vvp (string-trim (or (option-get opts "vvp-exe") "vvp"))) (vvp-wrap (string-trim-if-string (option-get opts "vvp-wrap")))
(iverilog (string-trim (or (option-get opts "iverilog-exe") "iverilog"))) (iverilog-wrap (string-trim-if-string (option-get opts "iverilog-wrap")))
(verilator (string-trim (or (option-get opts "verilator-exe") "verilator"))) (verilator-wrap (string-trim-if-string (option-get opts "verilator-wrap")))
(verilator-sim-wrap (string-trim-if-string (option-get opts "verilator-sim-wrap")))
(max-code-size (string->number (string-trim (or (option-get opts "max-len") "0")))) (max-code-size (string->number (string-trim (or (option-get opts "max-len") "0"))))
(work-base (string-trim (or (option-get opts "work-base") "./"))) (work-base (string-trim (or (option-get opts "work-base") "./")))
(stor-base (string-trim (or (option-get opts "stor-base") "./"))) (stor-base (string-trim (or (option-get opts "stor-base") "./")))
@ -665,9 +753,10 @@
(set! LOG-LEVEL log-level) (set! LOG-LEVEL log-level)
(logger LOG-INFO "Listen on '~a' port '~a'" addr port) (logger LOG-INFO "Listen on '~a' port '~a'" addr port)
(logger LOG-INFO "Server URL: '~a/~a'" host root) (logger LOG-INFO "Server URL: '~a/~a'" host root)
(logger LOG-INFO "iverilog: '~a'" iverilog) (logger LOG-INFO "iverilog wrapper: '~a'" iverilog-wrap)
(logger LOG-INFO "vvp: '~a'" vvp) (logger LOG-INFO "vvp wrapper: '~a'" vvp-wrap)
(logger LOG-INFO "verilator: '~a'" verilator) (logger LOG-INFO "verilator compiler wrapper: '~a'" verilator-wrap)
(logger LOG-INFO "verilator simulator wrapper: '~a'" verilator-sim-wrap)
(logger LOG-INFO "Max code size: ~a" max-code-size) (logger LOG-INFO "Max code size: ~a" max-code-size)
(logger LOG-INFO "Work base path: '~a'" work-base) (logger LOG-INFO "Work base path: '~a'" work-base)
(logger LOG-INFO "Storage base path: '~a'" stor-base) (logger LOG-INFO "Storage base path: '~a'" stor-base)
@ -677,6 +766,6 @@
(make-page-handler host root INDEX-FILE (make-page-handler host root INDEX-FILE
work-base stor-base work-base stor-base
max-code-size max-code-size
vvp iverilog iverilog-wrap vvp-wrap
verilator) verilator-wrap verilator-sim-wrap)
'http `(#:host ,addr #:port ,port))))))) 'http `(#:host ,addr #:port ,port)))))))

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@__;
logic clock = 1'b0;
initial forever #(5ns) clock = ~clock;
@TOPMODULE@ @TOPMODULE@ (clock);
initial begin
$dumpfile("@WORKDIR@/@TOPMODULE@.vcd");
$dumpvars(0, @TOPMODULE@);
end
endmodule

View File

@ -0,0 +1,58 @@
#include "V@TOPMODULE@.h"
#include <cstdint>
#include <verilated.h>
#include <verilated_vcd_c.h>
#define DUMPFILE "@WORKDIR@/@TOPMODULE@.vcd"
#define CLOCK_HALF_PERIOD 5000
int main(int argc, char **argv)
{
VerilatedContext *ctx = new VerilatedContext;
ctx->commandArgs(argc, argv);
/* Create model instance */
V@TOPMODULE@ *top = new V@TOPMODULE@(ctx);
#if (VM_TRACE == 1)
VerilatedVcdC *vcd = new VerilatedVcdC;
ctx->traceEverOn(true);
top->trace(vcd, 99);
vcd->open(DUMPFILE);
#endif
top->clock = 0;
/* ---- Evaluation loop ---- */
for (;;) {
/* Eval */
top->eval();
/* Trace steady-state values */
#if (VM_TRACE == 1)
if (vcd) vcd->dump(ctx->time());
#endif
/* Break exactly after calling $finish */
if (ctx->gotFinish()) break;
/* Clock event */
ctx->timeInc(CLOCK_HALF_PERIOD);
top->clock = top->clock ? 0 : 1;
}
top->final();
printf("[%lu] Stop simulation\n", ctx->time());
#if (VM_TRACE == 1)
if (vcd) {
vcd->close();
delete vcd;
}
#endif
delete top;
delete ctx;
return 0;
}

View File

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