Initial Chisel core implementation
This commit is contained in:
101
sim/verilator/testbench.cpp
Normal file
101
sim/verilator/testbench.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
#include <verilated.h>
|
||||
#include "VCore.h"
|
||||
#include "memory.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#define MAX_CYCLES 100000
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s <test.elf>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
VCore* core = new VCore;
|
||||
Memory* mem = new Memory();
|
||||
|
||||
if (!mem->load_elf(argv[1])) {
|
||||
fprintf(stderr, "Failed to load test binary\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Reset
|
||||
core->reset = 1;
|
||||
core->clock = 0;
|
||||
core->eval();
|
||||
core->clock = 1;
|
||||
core->eval();
|
||||
core->clock = 0;
|
||||
core->reset = 0;
|
||||
core->eval();
|
||||
|
||||
uint64_t cycle = 0;
|
||||
bool test_done = false;
|
||||
int exit_code = 0;
|
||||
|
||||
while (cycle < MAX_CYCLES && !test_done) {
|
||||
// Handle instruction memory interface
|
||||
if (core->io_imem_req_valid) {
|
||||
uint64_t pc = core->io_imem_req_bits;
|
||||
core->io_imem_resp_valid = 1;
|
||||
core->io_imem_resp_bits_0 = mem->read32(pc);
|
||||
core->io_imem_resp_bits_1 = mem->read32(pc + 4);
|
||||
} else {
|
||||
core->io_imem_resp_valid = 0;
|
||||
}
|
||||
|
||||
// Handle data memory interface
|
||||
if (core->io_dmem_req_valid) {
|
||||
uint64_t addr = core->io_dmem_req_bits_addr;
|
||||
|
||||
// Check for tohost write
|
||||
if (core->io_dmem_req_bits_isStore && addr == TOHOST_ADDR) {
|
||||
uint64_t tohost = core->io_dmem_req_bits_data;
|
||||
if (tohost == 1) {
|
||||
printf("[%lu] TEST PASSED\n", cycle);
|
||||
test_done = true;
|
||||
exit_code = 0;
|
||||
} else if (tohost & 1) {
|
||||
printf("[%lu] TEST FAILED: error code %lu\n", cycle, tohost >> 1);
|
||||
test_done = true;
|
||||
exit_code = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (core->io_dmem_req_bits_isStore) {
|
||||
switch (core->io_dmem_req_bits_size) {
|
||||
case 0: mem->write8(addr, core->io_dmem_req_bits_data & 0xff); break;
|
||||
case 1: mem->write16(addr, core->io_dmem_req_bits_data & 0xffff); break;
|
||||
case 2: mem->write32(addr, core->io_dmem_req_bits_data & 0xffffffff); break;
|
||||
default: mem->write64(addr, core->io_dmem_req_bits_data); break;
|
||||
}
|
||||
core->io_dmem_resp_valid = 0;
|
||||
} else {
|
||||
core->io_dmem_resp_bits = mem->read64(addr);
|
||||
core->io_dmem_resp_valid = 1;
|
||||
}
|
||||
} else {
|
||||
core->io_dmem_resp_valid = 0;
|
||||
}
|
||||
|
||||
// Clock cycle
|
||||
core->clock = 0;
|
||||
core->eval();
|
||||
core->clock = 1;
|
||||
core->eval();
|
||||
|
||||
cycle++;
|
||||
}
|
||||
|
||||
if (!test_done) {
|
||||
printf("[%lu] TEST TIMEOUT\n", cycle);
|
||||
exit_code = 2;
|
||||
}
|
||||
|
||||
delete core;
|
||||
delete mem;
|
||||
return exit_code;
|
||||
}
|
||||
Reference in New Issue
Block a user