-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
8f81ae6
commit 382ca37
Showing
4 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
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 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// 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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
# 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} | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
""".format(verilator_root= os.path.join("../../", verilator_root_path), # XXX | ||
disable_warnings="-Wno-lint -Wno-INITIALDLY", | ||
This comment has been minimized.
Sorry, something went wrong.
sbourdeauducq
Member
|
||
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("..") |
Why do you need to set VERILATOR_ROOT? It fails here with:
Vdut.mk:59: ../../../verilator/include/verilated.mk: No such file or directory
Removing it fixes the problem.