--- /dev/null
+from mibuild.generic_platform import *
+from mibuild.crg import SimpleCRG
+from mibuild.sim.verilator import VerilatorPlatform
+
+class SimPins(Pins):
+ def __init__(self, n):
+ Pins.__init__(self, "s "*n)
+
+_io = [
+ ("sys_clk", 0, SimPins(1)),
+ ("sys_rst", 0, SimPins(1)),
+ ("serial", 0,
+ Subsignal("source_stb", SimPins(1)),
+ Subsignal("source_ack", SimPins(1)),
+ Subsignal("source_data", SimPins(8)),
+
+ Subsignal("sink_stb", SimPins(1)),
+ Subsignal("sink_ack", SimPins(1)),
+ Subsignal("sink_data", SimPins(8)),
+ ),
+]
+
+class Platform(VerilatorPlatform):
+ is_sim = True
+ default_clk_name = "sys_clk"
+ default_clk_period = 1000 # on modern computers simulate at ~ 1MHz
+ def __init__(self):
+ VerilatorPlatform.__init__(self, "SIM", _io)
+
+ def do_finalize(self, fragment):
+ pass
--- /dev/null
+// This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
+// License: BSD
+
+#include <time.h>
+
+#include "Vdut.h"
+#include "verilated.h"
+#include "verilated_vcd_c.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <termios.h>
+
+int trace = 0;
+
+struct termios orig_termios;
+
+void reset_terminal_mode(void)
+{
+ tcsetattr(0, TCSANOW, &orig_termios);
+}
+
+void set_conio_terminal_mode(void)
+{
+ struct termios new_termios;
+
+ /* take two copies - one for now, one for later */
+ tcgetattr(0, &orig_termios);
+ memcpy(&new_termios, &orig_termios, sizeof(new_termios));
+
+ /* register cleanup handler, and set the new terminal mode */
+ atexit(reset_terminal_mode);
+ cfmakeraw(&new_termios);
+ tcsetattr(0, TCSANOW, &new_termios);
+}
+
+int kbhit(void)
+{
+ struct timeval tv = { 0L, 0L };
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ return select(1, &fds, NULL, NULL, &tv);
+}
+
+int getch(void)
+{
+ int r;
+ unsigned char c;
+ if ((r = read(0, &c, sizeof(c))) < 0) {
+ return r;
+ } else {
+ return c;
+ }
+}
+
+vluint64_t main_time = 0;
+double sc_time_stamp () {
+ return main_time;
+}
+
+Vdut* dut;
+VerilatedVcdC* tfp;
+unsigned int tick;
+
+/* ios */
+/* ios */
+
+int console_service() {
+ /* fpga --> console */
+ SERIAL_SOURCE_ACK = 1;
+ if(SERIAL_SOURCE_STB == 1) {
+ if (SERIAL_SOURCE_DATA == '\n')
+ putchar('\r');
+ putchar(SERIAL_SOURCE_DATA);
+ fflush(stdout);
+ }
+
+ /* console --> fpga */
+ SERIAL_SINK_STB = 0;
+ if (tick%(1000) == 0) {
+ if(kbhit()) {
+ char c = getch();
+ if (c == 27 && !kbhit()) {
+ printf("\r\n");
+ return -1;
+ } else {
+ SERIAL_SINK_STB = 1;
+ SERIAL_SINK_DATA = c;
+ }
+ }
+ }
+ return 0;
+}
+
+void sim_tick() {
+ SYS_CLK = tick%2;
+ dut->eval();
+ if (trace)
+ tfp->dump(tick);
+ tick++;
+}
+
+void sim_init() {
+ int i;
+ tick = 0;
+#ifdef SYS_RST
+ SYS_RST = 1;
+ SYS_CLK = 0;
+ for (i=0; i<8; i++)
+ sim_tick();
+ SYS_RST = 0;
+#endif
+}
+
+int main(int argc, char **argv, char **env) {
+
+ clock_t start;
+ clock_t end;
+ float speed;
+
+ set_conio_terminal_mode();
+
+ Verilated::commandArgs(argc, argv);
+ dut = new Vdut;
+
+ Verilated::traceEverOn(true);
+ tfp = new VerilatedVcdC;
+ dut->trace(tfp, 99);
+ tfp->open("dut.vcd");
+
+ start = clock();
+ sim_init();
+ bool run = true;
+ while(run) {
+ sim_tick();
+ if (SYS_CLK) {
+ if (console_service() != 0)
+ run = false;
+ }
+ }
+ end = clock();
+
+ speed = (tick/2)/((end-start)/CLOCKS_PER_SEC);
+
+ printf("averate speed: %3.3f MHz\n\r", speed/1000000);
+
+ tfp->close();
+
+ exit(0);
+}
--- /dev/null
+# This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
+# License: BSD
+
+import os, subprocess
+
+from migen.fhdl.std import *
+from migen.fhdl.structure import _Fragment
+from mibuild.generic_platform import *
+
+def _build_tb(platform, template):
+
+ def io_name(ressource, subsignal=None):
+ res = platform.lookup_request(ressource)
+ if subsignal is not None:
+ res = getattr(res, subsignal)
+ return platform.vns.get_name(res)
+
+ ios = """
+#define SYS_CLK dut->{sys_clk}
+
+#define SERIAL_SOURCE_STB dut->{serial_source_stb}
+#define SERIAL_SOURCE_ACK dut->{serial_source_ack}
+#define SERIAL_SOURCE_DATA dut->{serial_source_data}
+
+#define SERIAL_SINK_STB dut->{serial_sink_stb}
+#define SERIAL_SINK_ACK dut->{serial_sink_ack}
+#define SERIAL_SINK_DATA dut->{serial_sink_data}
+""".format(
+ sys_clk=io_name("sys_clk"),
+
+ serial_source_stb=io_name("serial", "source_stb"),
+ serial_source_ack=io_name("serial", "source_ack"),
+ serial_source_data=io_name("serial", "source_data"),
+
+ serial_sink_stb=io_name("serial", "sink_stb"),
+ serial_sink_ack=io_name("serial", "sink_ack"),
+ serial_sink_data=io_name("serial", "sink_data"),
+ )
+
+ content = ""
+ f = open(template, "r")
+ done = False
+ for l in f:
+ content += l
+ if "/* ios */" in l and not done:
+ content += ios
+ done = True
+
+ f.close()
+ tools.write_to_file("dut_tb.cpp", content)
+
+def _build_sim(platform, build_name, include_paths, verilator_root_path, template_file, trace):
+ include = ""
+ for path in include_paths:
+ include += "-I"+path+" "
+
+ build_script_contents = """# Autogenerated by mibuild
+ rm -rf obj_dir/
+verilator {disable_warnings} -O3 --cc dut.v --exe dut_tb.cpp {trace} {include}
+make -j -C obj_dir/ -f Vdut.mk Vdut VERILATOR_ROOT={verilator_root}
+
+""".format(verilator_root= os.path.join("../../", verilator_root_path), # XXX
+ disable_warnings="-Wno-lint -Wno-INITIALDLY",
+ trace="-trace" if trace else "",
+ include=include)
+ build_script_file = "build_" + build_name + ".sh"
+ tools.write_to_file(build_script_file, build_script_contents, force_unix=True)
+
+ _build_tb(platform, os.path.join("../", template_file)) # XXX
+ r = subprocess.call(["bash", build_script_file])
+ if r != 0:
+ raise OSError("Subprocess failed")
+
+def _run_sim(build_name):
+ run_script_contents = """obj_dir/Vdut
+"""
+ run_script_file = "run_" + build_name + ".sh"
+ tools.write_to_file(run_script_file, run_script_contents, force_unix=True)
+ r = subprocess.call(["bash", run_script_file])
+ if r != 0:
+ raise OSError("Subprocess failed")
+
+class VerilatorPlatform(GenericPlatform):
+ # XXX fix template / verilator_path
+ def build(self, soc, build_dir="build", build_name="top", run=True, trace=True,
+ template_file="../migen/mibuild/sim/dut_tb.cpp",
+ verilator_root_path="../verilator"):
+ tools.mkdir_noerror(build_dir)
+ os.chdir(build_dir)
+
+ self.soc = soc
+ fragment = soc.get_fragment()
+ self.finalize(fragment)
+ v_src, vns = self.get_verilog(fragment)
+ named_sc, named_pc = self.resolve_signals(vns)
+ self.vns = vns
+ v_file = "dut.v"
+ tools.write_to_file(v_file, v_src)
+
+ include_paths = []
+ for source in self.sources:
+ path = os.path.dirname(source[0]).replace("\\", "\/")
+ if path not in include_paths:
+ include_paths.append(path)
+ include_paths += self.verilog_include_paths
+ _build_sim(self, build_name, include_paths, verilator_root_path, template_file, trace)
+
+ if run:
+ _run_sim(build_name)
+
+ os.chdir("..")