/////////////////////////////////////////// // testbench.sv // // Written: David_Harris@hmc.edu 9 January 2021 // Modified: // // Purpose: Wally Testbench and helper modules // Applies test programs from the riscv-arch-test and Imperas suites // // A component of the Wally configurable RISC-V project. // // Copyright (C) 2021 Harvey Mudd College & Oklahoma State University // // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // // Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file // except in compliance with the License, or, at your option, the Apache License version 2.0. You // may obtain a copy of the License at // // https://solderpad.org/licenses/SHL-2.1/ // // Unless required by applicable law or agreed to in writing, any work distributed under the // License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// `include "wally-config.vh" `include "tests.vh" `define PrintHPMCounters 0 `define BPRED_LOGGER 0 `define I_CACHE_ADDR_LOGGER 0 `define D_CACHE_ADDR_LOGGER 0 module testbench; parameter DEBUG=0; parameter TEST="none"; logic clk; logic reset_ext, reset; parameter SIGNATURESIZE = 5000000; int test, i, errors, totalerrors; logic [31:0] sig32[0:SIGNATURESIZE]; logic [`XLEN-1:0] signature[0:SIGNATURESIZE]; logic [`XLEN-1:0] testadr, testadrNoBase; string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; logic [31:0] InstrW; string tests[]; logic [3:0] dummy; logic [`AHBW-1:0] HRDATAEXT; logic HREADYEXT, HRESPEXT; logic [`PA_BITS-1:0] HADDR; logic [`AHBW-1:0] HWDATA; logic [`XLEN/8-1:0] HWSTRB; logic HWRITE; logic [2:0] HSIZE; logic [2:0] HBURST; logic [3:0] HPROT; logic [1:0] HTRANS; logic HMASTLOCK; logic HCLK, HRESETn; logic [`XLEN-1:0] PCW; string ProgramAddrMapFile, ProgramLabelMapFile; integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 }; logic DCacheFlushDone, DCacheFlushStart; logic riscofTest; logic StartSample, EndSample; flopenr #(`XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW); flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); // check assertions for a legal configuration riscvassertions riscvassertions(); // pick tests based on modes supported initial begin $display("TEST is %s", TEST); //tests = '{}; if (`XLEN == 64) begin // RV64 case (TEST) "arch64i": tests = arch64i; "arch64priv": tests = arch64priv; "arch64c": if (`C_SUPPORTED) if (`ZICSR_SUPPORTED) tests = {arch64c, arch64cpriv}; else tests = {arch64c}; "arch64m": if (`M_SUPPORTED) tests = arch64m; "arch64f": if (`F_SUPPORTED) tests = arch64f; "arch64d": if (`D_SUPPORTED) tests = arch64d; "arch64zi": if (`ZIFENCEI_SUPPORTED) tests = arch64zi; "imperas64i": tests = imperas64i; "imperas64f": if (`F_SUPPORTED) tests = imperas64f; "imperas64d": if (`D_SUPPORTED) tests = imperas64d; "imperas64m": if (`M_SUPPORTED) tests = imperas64m; "wally64a": if (`A_SUPPORTED) tests = wally64a; "imperas64c": if (`C_SUPPORTED) tests = imperas64c; else tests = imperas64iNOc; "custom": tests = custom; "wally64i": tests = wally64i; "wally64priv": tests = wally64priv; "wally64periph": tests = wally64periph; "coremark": tests = coremark; "fpga": tests = fpga; "ahb" : tests = ahb; "coverage64gc" : tests = coverage64gc; "arch64zba": if (`ZBA_SUPPORTED) tests = arch64zba; "arch64zbb": if (`ZBB_SUPPORTED) tests = arch64zbb; "arch64zbc": if (`ZBC_SUPPORTED) tests = arch64zbc; "arch64zbs": if (`ZBS_SUPPORTED) tests = arch64zbs; endcase end else begin // RV32 case (TEST) "arch32i": tests = arch32i; "arch32priv": tests = arch32priv; "arch32c": if (`C_SUPPORTED) if (`ZICSR_SUPPORTED) tests = {arch32c, arch32cpriv}; else tests = {arch32c}; "arch32m": if (`M_SUPPORTED) tests = arch32m; "arch32f": if (`F_SUPPORTED) tests = arch32f; "arch32d": if (`D_SUPPORTED) tests = arch32d; "arch32zi": if (`ZIFENCEI_SUPPORTED) tests = arch32zi; "imperas32i": tests = imperas32i; "imperas32f": if (`F_SUPPORTED) tests = imperas32f; "imperas32m": if (`M_SUPPORTED) tests = imperas32m; "wally32a": if (`A_SUPPORTED) tests = wally32a; "imperas32c": if (`C_SUPPORTED) tests = imperas32c; else tests = imperas32iNOc; "wally32i": tests = wally32i; "wally32e": tests = wally32e; "wally32priv": tests = wally32priv; "wally32periph": tests = wally32periph; "embench": tests = embench; "coremark": tests = coremark; "arch32zba": if (`ZBA_SUPPORTED) tests = arch32zba; "arch32zbb": if (`ZBB_SUPPORTED) tests = arch32zbb; "arch32zbc": if (`ZBC_SUPPORTED) tests = arch32zbc; "arch32zbs": if (`ZBS_SUPPORTED) tests = arch32zbs; endcase end if (tests.size() == 0) begin $display("TEST %s not supported in this configuration", TEST); $stop; end end string signame, memfilename, pathname, objdumpfilename, adrstr, outputfile; integer outputFilePointer; logic [31:0] GPIOIN, GPIOOUT, GPIOEN; logic UARTSin, UARTSout; logic SDCCLK; logic SDCCmdIn; logic SDCCmdOut; logic SDCCmdOE; logic [3:0] SDCDatIn; tri1 [3:0] SDCDat; tri1 SDCCmd; logic HREADY; logic HSELEXT; logic InitializingMemories; integer ResetCount, ResetThreshold; logic InReset; logic BeginSample; // instantiate device to be tested assign GPIOIN = 0; assign UARTSin = 1; if(`EXT_MEM_SUPPORTED) begin ram_ahb #(.BASE(`EXT_MEM_BASE), .RANGE(`EXT_MEM_RANGE)) ram (.HCLK, .HRESETn, .HADDR, .HWRITE, .HTRANS, .HWDATA, .HSELRam(HSELEXT), .HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HWSTRB); end else begin assign HREADYEXT = 1; assign HRESPEXT = 0; assign HRDATAEXT = 0; end if(`FPGA) begin : sdcard sdModel sdcard (.sdClk(SDCCLK), .cmd(SDCCmd), .dat(SDCDat)); assign SDCCmd = SDCCmdOE ? SDCCmdOut : 1'bz; assign SDCCmdIn = SDCCmd; assign SDCDatIn = SDCDat; end else begin assign SDCCmd = '0; assign SDCDat = '0; end wallypipelinedsoc dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, .UARTSout, .SDCCmdIn, .SDCCmdOut, .SDCCmdOE, .SDCDatIn, .SDCCLK); // Track names of instructions instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrD, dut.core.ifu.InstrE, dut.core.ifu.InstrM, InstrW, InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // initialize tests localparam MemStartAddr = 0; localparam MemEndAddr = `UNCORE_RAM_RANGE>>1+(`XLEN/32); initial begin ResetCount = 0; ResetThreshold = 2; InReset = 1; test = 1; totalerrors = 0; testadr = 0; testadrNoBase = 0; // riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests // and tests[0] == "2" refers to WallyRiscvArchTests riscofTest = tests[0] == "1" | tests[0] == "2"; // fill memory with defined values to reduce Xs in simulation // Quick note the memory will need to be initialized. The C library does not // guarantee the initialized reads. For example a strcmp can read 6 byte // strings, but uses a load double to read them in. If the last 2 bytes are // not initialized the compare results in an 'x' which propagates through // the design. if (TEST == "coremark") for (i=MemStartAddr; i