2021-06-07 16:37:46 +00:00
///////////////////////////////////////////
// testbench-linux.sv
//
// Written: nboorstin@g.hmc.edu 2021
// Modified:
//
// Purpose: Testbench for buildroot or busybear linux
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2021-09-27 07:03:11 +00:00
2022-01-05 16:41:17 +00:00
// When letting Wally go for it, let wally make own interrupts
2021-06-07 16:37:46 +00:00
///////////////////////////////////////////
`include " wally-config.vh "
2021-10-10 00:22:30 +00:00
`define DEBUG_TRACE 2
2021-09-27 07:03:11 +00:00
// Debug Levels
// 0: don't check against QEMU
// 1: print disagreements with QEMU, but only halt on PCW disagreements
// 2: halt on any disagreement with QEMU except CSRs
// 3: halt on all disagreements with QEMU
// 4: print memory accesses whenever they happen
// 5: print everything
2021-07-30 01:26:50 +00:00
2022-01-05 16:25:08 +00:00
module testbench ;
2021-10-25 17:04:30 +00:00
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// CONFIG ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
2021-10-25 19:25:32 +00:00
// Recommend setting all of these in do script using -G option
parameter INSTR_LIMIT = 0 ; // # of instructions at which to stop
parameter INSTR_WAVEON = 0 ; // # of instructions at which to turn on waves in graphical sim
parameter CHECKPOINT = 0 ;
2021-08-24 16:08:46 +00:00
2021-06-24 05:42:35 +00:00
///////////////////////////////////////////////////////////////////////////////
2021-10-25 17:04:30 +00:00
////////////////////////////////// HARDWARE ///////////////////////////////////
2021-06-24 05:42:35 +00:00
///////////////////////////////////////////////////////////////////////////////
2021-12-07 21:12:06 +00:00
logic clk , reset_ext ;
2021-12-29 21:03:34 +00:00
logic reset ;
2021-10-25 20:26:44 +00:00
initial begin reset_ext < = 1 ; # 22 ; reset_ext < = 0 ; end
2021-10-25 17:04:30 +00:00
always begin clk < = 1 ; # 5 ; clk < = 0 ; # 5 ; end
logic [ `AHBW - 1 : 0 ] HRDATAEXT ;
logic HREADYEXT , HRESPEXT ;
logic HCLK , HRESETn ;
2021-12-03 00:09:43 +00:00
logic HREADY ;
logic HSELEXT ;
2021-06-07 16:37:46 +00:00
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 ;
2021-06-24 05:42:35 +00:00
logic [ 31 : 0 ] GPIOPinsIn ;
logic [ 31 : 0 ] GPIOPinsOut , GPIOPinsEn ;
logic UARTSin , UARTSout ;
2021-09-24 17:31:51 +00:00
logic SDCCLK ;
2021-12-03 00:09:43 +00:00
logic SDCCmdIn ;
logic SDCCmdOut ;
logic SDCCmdOE ;
logic [ 3 : 0 ] SDCDatIn ;
2021-09-24 17:31:51 +00:00
2021-06-07 16:37:46 +00:00
assign GPIOPinsIn = 0 ;
assign UARTSin = 1 ;
2021-12-29 21:03:34 +00:00
wallypipelinedsoc dut ( . clk , . reset , . reset_ext ,
2021-12-03 00:09:43 +00:00
. HRDATAEXT , . HREADYEXT , . HREADY , . HSELEXT , . HRESPEXT , . HCLK ,
. HRESETn , . HADDR , . HWDATA , . HWRITE , . HSIZE , . HBURST , . HPROT ,
. HTRANS , . HMASTLOCK ,
2022-01-02 21:18:16 +00:00
. TIMECLK ( 0 ) , . GPIOPinsIn , . GPIOPinsOut , . GPIOPinsEn ,
2021-12-03 00:09:43 +00:00
. UARTSin , . UARTSout ,
. SDCCLK , . SDCCmdIn , . SDCCmdOut , . SDCCmdOE , . SDCDatIn ) ;
2021-06-07 16:37:46 +00:00
2021-12-07 21:12:06 +00:00
2021-10-25 19:25:32 +00:00
// Write Back stage signals not needed by Wally itself
parameter nop = 'h13 ;
2021-10-25 17:04:30 +00:00
logic [ `XLEN - 1 : 0 ] PCW ;
logic [ 31 : 0 ] InstrW ;
logic InstrValidW ;
2021-12-20 00:24:40 +00:00
logic [ `XLEN - 1 : 0 ] IEUAdrW , WriteDataW ;
2021-10-25 17:04:30 +00:00
logic TrapW ;
2022-01-20 16:02:08 +00:00
`define FLUSHW dut.core.FlushW
`define STALLW dut.core.StallW
flopenrc # ( `XLEN ) PCWReg ( clk , reset , `FLUSHW , ~ `STALLW , dut . core . ifu . PCM , PCW ) ;
flopenr # ( 32 ) InstrWReg ( clk , reset , ~ `STALLW , `FLUSHW ? nop : dut . core . ifu . InstrM , InstrW ) ;
flopenrc # ( 1 ) controlregW ( clk , reset , `FLUSHW , ~ `STALLW , dut . core . ieu . c . InstrValidM , InstrValidW ) ;
flopenrc # ( `XLEN ) IEUAdrWReg ( clk , reset , `FLUSHW , ~ `STALLW , dut . core . IEUAdrM , IEUAdrW ) ;
flopenrc # ( `XLEN ) WriteDataWReg ( clk , reset , `FLUSHW , ~ `STALLW , dut . core . WriteDataM , WriteDataW ) ;
flopenr # ( 1 ) TrapWReg ( clk , reset , ~ `STALLW , dut . core . hzu . TrapM , TrapW ) ;
2021-06-07 16:37:46 +00:00
2021-06-24 05:42:35 +00:00
///////////////////////////////////////////////////////////////////////////////
2021-10-25 17:04:30 +00:00
//////////////////////// Signals & Macro DECLARATIONS /////////////////////////
2021-06-24 05:42:35 +00:00
///////////////////////////////////////////////////////////////////////////////
// Testbench Core
integer warningCount = 0 ;
2021-09-04 23:49:26 +00:00
integer errorCount = 0 ;
2021-10-25 17:04:30 +00:00
integer fault ;
string ProgramAddrMapFile , ProgramLabelMapFile ;
2021-10-25 19:25:32 +00:00
// Checkpointing
string checkpointDir ;
logic [ 1 : 0 ] initPriv ;
2021-10-25 17:04:30 +00:00
// Signals used to parse the trace file
2021-11-03 04:19:12 +00:00
`define DECLARE_TRACE_SCANNER_SIGNALS(STAGE) \
integer traceFile ` `STAGE ; \
integer matchCount ` `STAGE ; \
string line ` `STAGE ; \
string token ` `STAGE ; \
string ExpectedTokens ` `STAGE [ 31 : 0 ] ; \
integer index ` `STAGE ; \
integer StartIndex ` `STAGE , EndIndex ` `STAGE ; \
integer TokenIndex ` `STAGE ; \
integer MarkerIndex ` `STAGE ; \
integer NumCSR ` `STAGE ; \
logic [ `XLEN - 1 : 0 ] ExpectedPC ` `STAGE ; \
logic [ 31 : 0 ] ExpectedInstr ` `STAGE ; \
string text ` `STAGE ; \
string MemOp ` `STAGE ; \
string RegWrite ` `STAGE ; \
integer ExpectedRegAdr ` `STAGE ; \
logic [ `XLEN - 1 : 0 ] ExpectedRegValue ` `STAGE ; \
2021-12-20 00:24:40 +00:00
logic [ `XLEN - 1 : 0 ] ExpectedIEUAdr ` `STAGE , ExpectedMemReadData ` `STAGE , ExpectedMemWriteData ` `STAGE ; \
2021-11-03 04:19:12 +00:00
string ExpectedCSRArray ` `STAGE [ 10 : 0 ] ; \
logic [ `XLEN - 1 : 0 ] ExpectedCSRArrayValue ` `STAGE [ 10 : 0 ] ;
`DECLARE_TRACE_SCANNER_SIGNALS ( E )
`DECLARE_TRACE_SCANNER_SIGNALS ( M )
integer NextMIPexpected ;
integer NextMepcExpected ;
2021-08-06 21:06:50 +00:00
// Memory stage expected values from trace
2021-10-25 17:04:30 +00:00
logic checkInstrM ;
integer MIPexpected ;
2021-11-03 04:19:12 +00:00
string name ;
2021-10-25 17:04:30 +00:00
logic [ `AHBW - 1 : 0 ] readDataExpected ;
2021-08-06 21:06:50 +00:00
// Write back stage expected values from trace
2021-10-25 17:04:30 +00:00
logic checkInstrW ;
2021-08-06 21:06:50 +00:00
logic [ `XLEN - 1 : 0 ] ExpectedPCW ;
2021-09-04 23:49:26 +00:00
logic [ 31 : 0 ] ExpectedInstrW ;
string textW ;
string RegWriteW ;
integer ExpectedRegAdrW ;
2021-08-06 21:06:50 +00:00
logic [ `XLEN - 1 : 0 ] ExpectedRegValueW ;
2021-09-04 23:49:26 +00:00
string MemOpW ;
2021-12-20 00:24:40 +00:00
logic [ `XLEN - 1 : 0 ] ExpectedIEUAdrW , ExpectedMemReadDataW , ExpectedMemWriteDataW ;
2021-09-04 23:49:26 +00:00
integer NumCSRW ;
string ExpectedCSRArrayW [ 10 : 0 ] ;
2021-08-15 16:13:32 +00:00
logic [ `XLEN - 1 : 0 ] ExpectedCSRArrayValueW [ 10 : 0 ] ;
2021-08-13 19:39:05 +00:00
logic [ `XLEN - 1 : 0 ] ExpectedIntType ;
2021-09-07 19:36:47 +00:00
logic forcedInterrupt ;
2021-09-04 23:49:26 +00:00
integer NumCSRMIndex ;
integer NumCSRWIndex ;
2021-09-22 16:33:11 +00:00
integer NumCSRPostWIndex ;
2021-08-23 17:24:03 +00:00
logic [ `XLEN - 1 : 0 ] InstrCountW ;
2021-10-04 22:23:31 +00:00
integer RequestDelayedMIP ;
2021-11-03 04:19:12 +00:00
integer ForceMIPFuture ;
integer CSRIndex ;
longint MepcExpected ;
integer CheckMIPFutureE ;
integer CheckMIPFutureM ;
2021-10-25 17:04:30 +00:00
// Useful Aliases
2022-01-20 16:02:08 +00:00
`define RF dut.core.ieu.dp.regf.rf
`define PC dut.core.ifu.pcreg.q
`define CSR_BASE dut.core.priv.priv.csr
2021-12-30 20:55:48 +00:00
`define HPMCOUNTER `CSR_BASE.counters.counters.HPMCOUNTER_REGW
2021-12-30 03:01:21 +00:00
`define PMP_BASE `CSR_BASE.csrm.pmp
2021-10-25 17:04:30 +00:00
`define PMPCFG genblk2.PMPCFGreg.q
`define PMPADDR PMPADDRreg.q
2021-12-30 03:01:21 +00:00
`define MEDELEG `CSR_BASE.csrm.deleg.MEDELEGreg.q
`define MIDELEG `CSR_BASE.csrm.deleg.MIDELEGreg.q
2021-10-25 17:04:30 +00:00
`define MIE `CSR_BASE.csri.MIE_REGW
`define MIP `CSR_BASE.csri.MIP_REGW
`define MCAUSE `CSR_BASE.csrm.MCAUSEreg.q
2021-12-30 20:55:48 +00:00
`define SCAUSE `CSR_BASE.csrs.csrs.SCAUSEreg.q
2021-10-25 17:04:30 +00:00
`define MEPC `CSR_BASE.csrm.MEPCreg.q
2021-12-30 20:55:48 +00:00
`define SEPC `CSR_BASE.csrs.csrs.SEPCreg.q
2021-12-30 03:01:21 +00:00
`define MCOUNTEREN `CSR_BASE.csrm.counters.MCOUNTERENreg.q
2021-12-30 20:55:48 +00:00
`define SCOUNTEREN `CSR_BASE.csrs.csrs.scounteren.SCOUNTERENreg.q
2021-10-25 17:04:30 +00:00
`define MSCRATCH `CSR_BASE.csrm.MSCRATCHreg.q
2021-12-30 20:55:48 +00:00
`define SSCRATCH `CSR_BASE.csrs.csrs.SSCRATCHreg.q
2021-10-25 17:04:30 +00:00
`define MTVEC `CSR_BASE.csrm.MTVECreg.q
2021-12-30 20:55:48 +00:00
`define STVEC `CSR_BASE.csrs.csrs.STVECreg.q
`define SATP `CSR_BASE.csrs.csrs.genblk1.SATPreg.q
2021-10-25 17:04:30 +00:00
`define MSTATUS `CSR_BASE.csrsr.MSTATUS_REGW
`define STATUS_TSR `CSR_BASE.csrsr.STATUS_TSR_INT
`define STATUS_TW `CSR_BASE.csrsr.STATUS_TW_INT
`define STATUS_TVM `CSR_BASE.csrsr.STATUS_TVM_INT
`define STATUS_MXR `CSR_BASE.csrsr.STATUS_MXR_INT
`define STATUS_SUM `CSR_BASE.csrsr.STATUS_SUM_INT
`define STATUS_MPRV `CSR_BASE.csrsr.STATUS_MPRV_INT
`define STATUS_FS `CSR_BASE.csrsr.STATUS_FS_INT
`define STATUS_MPP `CSR_BASE.csrsr.STATUS_MPP
`define STATUS_SPP `CSR_BASE.csrsr.STATUS_SPP
`define STATUS_MPIE `CSR_BASE.csrsr.STATUS_MPIE
`define STATUS_SPIE `CSR_BASE.csrsr.STATUS_SPIE
`define STATUS_UPIE `CSR_BASE.csrsr.STATUS_UPIE
`define STATUS_MIE `CSR_BASE.csrsr.STATUS_MIE
`define STATUS_SIE `CSR_BASE.csrsr.STATUS_SIE
`define STATUS_UIE `CSR_BASE.csrsr.STATUS_UIE
2022-01-20 16:02:08 +00:00
`define PRIV dut.core.priv.priv.privmodereg.q
`define INSTRET dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]
2021-10-25 17:04:30 +00:00
// Common Macros
`define checkCSR(CSR) \
2021-09-22 16:33:11 +00:00
begin \
if ( CSR ! = ExpectedCSRArrayValueW [ NumCSRPostWIndex ] ) begin \
$display ( " %tns, %d instrs: CSR %s = %016x, does not equal expected value %016x " , $time , InstrCountW , ExpectedCSRArrayW [ NumCSRPostWIndex ] , CSR , ExpectedCSRArrayValueW [ NumCSRPostWIndex ] ) ; \
2021-09-27 07:03:11 +00:00
if ( `DEBUG_TRACE > = 3 ) fault = 1 ; \
2021-09-22 16:33:11 +00:00
end \
end
2021-09-27 07:03:11 +00:00
`define checkEQ(NAME, VAL, EXPECTED) \
if ( VAL ! = EXPECTED ) begin \
$display ( " %tns, %d instrs: %s %x differs from expected %x " , $time , InstrCountW , NAME , VAL , EXPECTED ) ; \
2022-01-02 21:47:21 +00:00
if ( ( NAME = = " PCW " ) | ( `DEBUG_TRACE > = 2 ) ) fault = 1 ; \
2021-09-27 07:03:11 +00:00
end
2021-09-22 16:33:11 +00:00
2021-10-25 17:04:30 +00:00
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////// INITIALIZATION ////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
2021-10-25 19:25:32 +00:00
// Checkpoint initializations
`define MAKE_CHECKPOINT_INIT_SIGNAL(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \
logic DIM init ` `SIGNAL [ ARRAY_MAX: ARRAY_MIN ] ; \
initial begin \
# 1 ; \
if ( CHECKPOINT ! = 0 ) $readmemh ( { checkpointDir , " checkpoint- " , ` " SIGNAL` " } , init ` `SIGNAL ) ; \
end
`define INIT_CHECKPOINT_SIMPLE_ARRAY(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \
`MAKE_CHECKPOINT_INIT_SIGNAL ( SIGNAL , DIM , ARRAY_MAX , ARRAY_MIN ) \
initial begin \
if ( CHECKPOINT ! = 0 ) begin \
force `SIGNAL = init ` `SIGNAL [ ARRAY_MAX: ARRAY_MIN ] ; \
2021-10-25 20:26:44 +00:00
while ( reset ! = = 1 ) # 1 ; \
while ( reset ! = = 0 ) # 1 ; \
# 1 ; \
2021-10-25 19:25:32 +00:00
release `SIGNAL ; \
end \
end
// For the annoying case where the pathname to the array elements includes
// a "genblk<i>" in the signal name
`define INIT_CHECKPOINT_GENBLK_ARRAY(SIGNAL_BASE,SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \
`MAKE_CHECKPOINT_INIT_SIGNAL ( SIGNAL , DIM , ARRAY_MAX , ARRAY_MIN ) \
for ( i = ARRAY_MIN ; i < ARRAY_MAX + 1 ; i = i + 1 ) begin \
initial begin \
if ( CHECKPOINT ! = 0 ) begin \
force `SIGNAL_BASE [ i ] . `SIGNAL = init ` `SIGNAL [ i ] ; \
2021-10-25 20:26:44 +00:00
while ( reset ! = = 1 ) # 1 ; \
while ( reset ! = = 0 ) # 1 ; \
# 1 ; \
2021-10-25 19:25:32 +00:00
release `SIGNAL_BASE [ i ] . `SIGNAL ; \
end \
end \
end
// Note that dimension usage is very intentional here.
// We are dancing around (un)packed type requirements.
`define INIT_CHECKPOINT_VAL(SIGNAL,DIM) \
`MAKE_CHECKPOINT_INIT_SIGNAL ( SIGNAL , DIM , 0 , 0 ) \
initial begin \
if ( CHECKPOINT ! = 0 ) begin \
force `SIGNAL = init ` `SIGNAL [ 0 ] ; \
2021-10-25 20:26:44 +00:00
while ( reset ! = = 1 ) # 1 ; \
while ( reset ! = = 0 ) # 1 ; \
# 1 ; \
2021-10-25 19:25:32 +00:00
release `SIGNAL ; \
end \
end
`INIT_CHECKPOINT_SIMPLE_ARRAY ( RF , [ `XLEN - 1 : 0 ] , 31 , 1 ) ;
2022-01-06 04:19:36 +00:00
`INIT_CHECKPOINT_SIMPLE_ARRAY ( HPMCOUNTER , [ `XLEN - 1 : 0 ] , `COUNTERS - 1 , 0 ) ;
2021-10-25 19:25:32 +00:00
`INIT_CHECKPOINT_VAL ( PC , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( MEDELEG , [ `XLEN - 1 : 0 ] ) ;
2021-11-06 10:44:23 +00:00
`INIT_CHECKPOINT_VAL ( MIDELEG , [ `XLEN - 1 : 0 ] ) ;
2021-10-25 19:25:32 +00:00
`INIT_CHECKPOINT_VAL ( MIE , [ 11 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( MIP , [ 11 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( MCAUSE , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( SCAUSE , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( MEPC , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( SEPC , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( MCOUNTEREN , [ 31 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( SCOUNTEREN , [ 31 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( MSCRATCH , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( SSCRATCH , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( MTVEC , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( STVEC , [ `XLEN - 1 : 0 ] ) ;
`INIT_CHECKPOINT_VAL ( SATP , [ `XLEN - 1 : 0 ] ) ;
2021-11-15 22:49:00 +00:00
`INIT_CHECKPOINT_VAL ( PRIV , [ 1 : 0 ] ) ;
2021-10-25 19:25:32 +00:00
`MAKE_CHECKPOINT_INIT_SIGNAL ( MSTATUS , [ `XLEN - 1 : 0 ] , 0 , 0 ) ;
2021-11-06 05:37:05 +00:00
integer ramFile ;
integer readResult ;
2021-07-30 01:26:50 +00:00
initial begin
2022-01-20 16:02:08 +00:00
force dut . core . priv . priv . SwIntM = 0 ;
force dut . core . priv . priv . TimerIntM = 0 ;
force dut . core . priv . priv . ExtIntM = 0 ;
2021-12-14 21:43:06 +00:00
$readmemh ( { `LINUX_TEST_VECTORS , " bootmem.txt " } , dut . uncore . bootrom . bootrom . RAM , 'h1000 > > 3 ) ;
2022-01-20 16:02:08 +00:00
$readmemb ( `TWO_BIT_PRELOAD , dut . core . ifu . bpred . bpred . Predictor . DirPredictor . PHT . mem ) ;
$readmemb ( `BTB_PRELOAD , dut . core . ifu . bpred . bpred . TargetPredictor . memory . mem ) ;
2021-10-25 17:04:30 +00:00
ProgramAddrMapFile = { `LINUX_TEST_VECTORS , " vmlinux.objdump.addr " } ;
ProgramLabelMapFile = { `LINUX_TEST_VECTORS , " vmlinux.objdump.lab " } ;
2021-10-25 19:25:32 +00:00
if ( CHECKPOINT = = 0 ) begin // normal
2021-12-14 21:43:06 +00:00
$readmemh ( { `LINUX_TEST_VECTORS , " ram.txt " } , dut . uncore . ram . ram . RAM ) ;
2021-11-03 04:19:12 +00:00
traceFileM = $fopen ( { `LINUX_TEST_VECTORS , " all.txt " } , " r " ) ;
traceFileE = $fopen ( { `LINUX_TEST_VECTORS , " all.txt " } , " r " ) ;
2021-10-24 13:47:35 +00:00
InstrCountW = '0 ;
2021-10-25 19:25:32 +00:00
end else begin // checkpoint
$sformat ( checkpointDir , " checkpoint%0d/ " , CHECKPOINT ) ;
checkpointDir = { `LINUX_TEST_VECTORS , checkpointDir } ;
2021-12-14 21:43:06 +00:00
//$readmemh({checkpointDir,"ram.txt"}, dut.uncore.ram.ram.RAM);
2021-11-06 05:37:05 +00:00
ramFile = $fopen ( { checkpointDir , " ram.bin " } , " rb " ) ;
2021-12-14 21:43:06 +00:00
readResult = $fread ( dut . uncore . ram . ram . RAM , ramFile ) ;
2021-11-06 05:37:05 +00:00
$fclose ( ramFile ) ;
2021-11-03 04:19:12 +00:00
traceFileE = $fopen ( { checkpointDir , " all.txt " } , " r " ) ;
traceFileM = $fopen ( { checkpointDir , " all.txt " } , " r " ) ;
2021-10-25 19:25:32 +00:00
InstrCountW = CHECKPOINT ;
// manual checkpoint initializations that don't neatly fit into MACRO
force { `STATUS_TSR , `STATUS_TW , `STATUS_TVM , `STATUS_MXR , `STATUS_SUM , `STATUS_MPRV } = initMSTATUS [ 0 ] [ 22 : 17 ] ;
force { `STATUS_FS , `STATUS_MPP } = initMSTATUS [ 0 ] [ 14 : 11 ] ;
force { `STATUS_SPP , `STATUS_MPIE } = initMSTATUS [ 0 ] [ 8 : 7 ] ;
force { `STATUS_SPIE , `STATUS_UPIE , `STATUS_MIE } = initMSTATUS [ 0 ] [ 5 : 3 ] ;
force { `STATUS_SIE , `STATUS_UIE } = initMSTATUS [ 0 ] [ 1 : 0 ] ;
force `INSTRET = CHECKPOINT ;
2021-10-25 20:26:44 +00:00
while ( reset ! = = 1 ) # 1 ;
while ( reset ! = = 0 ) # 1 ;
# 1 ;
2021-10-25 19:25:32 +00:00
release { `STATUS_TSR , `STATUS_TW , `STATUS_TVM , `STATUS_MXR , `STATUS_SUM , `STATUS_MPRV } ;
release { `STATUS_FS , `STATUS_MPP } ;
release { `STATUS_SPP , `STATUS_MPIE } ;
release { `STATUS_SPIE , `STATUS_UPIE , `STATUS_MIE } ;
release { `STATUS_SIE , `STATUS_UIE } ;
release `INSTRET ;
end
2021-11-03 04:19:12 +00:00
// Get the E-stage trace reader ahead of the M-stage trace reader
matchCountE = $fgets ( lineE , traceFileE ) ;
2021-07-30 01:26:50 +00:00
end
2021-08-15 16:13:32 +00:00
2021-07-30 01:26:50 +00:00
2021-10-25 17:04:30 +00:00
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// CORE /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
2021-09-04 23:49:26 +00:00
// Because qemu does not match exactly to wally it is necessary to read the the
2021-08-06 21:06:50 +00:00
// trace in the memory stage and detect if anything in wally must be overwritten.
// This includes mtimer, interrupts, and various bits in mstatus and xtval.
// then on the next posedge the expected state is registered.
// on the next falling edge the expected state is compared to the wally state.
// step 0: read the expected state
2022-01-20 16:02:08 +00:00
assign checkInstrM = dut . core . ieu . InstrValidM & ~ dut . core . priv . priv . trap . InstrPageFaultM & ~ dut . core . priv . priv . trap . InterruptM & ~ dut . core . StallM ;
2021-11-03 04:19:12 +00:00
`define SCAN_NEW_INSTR_FROM_TRACE(STAGE) \
/ / always check PC , instruction bits \
if ( checkInstrM ) begin \
/ / read 1 line of the trace file \
matchCount ` `STAGE = $fgets ( line ` `STAGE , traceFile ` `STAGE ) ; \
if ( `DEBUG_TRACE > = 5 ) $display ( " Time %t, line %x " , $time , line ` `STAGE ) ; \
/ / extract PC , Instr \
matchCount ` `STAGE = $sscanf ( line ` `STAGE , " %x %x %s " , ExpectedPC ` `STAGE , ExpectedInstr ` `STAGE , text ` `STAGE ) ; \
\
/ / for the life of me I cannot get any build in C or C + + string parsing functions / methods to work . \
/ / strtok was the best idea but it cannot be used correctly as system verilog does not have null \
/ / terminated strings . \
\
/ / Just going to do this char by char . \
StartIndex ` `STAGE = 0 ; \
TokenIndex ` `STAGE = 0 ; \
/ / $display ( " len = %d " , line ` `STAGE . len ( ) ) ; \
for ( index ` `STAGE = 0 ; index ` `STAGE < line ` `STAGE . len ( ) ; index ` `STAGE + + ) begin \
/ / $display ( " char = %s " , line ` `STAGE [ index ] ) ; \
if ( line ` `STAGE [ index ` `STAGE ] = = " " | | line ` `STAGE [ index ` `STAGE ] = = " \n " ) begin \
EndIndex ` `STAGE = index ` `STAGE ; \
ExpectedTokens ` `STAGE [ TokenIndex ` `STAGE ] = line ` `STAGE . substr ( StartIndex ` `STAGE , EndIndex ` `STAGE - 1 ) ; \
/ / $display ( " In Tokenizer %s " , line ` `STAGE . substr ( StartIndex , EndIndex - 1 ) ) ; \
StartIndex ` `STAGE = EndIndex ` `STAGE + 1 ; \
TokenIndex ` `STAGE + + ; \
end \
end \
\
MarkerIndex ` `STAGE = 3 ; \
NumCSR ` `STAGE = 0 ; \
MemOp ` `STAGE = " " ; \
RegWrite ` `STAGE = " " ; \
\
# 2 ; \
\
while ( TokenIndex ` `STAGE > MarkerIndex ` `STAGE ) begin \
/ / parse the GPR \
if ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE ] = = " GPR " ) begin \
RegWrite ` `STAGE = ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE ] ; \
matchCount ` `STAGE = $sscanf ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE + 1 ] , " %d " , ExpectedRegAdr ` `STAGE ) ; \
matchCount ` `STAGE = $sscanf ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE + 2 ] , " %x " , ExpectedRegValue ` `STAGE ) ; \
MarkerIndex ` `STAGE + = 3 ; \
/ / parse memory address , read data , and / or write data \
end else if ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE ] . substr ( 0 , 2 ) = = " Mem " ) begin \
MemOp ` `STAGE = ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE ] ; \
2021-12-20 00:24:40 +00:00
matchCount ` `STAGE = $sscanf ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE + 1 ] , " %x " , ExpectedIEUAdr ` `STAGE ) ; \
2021-11-03 04:19:12 +00:00
matchCount ` `STAGE = $sscanf ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE + 2 ] , " %x " , ExpectedMemWriteData ` `STAGE ) ; \
matchCount ` `STAGE = $sscanf ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE + 3 ] , " %x " , ExpectedMemReadData ` `STAGE ) ; \
MarkerIndex ` `STAGE + = 4 ; \
/ / parse CSRs , because there are 1 or more CSRs after the CSR token \
/ / we check if the CSR token or the number of CSRs is greater than 0. \
/ / if so then we want to parse for a CSR . \
end else if ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE ] = = " CSR " | | NumCSR ` `STAGE > 0 ) begin \
if ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE ] = = " CSR " ) begin \
/ / all additional CSR ' s won ' t have this token . \
MarkerIndex ` `STAGE + + ; \
end \
matchCount ` `STAGE = $sscanf ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE ] , " %s " , ExpectedCSRArray ` `STAGE [ NumCSR ` `STAGE ] ) ; \
matchCount ` `STAGE = $sscanf ( ExpectedTokens ` `STAGE [ MarkerIndex ` `STAGE + 1 ] , " %x " , ExpectedCSRArrayValue ` `STAGE [ NumCSR ` `STAGE ] ) ; \
MarkerIndex ` `STAGE + = 2 ; \
if ( ` " STAGE` " = = " E " ) begin \
/ / match MIP to QEMU ' s because interrupts are imprecise \
if ( ExpectedCSRArrayE [ NumCSRE ] . substr ( 0 , 2 ) = = " mip " ) begin \
CheckMIPFutureE = 1 ; \
NextMIPexpected = ExpectedCSRArrayValueE [ NumCSRE ] ; \
end \
if ( ExpectedCSRArrayE [ NumCSRE ] . substr ( 0 , 3 ) = = " mepc " ) begin \
2021-12-03 20:32:38 +00:00
/ / $display ( " hello! we are here. " ) ; \
2021-11-03 04:19:12 +00:00
MepcExpected = ExpectedCSRArrayValueE [ NumCSRE ] ; \
$display ( " %tns: MepcExpected: %x " , $time , MepcExpected ) ; \
end \
end \
\
NumCSR ` `STAGE + + ; \
end \
end \
if ( ` " STAGE` " = = " M " ) begin \
/ / override on special conditions \
2022-01-20 16:02:08 +00:00
if ( dut . core . lsu . LSUPAdrM = = 'h10000005 ) \
2021-11-25 19:01:59 +00:00
/ / $display ( " %tns, %d instrs: Overwrite UART's LSR in memory stage. " , $time , InstrCountW - 1 ) ; \
2022-01-20 16:02:08 +00:00
force dut . core . ieu . dp . ReadDataM = ExpectedMemReadDataM ; \
2021-12-08 22:11:43 +00:00
else \
2022-01-20 16:02:08 +00:00
release dut . core . ieu . dp . ReadDataM ; \
2021-12-21 03:26:38 +00:00
if ( textM . substr ( 0 , 5 ) = = " rdtime " ) begin \
2021-12-08 22:11:43 +00:00
/ / $display ( " %tns, %d instrs: Overwrite MTIME_CLINT on read of MTIME in memory stage. " , $time , InstrCountW - 1 ) ; \
2021-11-03 04:19:12 +00:00
force dut . uncore . clint . clint . MTIME = ExpectedRegValueM ; \
end \
end \
end \
2021-07-30 01:26:50 +00:00
always @ ( negedge clk ) begin
2021-11-03 04:19:12 +00:00
`SCAN_NEW_INSTR_FROM_TRACE ( E )
end
2021-08-13 19:39:05 +00:00
2021-11-03 04:19:12 +00:00
always @ ( negedge clk ) begin
`SCAN_NEW_INSTR_FROM_TRACE ( M )
end
// MIP spoofing
always @ ( posedge clk ) begin
# 1 ;
if ( CheckMIPFutureE ) CheckMIPFutureE < = 0 ;
CheckMIPFutureM < = CheckMIPFutureE ;
if ( CheckMIPFutureM ) begin
2021-11-17 00:46:17 +00:00
// $display("%tns: ExpectedPCM %x",$time,ExpectedPCM);
// $display("%tns: ExpectedPCE %x",$time,ExpectedPCE);
// $display("%tns: ExpectedPCW %x",$time,ExpectedPCW);
2022-01-20 16:02:08 +00:00
if ( ( ExpectedPCE ! = MepcExpected ) & ( ( MepcExpected - ExpectedPCE ) * ( MepcExpected - ExpectedPCE ) < = 200 ) | | ~ dut . core . ieu . c . InstrValidM ) begin
2021-11-11 17:35:51 +00:00
RequestDelayedMIP < = 1 ;
2021-11-03 04:19:12 +00:00
$display ( " %tns: Requesting Delayed MIP. Current MEPC value is %x " , $time , MepcExpected ) ;
end else begin // update MIP immediately
$display ( " %tns: Updating MIP to %x " , $time , NextMIPexpected ) ;
MIPexpected = NextMIPexpected ;
2022-01-20 16:02:08 +00:00
force dut . core . priv . priv . csr . csri . MIP_REGW = MIPexpected ;
2021-08-13 19:39:05 +00:00
end
2021-11-17 00:46:17 +00:00
// $display("%tn: ExpectedCSRArrayM = %p",$time,ExpectedCSRArrayM);
// $display("%tn: ExpectedCSRArrayValueM = %p",$time,ExpectedCSRArrayValueM);
// $display("%tn: ExpectedTokens = %p",$time,ExpectedTokensM);
// $display("%tn: MepcExpected = %x",$time,MepcExpected);
// $display("%tn: ExpectedPCE = %x",$time,ExpectedPCE);
// $display("%tns: Difference/multiplication thing: %x",$time,(MepcExpected - ExpectedPCE) * (MepcExpected - ExpectedPCE));
// $display("%tn: ExpectedCSRArrayM[NumCSRM] %x",$time,ExpectedCSRArrayM[NumCSRM]);
// $display("%tn: ExpectedCSRArrayValueM[NumCSRM] %x",$time,ExpectedCSRArrayValueM[NumCSRM]);
2021-09-22 16:33:11 +00:00
end
2021-11-17 00:46:17 +00:00
if ( RequestDelayedMIP & checkInstrM ) begin
2022-01-20 16:02:08 +00:00
$display ( " %tns: Executing Delayed MIP. Current MEPC value is %x " , $time , dut . core . priv . priv . csr . csrm . MEPC_REGW ) ;
2021-11-03 04:19:12 +00:00
$display ( " %tns: Updating MIP to %x " , $time , NextMIPexpected ) ;
MIPexpected = NextMIPexpected ;
2022-01-20 16:02:08 +00:00
force dut . core . priv . priv . csr . csri . MIP_REGW = MIPexpected ;
$display ( " %tns: Finished Executing Delayed MIP. Current MEPC value is %x " , $time , dut . core . priv . priv . csr . csrm . MEPC_REGW ) ;
2021-11-03 04:19:12 +00:00
RequestDelayedMIP = 0 ;
2021-09-22 16:33:11 +00:00
end
2021-08-06 21:06:50 +00:00
end
// step 1: register expected state into the write back stage.
always @ ( posedge clk ) begin
2021-08-09 03:50:31 +00:00
if ( reset ) begin
2021-08-06 21:06:50 +00:00
ExpectedPCW < = '0 ;
ExpectedInstrW < = '0 ;
textW < = " " ;
RegWriteW < = " " ;
ExpectedRegAdrW < = '0 ;
ExpectedRegValueW < = '0 ;
2021-12-20 00:24:40 +00:00
ExpectedIEUAdrW < = '0 ;
2021-08-06 21:06:50 +00:00
MemOpW < = " " ;
ExpectedMemWriteDataW < = '0 ;
ExpectedMemReadDataW < = '0 ;
NumCSRW < = '0 ;
2022-01-20 16:02:08 +00:00
end else if ( ~ dut . core . StallW ) begin
if ( dut . core . FlushW ) begin
2021-09-07 02:59:54 +00:00
ExpectedPCW < = '0 ;
ExpectedInstrW < = '0 ;
textW < = " " ;
RegWriteW < = " " ;
ExpectedRegAdrW < = '0 ;
ExpectedRegValueW < = '0 ;
2021-12-20 00:24:40 +00:00
ExpectedIEUAdrW < = '0 ;
2021-09-07 02:59:54 +00:00
MemOpW < = " " ;
ExpectedMemWriteDataW < = '0 ;
ExpectedMemReadDataW < = '0 ;
NumCSRW < = '0 ;
2022-01-20 16:02:08 +00:00
end else if ( dut . core . ieu . c . InstrValidM ) begin
2021-09-07 02:59:54 +00:00
ExpectedPCW < = ExpectedPCM ;
ExpectedInstrW < = ExpectedInstrM ;
textW < = textM ;
RegWriteW < = RegWriteM ;
ExpectedRegAdrW < = ExpectedRegAdrM ;
ExpectedRegValueW < = ExpectedRegValueM ;
2021-12-20 00:24:40 +00:00
ExpectedIEUAdrW < = ExpectedIEUAdrM ;
2021-09-07 02:59:54 +00:00
MemOpW < = MemOpM ;
ExpectedMemWriteDataW < = ExpectedMemWriteDataM ;
ExpectedMemReadDataW < = ExpectedMemReadDataM ;
NumCSRW < = NumCSRM ;
for ( NumCSRWIndex = 0 ; NumCSRWIndex < NumCSRM ; NumCSRWIndex + + ) begin
ExpectedCSRArrayW [ NumCSRWIndex ] = ExpectedCSRArrayM [ NumCSRWIndex ] ;
ExpectedCSRArrayValueW [ NumCSRWIndex ] = ExpectedCSRArrayValueM [ NumCSRWIndex ] ;
end
2021-08-09 03:50:31 +00:00
end
2021-08-06 21:06:50 +00:00
# 1 ;
2021-09-22 16:33:11 +00:00
// override on special conditions
2022-01-20 16:02:08 +00:00
if ( ~ dut . core . StallW ) begin
2021-12-21 03:26:38 +00:00
if ( textW . substr ( 0 , 5 ) = = " rdtime " ) begin
2021-09-22 16:33:11 +00:00
//$display("%tns, %d instrs: Releasing force of MTIME_CLINT.", $time, InstrCountW);
2021-09-07 02:59:54 +00:00
release dut . uncore . clint . clint . MTIME ;
2021-09-22 16:33:11 +00:00
end
2021-12-20 00:24:40 +00:00
//if (ExpectedIEUAdrM == 'h10000005) begin
2021-09-07 02:59:54 +00:00
//$display("%tns, %d instrs: releasing force of ReadDataM.", $time, InstrCountW);
2022-01-20 16:02:08 +00:00
//release dut.core.ieu.dp.ReadDataM;
2021-12-08 22:11:43 +00:00
//end
2021-08-13 19:39:05 +00:00
end
2021-08-06 21:06:50 +00:00
end
end
// step2: make all checks in the write back stage.
2022-01-20 16:02:08 +00:00
assign checkInstrW = InstrValidW & ~ dut . core . StallW ; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
2021-08-06 21:06:50 +00:00
always @ ( negedge clk ) begin
// always check PC, instruction bits
if ( checkInstrW ) begin
2021-08-23 17:24:03 +00:00
InstrCountW + = 1 ;
2021-09-15 21:30:59 +00:00
// print progress message
if ( InstrCountW % 'd100000 = = 0 ) $display ( " Reached %d instructions " , InstrCountW ) ;
2021-10-23 20:17:30 +00:00
// turn on waves
if ( InstrCountW = = INSTR_WAVEON ) $stop ;
// end sim
2022-01-02 21:47:21 +00:00
if ( ( InstrCountW = = INSTR_LIMIT ) & ( INSTR_LIMIT ! = 0 ) ) $stop ;
2021-08-06 21:06:50 +00:00
fault = 0 ;
2021-09-27 07:03:11 +00:00
if ( `DEBUG_TRACE > = 1 ) begin
`checkEQ ( " PCW " , PCW , ExpectedPCW )
2021-10-25 17:04:30 +00:00
//`checkEQ("InstrW",InstrW,ExpectedInstrW) <-- not viable because of
// compressed to uncompressed conversion
2022-01-20 16:02:08 +00:00
`checkEQ ( " Instr Count " , dut . core . priv . priv . csr . counters . counters . INSTRET_REGW , InstrCountW )
2021-09-27 07:03:11 +00:00
# 2 ; // delay 2 ns.
if ( `DEBUG_TRACE > = 5 ) begin
2022-01-20 16:02:08 +00:00
$display ( " %tns, %d instrs: Reg Write Address %02d ? expected value: %02d " , $time , InstrCountW , dut . core . ieu . dp . regf . a3 , ExpectedRegAdrW ) ;
$display ( " %tns, %d instrs: RF[%02d] %016x ? expected value: %016x " , $time , InstrCountW , ExpectedRegAdrW , dut . core . ieu . dp . regf . rf [ ExpectedRegAdrW ] , ExpectedRegValueW ) ;
2021-09-22 16:33:11 +00:00
end
2021-09-27 07:03:11 +00:00
if ( RegWriteW = = " GPR " ) begin
2022-01-20 16:02:08 +00:00
`checkEQ ( " Reg Write Address " , dut . core . ieu . dp . regf . a3 , ExpectedRegAdrW )
2021-10-10 17:09:59 +00:00
$sformat ( name , " RF[%02d] " , ExpectedRegAdrW ) ;
2022-01-20 16:02:08 +00:00
`checkEQ ( name , dut . core . ieu . dp . regf . rf [ ExpectedRegAdrW ] , ExpectedRegValueW )
2021-09-15 21:30:59 +00:00
end
2021-09-27 07:03:11 +00:00
if ( MemOpW . substr ( 0 , 2 ) = = " Mem " ) begin
2021-12-20 00:24:40 +00:00
if ( `DEBUG_TRACE > = 4 ) $display ( " \t IEUAdrW: %016x ? expected: %016x " , IEUAdrW , ExpectedIEUAdrW ) ;
`checkEQ ( " IEUAdrW " , IEUAdrW , ExpectedIEUAdrW )
2021-09-27 07:03:11 +00:00
if ( MemOpW = = " MemR " | | MemOpW = = " MemRW " ) begin
2022-01-20 16:02:08 +00:00
if ( `DEBUG_TRACE > = 4 ) $display ( " \t ReadDataW: %016x ? expected: %016x " , dut . core . ieu . dp . ReadDataW , ExpectedMemReadDataW ) ;
`checkEQ ( " ReadDataW " , dut . core . ieu . dp . ReadDataW , ExpectedMemReadDataW )
2021-11-03 04:19:12 +00:00
end else if ( MemOpW = = " MemW " | | MemOpW = = " MemRW " ) begin
2021-09-27 07:03:11 +00:00
if ( `DEBUG_TRACE > = 4 ) $display ( " \t WriteDataW: %016x ? expected: %016x " , WriteDataW , ExpectedMemWriteDataW ) ;
`checkEQ ( " WriteDataW " , ExpectedMemWriteDataW , ExpectedMemWriteDataW )
2021-09-22 16:33:11 +00:00
end
end
2021-09-27 07:03:11 +00:00
// check csr
for ( NumCSRPostWIndex = 0 ; NumCSRPostWIndex < NumCSRW ; NumCSRPostWIndex + + ) begin
case ( ExpectedCSRArrayW [ NumCSRPostWIndex ] )
2022-01-20 16:02:08 +00:00
" mhartid " : `checkCSR ( dut . core . priv . priv . csr . csrm . MHARTID_REGW )
" mstatus " : `checkCSR ( dut . core . priv . priv . csr . csrm . MSTATUS_REGW )
" mtvec " : `checkCSR ( dut . core . priv . priv . csr . csrm . MTVEC_REGW )
" mip " : `checkCSR ( dut . core . priv . priv . csr . csrm . MIP_REGW )
" mie " : `checkCSR ( dut . core . priv . priv . csr . csrm . MIE_REGW )
" mideleg " : `checkCSR ( dut . core . priv . priv . csr . csrm . MIDELEG_REGW )
" medeleg " : `checkCSR ( dut . core . priv . priv . csr . csrm . MEDELEG_REGW )
" mepc " : `checkCSR ( dut . core . priv . priv . csr . csrm . MEPC_REGW )
" mtval " : `checkCSR ( dut . core . priv . priv . csr . csrm . MTVAL_REGW )
" sepc " : `checkCSR ( dut . core . priv . priv . csr . csrs . SEPC_REGW )
" scause " : `checkCSR ( dut . core . priv . priv . csr . csrs . csrs . SCAUSE_REGW )
" stvec " : `checkCSR ( dut . core . priv . priv . csr . csrs . STVEC_REGW )
" stval " : `checkCSR ( dut . core . priv . priv . csr . csrs . csrs . STVAL_REGW )
2021-09-27 07:03:11 +00:00
endcase
end
if ( fault = = 1 ) begin
errorCount + = 1 ;
$display ( " processed %0d instructions with %0d warnings " , InstrCountW , warningCount ) ;
$stop ;
end
end // if (`DEBUG_TRACE >= 1)
2021-08-13 19:39:05 +00:00
end // if (checkInstrW)
end // always @ (negedge clk)
2021-08-24 16:08:46 +00:00
// track the current function
FunctionName FunctionName ( . reset ( reset ) ,
2021-09-27 07:03:11 +00:00
. clk ( clk ) ,
. ProgramAddrMapFile ( ProgramAddrMapFile ) ,
. ProgramLabelMapFile ( ProgramLabelMapFile ) ) ;
2021-08-13 19:39:05 +00:00
2021-06-24 05:42:35 +00:00
2021-07-19 19:13:03 +00:00
2021-06-07 16:37:46 +00:00
2021-06-24 05:42:35 +00:00
///////////////////////////////////////////////////////////////////////////////
2021-10-25 17:04:30 +00:00
//////////////////////////////// Extra Features ///////////////////////////////
2021-06-24 05:42:35 +00:00
///////////////////////////////////////////////////////////////////////////////
// Instr Opcode Tracking
// For waveview convenience
string InstrFName , InstrDName , InstrEName , InstrMName , InstrWName ;
2022-01-20 16:02:08 +00:00
instrTrackerTB it ( clk , reset , dut . core . ieu . dp . FlushE ,
dut . core . ifu . FinalInstrRawF ,
dut . core . ifu . InstrD , dut . core . ifu . InstrE ,
dut . core . ifu . InstrM , InstrW ,
2021-06-24 05:42:35 +00:00
InstrFName , InstrDName , InstrEName , InstrMName , InstrWName ) ;
2021-06-07 16:37:46 +00:00
2021-06-24 05:42:35 +00:00
// ------------------
// Address Translator
// ------------------
/ * *
2021-12-14 21:43:06 +00:00
* Walk the page table stored in ram according to sv39 logic and translate a
2021-06-24 05:42:35 +00:00
* virtual address to a physical address .
*
* See section 4.3 .2 of the RISC - V Privileged specification for a full
* explanation of the below algorithm .
*/
2021-07-21 23:47:13 +00:00
logic SvMode , PTE_R , PTE_X ;
logic [ `XLEN - 1 : 0 ] SATP , PTE ;
logic [ 55 : 0 ] BaseAdr , PAdr ;
logic [ 8 : 0 ] VPN [ 2 : 0 ] ;
logic [ 11 : 0 ] Offset ;
2021-06-24 05:42:35 +00:00
function logic [ `XLEN - 1 : 0 ] adrTranslator (
input logic [ `XLEN - 1 : 0 ] adrIn ) ;
begin
int i ;
// Grab the SATP register from privileged unit
2022-01-20 16:02:08 +00:00
SATP = dut . core . priv . priv . csr . SATP_REGW ;
2021-06-24 05:42:35 +00:00
// Split the virtual address into page number segments and offset
VPN [ 2 ] = adrIn [ 38 : 30 ] ;
VPN [ 1 ] = adrIn [ 29 : 21 ] ;
VPN [ 0 ] = adrIn [ 20 : 12 ] ;
Offset = adrIn [ 11 : 0 ] ;
// We do not support sv48; only sv39
SvMode = SATP [ 63 ] ;
// Only perform translation if translation is on and the processor is not
// in machine mode
2022-01-20 16:02:08 +00:00
if ( SvMode & ( dut . core . priv . priv . PrivilegeModeW ! = `M_MODE ) ) begin
2021-06-24 05:42:35 +00:00
BaseAdr = SATP [ 43 : 0 ] < < 12 ;
for ( i = 2 ; i > = 0 ; i - - ) begin
PAdr = BaseAdr + ( VPN [ i ] < < 3 ) ;
2021-12-14 21:43:06 +00:00
// ram.RAM is 64-bit addressed. PAdr specifies a byte. We right shift
2021-06-24 05:42:35 +00:00
// by 3 (the PTE size) to get the requested 64-bit PTE.
2021-12-14 21:43:06 +00:00
PTE = dut . uncore . ram . ram . RAM [ PAdr > > 3 ] ;
2021-06-24 05:42:35 +00:00
PTE_R = PTE [ 1 ] ;
PTE_X = PTE [ 3 ] ;
if ( PTE_R | | PTE_X ) begin
// Leaf page found
break ;
end else begin
// Go to next level of table
BaseAdr = PTE [ 53 : 10 ] < < 12 ;
2021-06-07 16:37:46 +00:00
end
end
2021-06-24 05:42:35 +00:00
// Determine which parts of the PTE page number to use based on the
// level of the page table we reached.
if ( i = = 2 ) begin
// Gigapage
assign adrTranslator = { 8 'b0 , PTE [ 53 : 28 ] , VPN [ 1 ] , VPN [ 0 ] , Offset } ;
end else if ( i = = 1 ) begin
// Megapage
assign adrTranslator = { 8 'b0 , PTE [ 53 : 19 ] , VPN [ 0 ] , Offset } ;
end else begin
// Kilopage
assign adrTranslator = { 8 'b0 , PTE [ 53 : 10 ] , Offset } ;
end
end else begin
// Direct translation if address translation is not on
assign adrTranslator = adrIn ;
2021-06-07 16:37:46 +00:00
end
end
2021-06-24 05:42:35 +00:00
endfunction
endmodule