2021-10-10 22:07:51 +00:00
///////////////////////////////////////////
// testbench.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
2024-09-29 17:18:04 +00:00
// Modified:
2021-10-10 22:07:51 +00:00
//
// Purpose: Wally Testbench and helper modules
2024-09-29 17:18:04 +00:00
// Applies test programs from the riscv-arch-test and other custom tests
//
2021-10-10 22:07:51 +00:00
// A component of the Wally configurable RISC-V project.
2024-09-29 17:18:04 +00:00
//
2021-10-10 22:07:51 +00:00
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
2023-02-04 16:19:20 +00:00
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
2021-10-10 22:07:51 +00:00
//
2024-09-29 17:18:04 +00:00
// 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
2023-02-04 16:19:20 +00:00
// may obtain a copy of the License at
2021-10-10 22:07:51 +00:00
//
2023-02-04 16:19:20 +00:00
// https://solderpad.org/licenses/SHL-2.1/
//
2024-09-29 17:18:04 +00:00
// 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
2023-02-04 16:19:20 +00:00
// and limitations under the License.
2022-01-07 12:58:40 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////
2021-10-10 22:07:51 +00:00
2023-05-31 21:51:00 +00:00
`include " config.vh "
2021-10-10 22:07:51 +00:00
`include " tests.vh "
2023-07-18 20:07:10 +00:00
`include " BranchPredictorType.vh "
2021-10-10 22:07:51 +00:00
2024-02-07 21:38:18 +00:00
`ifdef USE_IMPERAS_DV
`include " idv/idv.svh "
`endif
2024-04-21 06:13:13 +00:00
import cvw::* ;
module testbench ;
2023-05-31 21:51:00 +00:00
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off WIDTHEXPAND */
2021-10-10 22:07:51 +00:00
parameter DEBUG = 0 ;
2023-11-13 20:12:27 +00:00
parameter PrintHPMCounters = 0 ;
2023-12-20 20:55:37 +00:00
parameter BPRED_LOGGER = 0 ;
2023-11-13 20:12:27 +00:00
parameter I_CACHE_ADDR_LOGGER = 0 ;
parameter D_CACHE_ADDR_LOGGER = 0 ;
2024-07-24 17:47:50 +00:00
parameter RVVI_SYNTH_SUPPORTED = 0 ;
2024-12-02 21:52:44 +00:00
parameter MAKE_VCD = 0 ;
2024-09-29 17:18:04 +00:00
2024-12-19 22:09:42 +00:00
// TREK Requires a license for the Breker tool. See tests/breker/README.md for details
2024-11-27 08:13:17 +00:00
`ifdef USE_TREK_DV
event trek_start ;
always @ ( testbench . trek_start ) begin
trek_uvm_pkg : : trek_uvm_events : : do_backdoor_init ( ) ;
end
`endif
2024-02-07 21:38:18 +00:00
`ifdef USE_IMPERAS_DV
import idvPkg::* ;
import rvviApiPkg::* ;
import idvApiPkg::* ;
`endif
2024-04-21 15:38:13 +00:00
`ifdef VERILATOR
import "DPI-C" function string getenvval ( input string env_name ) ;
2024-07-23 08:58:19 +00:00
string RISCV_DIR = getenvval ( " RISCV " ) ;
2024-07-03 23:52:16 +00:00
string WALLY_DIR = getenvval ( " WALLY " ) ; // ~/cvw typical
2024-06-21 22:17:59 +00:00
`elsif VCS
2024-05-08 11:25:03 +00:00
import "DPI-C" function string getenv ( input string env_name ) ;
2024-07-23 08:58:19 +00:00
string RISCV_DIR = getenv ( " RISCV " ) ;
2024-09-29 17:18:04 +00:00
string WALLY_DIR = getenv ( " WALLY " ) ;
2024-04-21 15:38:13 +00:00
`else
2024-07-23 08:58:19 +00:00
string RISCV_DIR = " $RISCV " ;
2024-07-03 23:52:16 +00:00
string WALLY_DIR = " $WALLY " ;
2024-04-21 15:38:13 +00:00
`endif
`include " parameter-defs.vh "
2023-06-12 16:00:30 +00:00
2021-10-10 22:07:51 +00:00
logic clk ;
2021-10-25 17:05:41 +00:00
logic reset_ext , reset ;
2023-06-12 19:06:17 +00:00
logic ResetMem ;
2024-04-06 18:11:22 +00:00
// Variables that can be overwritten with $value$plusargs at start of simulation
2024-05-16 18:59:15 +00:00
string TEST , ElfFile ;
2024-04-06 18:11:22 +00:00
integer INSTR_LIMIT ;
2021-10-10 22:07:51 +00:00
2023-06-14 21:35:55 +00:00
// DUT signals
2023-06-12 16:00:30 +00:00
logic [ P . AHBW - 1 : 0 ] HRDATAEXT ;
2024-09-29 17:18:04 +00:00
logic HREADYEXT , HRESPEXT ;
2023-06-12 16:00:30 +00:00
logic [ P . PA_BITS - 1 : 0 ] HADDR ;
logic [ P . AHBW - 1 : 0 ] HWDATA ;
logic [ P . XLEN / 8 - 1 : 0 ] HWSTRB ;
2023-06-14 21:35:55 +00:00
logic HWRITE ;
logic [ 2 : 0 ] HSIZE ;
logic [ 2 : 0 ] HBURST ;
logic [ 3 : 0 ] HPROT ;
logic [ 1 : 0 ] HTRANS ;
logic HMASTLOCK ;
logic HCLK , HRESETn ;
2021-10-10 22:07:51 +00:00
2023-06-14 21:35:55 +00:00
logic [ 31 : 0 ] GPIOIN , GPIOOUT , GPIOEN ;
logic UARTSin , UARTSout ;
2023-11-01 17:14:15 +00:00
logic SPIIn , SPIOut ;
logic [ 3 : 0 ] SPICS ;
2024-07-25 16:19:15 +00:00
logic SPICLK ;
logic SDCCmd ;
logic SDCIn ;
logic [ 3 : 0 ] SDCCS ;
2024-09-29 17:18:04 +00:00
logic SDCCLK ;
2021-10-10 22:07:51 +00:00
2023-06-14 21:35:55 +00:00
logic HREADY ;
logic HSELEXT ;
2023-05-31 21:51:00 +00:00
2024-09-29 17:18:04 +00:00
2023-04-14 02:06:09 +00:00
string ProgramAddrMapFile , ProgramLabelMapFile ;
2023-06-13 20:09:40 +00:00
integer ProgramAddrLabelArray [ string ] ;
2023-04-14 02:06:09 +00:00
2023-06-14 21:35:55 +00:00
int test , i , errors , totalerrors ;
string outputfile ;
integer outputFilePointer ;
2023-04-14 02:06:09 +00:00
2023-06-14 21:35:55 +00:00
string tests [ ] ;
2023-04-14 02:06:09 +00:00
logic DCacheFlushDone , DCacheFlushStart ;
2024-09-29 17:18:04 +00:00
logic riscofTest ;
2023-06-14 17:11:55 +00:00
logic Validate ;
logic SelectTest ;
2023-12-20 18:25:34 +00:00
logic TestComplete ;
2024-06-20 07:57:58 +00:00
logic PrevPCZero ;
2024-05-24 21:10:58 +00:00
logic RVVIStall ;
2021-10-10 22:07:51 +00:00
initial begin
2024-04-06 18:11:22 +00:00
// look for arguments passed to simulation, or use defaults
if ( ! $value$plusargs ( " TEST=%s " , TEST ) )
TEST = " none " ;
2024-05-16 18:59:15 +00:00
if ( ! $value$plusargs ( " ElfFile=%s " , ElfFile ) )
ElfFile = " none " ;
2024-04-06 18:11:22 +00:00
if ( ! $value$plusargs ( " INSTR_LIMIT=%d " , INSTR_LIMIT ) )
INSTR_LIMIT = 0 ;
2024-07-02 21:22:51 +00:00
//$display("TEST = %s ElfFile = %s", TEST, ElfFile);
2024-09-29 17:18:04 +00:00
2024-04-06 18:11:22 +00:00
// pick tests based on modes supported
2021-12-30 00:53:39 +00:00
//tests = '{};
2023-06-12 16:00:30 +00:00
if ( P . XLEN = = 64 ) begin // RV64
2021-10-10 22:07:51 +00:00
case ( TEST )
2023-12-15 13:05:53 +00:00
" arch64i " : tests = arch64i ;
" arch64priv " : tests = arch64priv ;
2024-09-29 17:18:04 +00:00
" arch64c " : if ( P . ZCA_SUPPORTED )
2023-06-12 16:00:30 +00:00
if ( P . ZICSR_SUPPORTED ) tests = { arch64c , arch64cpriv } ;
2023-12-15 13:05:53 +00:00
else tests = { arch64c } ;
2023-06-12 16:00:30 +00:00
" arch64m " : if ( P . M_SUPPORTED ) tests = arch64m ;
2024-08-08 12:27:35 +00:00
" arch64a_amo " : if ( P . ZAAMO_SUPPORTED ) tests = arch64a_amo ;
2023-06-12 16:00:30 +00:00
" arch64f " : if ( P . F_SUPPORTED ) tests = arch64f ;
2024-09-29 17:18:04 +00:00
" arch64d " : if ( P . D_SUPPORTED ) tests = arch64d ;
2023-12-19 21:24:11 +00:00
" arch64f_fma " : if ( P . F_SUPPORTED ) tests = arch64f_fma ;
2024-09-29 17:18:04 +00:00
" arch64d_fma " : if ( P . D_SUPPORTED ) tests = arch64d_fma ;
2024-01-31 22:52:15 +00:00
" arch64f_divsqrt " : if ( P . F_SUPPORTED ) tests = arch64f_divsqrt ;
2024-09-29 17:18:04 +00:00
" arch64d_divsqrt " : if ( P . D_SUPPORTED ) tests = arch64d_divsqrt ;
2023-12-19 21:24:11 +00:00
" arch64zifencei " : if ( P . ZIFENCEI_SUPPORTED ) tests = arch64zifencei ;
2024-01-11 15:37:15 +00:00
" arch64zicond " : if ( P . ZICOND_SUPPORTED ) tests = arch64zicond ;
2024-03-07 18:48:52 +00:00
" wally64q " : if ( P . Q_SUPPORTED ) tests = wally64q ;
2024-08-08 12:27:35 +00:00
" wally64a_lrsc " : if ( P . ZALRSC_SUPPORTED ) tests = wally64a_lrsc ;
2023-12-15 13:05:53 +00:00
" custom " : tests = custom ;
" wally64priv " : tests = wally64priv ;
" wally64periph " : tests = wally64periph ;
" coremark " : tests = coremark ;
" fpga " : tests = fpga ;
2024-02-01 05:39:18 +00:00
" ahb64 " : tests = ahb64 ;
2023-12-15 13:05:53 +00:00
" coverage64gc " : tests = coverage64gc ;
2023-06-12 16:00:30 +00:00
" arch64zba " : if ( P . ZBA_SUPPORTED ) tests = arch64zba ;
" arch64zbb " : if ( P . ZBB_SUPPORTED ) tests = arch64zbb ;
" arch64zbc " : if ( P . ZBC_SUPPORTED ) tests = arch64zbc ;
" arch64zbs " : if ( P . ZBS_SUPPORTED ) tests = arch64zbs ;
2023-12-19 21:24:11 +00:00
" arch64zicboz " : if ( P . ZICBOZ_SUPPORTED ) tests = arch64zicboz ;
" arch64zcb " : if ( P . ZCB_SUPPORTED ) tests = arch64zcb ;
2024-01-15 21:24:57 +00:00
" arch64zfh " : if ( P . ZFH_SUPPORTED ) tests = arch64zfh ;
2024-09-29 17:18:04 +00:00
" arch64zfh_fma " : if ( P . ZFH_SUPPORTED ) tests = arch64zfh_fma ;
2024-01-31 22:52:15 +00:00
" arch64zfh_divsqrt " : if ( P . ZFH_SUPPORTED ) tests = arch64zfh_divsqrt ;
2024-01-17 01:27:40 +00:00
" arch64zfaf " : if ( P . ZFA_SUPPORTED ) tests = arch64zfaf ;
" arch64zfad " : if ( P . ZFA_SUPPORTED & P . D_SUPPORTED ) tests = arch64zfad ;
2024-02-05 18:46:14 +00:00
" buildroot " : tests = buildroot ;
2024-02-28 23:05:08 +00:00
" arch64zbkb " : if ( P . ZBKB_SUPPORTED ) tests = arch64zbkb ;
" arch64zbkc " : if ( P . ZBKC_SUPPORTED ) tests = arch64zbkc ;
" arch64zbkx " : if ( P . ZBKX_SUPPORTED ) tests = arch64zbkx ;
" arch64zknd " : if ( P . ZKND_SUPPORTED ) tests = arch64zknd ;
" arch64zkne " : if ( P . ZKNE_SUPPORTED ) tests = arch64zkne ;
" arch64zknh " : if ( P . ZKNH_SUPPORTED ) tests = arch64zknh ;
2024-11-16 06:52:21 +00:00
" arch64pmp " : if ( P . PMP_ENTRIES > 0 ) tests = arch64pmp ;
2024-09-29 17:18:04 +00:00
endcase
2021-10-10 22:07:51 +00:00
end else begin // RV32
case ( TEST )
2024-09-29 17:18:04 +00:00
" arch32e " : tests = arch32e ;
2023-12-15 13:05:53 +00:00
" arch32i " : tests = arch32i ;
" arch32priv " : tests = arch32priv ;
2024-09-29 17:18:04 +00:00
" arch32c " : if ( P . C_SUPPORTED )
2023-06-12 16:00:30 +00:00
if ( P . ZICSR_SUPPORTED ) tests = { arch32c , arch32cpriv } ;
2023-12-15 13:05:53 +00:00
else tests = { arch32c } ;
2023-06-12 16:00:30 +00:00
" arch32m " : if ( P . M_SUPPORTED ) tests = arch32m ;
2024-09-29 17:18:04 +00:00
" arch32a_amo " : if ( P . ZAAMO_SUPPORTED ) tests = arch32a_amo ;
2023-06-12 16:00:30 +00:00
" arch32f " : if ( P . F_SUPPORTED ) tests = arch32f ;
" arch32d " : if ( P . D_SUPPORTED ) tests = arch32d ;
2023-12-19 21:24:11 +00:00
" arch32f_fma " : if ( P . F_SUPPORTED ) tests = arch32f_fma ;
" arch32d_fma " : if ( P . D_SUPPORTED ) tests = arch32d_fma ;
2024-01-31 22:52:15 +00:00
" arch32f_divsqrt " : if ( P . F_SUPPORTED ) tests = arch32f_divsqrt ;
2024-09-29 17:18:04 +00:00
" arch32d_divsqrt " : if ( P . D_SUPPORTED ) tests = arch32d_divsqrt ;
2023-12-19 21:24:11 +00:00
" arch32zifencei " : if ( P . ZIFENCEI_SUPPORTED ) tests = arch32zifencei ;
2024-01-11 15:37:15 +00:00
" arch32zicond " : if ( P . ZICOND_SUPPORTED ) tests = arch32zicond ;
2024-09-29 17:18:04 +00:00
" wally32a_lrsc " : if ( P . ZALRSC_SUPPORTED ) tests = wally32a_lrsc ;
2023-12-15 13:05:53 +00:00
" wally32priv " : tests = wally32priv ;
" wally32periph " : tests = wally32periph ;
2024-02-01 05:39:18 +00:00
" ahb32 " : tests = ahb32 ;
2023-12-15 13:05:53 +00:00
" embench " : tests = embench ;
" coremark " : tests = coremark ;
2023-06-12 16:00:30 +00:00
" arch32zba " : if ( P . ZBA_SUPPORTED ) tests = arch32zba ;
" arch32zbb " : if ( P . ZBB_SUPPORTED ) tests = arch32zbb ;
" arch32zbc " : if ( P . ZBC_SUPPORTED ) tests = arch32zbc ;
" arch32zbs " : if ( P . ZBS_SUPPORTED ) tests = arch32zbs ;
2023-12-19 21:24:11 +00:00
" arch32zicboz " : if ( P . ZICBOZ_SUPPORTED ) tests = arch32zicboz ;
" arch32zcb " : if ( P . ZCB_SUPPORTED ) tests = arch32zcb ;
2024-01-15 21:24:57 +00:00
" arch32zfh " : if ( P . ZFH_SUPPORTED ) tests = arch32zfh ;
2024-09-29 17:18:04 +00:00
" arch32zfh_fma " : if ( P . ZFH_SUPPORTED ) tests = arch32zfh_fma ;
2024-01-31 22:52:15 +00:00
" arch32zfh_divsqrt " : if ( P . ZFH_SUPPORTED ) tests = arch32zfh_divsqrt ;
2024-01-15 21:24:57 +00:00
" arch32zfaf " : if ( P . ZFA_SUPPORTED ) tests = arch32zfaf ;
2024-01-17 01:27:40 +00:00
" arch32zfad " : if ( P . ZFA_SUPPORTED & P . D_SUPPORTED ) tests = arch32zfad ;
2024-02-28 23:05:08 +00:00
" arch32zbkb " : if ( P . ZBKB_SUPPORTED ) tests = arch32zbkb ;
" arch32zbkc " : if ( P . ZBKC_SUPPORTED ) tests = arch32zbkc ;
" arch32zbkx " : if ( P . ZBKX_SUPPORTED ) tests = arch32zbkx ;
" arch32zknd " : if ( P . ZKND_SUPPORTED ) tests = arch32zknd ;
" arch32zkne " : if ( P . ZKNE_SUPPORTED ) tests = arch32zkne ;
" arch32zknh " : if ( P . ZKNH_SUPPORTED ) tests = arch32zknh ;
2024-11-16 06:52:21 +00:00
" arch32pmp " : if ( P . PMP_ENTRIES > 0 ) tests = arch32pmp ;
" arch32vm_sv32 " : if ( P . VIRTMEM_SUPPORTED ) tests = arch32vm_sv32 ;
2021-10-10 22:07:51 +00:00
endcase
end
2024-05-16 18:59:15 +00:00
if ( tests . size ( ) = = 0 & ElfFile = = " none " ) begin
if ( tests . size ( ) = = 0 ) begin
$display ( " TEST %s not supported in this configuration " , TEST ) ;
end else if ( ElfFile = = " none " ) begin
$display ( " ElfFile %s not found " , ElfFile ) ;
end
2024-02-05 02:56:40 +00:00
$finish ;
2021-10-10 22:07:51 +00:00
end
2024-12-02 21:52:44 +00:00
if ( MAKE_VCD ) begin
$dumpfile ( " testbench.vcd " ) ;
$dumpvars ;
end
2023-06-12 19:06:17 +00:00
end // initial begin
// Model the testbench as an fsm.
// Do this in parts so it easier to verify
// part 1: build a version which echos the same behavior as the below code, but does not drive anything
// part 2: drive some of the controls
// part 3: drive all logic and remove old inital and always @ negedge clk block
2023-06-13 18:18:46 +00:00
typedef enum logic [ 3 : 0 ] { STATE_TESTBENCH_RESET ,
STATE_INIT_TEST ,
2023-06-12 19:06:17 +00:00
STATE_RESET_MEMORIES ,
2023-06-13 21:24:38 +00:00
STATE_RESET_MEMORIES2 ,
2023-06-12 19:06:17 +00:00
STATE_LOAD_MEMORIES ,
STATE_RESET_TEST ,
STATE_RUN_TEST ,
2023-12-20 18:25:34 +00:00
STATE_COPY_RAM ,
2023-06-12 20:08:23 +00:00
STATE_CHECK_TEST ,
STATE_CHECK_TEST_WAIT ,
2023-06-14 16:50:12 +00:00
STATE_VALIDATE ,
STATE_INCR_TEST } statetype ;
2023-06-12 19:06:17 +00:00
statetype CurrState , NextState ;
logic TestBenchReset ;
logic [ 2 : 0 ] ResetCount , ResetThreshold ;
logic LoadMem ;
logic ResetCntEn ;
logic ResetCntRst ;
2023-12-20 19:16:32 +00:00
logic CopyRAM ;
2021-10-10 22:07:51 +00:00
2024-05-16 20:29:12 +00:00
string signame , elffilename , memfilename , bootmemfilename , uartoutfilename , pathname ;
2023-12-20 20:55:37 +00:00
integer begin_signature_addr , end_signature_addr , signature_size ;
2024-04-20 23:56:54 +00:00
integer uartoutfile ;
2023-06-12 19:06:17 +00:00
assign ResetThreshold = 3 'd5 ;
initial begin
2024-04-21 05:52:08 +00:00
TestBenchReset = 1 'b1 ;
2023-06-12 19:06:17 +00:00
# 100 ;
2024-04-21 05:52:08 +00:00
TestBenchReset = 1 'b0 ;
2021-10-10 22:07:51 +00:00
end
2023-06-14 17:11:55 +00:00
always_ff @ ( posedge clk )
2024-03-25 19:20:25 +00:00
if ( TestBenchReset ) CurrState < = STATE_TESTBENCH_RESET ;
2024-09-29 17:18:04 +00:00
else CurrState < = NextState ;
2021-10-10 22:07:51 +00:00
2023-06-15 19:57:05 +00:00
// fsm next state logic
2023-06-12 19:06:17 +00:00
always_comb begin
2024-09-29 17:18:04 +00:00
// riscof tests have a different signature, tests[0] == "0" refers to RiscvArchTests
// and tests[0] == "1" refers to WallyRiscvArchTests
riscofTest = tests [ 0 ] = = " 0 " | tests [ 0 ] = = " 1 " ;
2023-06-13 18:18:46 +00:00
pathname = tvpaths [ tests [ 0 ] . atoi ( ) ] ;
case ( CurrState )
2023-06-15 19:57:05 +00:00
STATE_TESTBENCH_RESET: NextState = STATE_INIT_TEST ;
STATE_INIT_TEST: NextState = STATE_RESET_MEMORIES ;
STATE_RESET_MEMORIES: NextState = STATE_RESET_MEMORIES2 ;
STATE_RESET_MEMORIES2: NextState = STATE_LOAD_MEMORIES ; // Give the reset enough time to ensure the bus is reset before loading the memories.
STATE_LOAD_MEMORIES: NextState = STATE_RESET_TEST ;
STATE_RESET_TEST: if ( ResetCount < ResetThreshold ) NextState = STATE_RESET_TEST ;
else NextState = STATE_RUN_TEST ;
2023-12-20 18:25:34 +00:00
STATE_RUN_TEST: if ( TestComplete ) NextState = STATE_COPY_RAM ;
2023-06-15 19:57:05 +00:00
else NextState = STATE_RUN_TEST ;
2023-12-20 18:25:34 +00:00
STATE_COPY_RAM: NextState = STATE_CHECK_TEST ;
2023-06-15 19:57:05 +00:00
STATE_CHECK_TEST: if ( DCacheFlushDone ) NextState = STATE_VALIDATE ;
else NextState = STATE_CHECK_TEST_WAIT ;
STATE_CHECK_TEST_WAIT: if ( DCacheFlushDone ) NextState = STATE_VALIDATE ;
else NextState = STATE_CHECK_TEST_WAIT ;
STATE_VALIDATE: NextState = STATE_INIT_TEST ;
STATE_INCR_TEST: NextState = STATE_INIT_TEST ;
default : NextState = STATE_TESTBENCH_RESET ;
2023-06-12 19:06:17 +00:00
endcase
end // always_comb
2024-09-29 17:18:04 +00:00
// fsm output control logic
assign reset_ext = CurrState = = STATE_TESTBENCH_RESET | CurrState = = STATE_INIT_TEST |
CurrState = = STATE_RESET_MEMORIES | CurrState = = STATE_RESET_MEMORIES2 |
2023-06-15 19:57:05 +00:00
CurrState = = STATE_LOAD_MEMORIES | CurrState = = STATE_RESET_TEST ;
2024-09-29 17:18:04 +00:00
// this initialization is very expensive, only do it for coremark.
2023-06-15 19:57:05 +00:00
assign ResetMem = ( CurrState = = STATE_RESET_MEMORIES | CurrState = = STATE_RESET_MEMORIES2 ) & TEST = = " coremark " ;
assign LoadMem = CurrState = = STATE_LOAD_MEMORIES ;
assign ResetCntRst = CurrState = = STATE_INIT_TEST ;
assign ResetCntEn = CurrState = = STATE_RESET_TEST ;
assign Validate = CurrState = = STATE_VALIDATE ;
assign SelectTest = CurrState = = STATE_INIT_TEST ;
2023-12-20 18:25:34 +00:00
assign CopyRAM = TestComplete & CurrState = = STATE_RUN_TEST ;
assign DCacheFlushStart = CurrState = = STATE_COPY_RAM ;
2023-06-15 19:57:05 +00:00
// fsm reset counter
counter # ( 3 ) RstCounter ( clk , ResetCntRst , ResetCntEn , ResetCount ) ;
2023-06-12 19:06:17 +00:00
2023-06-15 19:57:05 +00:00
////////////////////////////////////////////////////////////////////////////////
// Find the test vector files and populate the PC to function label converter
////////////////////////////////////////////////////////////////////////////////
2023-06-16 17:27:22 +00:00
logic [ P . XLEN - 1 : 0 ] testadr ;
2024-05-07 17:41:02 +00:00
//VCS ignores the dynamic types while processing the implicit sensitivity lists of always @*, always_comb, and always_latch
//procedural blocks. VCS supports the dynamic types in the implicit sensitivity list of always @* block as specified in the Section 9.2 of the IEEE Standard SystemVerilog Specification 1800-2012.
//To support memory load and dump task verbosity: flag : -diag sys_task_mem
always @ ( * ) begin
2024-04-03 17:39:02 +00:00
begin_signature_addr = ProgramAddrLabelArray [ " begin_signature " ] ;
2024-05-07 17:41:02 +00:00
end_signature_addr = ProgramAddrLabelArray [ " sig_end_canary " ] ;
2024-04-03 17:39:02 +00:00
signature_size = end_signature_addr - begin_signature_addr ;
end
2024-04-12 23:06:10 +00:00
logic EcallFaultM ;
if ( P . ZICSR_SUPPORTED )
assign EcallFaultM = dut . core . priv . priv . EcallFaultM ;
else
assign EcallFaultM = 0 ;
2024-09-29 17:18:04 +00:00
2023-06-14 17:11:55 +00:00
always @ ( posedge clk ) begin
2024-04-03 13:51:18 +00:00
////////////////////////////////////////////////////////////////////////////////
// Verify the test ran correctly by checking the memory against a known signature.
////////////////////////////////////////////////////////////////////////////////
if ( TestBenchReset ) test = 1 ;
2024-04-06 17:34:21 +00:00
if ( P . ZICSR_SUPPORTED & TEST = = " coremark " )
2024-04-12 23:06:10 +00:00
if ( EcallFaultM ) begin
2024-04-03 13:51:18 +00:00
$display ( " Benchmark: coremark is done. " ) ;
$stop ;
end
2023-06-14 17:11:55 +00:00
if ( SelectTest ) begin
2024-09-29 17:18:04 +00:00
if ( riscofTest ) begin
2024-05-16 18:59:15 +00:00
memfilename = { pathname , tests [ test ] , " /ref/ref.elf.memfile " } ;
2024-05-16 20:29:12 +00:00
elffilename = { pathname , tests [ test ] , " ref/ref.elf " } ;
2024-05-16 18:59:15 +00:00
ProgramAddrMapFile = { pathname , tests [ test ] , " /ref/ref.elf.objdump.addr " } ;
ProgramLabelMapFile = { pathname , tests [ test ] , " /ref/ref.elf.objdump.lab " } ;
2024-09-29 17:18:04 +00:00
end else if ( TEST = = " buildroot " ) begin
2024-02-05 18:46:14 +00:00
memfilename = { RISCV_DIR , " /linux-testvectors/ram.bin " } ;
2024-05-16 20:29:12 +00:00
elffilename = " buildroot " ;
2024-02-05 18:46:14 +00:00
bootmemfilename = { RISCV_DIR , " /linux-testvectors/bootmem.bin " } ;
2024-04-06 21:10:18 +00:00
uartoutfilename = { " logs/ " , TEST , " _uart.out " } ;
2024-04-22 03:08:35 +00:00
uartoutfile = $fopen ( uartoutfilename , " w " ) ; // delete UART output file
2024-02-05 19:09:31 +00:00
ProgramAddrMapFile = { RISCV_DIR , " /buildroot/output/images/disassembly/vmlinux.objdump.addr " } ;
ProgramLabelMapFile = { RISCV_DIR , " /buildroot/output/images/disassembly/vmlinux.objdump.lab " } ;
2024-07-25 16:19:15 +00:00
end else if ( TEST = = " fpga " ) begin
bootmemfilename = { WALLY_DIR , " /fpga/src/boot.mem " } ;
memfilename = { WALLY_DIR , " /fpga/src/data.mem " } ;
ProgramAddrMapFile = { WALLY_DIR , " /fpga/zsbl/bin/boot.objdump.addr " } ;
ProgramLabelMapFile = { WALLY_DIR , " /fpga/zsbl/bin/boot.objdump.lab " } ;
2024-05-16 18:59:15 +00:00
end else if ( ElfFile ! = " none " ) begin
2024-05-16 20:29:12 +00:00
elffilename = ElfFile ;
2024-05-16 18:59:15 +00:00
memfilename = { ElfFile , " .memfile " } ;
ProgramAddrMapFile = { ElfFile , " .objdump.addr " } ;
ProgramLabelMapFile = { ElfFile , " .objdump.lab " } ;
2023-06-14 17:11:55 +00:00
end else begin
2024-05-16 20:29:12 +00:00
elffilename = { pathname , tests [ test ] , " .elf " } ;
2024-05-16 18:59:15 +00:00
memfilename = { pathname , tests [ test ] , " .elf.memfile " } ;
2023-06-14 17:11:55 +00:00
ProgramAddrMapFile = { pathname , tests [ test ] , " .elf.objdump.addr " } ;
ProgramLabelMapFile = { pathname , tests [ test ] , " .elf.objdump.lab " } ;
end
2024-09-29 17:18:04 +00:00
// declare memory labels that interest us, the updateProgramAddrLabelArray task will find
// the addr of each label and fill the array. To expand, add more elements to this array
2023-06-14 17:11:55 +00:00
// and initialize them to zero (also initilaize them to zero at the start of the next test)
2024-07-03 23:52:16 +00:00
updateProgramAddrLabelArray ( ProgramAddrMapFile , ProgramLabelMapFile , memfilename , WALLY_DIR , ProgramAddrLabelArray ) ;
2023-06-14 17:11:55 +00:00
end
if ( Validate ) begin
2024-06-20 07:57:58 +00:00
if ( PrevPCZero ) totalerrors = totalerrors + 1 ; // error if PC is stuck at zero
2024-04-20 23:56:54 +00:00
if ( TEST = = " buildroot " )
$fclose ( uartoutfile ) ;
2023-06-15 19:57:05 +00:00
if ( TEST = = " embench " ) begin
2023-06-14 17:23:26 +00:00
// Writes contents of begin_signature to .sim.output file
2024-09-29 17:18:04 +00:00
// this contains instret and cycles for start and end of test run, used by embench
// python speed script to calculate embench speed score.
// also, begin_signature contains the results of the self checking mechanism,
2023-06-14 17:23:26 +00:00
// which will be read by the python script for error checking
$display ( " Embench Benchmark: %s is done. " , tests [ test ] ) ;
if ( riscofTest ) outputfile = { pathname , tests [ test ] , " /ref/ref.sim.output " } ;
else outputfile = { pathname , tests [ test ] , " .sim.output " } ;
outputFilePointer = $fopen ( outputfile , " w " ) ;
i = 0 ;
2023-06-16 17:27:22 +00:00
testadr = ( $unsigned ( begin_signature_addr ) ) / ( P . XLEN / 8 ) ;
while ( $unsigned ( i ) < $unsigned ( 5 'd5 ) ) begin
$fdisplayh ( outputFilePointer , DCacheFlushFSM . ShadowRAM [ testadr + i ] ) ;
i = i + 1 ;
end
2023-06-14 17:23:26 +00:00
$fclose ( outputFilePointer ) ;
$display ( " Embench Benchmark: created output file: %s " , outputfile ) ;
end else if ( TEST = = " coverage64gc " ) begin
2024-10-02 20:41:14 +00:00
$display ( " %s ran. Coverage tests don't get checked " , tests [ test ] ) ;
2024-05-16 18:59:15 +00:00
end else if ( ElfFile ! = " none " ) begin
2024-12-11 19:54:39 +00:00
`ifdef USE_TREK_DV
$display ( " Breker test is done. " ) ;
`else
$display ( " Single Elf file tests are not signatured verified. " ) ;
`endif
2024-06-27 04:18:40 +00:00
`ifdef QUESTA
$stop ; // if this is changed to $finish for Questa, wally-batch.do does not go to the next step to run coverage, and wally.do terminates without allowing GUI debug
2024-05-16 18:59:15 +00:00
`else
2024-06-27 04:18:40 +00:00
$finish ;
2024-05-16 18:59:15 +00:00
`endif
2024-09-29 17:18:04 +00:00
end else begin
2023-06-14 17:23:26 +00:00
// for tests with no self checking mechanism, read .signature.output file and compare to check for errors
// clear signature to prevent contamination from previous tests
2024-02-01 18:22:28 +00:00
if ( ! begin_signature_addr )
$display ( " begin_signature addr not found in %s " , ProgramLabelMapFile ) ;
2024-09-29 17:18:04 +00:00
else if ( TEST ! = " embench " ) begin
2024-05-07 17:41:02 +00:00
CheckSignature ( pathname , tests [ test ] , riscofTest , begin_signature_addr , errors ) ;
2024-02-01 18:22:28 +00:00
if ( errors > 0 ) totalerrors = totalerrors + 1 ;
end
2023-06-14 17:23:26 +00:00
end
2024-09-29 17:18:04 +00:00
test = test + 1 ;
2023-06-14 17:11:55 +00:00
if ( test = = tests . size ( ) ) begin
if ( totalerrors = = 0 ) $display ( " SUCCESS! All tests ran without failures. " ) ;
else $display ( " FAIL: %d test programs had errors " , totalerrors ) ;
2024-06-27 04:18:40 +00:00
`ifdef QUESTA
$stop ; // if this is changed to $finish for Questa, wally-batch.do does not go to the next step to run coverage, and wally.do terminates without allowing GUI debug
2024-04-03 13:51:18 +00:00
`else
2024-06-27 04:18:40 +00:00
$finish ;
2024-04-03 13:51:18 +00:00
`endif
2023-06-14 17:11:55 +00:00
end
end
2024-06-27 05:39:43 +00:00
end
2023-06-14 17:11:55 +00:00
2023-06-12 19:06:17 +00:00
////////////////////////////////////////////////////////////////////////////////
// load memories with program image
////////////////////////////////////////////////////////////////////////////////
2023-12-20 18:25:34 +00:00
2023-12-20 20:55:37 +00:00
integer ShadowIndex ;
integer LogXLEN ;
integer StartIndex ;
integer EndIndex ;
integer BaseIndex ;
2024-07-08 19:48:52 +00:00
integer memFile , uncoreMemFile ;
2024-02-05 18:46:14 +00:00
integer readResult ;
2023-12-20 18:25:34 +00:00
if ( P . SDC_SUPPORTED ) begin
always @ ( posedge clk ) begin
if ( LoadMem ) begin
2023-06-13 18:52:02 +00:00
string romfilename , sdcfilename ;
romfilename = { " ../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile " } ;
2024-09-29 17:18:04 +00:00
sdcfilename = { " ../testbench/sdc/ramdisk2.hex " } ;
2024-04-15 22:58:09 +00:00
//$readmemh(romfilename, dut.uncoregen.uncore.bootrom.bootrom.memory.ROM);
2023-10-13 19:08:17 +00:00
//$readmemh(sdcfilename, sdcard.sdcard.FLASHmem);
2023-06-13 18:52:02 +00:00
// shorten sdc timers for simulation
2024-04-15 22:58:09 +00:00
//dut.uncoregen.uncore.sdc.SDC.LimitTimers = 1;
2023-12-20 18:25:34 +00:00
end
end
end else if ( P . IROM_SUPPORTED ) begin
always @ ( posedge clk ) begin
if ( LoadMem ) begin
$readmemh ( memfilename , dut . core . ifu . irom . irom . rom . ROM ) ;
end
end
2023-12-20 20:55:37 +00:00
end else if ( P . BUS_SUPPORTED ) begin : bus_supported
2023-12-20 18:25:34 +00:00
always @ ( posedge clk ) begin
if ( LoadMem ) begin
2024-02-05 18:46:14 +00:00
if ( TEST = = " buildroot " ) begin
memFile = $fopen ( bootmemfilename , " rb " ) ;
2024-06-14 16:50:07 +00:00
if ( memFile = = 0 ) begin
$display ( " Error: Could not open file %s " , memfilename ) ;
$finish ;
end
2024-07-05 16:13:18 +00:00
if ( P . BOOTROM_SUPPORTED )
readResult = $fread ( dut . uncoregen . uncore . bootrom . bootrom . memory . ROM , memFile ) ;
else begin
$display ( " Buildroot test requires BOOTROM_SUPPORTED " ) ;
$finish ;
end
2024-02-05 18:46:14 +00:00
$fclose ( memFile ) ;
memFile = $fopen ( memfilename , " rb " ) ;
2024-06-14 16:50:07 +00:00
if ( memFile = = 0 ) begin
$display ( " Error: Could not open file %s " , memfilename ) ;
$finish ;
end
2024-06-14 10:35:05 +00:00
readResult = $fread ( dut . uncoregen . uncore . ram . ram . memory . ram . RAM , memFile ) ;
2024-02-05 18:46:14 +00:00
$fclose ( memFile ) ;
2024-07-25 16:19:15 +00:00
end else if ( TEST = = " fpga " ) begin
memFile = $fopen ( bootmemfilename , " rb " ) ;
if ( memFile = = 0 ) begin
$display ( " Error: Could not open file %s " , memfilename ) ;
$finish ;
end
if ( P . BOOTROM_SUPPORTED ) begin
readResult = $fread ( dut . uncoregen . uncore . bootrom . bootrom . memory . ROM , memFile ) ;
end
$fclose ( memFile ) ;
memFile = $fopen ( memfilename , " rb " ) ;
if ( memFile = = 0 ) begin
$display ( " Error: Could not open file %s " , memfilename ) ;
$finish ;
end
readResult = $fread ( dut . uncoregen . uncore . ram . ram . memory . ram . RAM , memFile ) ;
$fclose ( memFile ) ;
2024-07-08 19:48:52 +00:00
end else begin
uncoreMemFile = $fopen ( memfilename , " r " ) ; // Is there a better way to test if a file exists?
if ( uncoreMemFile = = 0 ) begin
$display ( " Error: Could not open file %s " , memfilename ) ;
$finish ;
end else begin
$fclose ( uncoreMemFile ) ;
$readmemh ( memfilename , dut . uncoregen . uncore . ram . ram . memory . ram . RAM ) ;
2024-11-27 08:13:17 +00:00
`ifdef USE_TREK_DV
- > trek_start ;
$display ( " starting Trek.... " ) ;
`endif
2024-07-08 19:48:52 +00:00
end
end
2024-02-05 18:46:14 +00:00
if ( TEST = = " embench " ) $display ( " Read memfile %s " , memfilename ) ;
2023-12-20 18:25:34 +00:00
end
if ( CopyRAM ) begin
2023-12-20 20:55:37 +00:00
LogXLEN = ( 1 + P . XLEN / 32 ) ; // 2 for rv32 and 3 for rv64
StartIndex = begin_signature_addr > > LogXLEN ;
EndIndex = ( end_signature_addr > > LogXLEN ) + 8 ;
BaseIndex = P . UNCORE_RAM_BASE > > LogXLEN ;
for ( ShadowIndex = StartIndex ; ShadowIndex < = EndIndex ; ShadowIndex + + ) begin
2024-06-14 10:35:05 +00:00
testbench . DCacheFlushFSM . ShadowRAM [ ShadowIndex ] = dut . uncoregen . uncore . ram . ram . memory . ram . RAM [ ShadowIndex - BaseIndex ] ;
2023-12-20 18:25:34 +00:00
end
end
end
2024-09-29 17:18:04 +00:00
end
2023-12-20 18:25:34 +00:00
if ( P . DTIM_SUPPORTED ) begin
always @ ( posedge clk ) begin
if ( LoadMem ) begin
2024-06-14 10:35:05 +00:00
$readmemh ( memfilename , dut . core . lsu . dtim . dtim . ram . ram . RAM ) ;
2023-12-20 18:25:34 +00:00
end
if ( CopyRAM ) begin
2023-12-20 20:55:37 +00:00
LogXLEN = ( 1 + P . XLEN / 32 ) ; // 2 for rv32 and 3 for rv64
StartIndex = begin_signature_addr > > LogXLEN ;
EndIndex = ( end_signature_addr > > LogXLEN ) + 8 ;
BaseIndex = P . UNCORE_RAM_BASE > > LogXLEN ;
for ( ShadowIndex = StartIndex ; ShadowIndex < = EndIndex ; ShadowIndex + + ) begin
2024-06-14 10:35:05 +00:00
testbench . DCacheFlushFSM . ShadowRAM [ ShadowIndex ] = dut . core . lsu . dtim . dtim . ram . ram . RAM [ ShadowIndex - BaseIndex ] ;
2023-12-20 18:25:34 +00:00
end
end
2023-06-13 18:52:02 +00:00
end
2023-12-20 18:25:34 +00:00
end
2024-01-06 06:41:57 +00:00
integer adrindex ;
if ( P . UNCORE_RAM_SUPPORTED )
2024-09-29 17:18:04 +00:00
always @ ( posedge clk )
2024-01-07 15:14:12 +00:00
if ( ResetMem ) // program memory is sometimes reset (e.g. for CoreMark, which needs zeroed memory)
2024-09-29 17:18:04 +00:00
for ( adrindex = 0 ; adrindex < ( P . UNCORE_RAM_RANGE > > 1 + ( P . XLEN / 32 ) ) ; adrindex = adrindex + 1 )
2024-06-14 10:35:05 +00:00
dut . uncoregen . uncore . ram . ram . memory . ram . RAM [ adrindex ] = '0 ;
2024-01-06 06:41:57 +00:00
2023-06-15 19:57:05 +00:00
////////////////////////////////////////////////////////////////////////////////
// Actual hardware
////////////////////////////////////////////////////////////////////////////////
2022-08-24 18:27:18 +00:00
2021-10-10 22:07:51 +00:00
// instantiate device to be tested
2024-04-21 00:22:31 +00:00
assign GPIOIN = '0 ;
assign UARTSin = 1 'b1 ;
assign SPIIn = 1 'b0 ;
2022-08-24 18:27:18 +00:00
2023-06-12 16:00:30 +00:00
if ( P . EXT_MEM_SUPPORTED ) begin
2024-11-16 20:53:10 +00:00
ram_ahb # ( . P ( P ) , . RANGE ( P . EXT_MEM_RANGE ) )
2024-09-29 17:18:04 +00:00
ram ( . HCLK , . HRESETn , . HADDR , . HWRITE , . HTRANS , . HWDATA , . HSELRam ( HSELEXT ) ,
2023-06-15 19:57:05 +00:00
. HREADRam ( HRDATAEXT ) , . HREADYRam ( HREADYEXT ) , . HRESPRam ( HRESPEXT ) , . HREADY , . HWSTRB ) ;
2024-09-29 17:18:04 +00:00
end else begin
2024-04-21 00:22:31 +00:00
assign HREADYEXT = 1 'b1 ;
assign { HRESPEXT , HRDATAEXT } = '0 ;
2022-08-24 18:27:18 +00:00
end
2023-10-13 19:08:17 +00:00
if ( P . SDC_SUPPORTED ) begin : sdcard
2024-06-19 20:51:37 +00:00
// JP: Add back sd card when sd card AHB implementation done
/ * - - - - - \ / - - - - - EXCLUDED - - - - - \ / - - - - -
2022-08-24 18:27:18 +00:00
sdModel sdcard
( . sdClk ( SDCCLK ) ,
2024-09-29 17:18:04 +00:00
. cmd ( SDCCmd ) ,
2022-08-24 18:27:18 +00:00
. dat ( SDCDat ) ) ;
assign SDCCmd = SDCCmdOE ? SDCCmdOut : 1 ' bz ;
assign SDCCmdIn = SDCCmd ;
2023-10-17 19:13:18 +00:00
assign SDCDat = sd_dat_reg_t ? sd_dat_reg_o : sd_dat_i ;
2022-08-24 18:27:18 +00:00
assign SDCDatIn = SDCDat ;
2024-06-19 20:51:37 +00:00
- - - - - / \ - - - - - EXCLUDED - - - - - / \ - - - - - */
2022-08-24 18:27:18 +00:00
end else begin
2024-07-25 16:19:15 +00:00
assign SDCIn = 1 'b1 ;
2024-09-29 17:18:04 +00:00
2022-08-24 18:27:18 +00:00
end
2021-10-10 22:07:51 +00:00
2024-09-29 17:18:04 +00:00
wallypipelinedsoc # ( P ) dut ( . clk , . reset_ext , . reset , . ExternalStall ( RVVIStall ) ,
2024-08-06 22:09:39 +00:00
. HRDATAEXT , . HREADYEXT , . HRESPEXT , . HSELEXT ,
2023-06-15 19:57:05 +00:00
. HCLK , . HRESETn , . HADDR , . HWDATA , . HWSTRB , . HWRITE , . HSIZE , . HBURST , . HPROT ,
. HTRANS , . HMASTLOCK , . HREADY , . TIMECLK ( 1 'b0 ) , . GPIOIN , . GPIOOUT , . GPIOEN ,
2024-09-29 17:18:04 +00:00
. UARTSin , . UARTSout , . SPIIn , . SPIOut , . SPICS , . SPICLK , . SDCIn , . SDCCmd , . SDCCS , . SDCCLK ) ;
2021-10-10 22:07:51 +00:00
// generate clock to sequence tests
2023-06-15 19:57:05 +00:00
always begin
2024-04-21 05:52:08 +00:00
clk = 1 'b1 ; # 5 ; clk = 1 'b0 ; # 5 ;
2023-01-06 00:00:11 +00:00
end
2023-03-03 19:10:01 +00:00
2024-07-24 17:47:50 +00:00
if ( RVVI_SYNTH_SUPPORTED ) begin : rvvi_synth
2024-07-23 22:39:38 +00:00
localparam MAX_CSRS = 5 ;
2024-07-24 17:47:50 +00:00
localparam logic [ 31 : 0 ] RVVI_INIT_TIME_OUT = 32 'd4 ;
localparam logic [ 31 : 0 ] RVVI_PACKET_DELAY = 32 'd2 ;
2024-05-24 21:10:58 +00:00
logic [ 3 : 0 ] mii_txd ;
logic mii_tx_en , mii_tx_er ;
2024-06-20 19:54:12 +00:00
2024-09-29 17:18:04 +00:00
rvvitbwrapper # ( P , MAX_CSRS , RVVI_INIT_TIME_OUT , RVVI_PACKET_DELAY )
2024-07-24 18:10:57 +00:00
rvvitbwrapper ( . clk , . reset , . RVVIStall , . mii_tx_clk ( clk ) , . mii_txd , . mii_tx_en , . mii_tx_er ,
. mii_rx_clk ( clk ) , . mii_rxd ( '0 ) , . mii_rx_dv ( '0 ) , . mii_rx_er ( '0 ) ) ;
2024-05-24 21:10:58 +00:00
end else begin
assign RVVIStall = '0 ;
end
2024-09-29 17:18:04 +00:00
2024-05-24 21:10:58 +00:00
2024-01-07 15:14:12 +00:00
/ *
// Print key info each cycle for debugging
2024-09-29 17:18:04 +00:00
always @ ( posedge clk ) begin
2024-01-07 15:14:12 +00:00
# 2 ;
$display ( " PCM: %x InstrM: %x (%5s) WriteDataM: %x IEUResultM: %x " ,
dut . core . PCM , dut . core . InstrM , InstrMName , dut . core . WriteDataM , dut . core . ieu . dp . IEUResultM ) ;
end
*/
2023-06-15 19:57:05 +00:00
////////////////////////////////////////////////////////////////////////////////
// Support logic
////////////////////////////////////////////////////////////////////////////////
2023-11-03 12:24:15 +00:00
// Duplicate copy of pipeline registers that are optimized out of some configurations
logic [ 31 : 0 ] NextInstrE , InstrM ;
mux2 # ( 32 ) FlushInstrMMux ( dut . core . ifu . InstrE , dut . core . ifu . nop , dut . core . ifu . FlushM , NextInstrE ) ;
flopenr # ( 32 ) InstrMReg ( clk , reset , ~ dut . core . ifu . StallM , NextInstrE , InstrM ) ;
2023-07-02 20:29:27 +00:00
// Track names of instructions
string InstrFName , InstrDName , InstrEName , InstrMName , InstrWName ;
logic [ 31 : 0 ] InstrW ;
2023-11-03 12:24:15 +00:00
flopenr # ( 32 ) InstrWReg ( clk , reset , ~ dut . core . ieu . dp . StallW , InstrM , InstrW ) ;
2023-07-02 20:29:27 +00:00
instrTrackerTB it ( clk , reset , dut . core . ieu . dp . FlushE ,
dut . core . ifu . InstrRawF [ 31 : 0 ] ,
dut . core . ifu . InstrD , dut . core . ifu . InstrE ,
2023-11-03 12:24:15 +00:00
InstrM , InstrW ,
2023-07-02 20:29:27 +00:00
InstrFName , InstrDName , InstrEName , InstrMName , InstrWName ) ;
// watch for problems such as lockup, reading unitialized memory, bad configs
2024-07-02 21:22:51 +00:00
watchdog # ( P . XLEN , 1000000 ) watchdog ( . clk , . reset , . TEST ) ; // check if PCW is stuck
2024-09-29 17:18:04 +00:00
ramxdetector # ( P . XLEN , P . LLEN ) ramxdetector ( clk , dut . core . lsu . MemRWM [ 1 ] , dut . core . lsu . LSULoadAccessFaultM , dut . core . lsu . ReadDataM ,
2023-11-03 12:24:15 +00:00
dut . core . ifu . PCM , InstrM , dut . core . lsu . IEUAdrM , InstrMName ) ;
2023-06-15 19:57:05 +00:00
riscvassertions # ( P ) riscvassertions ( ) ; // check assertions for a legal configuration
2024-04-06 17:34:21 +00:00
loggers # ( P , PrintHPMCounters , I_CACHE_ADDR_LOGGER , D_CACHE_ADDR_LOGGER , BPRED_LOGGER )
loggers ( clk , reset , DCacheFlushStart , DCacheFlushDone , memfilename , TEST ) ;
2023-01-06 00:00:11 +00:00
2021-10-10 22:07:51 +00:00
// track the current function or global label
2024-06-20 07:57:58 +00:00
if ( DEBUG > 0 | ( ( PrintHPMCounters | BPRED_LOGGER ) & P . ZICNTR_SUPPORTED ) ) begin : FunctionName
FunctionName # ( P ) FunctionName ( . reset ( reset_ext | TestBenchReset ) ,
. clk ( clk ) , . ProgramAddrMapFile ( ProgramAddrMapFile ) , . ProgramLabelMapFile ( ProgramLabelMapFile ) ) ;
end
2021-10-10 22:07:51 +00:00
2024-04-06 04:39:41 +00:00
// Append UART output to file for tests
2024-04-13 04:30:33 +00:00
if ( P . UART_SUPPORTED ) begin : uart_logger
always @ ( posedge clk ) begin
if ( TEST = = " buildroot " ) begin
2024-04-15 22:58:09 +00:00
if ( ~ dut . uncoregen . uncore . uartgen . uart . MEMWb & dut . uncoregen . uncore . uartgen . uart . uartPC . A = = 3 'b000 & ~ dut . uncoregen . uncore . uartgen . uart . uartPC . DLAB ) begin
2024-04-22 03:08:35 +00:00
$fwrite ( uartoutfile , " %c " , dut . uncoregen . uncore . uartgen . uart . uartPC . Din ) ; // append characters one at a time so we see a consistent log appearing during the run
$fflush ( uartoutfile ) ;
2024-04-13 04:30:33 +00:00
end
2024-04-06 00:18:03 +00:00
end
end
end
2021-10-10 22:07:51 +00:00
// Termination condition
2024-09-29 17:18:04 +00:00
// Terminate on
2024-06-19 20:51:37 +00:00
// 1. jump to self loop (0x0000006f)
// 2. a store word writes to the address "tohost"
// 3. or PC is stuck at 0
2024-06-20 07:57:58 +00:00
always @ ( posedge clk ) begin
// if (reset) PrevPCZero <= 0;
// else if (dut.core.InstrValidM) PrevPCZero <= (FunctionName.PCM == 0 & dut.core.ifu.InstrM == 0);
TestComplete < = ( ( InstrM = = 32 'h6f ) & dut . core . InstrValidM ) |
( ( dut . core . lsu . IEUAdrM = = ProgramAddrLabelArray [ " tohost " ] & dut . core . lsu . IEUAdrM ! = 0 ) & InstrMName = = " SW " ) ; // |
// (FunctionName.PCM == 0 & dut.core.ifu.InstrM == 0 & dut.core.InstrValidM & PrevPCZero));
// if (FunctionName.PCM == 0 & dut.core.ifu.InstrM == 0 & dut.core.InstrValidM & PrevPCZero)
// $error("Program fetched illegal instruction 0x00000000 from address 0x00000000 twice in a row. Usually due to fault with no fault handler.");
2024-09-29 17:18:04 +00:00
end
2024-06-20 07:57:58 +00:00
2024-04-21 00:22:31 +00:00
DCacheFlushFSM # ( P ) DCacheFlushFSM ( . clk , . start ( DCacheFlushStart ) , . done ( DCacheFlushDone ) ) ;
2023-05-03 17:52:32 +00:00
2024-04-06 18:11:22 +00:00
if ( P . ZICSR_SUPPORTED ) begin
2024-02-05 20:41:52 +00:00
logic [ P . XLEN - 1 : 0 ] Minstret ;
2024-09-29 17:18:04 +00:00
assign Minstret = testbench . dut . core . priv . priv . csr . counters . counters . HPMCOUNTER_REGW [ 2 ] ;
2024-02-05 20:41:52 +00:00
always @ ( negedge clk ) begin
2024-04-06 18:11:22 +00:00
if ( INSTR_LIMIT > 0 ) begin
2024-05-15 17:50:23 +00:00
if ( ( Minstret ! = 0 ) & ( Minstret % 'd100000 = = 0 ) ) $display ( " Reached %d instructions " , Minstret ) ;
2024-05-09 14:58:53 +00:00
if ( ( Minstret = = INSTR_LIMIT ) & ( INSTR_LIMIT ! = 0 ) ) begin $finish ; end
2024-04-06 18:11:22 +00:00
end
2024-02-05 20:41:52 +00:00
end
2024-02-07 21:38:18 +00:00
end
////////////////////////////////////////////////////////////////////////////////
// ImperasDV Co-simulator hooks
////////////////////////////////////////////////////////////////////////////////
`ifdef USE_IMPERAS_DV
rvviTrace # ( . XLEN ( P . XLEN ) , . FLEN ( P . FLEN ) ) rvvi ( ) ;
wallyTracer # ( P ) wallyTracer ( rvvi ) ;
trace2log idv_trace2log ( rvvi ) ;
2024-05-27 22:25:20 +00:00
trace2cov idv_trace2cov ( rvvi ) ;
2024-02-07 21:38:18 +00:00
// enabling of comparison types
trace2api # ( . CMP_PC ( 1 ) ,
. CMP_INS ( 1 ) ,
. CMP_GPR ( 1 ) ,
. CMP_FPR ( 1 ) ,
. CMP_VR ( 0 ) ,
. CMP_CSR ( 1 )
) idv_trace2api ( rvvi ) ;
2024-05-16 20:29:12 +00:00
string filename ;
2024-02-07 21:38:18 +00:00
initial begin
2024-05-17 21:45:01 +00:00
// imperasDV requires the elffile be defined at the begining of the simulation.
2024-02-07 21:38:18 +00:00
int iter ;
2024-05-17 22:34:29 +00:00
longint x64 ;
int x32 [ 2 ] ;
longint index ;
string memfilenameImperasDV , bootmemfilenameImperasDV ;
2024-02-07 21:38:18 +00:00
# 1 ;
IDV_MAX_ERRORS = 3 ;
2024-05-17 21:45:01 +00:00
elffilename = ElfFile ;
2024-02-07 21:38:18 +00:00
// Initialize REF (do this before initializing the DUT)
if ( ! rvviVersionCheck ( RVVI_API_VERSION ) ) begin
$display ( $sformatf ( " %m @ t=%0t: Expecting RVVI API version %0d. " , $time , RVVI_API_VERSION ) ) ;
$fatal ;
end
2024-09-29 17:18:04 +00:00
2024-02-07 21:38:18 +00:00
void ' ( rvviRefConfigSetString ( IDV_CONFIG_MODEL_VENDOR , " riscv.ovpworld.org " ) ) ;
void ' ( rvviRefConfigSetString ( IDV_CONFIG_MODEL_NAME , " riscv " ) ) ;
2024-07-14 04:42:14 +00:00
void ' ( rvviRefConfigSetString ( IDV_CONFIG_MODEL_VARIANT , " RV64GCK " ) ) ;
2024-08-29 17:44:37 +00:00
void ' ( rvviRefConfigSetInt ( IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH , XLEN = = 64 ? 56 : 34 ) ) ;
2024-02-07 21:38:18 +00:00
void ' ( rvviRefConfigSetInt ( IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS , 6 ) ) ;
2024-09-29 17:18:04 +00:00
if ( elffilename = = " buildroot " ) filename = " " ;
2024-05-16 20:29:12 +00:00
else filename = elffilename ;
2024-05-17 22:34:29 +00:00
// use the ImperasDV rvviRefInit to load the reference model with an elf file
if ( elffilename ! = " none " ) begin
if ( ! rvviRefInit ( filename ) ) begin
$display ( $sformatf ( " %m @ t=%0t: rvviRefInit failed " , $time ) ) ;
$fatal ;
end
2024-06-14 16:50:07 +00:00
end else begin // for buildroot use the binary instead to load the reference model.
2024-05-17 22:34:29 +00:00
if ( ! rvviRefInit ( " " ) ) begin // still have to call with nothing
$display ( $sformatf ( " %m @ t=%0t: rvviRefInit failed " , $time ) ) ;
$fatal ;
2024-09-29 17:18:04 +00:00
end
2024-05-17 22:34:29 +00:00
memfilenameImperasDV = { RISCV_DIR , " /linux-testvectors/ram.bin " } ;
bootmemfilenameImperasDV = { RISCV_DIR , " /linux-testvectors/bootmem.bin " } ;
$display ( " RVVI Loading bootmem.bin " ) ;
memFile = $fopen ( bootmemfilenameImperasDV , " rb " ) ;
index = 'h1000 - 8 ;
while ( ! $feof ( memFile ) ) begin
index + = 8 ;
readResult = $fread ( x64 , memFile ) ;
if ( x64 = = 0 ) continue ;
x32 [ 0 ] = x64 & 'hffffffff ;
x32 [ 1 ] = x64 > > 32 ;
rvviRefMemoryWrite ( 0 , index + 0 , x32 [ 0 ] , 4 ) ;
rvviRefMemoryWrite ( 0 , index + 4 , x32 [ 1 ] , 4 ) ;
//$display("boot %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]);
end
$fclose ( memFile ) ;
2024-09-29 17:18:04 +00:00
2024-05-17 22:34:29 +00:00
$display ( " RVVI Loading ram.bin " ) ;
memFile = $fopen ( memfilenameImperasDV , " rb " ) ;
index = 'h80000000 - 8 ;
while ( ! $feof ( memFile ) ) begin
index + = 8 ;
readResult = $fread ( x64 , memFile ) ;
if ( x64 = = 0 ) continue ;
x32 [ 0 ] = x64 & 'hffffffff ;
x32 [ 1 ] = x64 > > 32 ;
rvviRefMemoryWrite ( 0 , index + 0 , x32 [ 0 ] , 4 ) ;
rvviRefMemoryWrite ( 0 , index + 4 , x32 [ 1 ] , 4 ) ;
//$display("ram %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]);
end
$fclose ( memFile ) ;
2024-09-29 17:18:04 +00:00
2024-05-17 22:34:29 +00:00
$display ( " RVVI Loading Complete " ) ;
2024-09-29 17:18:04 +00:00
2024-05-17 22:34:29 +00:00
void ' ( rvviRefPcSet ( 0 , P . RESET_VECTOR ) ) ; // set BOOTROM address
2024-02-07 21:38:18 +00:00
end
// Volatile CSRs
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hC00 ) ) ; // CYCLE
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hB00 ) ) ; // MCYCLE
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hC02 ) ) ; // INSTRET
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hB02 ) ) ; // MINSTRET
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hC01 ) ) ; // TIME
2024-08-29 17:44:37 +00:00
if ( P . XLEN = = 32 ) begin
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hC80 ) ) ; // CYCLEH
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hB80 ) ) ; // MCYCLEH
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hC82 ) ) ; // INSTRETH
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hB82 ) ) ; // MINSTRETH
2024-09-29 17:18:04 +00:00
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hC81 ) ) ; // TIMEH
2024-08-29 17:44:37 +00:00
end
2024-02-07 21:38:18 +00:00
// User HPMCOUNTER3 - HPMCOUNTER31
for ( iter = 'hC03 ; iter < = 'hC1F ; iter + + ) begin
void ' ( rvviRefCsrSetVolatile ( 0 , iter ) ) ; // HPMCOUNTERx
2024-09-29 17:18:04 +00:00
if ( P . XLEN = = 32 )
2024-08-29 17:44:37 +00:00
void ' ( rvviRefCsrSetVolatile ( 0 , iter + 128 ) ) ; // HPMCOUNTERxH
2024-09-29 17:18:04 +00:00
end
2024-02-07 21:38:18 +00:00
// Machine MHPMCOUNTER3 - MHPMCOUNTER31
for ( iter = 'hB03 ; iter < = 'hB1F ; iter + + ) begin
void ' ( rvviRefCsrSetVolatile ( 0 , iter ) ) ; // MHPMCOUNTERx
2024-09-29 17:18:04 +00:00
if ( P . XLEN = = 32 )
2024-08-29 17:44:37 +00:00
void ' ( rvviRefCsrSetVolatile ( 0 , iter + 128 ) ) ; // MHPMCOUNTERxH
2024-09-29 17:18:04 +00:00
end
2024-02-07 21:38:18 +00:00
// cannot predict this register due to latency between
// pending and taken
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'h344 ) ) ; // MIP
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'h144 ) ) ; // SIP
// Privileges for PMA are set in the imperas.ic
// volatile (IO) regions are defined here
// only real ROM/RAM areas are BOOTROM and UNCORE_RAM
if ( P . CLINT_SUPPORTED ) begin
void ' ( rvviRefMemorySetVolatile ( P . CLINT_BASE , ( P . CLINT_BASE + P . CLINT_RANGE ) ) ) ;
end
if ( P . GPIO_SUPPORTED ) begin
void ' ( rvviRefMemorySetVolatile ( P . GPIO_BASE , ( P . GPIO_BASE + P . GPIO_RANGE ) ) ) ;
end
if ( P . UART_SUPPORTED ) begin
void ' ( rvviRefMemorySetVolatile ( P . UART_BASE , ( P . UART_BASE + P . UART_RANGE ) ) ) ;
end
if ( P . PLIC_SUPPORTED ) begin
void ' ( rvviRefMemorySetVolatile ( P . PLIC_BASE , ( P . PLIC_BASE + P . PLIC_RANGE ) ) ) ;
end
if ( P . SDC_SUPPORTED ) begin
void ' ( rvviRefMemorySetVolatile ( P . SDC_BASE , ( P . SDC_BASE + P . SDC_RANGE ) ) ) ;
end
if ( P . SPI_SUPPORTED ) begin
void ' ( rvviRefMemorySetVolatile ( P . SPI_BASE , ( P . SPI_BASE + P . SPI_RANGE ) ) ) ;
end
if ( P . XLEN = = 32 ) begin
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hC80 ) ) ; // CYCLEH
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hB80 ) ) ; // MCYCLEH
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hC82 ) ) ; // INSTRETH
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'hB82 ) ) ; // MINSTRETH
end
void ' ( rvviRefCsrSetVolatile ( 0 , 32 'h104 ) ) ; // SIE - Temporary!!!!
2024-09-29 17:18:04 +00:00
2024-02-05 19:19:48 +00:00
end
2024-11-27 06:09:11 +00:00
if ( P . ZICSR_SUPPORTED ) begin
always @ ( dut . core . priv . priv . csr . csri . MIP_REGW [ 7 ] ) void ' ( rvvi . net_push ( " MTimerInterrupt " , dut . core . priv . priv . csr . csri . MIP_REGW [ 7 ] ) ) ;
always @ ( dut . core . priv . priv . csr . csri . MIP_REGW [ 11 ] ) void ' ( rvvi . net_push ( " MExternalInterrupt " , dut . core . priv . priv . csr . csri . MIP_REGW [ 11 ] ) ) ;
always @ ( dut . core . priv . priv . csr . csri . MIP_REGW [ 9 ] ) void ' ( rvvi . net_push ( " SExternalInterrupt " , dut . core . priv . priv . csr . csri . MIP_REGW [ 9 ] ) ) ;
always @ ( dut . core . priv . priv . csr . csri . MIP_REGW [ 3 ] ) void ' ( rvvi . net_push ( " MSWInterrupt " , dut . core . priv . priv . csr . csri . MIP_REGW [ 3 ] ) ) ;
always @ ( dut . core . priv . priv . csr . csri . MIP_REGW [ 1 ] ) void ' ( rvvi . net_push ( " SSWInterrupt " , dut . core . priv . priv . csr . csri . MIP_REGW [ 1 ] ) ) ;
always @ ( dut . core . priv . priv . csr . csri . MIP_REGW [ 5 ] ) void ' ( rvvi . net_push ( " STimerInterrupt " , dut . core . priv . priv . csr . csri . MIP_REGW [ 5 ] ) ) ;
end
2024-02-07 21:38:18 +00:00
final begin
void ' ( rvviRefShutdown ( ) ) ;
end
`endif
////////////////////////////////////////////////////////////////////////////////
// END of ImperasDV Co-simulator hooks
////////////////////////////////////////////////////////////////////////////////
2023-06-14 22:02:49 +00:00
task automatic CheckSignature ;
// This task must be declared inside this module as it needs access to parameter P. There is
// no way to pass P to the task unless we convert it to a module.
2024-09-29 17:18:04 +00:00
2023-06-14 22:02:49 +00:00
input string pathname ;
input string TestName ;
input logic riscofTest ;
input integer begin_signature_addr ;
output integer errors ;
2024-01-07 15:14:12 +00:00
int fd , code ;
string line ;
int siglines , sigentries ;
2023-06-14 22:02:49 +00:00
localparam SIGNATURESIZE = 5000000 ;
integer i ;
logic [ 31 : 0 ] sig32 [ 0 : SIGNATURESIZE ] ;
2024-01-07 17:00:19 +00:00
logic [ 31 : 0 ] parsed ;
2023-06-14 22:02:49 +00:00
logic [ P . XLEN - 1 : 0 ] signature [ 0 : SIGNATURESIZE ] ;
2023-07-07 21:34:08 +00:00
string signame ;
2023-06-14 22:02:49 +00:00
logic [ P . XLEN - 1 : 0 ] testadr , testadrNoBase ;
2024-04-03 14:23:02 +00:00
2024-09-29 17:18:04 +00:00
//$display("Invoking CheckSignature %s %s %0t", pathname, TestName, $time);
2024-01-07 15:14:12 +00:00
// read .signature.output file and compare to check for errors
2023-06-14 22:02:49 +00:00
if ( riscofTest ) signame = { pathname , TestName , " /ref/Reference-sail_c_simulator.signature " } ;
else signame = { pathname , TestName , " .signature.output " } ;
2024-01-07 15:14:12 +00:00
// read signature file from memory and count lines. Can't use readmemh because we need the line count
// $readmemh(signame, sig32);
fd = $fopen ( signame , " r " ) ;
siglines = 0 ;
if ( fd = = 0 ) $display ( " Unable to read %s " , signame ) ;
else begin
while ( ! $feof ( fd ) ) begin
code = $fgets ( line , fd ) ;
2024-01-07 17:00:19 +00:00
if ( code ! = 0 ) begin
2024-01-07 15:14:12 +00:00
int errno ;
string errstr ;
errno = $ferror ( fd , errstr ) ;
2024-01-07 17:00:19 +00:00
if ( errno ! = 0 ) $display ( " Error %d (code %d) reading line %d of %s: %s " , errno , code , siglines , signame , errstr ) ;
if ( line . len ( ) > 1 ) begin // skip blank lines
if ( $sscanf ( line , " %x " , parsed ) ! = 0 ) begin
sig32 [ siglines ] = parsed ;
siglines = siglines + 1 ; // increment if line is not blank
end
end
2024-01-07 15:14:12 +00:00
end
2023-04-14 02:06:09 +00:00
end
2024-01-07 15:14:12 +00:00
$fclose ( fd ) ;
2023-03-27 23:36:02 +00:00
end
2023-02-20 05:48:16 +00:00
2024-01-07 15:14:12 +00:00
// Check valid number of lines were read
2024-09-29 17:18:04 +00:00
if ( siglines = = 0 ) begin
errors = 1 ;
2024-01-07 15:14:12 +00:00
$display ( " Error: empty test file %s " , signame ) ;
end else if ( P . XLEN = = 64 & ( siglines % 2 ) ) begin
errors = 1 ;
$display ( " Error: RV64 signature has odd number of lines %s " , signame ) ;
end else errors = 0 ;
// copy lines into signature, converting to XLEN if necessary
sigentries = ( P . XLEN = = 32 ) ? siglines : siglines / 2 ; // number of signature entries
2024-01-07 17:00:19 +00:00
for ( i = 0 ; i < sigentries ; i + + ) begin
2024-01-07 15:14:12 +00:00
signature [ i ] = ( P . XLEN = = 32 ) ? sig32 [ i ] : { sig32 [ i * 2 + 1 ] , sig32 [ i * 2 ] } ;
2024-01-07 17:00:19 +00:00
//$display("XLEN = %d signature[%d] = %x", P.XLEN, i, signature[i]);
end
2024-01-07 15:14:12 +00:00
2023-06-14 22:02:49 +00:00
// Check errors
testadr = ( $unsigned ( begin_signature_addr ) ) / ( P . XLEN / 8 ) ;
testadrNoBase = ( begin_signature_addr - P . UNCORE_RAM_BASE ) / ( P . XLEN / 8 ) ;
2024-01-07 15:14:12 +00:00
for ( i = 0 ; i < sigentries ; i + + ) begin
2024-09-29 17:18:04 +00:00
if ( signature [ i ] ! = = testbench . DCacheFlushFSM . ShadowRAM [ testadr + i ] ) begin
2023-06-14 22:02:49 +00:00
errors = errors + 1 ;
2024-09-29 17:18:04 +00:00
$display ( " Error on test %s result %d: adr = %h sim (D$) %h signature = %h " ,
2024-04-12 23:06:10 +00:00
TestName , i , ( testadr + i ) * ( P . XLEN / 8 ) , testbench . DCacheFlushFSM . ShadowRAM [ testadr + i ] , signature [ i ] ) ;
2024-02-07 14:27:53 +00:00
$stop ; // if this is changed to $finish, wally-batch.do does not get to the next step to run coverage
2023-04-14 02:06:09 +00:00
end
2022-05-17 01:03:09 +00:00
end
2024-01-07 15:14:12 +00:00
if ( errors ) $display ( " %s failed with %d errors. :( " , TestName , errors ) ;
else $display ( " %s succeeded. Brilliant!!! " , TestName ) ;
endtask
2024-09-29 17:18:04 +00:00
2024-05-02 18:53:04 +00:00
`ifdef PMP_COVERAGE
test_pmp_coverage # ( P ) pmp_inst ( clk ) ;
`endif
2023-05-31 21:51:00 +00:00
/* verilator lint_on WIDTHTRUNC */
/* verilator lint_on WIDTHEXPAND */
2021-10-10 22:07:51 +00:00
endmodule
/* verilator lint_on STMTDLY */
/* verilator lint_on WIDTH */
2022-06-17 22:07:16 +00:00
task automatic updateProgramAddrLabelArray ;
2023-05-31 21:51:00 +00:00
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off WIDTHEXPAND */
2024-07-03 23:52:16 +00:00
input string ProgramAddrMapFile , ProgramLabelMapFile , memfilename , WALLY_DIR ;
2022-06-17 22:07:16 +00:00
inout integer ProgramAddrLabelArray [ string ] ;
// Gets the memory location of begin_signature
integer ProgramLabelMapFP , ProgramAddrMapFP ;
2024-07-03 23:52:16 +00:00
string cmd ;
// if memfile, label, or addr files are out of date or don't exist, generate them
2024-07-04 14:36:56 +00:00
cmd = { " make -s -f " , WALLY_DIR , " /testbench/Makefile " , memfilename , " " , ProgramAddrMapFile } ;
2024-07-03 23:52:16 +00:00
$system ( cmd ) ;
2023-12-20 20:55:37 +00:00
2022-06-17 22:07:16 +00:00
ProgramLabelMapFP = $fopen ( ProgramLabelMapFile , " r " ) ;
ProgramAddrMapFP = $fopen ( ProgramAddrMapFile , " r " ) ;
2023-06-13 20:09:40 +00:00
2022-06-17 22:07:16 +00:00
if ( ProgramLabelMapFP & ProgramAddrMapFP ) begin // check we found both files
2023-06-13 20:09:40 +00:00
ProgramAddrLabelArray [ " begin_signature " ] = 0 ;
ProgramAddrLabelArray [ " tohost " ] = 0 ;
2023-12-20 20:55:37 +00:00
ProgramAddrLabelArray [ " sig_end_canary " ] = 0 ;
2022-06-17 22:07:16 +00:00
while ( ! $feof ( ProgramLabelMapFP ) ) begin
string label , adrstr ;
integer returncode ;
returncode = $fscanf ( ProgramLabelMapFP , " %s \n " , label ) ;
returncode = $fscanf ( ProgramAddrMapFP , " %s \n " , adrstr ) ;
2023-04-14 02:06:09 +00:00
if ( ProgramAddrLabelArray . exists ( label ) ) ProgramAddrLabelArray [ label ] = adrstr . atohex ( ) ;
2022-06-17 22:07:16 +00:00
end
2024-09-29 17:18:04 +00:00
end
2023-12-20 20:55:37 +00:00
2024-01-19 05:36:52 +00:00
// if(ProgramAddrLabelArray["begin_signature"] == 0) $display("Couldn't find begin_signature in %s", ProgramLabelMapFile);
// if(ProgramAddrLabelArray["sig_end_canary"] == 0) $display("Couldn't find sig_end_canary in %s", ProgramLabelMapFile);
2023-12-20 20:55:37 +00:00
2022-06-17 22:07:16 +00:00
$fclose ( ProgramLabelMapFP ) ;
$fclose ( ProgramAddrMapFP ) ;
2023-05-31 21:51:00 +00:00
/* verilator lint_on WIDTHTRUNC */
/* verilator lint_on WIDTHEXPAND */
2022-07-17 21:20:04 +00:00
endtask
2023-01-12 16:09:34 +00:00