#include #include "VCore.h" #include "VCore___024root.h" #include "memory.h" #include #include #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) { fprintf(stderr, "Usage: %s \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; } uint64_t tohost_addr = mem->get_tohost_addr(); // 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; 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); } 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; 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); 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) { 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; 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 ((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; } delete core; delete mem; return exit_code; }