Refine tester. test common and dhry at the same time.
This commit is contained in:
parent
361dba595d
commit
ce40766cbd
3
Makefile
3
Makefile
|
@ -27,7 +27,8 @@ test_wb_vcd: testbench_wb.vvp firmware/firmware.hex
|
||||||
$(VVP) -N $< +vcd +trace +noerror
|
$(VVP) -N $< +vcd +trace +noerror
|
||||||
|
|
||||||
test_verilator: testbench_verilator firmware/firmware.hex
|
test_verilator: testbench_verilator firmware/firmware.hex
|
||||||
./testbench_verilator
|
./testbench_verilator 0
|
||||||
|
./testbench_verilator 1
|
||||||
|
|
||||||
testbench_verilator: testbench_wb.v picorv32.v testbench.cc
|
testbench_verilator: testbench_wb.v picorv32.v testbench.cc
|
||||||
$(VERILATOR) --cc --exe -Wno-lint -trace --top-module picorv32_wrapper testbench_wb.v picorv32.v testbench.cc \
|
$(VERILATOR) --cc --exe -Wno-lint -trace --top-module picorv32_wrapper testbench_wb.v picorv32.v testbench.cc \
|
||||||
|
|
|
@ -2,94 +2,69 @@
|
||||||
// Based on riscv newlib libgloss/riscv/sys_*.c
|
// Based on riscv newlib libgloss/riscv/sys_*.c
|
||||||
// Written by Clifford Wolf.
|
// Written by Clifford Wolf.
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#define UNIMPL_FUNC(_f) ".globl " #_f "\n.type " #_f ", @function\n" #_f ":\n"
|
#define UNIMPL_FUNC(_f) ".globl " #_f "\n.type " #_f ", @function\n" #_f ":\n"
|
||||||
|
|
||||||
asm (
|
asm(".text\n"
|
||||||
".text\n"
|
".align 2\n" UNIMPL_FUNC(_open) UNIMPL_FUNC(_openat) UNIMPL_FUNC(_lseek)
|
||||||
".align 2\n"
|
UNIMPL_FUNC(_stat) UNIMPL_FUNC(_lstat) UNIMPL_FUNC(_fstatat)
|
||||||
UNIMPL_FUNC(_open)
|
UNIMPL_FUNC(_isatty) UNIMPL_FUNC(_access) UNIMPL_FUNC(_faccessat)
|
||||||
UNIMPL_FUNC(_openat)
|
UNIMPL_FUNC(_link) UNIMPL_FUNC(_unlink) UNIMPL_FUNC(_execve)
|
||||||
UNIMPL_FUNC(_lseek)
|
UNIMPL_FUNC(_getpid) UNIMPL_FUNC(_fork) UNIMPL_FUNC(_kill)
|
||||||
UNIMPL_FUNC(_stat)
|
UNIMPL_FUNC(_wait) UNIMPL_FUNC(_times) UNIMPL_FUNC(
|
||||||
UNIMPL_FUNC(_lstat)
|
_gettimeofday) UNIMPL_FUNC(_ftime)
|
||||||
UNIMPL_FUNC(_fstatat)
|
UNIMPL_FUNC(_utime) UNIMPL_FUNC(_chown)
|
||||||
UNIMPL_FUNC(_isatty)
|
UNIMPL_FUNC(_chmod) UNIMPL_FUNC(_chdir)
|
||||||
UNIMPL_FUNC(_access)
|
UNIMPL_FUNC(_getcwd) UNIMPL_FUNC(
|
||||||
UNIMPL_FUNC(_faccessat)
|
_sysconf) "j unimplemented_syscall\n");
|
||||||
UNIMPL_FUNC(_link)
|
|
||||||
UNIMPL_FUNC(_unlink)
|
|
||||||
UNIMPL_FUNC(_execve)
|
|
||||||
UNIMPL_FUNC(_getpid)
|
|
||||||
UNIMPL_FUNC(_fork)
|
|
||||||
UNIMPL_FUNC(_kill)
|
|
||||||
UNIMPL_FUNC(_wait)
|
|
||||||
UNIMPL_FUNC(_times)
|
|
||||||
UNIMPL_FUNC(_gettimeofday)
|
|
||||||
UNIMPL_FUNC(_ftime)
|
|
||||||
UNIMPL_FUNC(_utime)
|
|
||||||
UNIMPL_FUNC(_chown)
|
|
||||||
UNIMPL_FUNC(_chmod)
|
|
||||||
UNIMPL_FUNC(_chdir)
|
|
||||||
UNIMPL_FUNC(_getcwd)
|
|
||||||
UNIMPL_FUNC(_sysconf)
|
|
||||||
"j unimplemented_syscall\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
void unimplemented_syscall()
|
void unimplemented_syscall() {
|
||||||
{
|
const char *p = "Unimplemented system call called!\n";
|
||||||
const char *p = "Unimplemented system call called!\n";
|
while (*p) *(volatile int *)0x10000000 = *(p++);
|
||||||
while (*p)
|
asm volatile("ebreak");
|
||||||
*(volatile int*)0x10000000 = *(p++);
|
__builtin_unreachable();
|
||||||
asm volatile ("ebreak");
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t _read(int file, void *ptr, size_t len)
|
ssize_t _read(int file, void *ptr, size_t len) {
|
||||||
{
|
// always EOF
|
||||||
// always EOF
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t _write(int file, const void *ptr, size_t len)
|
ssize_t _write(int file, const void *ptr, size_t len) {
|
||||||
{
|
const void *eptr = ptr + len;
|
||||||
const void *eptr = ptr + len;
|
while (ptr != eptr) *(volatile int *)0x10000000 = *(char *)(ptr++);
|
||||||
while (ptr != eptr)
|
return len;
|
||||||
*(volatile int*)0x10000000 = *(char*)(ptr++);
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _close(int file)
|
int _close(int file) {
|
||||||
{
|
// close is called before _exit()
|
||||||
// close is called before _exit()
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fstat(int file, struct stat *st)
|
int _fstat(int file, struct stat *st) {
|
||||||
{
|
// fstat is called during libc startup
|
||||||
// fstat is called during libc startup
|
errno = ENOENT;
|
||||||
errno = ENOENT;
|
return -1;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *_sbrk(ptrdiff_t incr)
|
void *_sbrk(ptrdiff_t incr) {
|
||||||
{
|
extern unsigned char _end[]; // Defined by linker
|
||||||
extern unsigned char _end[]; // Defined by linker
|
static unsigned long heap_end;
|
||||||
static unsigned long heap_end;
|
|
||||||
|
|
||||||
if (heap_end == 0)
|
if (heap_end == 0) heap_end = (long)_end;
|
||||||
heap_end = (long)_end;
|
|
||||||
|
|
||||||
heap_end += incr;
|
heap_end += incr;
|
||||||
return (void *)(heap_end - incr);
|
return (void *)(heap_end - incr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _exit(int exit_status)
|
void _exit(int exit_status) {
|
||||||
{
|
asm volatile("li a0, 0x20000000");
|
||||||
asm volatile ("ebreak");
|
asm volatile("li a1, 123456789");
|
||||||
__builtin_unreachable();
|
asm volatile("sw a1,0(a0)");
|
||||||
}
|
|
||||||
|
|
||||||
|
asm volatile("ebreak");
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
80
testbench.cc
80
testbench.cc
|
@ -1,46 +1,52 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "Vpicorv32_wrapper.h"
|
#include "Vpicorv32_wrapper.h"
|
||||||
#include "verilated_vcd_c.h"
|
#include "verilated_vcd_c.h"
|
||||||
|
|
||||||
int main(int argc, char **argv, char **env)
|
int main(int argc, char** argv, char** env) {
|
||||||
{
|
printf("Built with %s %s.\n", Verilated::productName(),
|
||||||
printf("Built with %s %s.\n", Verilated::productName(), Verilated::productVersion());
|
Verilated::productVersion());
|
||||||
printf("Recommended: Verilator 4.0 or later.\n");
|
printf("Recommended: Verilator 4.0 or later.\n");
|
||||||
|
|
||||||
Verilated::commandArgs(argc, argv);
|
Verilated::commandArgs(argc, argv);
|
||||||
Vpicorv32_wrapper* top = new Vpicorv32_wrapper;
|
Vpicorv32_wrapper* top = new Vpicorv32_wrapper;
|
||||||
|
|
||||||
// Tracing (vcd)
|
if (argc > 0 && argv[1][0] == '1')
|
||||||
VerilatedVcdC* tfp = NULL;
|
top->testcase = 1;
|
||||||
const char* flag_vcd = Verilated::commandArgsPlusMatch("vcd");
|
else
|
||||||
if (flag_vcd && 0==strcmp(flag_vcd, "+vcd")) {
|
top->testcase = 0;
|
||||||
Verilated::traceEverOn(true);
|
|
||||||
tfp = new VerilatedVcdC;
|
|
||||||
top->trace (tfp, 99);
|
|
||||||
tfp->open("testbench.vcd");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tracing (data bus, see showtrace.py)
|
// Tracing (vcd)
|
||||||
FILE *trace_fd = NULL;
|
VerilatedVcdC* tfp = NULL;
|
||||||
const char* flag_trace = Verilated::commandArgsPlusMatch("trace");
|
const char* flag_vcd = Verilated::commandArgsPlusMatch("vcd");
|
||||||
if (flag_trace && 0==strcmp(flag_trace, "+trace")) {
|
if (flag_vcd && 0 == strcmp(flag_vcd, "+vcd")) {
|
||||||
trace_fd = fopen("testbench.trace", "w");
|
Verilated::traceEverOn(true);
|
||||||
}
|
tfp = new VerilatedVcdC;
|
||||||
|
top->trace(tfp, 99);
|
||||||
|
tfp->open("testbench.vcd");
|
||||||
|
}
|
||||||
|
|
||||||
top->wb_clk = 0;
|
// Tracing (data bus, see showtrace.py)
|
||||||
top->wb_rst = 1;
|
FILE* trace_fd = NULL;
|
||||||
|
const char* flag_trace = Verilated::commandArgsPlusMatch("trace");
|
||||||
|
if (flag_trace && 0 == strcmp(flag_trace, "+trace")) {
|
||||||
|
trace_fd = fopen("testbench.trace", "w");
|
||||||
|
}
|
||||||
|
|
||||||
int t = 0;
|
top->wb_clk = 0;
|
||||||
while (!Verilated::gotFinish()) {
|
top->wb_rst = 1;
|
||||||
if (t > 200)
|
|
||||||
top->wb_rst = 0;
|
int t = 0;
|
||||||
top->wb_clk = !top->wb_clk;
|
while (!Verilated::gotFinish()) {
|
||||||
top->eval();
|
if (t > 200) top->wb_rst = 0;
|
||||||
if (tfp) tfp->dump (t);
|
top->wb_clk = !top->wb_clk;
|
||||||
if (trace_fd && top->wb_clk && top->trace_valid) fprintf(trace_fd, "%9.9lx\n", top->trace_data);
|
top->eval();
|
||||||
t += 5;
|
if (tfp) tfp->dump(t);
|
||||||
}
|
if (trace_fd && top->wb_clk && top->trace_valid)
|
||||||
if (tfp) tfp->close();
|
fprintf(trace_fd, "%9.9lx\n", top->trace_data);
|
||||||
delete top;
|
t += 5;
|
||||||
exit(0);
|
}
|
||||||
|
if (tfp) tfp->close();
|
||||||
|
delete top;
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,8 @@ module picorv32_wrapper #(
|
||||||
input wb_rst,
|
input wb_rst,
|
||||||
output trap,
|
output trap,
|
||||||
output trace_valid,
|
output trace_valid,
|
||||||
output [35:0] trace_data
|
output [35:0] trace_data,
|
||||||
|
input testcase
|
||||||
);
|
);
|
||||||
wire exit;
|
wire exit;
|
||||||
reg [31:0] irq = 0;
|
reg [31:0] irq = 0;
|
||||||
|
@ -99,9 +100,10 @@ module picorv32_wrapper #(
|
||||||
|
|
||||||
reg [1023:0] firmware_file;
|
reg [1023:0] firmware_file;
|
||||||
initial begin
|
initial begin
|
||||||
if (!$value$plusargs("firmware=%s", firmware_file))
|
if (!testcase) firmware_file = "firmware/firmware.hex";
|
||||||
firmware_file = "firmware/firmware.hex";
|
else firmware_file = "dhrystone/dhry.hex";
|
||||||
// firmware_file = "dhrystone/dhry.hex";
|
// if (!$value$plusargs("firmware=%s", firmware_file))
|
||||||
|
// firmware_file = "firmware/firmware.hex";
|
||||||
$readmemh(firmware_file, uut.memory);
|
$readmemh(firmware_file, uut.memory);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue