`include "wally-config.vh" module testbench_busybear(); logic clk, reset; logic [31:0] GPIOPinsIn; logic [31:0] GPIOPinsOut, GPIOPinsEn; // instantiate device to be tested logic [`XLEN-1:0] PCF; logic [31:0] InstrF; logic InstrAccessFaultF, DataAccessFaultM; logic TimerIntM = 0, SwIntM = 0; // from CLINT logic ExtIntM = 0; // not yet connected logic [`AHBW-1:0] HRDATA; logic HREADY, HRESP; logic [31:0] HADDR; logic [`AHBW-1:0] HWDATA; logic HWRITE; logic [2:0] HSIZE; logic [2:0] HBURST; logic [3:0] HPROT; logic [1:0] HTRANS; logic HMASTLOCK; logic HCLK, HRESETn; assign GPIOPinsIn = 0; assign UARTSin = 1; assign HREADY = 1; assign HRESP = 0; assign HRDATA = 0; // for now, seem to need these to be zero until we get a better idea assign InstrAccessFaultF = 0; assign DataAccessFaultM = 0; // instantiate processor and memories wallypipelinedhart dut(.*); // initialize test initial begin reset <= 1; # 22; reset <= 0; end // read pc trace file integer data_file_PC, scan_file_PC; initial begin data_file_PC = $fopen("../busybear-testgen/parsedPC.txt", "r"); if (data_file_PC == 0) begin $display("file couldn't be opened"); $stop; end end integer data_file_PCW, scan_file_PCW; initial begin data_file_PCW = $fopen("../busybear-testgen/parsedPC.txt", "r"); if (data_file_PCW == 0) begin $display("file couldn't be opened"); $stop; end end // read register trace file integer data_file_rf, scan_file_rf; initial begin data_file_rf = $fopen("../busybear-testgen/parsedRegs.txt", "r"); if (data_file_rf == 0) begin $display("file couldn't be opened"); $stop; end end // read CSR trace file integer data_file_csr, scan_file_csr; initial begin data_file_csr = $fopen("../busybear-testgen/parsedCSRs.txt", "r"); if (data_file_csr == 0) begin $display("file couldn't be opened"); $stop; end end // read memreads trace file integer data_file_memR, scan_file_memR; initial begin data_file_memR = $fopen("../busybear-testgen/parsedMemRead.txt", "r"); if (data_file_memR == 0) begin $display("file couldn't be opened"); $stop; end end // read memwrite trace file integer data_file_memW, scan_file_memW; initial begin data_file_memW = $fopen("../busybear-testgen/parsedMemWrite.txt", "r"); if (data_file_memW == 0) begin $display("file couldn't be opened"); $stop; end end logic [63:0] pcExpected; logic [63:0] regExpected; integer regNumExpected; genvar i; generate for(i=1; i<32; i++) begin always @(dut.ieu.dp.regf.rf[i]) begin if ($time != 0) begin scan_file_rf = $fscanf(data_file_rf, "%d\n", regNumExpected); scan_file_rf = $fscanf(data_file_rf, "%x\n", regExpected); if (i != regNumExpected) begin $display("%t ps, instr %0d: wrong register changed: %0d, %0d expected", $time, instrs, i, regNumExpected); end if (dut.ieu.dp.regf.rf[i] != regExpected) begin $display("%t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.ieu.dp.regf.rf[i], regExpected); end end end end endgenerate logic [`XLEN-1:0] readAdrExpected; // this might need to change always @(dut.MemRWM[1] or HADDR) begin if (dut.MemRWM[1]) begin if($feof(data_file_memR)) begin $display("no more memR data to read"); $stop; end scan_file_memR = $fscanf(data_file_memR, "%x\n", readAdrExpected); scan_file_memR = $fscanf(data_file_memR, "%x\n", HRDATA); #1; if (HADDR != readAdrExpected) begin $display("%t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrExpected); end end end logic [`XLEN-1:0] writeDataExpected, writeAdrExpected; // this might need to change always @(HWDATA or HADDR or HSIZE) begin #1; if (HWRITE) begin if($feof(data_file_memW)) begin $display("no more memW data to read"); $stop; end scan_file_memW = $fscanf(data_file_memW, "%x\n", writeDataExpected); scan_file_memW = $fscanf(data_file_memW, "%x\n", writeAdrExpected); if (writeDataExpected != HWDATA) begin $display("%t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected); end if (writeAdrExpected != HADDR) begin $display("%t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrExpected); end end end `define CHECK_CSR(CSR) \ string CSR; \ logic [63:0] expected``CSR``; \ //CSR checking \ always @(dut.priv.csr.``CSR``_REGW) begin \ if ($time > 1) begin \ scan_file_csr = $fscanf(data_file_csr, "%s\n", CSR); \ scan_file_csr = $fscanf(data_file_csr, "%x\n", expected``CSR``); \ if(CSR.icompare(`"CSR`")) begin \ $display("%t ps, instr %0d: %s changed, expected %s", $time, instrs, `"CSR`", CSR); \ end \ if(dut.priv.csr.``CSR``_REGW != ``expected``CSR) begin \ $display("%t ps, instr %0d: %s does not equal %s expected: %x, %x", $time, instrs, CSR, CSR, dut.priv.csr.``CSR``_REGW, ``expected``CSR); \ end \ end \ end //`CHECK_CSR(FCSR) `CHECK_CSR(MCOUNTEREN) `CHECK_CSR(MEDELEG) `CHECK_CSR(MIDELEG) `CHECK_CSR(MIE) //`CHECK_CSR(MSCRATCH) `CHECK_CSR(MSTATUS) `CHECK_CSR(MTVEC) //`CHECK_CSR(SATP) `CHECK_CSR(SCOUNTEREN) logic speculative; initial begin speculative = 0; speculative = 0; end logic [63:0] lastInstrF, lastPC, lastPC2; string PCtextW, PCtext2W; logic [31:0] InstrWExpected; logic [63:0] PCWExpected; always @(dut.ifu.PCW or dut.ieu.InstrValidW) begin if(dut.ieu.InstrValidW && dut.ifu.PCW != 0) begin if($feof(data_file_PCW)) begin $display("no more PC data to read"); $stop; end scan_file_PCW = $fscanf(data_file_PCW, "%s\n", PCtextW); if (PCtextW != "ret") begin scan_file_PC = $fscanf(data_file_PCW, "%s\n", PCtext2W); PCtextW = {PCtextW, " ", PCtext2W}; end scan_file_PCW = $fscanf(data_file_PCW, "%x\n", InstrWExpected); // then expected PC value scan_file_PCW = $fscanf(data_file_PCW, "%x\n", PCWExpected); if(dut.ifu.PCW != PCWExpected) begin $display("%t ps, instr %0d: PCW does not equal PCW expected: %x, %x", $time, instrs, dut.ifu.PCW, PCWExpected); end //if(it.InstrW != InstrWExpected) begin // $display("%t ps, instr %0d: InstrW does not equal InstrW expected: %x, %x", $time, instrs, it.InstrW, InstrWExpected); //end end end string PCtext, PCtext2; integer instrs; initial begin instrs = 0; end always @(PCF) begin lastInstrF = InstrF; lastPC <= PCF; lastPC2 <= lastPC; if (speculative && lastPC != pcExpected) begin speculative = (PCF != pcExpected); end else begin //if (~speculative) begin if($feof(data_file_PC)) begin $display("no more PC data to read"); $stop; end // first read instruction scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext); if (PCtext != "ret") begin scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext2); PCtext = {PCtext, " ", PCtext2}; end scan_file_PC = $fscanf(data_file_PC, "%x\n", InstrF); if(InstrF[6:0] == 7'b1010011) begin // for now, NOP out any float instrs InstrF = 32'b0010011; $display("warning: NOPing out %s at PC=%0x", PCtext, PCF); end // then expected PC value scan_file_PC = $fscanf(data_file_PC, "%x\n", pcExpected); if (instrs <= 10 || (instrs <= 100 && instrs % 10 == 0) || (instrs <= 1000 && instrs % 100 == 0) || (instrs <= 10000 && instrs % 1000 == 0) || (instrs <= 100000 && instrs % 10000 == 0)) begin $display("loaded %0d instructions", instrs); end instrs += 1; // are we at a branch/jump? casex (lastInstrF[15:0]) 16'bXXXXXXXXX1101111, // JAL 16'bXXXXXXXXX1100111, // JALR 16'bXXXXXXXXX1100011, // B 16'b110XXXXXXXXXXX01, // C.BEQZ 16'b111XXXXXXXXXXX01, // C.BNEZ 16'b101XXXXXXXXXXX01: // C.J speculative = 1; 16'b1001000000000010: // C.EBREAK: speculative = 0; // tbh don't really know what should happen here 16'b1000XXXXX0000010, // C.JR 16'b1001XXXXX0000010: // C.JALR //this is RV64 only so no C.JAL speculative = 1; default: speculative = 0; endcase //check things! if ((~speculative) && (PCF !== pcExpected)) begin $display("%t ps, instr %0d: PC does not equal PC expected: %x, %x", $time, instrs, PCF, pcExpected); // $stop; end end end // Track names of instructions string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; logic [31:0] InstrW; instrNameDecTB dec(InstrF, InstrFName); instrTrackerTB it(clk, reset, dut.ieu.dp.FlushE, dut.ifu.InstrD, dut.ifu.InstrE, dut.ifu.InstrM, InstrW, InstrDName, InstrEName, InstrMName, InstrWName); // generate clock to sequence tests always begin clk <= 1; # 5; clk <= 0; # 5; end //// check results //always @(negedge clk) // begin // if(MemWrite) begin // if(DataAdr === 84 & WriteData === 71) begin // $display("Simulation succeeded"); // $stop; // end else if (DataAdr !== 80) begin // $display("Simulation failed"); // $stop; // end // end // end endmodule