fix: resolve OoO simulation timeout
This commit is contained in:
@@ -1,25 +1,56 @@
|
||||
VERILATOR = verilator
|
||||
VERILATOR_FLAGS = --cc --exe --build -Wall --trace -Wno-fatal
|
||||
JOBS ?= 8
|
||||
TRACE ?= 0
|
||||
FAST ?= 1
|
||||
SPLIT ?= 20000
|
||||
SPLIT_CFUNCS ?= 20000
|
||||
VERILATE_JOBS ?= $(JOBS)
|
||||
BUILD_JOBS ?= $(JOBS)
|
||||
|
||||
VERILATOR_FLAGS = --cc --exe --build --verilate-jobs $(VERILATE_JOBS) --build-jobs $(BUILD_JOBS) -Wall -Wno-fatal
|
||||
VERILATOR_FLAGS += --output-split $(SPLIT) --output-split-cfuncs $(SPLIT_CFUNCS)
|
||||
ifeq ($(TRACE),1)
|
||||
VERILATOR_FLAGS += --trace
|
||||
endif
|
||||
ifeq ($(FAST),1)
|
||||
VERILATOR_FLAGS += -CFLAGS "-std=c++14 -O0"
|
||||
else
|
||||
VERILATOR_FLAGS += -CFLAGS "-std=c++14 -O2"
|
||||
endif
|
||||
SBT = env SBT_OPTS="-Dsbt.boot.directory=/tmp/sbt-boot -Dsbt.ivy.home=/tmp/sbt-ivy" COURSIER_CACHE=/tmp/coursier-cache sbt
|
||||
|
||||
CHISEL_DIR = ../..
|
||||
OOO ?= 0
|
||||
ifeq ($(OOO),1)
|
||||
RUN_MAIN = CoreOoO
|
||||
GENERATED_DIR = $(CHISEL_DIR)/generated-ooo
|
||||
else
|
||||
RUN_MAIN = Core
|
||||
GENERATED_DIR = $(CHISEL_DIR)/generated
|
||||
endif
|
||||
SRC_FILES = testbench.cpp memory.cpp
|
||||
|
||||
VERILOG_FILES = $(GENERATED_DIR)/Core.sv
|
||||
VERILOG_STAMP = $(GENERATED_DIR)/.Core.sv.stamp
|
||||
SCALA_SOURCES = $(shell find $(CHISEL_DIR)/src/main/scala -name '*.scala')
|
||||
|
||||
TARGET = obj_dir/VCore
|
||||
|
||||
.PHONY: all verilog compile run clean
|
||||
.PHONY: all verilog compile run clean regenerate
|
||||
|
||||
all: compile
|
||||
|
||||
verilog:
|
||||
@echo "Generating Verilog from Chisel..."
|
||||
cd $(CHISEL_DIR) && $(SBT) "runMain Core"
|
||||
verilog: $(VERILOG_STAMP)
|
||||
|
||||
compile: verilog
|
||||
$(VERILOG_STAMP): $(SCALA_SOURCES) $(CHISEL_DIR)/build.sbt
|
||||
@echo "Generating Verilog from Chisel..."
|
||||
cd $(CHISEL_DIR) && $(SBT) "runMain $(RUN_MAIN)"
|
||||
@touch $@
|
||||
|
||||
$(VERILOG_FILES): $(VERILOG_STAMP)
|
||||
@test -f $@
|
||||
|
||||
compile: $(VERILOG_FILES)
|
||||
@echo "Compiling with Verilator..."
|
||||
$(VERILATOR) $(VERILATOR_FLAGS) \
|
||||
-I$(GENERATED_DIR) \
|
||||
@@ -38,6 +69,10 @@ test-simple: compile
|
||||
@echo "Running simple test..."
|
||||
./$(TARGET) ../../riscv-tests/isa/rv64ui-p-simple
|
||||
|
||||
regenerate:
|
||||
rm -f $(VERILOG_STAMP)
|
||||
$(MAKE) verilog OOO=$(OOO)
|
||||
|
||||
clean:
|
||||
rm -rf obj_dir
|
||||
rm -rf $(GENERATED_DIR)
|
||||
|
||||
@@ -1,10 +1,53 @@
|
||||
#include <verilated.h>
|
||||
#include "VCore.h"
|
||||
#include "VCore___024root.h"
|
||||
#include "memory.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#define MAX_CYCLES 100000
|
||||
#define MAX_CYCLES 300000
|
||||
|
||||
static void dump_rob_entry(VCore* core, unsigned idx, const char* label) {
|
||||
#define ROB_ENTRY_CASE(n) \
|
||||
case n: \
|
||||
fprintf(stderr, \
|
||||
"%s[%u]: valid=%u completed=%u exception=%u mispredict=%u " \
|
||||
"arch=%u writes=%u op=%u dest=%u old=%u cause=0x%lx bad=0x%lx redirect=0x%lx\n", \
|
||||
label, idx, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__valid_##n, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__completed_##n, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__exception_##n, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__branchMispredict_##n, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__entries_##n##_archDest, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__entries_##n##_writesDest, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__entries_##n##_opClass, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__entries_##n##_dest, \
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__entries_##n##_oldDest, \
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__exceptionCause_##n, \
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__badAddr_##n, \
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__redirectPc_##n); \
|
||||
break
|
||||
|
||||
switch (idx & 63U) {
|
||||
ROB_ENTRY_CASE(0); ROB_ENTRY_CASE(1); ROB_ENTRY_CASE(2); ROB_ENTRY_CASE(3);
|
||||
ROB_ENTRY_CASE(4); ROB_ENTRY_CASE(5); ROB_ENTRY_CASE(6); ROB_ENTRY_CASE(7);
|
||||
ROB_ENTRY_CASE(8); ROB_ENTRY_CASE(9); ROB_ENTRY_CASE(10); ROB_ENTRY_CASE(11);
|
||||
ROB_ENTRY_CASE(12); ROB_ENTRY_CASE(13); ROB_ENTRY_CASE(14); ROB_ENTRY_CASE(15);
|
||||
ROB_ENTRY_CASE(16); ROB_ENTRY_CASE(17); ROB_ENTRY_CASE(18); ROB_ENTRY_CASE(19);
|
||||
ROB_ENTRY_CASE(20); ROB_ENTRY_CASE(21); ROB_ENTRY_CASE(22); ROB_ENTRY_CASE(23);
|
||||
ROB_ENTRY_CASE(24); ROB_ENTRY_CASE(25); ROB_ENTRY_CASE(26); ROB_ENTRY_CASE(27);
|
||||
ROB_ENTRY_CASE(28); ROB_ENTRY_CASE(29); ROB_ENTRY_CASE(30); ROB_ENTRY_CASE(31);
|
||||
ROB_ENTRY_CASE(32); ROB_ENTRY_CASE(33); ROB_ENTRY_CASE(34); ROB_ENTRY_CASE(35);
|
||||
ROB_ENTRY_CASE(36); ROB_ENTRY_CASE(37); ROB_ENTRY_CASE(38); ROB_ENTRY_CASE(39);
|
||||
ROB_ENTRY_CASE(40); ROB_ENTRY_CASE(41); ROB_ENTRY_CASE(42); ROB_ENTRY_CASE(43);
|
||||
ROB_ENTRY_CASE(44); ROB_ENTRY_CASE(45); ROB_ENTRY_CASE(46); ROB_ENTRY_CASE(47);
|
||||
ROB_ENTRY_CASE(48); ROB_ENTRY_CASE(49); ROB_ENTRY_CASE(50); ROB_ENTRY_CASE(51);
|
||||
ROB_ENTRY_CASE(52); ROB_ENTRY_CASE(53); ROB_ENTRY_CASE(54); ROB_ENTRY_CASE(55);
|
||||
ROB_ENTRY_CASE(56); ROB_ENTRY_CASE(57); ROB_ENTRY_CASE(58); ROB_ENTRY_CASE(59);
|
||||
ROB_ENTRY_CASE(60); ROB_ENTRY_CASE(61); ROB_ENTRY_CASE(62); ROB_ENTRY_CASE(63);
|
||||
}
|
||||
#undef ROB_ENTRY_CASE
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
@@ -35,11 +78,20 @@ int main(int argc, char** argv) {
|
||||
uint64_t cycle = 0;
|
||||
bool test_done = false;
|
||||
int exit_code = 0;
|
||||
int bad_access_reports = 0;
|
||||
bool saw_tohost_req = false;
|
||||
int flush_reports = 0;
|
||||
int csr_reports = 0;
|
||||
int store_reports = 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;
|
||||
if ((pc < MEM_BASE || pc >= MEM_BASE + MEM_SIZE) && bad_access_reports < 32) {
|
||||
fprintf(stderr, "[%lu] Bad imem fetch pc=0x%lx\n", cycle, pc);
|
||||
bad_access_reports++;
|
||||
}
|
||||
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);
|
||||
@@ -50,9 +102,20 @@ int main(int argc, char** argv) {
|
||||
// Handle data memory interface
|
||||
if (core->io_dmem_req_valid) {
|
||||
uint64_t addr = core->io_dmem_req_bits_addr;
|
||||
if ((addr < MEM_BASE || addr >= MEM_BASE + MEM_SIZE) && addr != TOHOST_ADDR && bad_access_reports < 32) {
|
||||
fprintf(stderr,
|
||||
"[%lu] Bad dmem %s addr=0x%lx data=0x%lx size=%u\n",
|
||||
cycle,
|
||||
core->io_dmem_req_bits_isStore ? "store" : "load",
|
||||
addr,
|
||||
(uint64_t)core->io_dmem_req_bits_data,
|
||||
(unsigned)core->io_dmem_req_bits_size);
|
||||
bad_access_reports++;
|
||||
}
|
||||
|
||||
// Check for tohost write
|
||||
if (core->io_dmem_req_bits_isStore && addr == TOHOST_ADDR) {
|
||||
saw_tohost_req = true;
|
||||
uint64_t tohost = core->io_dmem_req_bits_data;
|
||||
if (tohost == 1) {
|
||||
printf("[%lu] TEST PASSED\n", cycle);
|
||||
@@ -66,6 +129,15 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
if (core->io_dmem_req_bits_isStore) {
|
||||
if (store_reports < 64) {
|
||||
fprintf(stderr,
|
||||
"[%lu] STORE addr=0x%lx data=0x%lx size=%u\n",
|
||||
cycle,
|
||||
addr,
|
||||
(uint64_t)core->io_dmem_req_bits_data,
|
||||
(unsigned)core->io_dmem_req_bits_size);
|
||||
store_reports++;
|
||||
}
|
||||
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;
|
||||
@@ -88,10 +160,112 @@ int main(int argc, char** argv) {
|
||||
core->eval();
|
||||
|
||||
cycle++;
|
||||
|
||||
if ((core->rootp->Core__DOT__backend__DOT__commitCsr0 ||
|
||||
(core->rootp->Core__DOT__backend__DOT___commit_io_commitReady_1 &&
|
||||
core->rootp->Core__DOT__backend__DOT___rename_io_commitEntry_1_csrValid)) &&
|
||||
csr_reports < 64) {
|
||||
fprintf(stderr,
|
||||
"[%lu] CSR commit slot0=%u slot1=%u addr=0x%x cmd=%u next=0x%lx mtvec=0x%lx\n",
|
||||
cycle,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__commitCsr0,
|
||||
(unsigned)(core->rootp->Core__DOT__backend__DOT___commit_io_commitReady_1 &&
|
||||
core->rootp->Core__DOT__backend__DOT___rename_io_commitEntry_1_csrValid),
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__csr__io_cmd_addr,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__csr__io_cmd_cmd,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__csr__DOT__unnamedblk1__DOT__next,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__csr__DOT__mtvecReg);
|
||||
csr_reports++;
|
||||
}
|
||||
if (core->rootp->Core__DOT___backend_io_flush && flush_reports < 64) {
|
||||
fprintf(stderr,
|
||||
"[%lu] FLUSH exception=%u mtvec=0x%lx mepc=0x%lx mcause=0x%lx frontend_pc=0x%lx\n",
|
||||
cycle,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT___commit_io_exception,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__csr__DOT__mtvecReg,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__csr__DOT__mepcReg,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__csr__DOT__mcause,
|
||||
(uint64_t)core->rootp->Core__DOT__frontend__DOT__pc);
|
||||
flush_reports++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_done) {
|
||||
printf("[%lu] TEST TIMEOUT\n", cycle);
|
||||
fprintf(stderr,
|
||||
"Timeout state: frontend_pc=0x%lx ic_state=%u ic_lookup=0x%lx ic_miss=0x%lx "
|
||||
"fetchValid=%u fetchReady=%u feOut=%u issueInReady0=%u robCount=%u "
|
||||
"rsFree=0x%x freeMask=0x%lx "
|
||||
"issueReady=%u/%u issue0_pc=0x%lx issue1_pc=0x%lx "
|
||||
"robHead=%u robTail=%u mtvec=0x%lx mepc=0x%lx mcause=0x%lx "
|
||||
"flush=%u commitReady=%u/%u commitValid1=%u sawTohost=%u\n",
|
||||
core->rootp->Core__DOT__frontend__DOT__pc,
|
||||
(unsigned)core->rootp->Core__DOT__frontend__DOT__icache__DOT__state,
|
||||
core->rootp->Core__DOT__frontend__DOT__icache__DOT__lookupAddr,
|
||||
core->rootp->Core__DOT__frontend__DOT__icache__DOT__missAddr,
|
||||
(unsigned)core->rootp->Core__DOT__fetchValid,
|
||||
(unsigned)core->rootp->Core__DOT__fetchReady,
|
||||
(unsigned)core->rootp->Core__DOT___frontend_io_outValid,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT___issue_io_inReady_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__count,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__freeMask,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__rename__DOT__freeList__DOT__freeMask,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue_io_outReady_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue_io_outReady_1,
|
||||
core->rootp->Core__DOT__backend__DOT___issue_io_out_0_decoded_pc,
|
||||
core->rootp->Core__DOT__backend__DOT___issue_io_out_1_decoded_pc,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__head,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__tail,
|
||||
core->rootp->Core__DOT__backend__DOT__csr__DOT__mtvecReg,
|
||||
core->rootp->Core__DOT__backend__DOT__csr__DOT__mepcReg,
|
||||
core->rootp->Core__DOT__backend__DOT__csr__DOT__mcause,
|
||||
(unsigned)core->rootp->Core__DOT___backend_io_flush,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT___commit_io_commitReady_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT___commit_io_commitReady_1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT___rename_io_commitValid_1,
|
||||
saw_tohost_req ? 1u : 0u);
|
||||
unsigned head = (unsigned)core->rootp->Core__DOT__backend__DOT__rename__DOT__rob__DOT__head;
|
||||
dump_rob_entry(core, head, "robHead");
|
||||
dump_rob_entry(core, head + 1U, "robNext");
|
||||
fprintf(stderr,
|
||||
"rs0: valid=%u ready=%u pc=0x%lx inst=0x%08x rob=%u prs=%u/%u readySrc=%u/%u prd=%u\n",
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__valid_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__readyVec_0,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_0_decoded_pc,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_0_decoded_inst,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_0_robIdx,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_0_prs1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_0_prs2,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_0_src1Ready,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_0_src2Ready,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_0_prd);
|
||||
fprintf(stderr,
|
||||
"rs1: valid=%u ready=%u pc=0x%lx inst=0x%08x rob=%u prs=%u/%u readySrc=%u/%u prd=%u issueOH=0x%x/0x%x\n",
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__valid_1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__readyVec_1,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_1_decoded_pc,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_1_decoded_inst,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_1_robIdx,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_1_prs1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_1_prs2,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_1_src1Ready,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_1_src2Ready,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__slots_1_prd,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__issue0OH,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT__issue__DOT__queue__DOT__intRs__DOT__issue1OH);
|
||||
fprintf(stderr,
|
||||
"complete: valid=%u/%u idx0=%u exc=%u/%u mis=%u/%u cause=0x%lx/0x%lx redirect=0x%lx/0x%lx\n",
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeValid_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeValid_1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeIdx_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeException_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeException_1,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeMispredict_0,
|
||||
(unsigned)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeMispredict_1,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeCause_0,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeCause_1,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeRedirectPc_0,
|
||||
(uint64_t)core->rootp->Core__DOT__backend__DOT____Vcellinp__rename__io_completeRedirectPc_1);
|
||||
exit_code = 2;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user