diff --git a/sim/Makefile b/sim/Makefile index 540c9418f..9cf3f0034 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -18,7 +18,8 @@ all: riscoftests memfiles coveragetests coverage: #make -C ../tests/coverage --jobs #iter-elf.bash --cover --search ../tests/coverage - vcover merge -out cov/cov.ucdb cov/rv64gc_arch64i.ucdb cov/rv64gc*.ucdb riscv.ucdb -logfile cov/log + vcover merge -out cov/cov.ucdb cov/rv64gc_arch64i.ucdb cov/rv64gc*.ucdb cov/buildroot_buildroot.ucdb riscv.ucdb -logfile cov/log +# vcover merge -out cov/cov.ucdb cov/rv64gc_arch64i.ucdb cov/rv64gc*.ucdb riscv.ucdb /home/rthompson/buildroot_buildroot-no-trace.ucdb -logfile cov/log vcover report -details cov/cov.ucdb > cov/rv64gc_coverage_details.rpt vcover report cov/cov.ucdb -details -instance=/core/ebu. > cov/rv64gc_coverage_ebu.rpt vcover report cov/cov.ucdb -details -instance=/core/priv. > cov/rv64gc_coverage_priv.rpt diff --git a/sim/coverage-exclusions-rv64gc.do b/sim/coverage-exclusions-rv64gc.do index 9905c897b..d58e4c514 100644 --- a/sim/coverage-exclusions-rv64gc.do +++ b/sim/coverage-exclusions-rv64gc.do @@ -24,8 +24,12 @@ #// and limitations under the License. #//////////////////////////////////////////////////////////////////////////////////////////////// +# This file should be a last resort. It's preferable to put +# // coverage off +# statements inline with the code whenever possible. + # LZA (i<64) statement confuses coverage tool -# This is ugly to exlcude the whole file - is there a better option +# This is ugly to exlcude the whole file - is there a better option? // coverage off isn't working coverage exclude -srcfile lzc.sv diff --git a/sim/imperas.ic b/sim/imperas.ic index 167c0cc44..4c221f2af 100644 --- a/sim/imperas.ic +++ b/sim/imperas.ic @@ -4,20 +4,36 @@ --showcommands # Core settings +--override cpu/priv_version=1.12 +--override cpu/user_version=20191213 +# arch +--override cpu/mimpid=0x100 +--override refRoot/cpu/tvec_align=64 + +# clarify +#--override refRoot/cpu/mtvec_sext=F + +--override cpu/tval_ii_code=T + +#--override cpu/time_undefined=T +#--override cpu/cycle_undefined=T +#--override cpu/instret_undefined=T +#--override cpu/hpmcounter_undefined=T + +--override cpu/reset_address=0x80000000 + --override cpu/unaligned=F --override cpu/ignore_non_leaf_DAU=1 --override cpu/wfi_is_nop=T ---override cpu/mimpid=0x100 --override cpu/misa_Extensions_mask=0x0 +#--override cpu/updatePTEA=T +#--override cpu/updatePTED=T +--override cpu/Sstc=T # THIS NEEDS FIXING to 16 --override cpu/PMP_registers=16 --override cpu/PMP_undefined=T -# Illegal instruction should not contain the bit pattern -# illegal pmp read contained this -# --override cpu/tval_ii_code=F - # PMA Settings # 'r': read access allowed # 'w': write access allowed @@ -48,15 +64,10 @@ #-override refRoot/cpu/cv/extensions=RV32I # Add Imperas simulator application instruction tracing ---override cpu/show_c_prefix=T ---trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange --traceafter 10500000 - -# Exceptions and pagetables debug ---override cpu/debugflags=6 - -# Turn on verbose output for Imperas simulator and Model --verbose ---override cpu/verbose=1 +--trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange --traceafter 0 +--override cpu/debugflags=6 --override cpu/verbose=1 +--override cpu/show_c_prefix=T # Store simulator output to logfile --output imperas.log diff --git a/sim/regression-wally b/sim/regression-wally index 7a509c890..c70177206 100755 --- a/sim/regression-wally +++ b/sim/regression-wally @@ -56,7 +56,12 @@ def getBuildrootTC(boot): BRgrepstr="WallyHostname login:" else: name="buildroot" - BRcmd="vsim > {} -c < {} -c < {} -c < cov/rv64gc_coverage_details.rpt') - #os.system('vcover report -below 100 cov/cov.ucdb > cov/rv64gc_coverage.rpt') - #os.system('vcover report -recursive cov/cov.ucdb > cov/rv64gc_recursive.rpt') - #os.system('vcover report -details -threshH 100 -html cov/cov.ucdb') # Count the number of failures if num_fail: print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail) diff --git a/sim/wally-batch.do b/sim/wally-batch.do index 7815e94fc..df49518c1 100644 --- a/sim/wally-batch.do +++ b/sim/wally-batch.do @@ -46,7 +46,7 @@ mkdir -p cov # Check if measuring coverage set coverage 0 if {$argc >= 3} { - if {$3 eq "-coverage"} { + if {$3 eq "-coverage" || ($argc >= 7 && $7 eq "-coverage")} { set coverage 1 } } @@ -61,8 +61,14 @@ if {$argc >= 3} { if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 # start and run simulation - vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G CHECKPOINT=$6 -o testbenchopt - vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7 + if { $coverage } { + echo "wally-batch buildroot coverage" + vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G CHECKPOINT=$6 -o testbenchopt +cover=sbecf + vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7 -cover + } else { + vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G CHECKPOINT=$6 -o testbenchopt + vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7 + } run -all run -all @@ -139,6 +145,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { } if {$coverage} { + echo "Saving coverage to ${1}_${2}.ucdb" do coverage-exclusions-rv64gc.do # beware: this assumes testing the rv64gc configuration coverage save -instance /testbench/dut/core cov/${1}_${2}.ucdb } diff --git a/src/cache/cache.sv b/src/cache/cache.sv index da7f83276..56044384b 100644 --- a/src/cache/cache.sv +++ b/src/cache/cache.sv @@ -96,8 +96,7 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache; logic SelFetchBuffer; logic CacheEn; - logic [CACHEWORDSPERLINE-1:0] MemPAdrDecoded; - logic [LINELEN/8-1:0] LineByteMask, DemuxedByteMask, FetchBufferByteSel; + logic [LINELEN/8-1:0] LineByteMask; logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr; genvar index; @@ -161,21 +160,30 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE ///////////////////////////////////////////////////////////////////////////////////////////// // Write Path ///////////////////////////////////////////////////////////////////////////////////////////// + if(!READ_ONLY_CACHE) begin:WriteSelLogic + logic [CACHEWORDSPERLINE-1:0] MemPAdrDecoded; + logic [LINELEN/8-1:0] DemuxedByteMask, FetchBufferByteSel; - // Adjust byte mask from word to cache line - onehotdecoder #(LOGCWPL) adrdec(.bin(PAdr[LOGCWPL+LOGLLENBYTES-1:LOGLLENBYTES]), .decoded(MemPAdrDecoded)); - for(index = 0; index < 2**LOGCWPL; index++) begin - assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0; - end - assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1. - assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0; + // Adjust byte mask from word to cache line + onehotdecoder #(LOGCWPL) adrdec(.bin(PAdr[LOGCWPL+LOGLLENBYTES-1:LOGLLENBYTES]), .decoded(MemPAdrDecoded)); + for(index = 0; index < 2**LOGCWPL; index++) begin + assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0; + end + assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1. - // Merge write data into fetched cache line for store miss - for(index = 0; index < LINELEN/8; index++) begin - mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]), - .d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index]), .y(LineWriteData[8*index+7:8*index])); + // Merge write data into fetched cache line for store miss + for(index = 0; index < LINELEN/8; index++) begin + mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]), + .d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index]), .y(LineWriteData[8*index+7:8*index])); + end + assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0; end - + else + begin:WriteSelLogic + // No need for this mux if the cache does not handle writes. + assign LineWriteData = FetchBuffer; + assign LineByteMask = '1; + end ///////////////////////////////////////////////////////////////////////////////////////////// // Flush logic ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cache/cacheLRU.sv b/src/cache/cacheLRU.sv index 05e26f4bf..780807943 100644 --- a/src/cache/cacheLRU.sv +++ b/src/cache/cacheLRU.sv @@ -98,7 +98,9 @@ module cacheLRU assign LRUUpdate[t1] = LRUUpdate[s] & WayEncoded[r]; end - mux2 #(1) LRUMuxes[NUMWAYS-2:0](CurrLRU, ~WayExpanded, LRUUpdate, NextLRU); + // The root node of the LRU tree will always be selected in LRUUpdate. No mux needed. + assign NextLRU[NUMWAYS-2] = ~WayExpanded[NUMWAYS-2]; + mux2 #(1) LRUMuxes[NUMWAYS-3:0](CurrLRU[NUMWAYS-3:0], ~WayExpanded[NUMWAYS-3:0], LRUUpdate[NUMWAYS-3:0], NextLRU[NUMWAYS-3:0]); // Compute next victim way. for(s = NUMWAYS-2; s >= NUMWAYS/2; s--) begin @@ -128,8 +130,8 @@ module cacheLRU always_ff @(posedge clk) begin if (reset) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0; if(CacheEn) begin - if((InvalidateCache | FlushCache) & ~FlushStage) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0; - else if (LRUWriteEn & ~FlushStage) begin + // if((InvalidateCache | FlushCache) & ~FlushStage) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0; + if (LRUWriteEn & ~FlushStage) begin LRUMemory[PAdr] <= NextLRU; end if(LRUWriteEn & ~FlushStage & (PAdr == CacheSet)) diff --git a/src/cache/cachefsm.sv b/src/cache/cachefsm.sv index c51257be7..cd1d43c55 100644 --- a/src/cache/cachefsm.sv +++ b/src/cache/cachefsm.sv @@ -135,7 +135,7 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( end // com back to CPU - assign CacheCommitted = CurrState != STATE_READY; + assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & CurrState == STATE_READ_HOLD); assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) | (CurrState == STATE_FETCH) | (CurrState == STATE_WRITEBACK) | diff --git a/src/ebu/ahbcacheinterface.sv b/src/ebu/ahbcacheinterface.sv index b30a15096..e2e7d3696 100644 --- a/src/ebu/ahbcacheinterface.sv +++ b/src/ebu/ahbcacheinterface.sv @@ -33,7 +33,8 @@ module ahbcacheinterface #( parameter BEATSPERLINE, // Number of AHBW words (beats) in cacheline parameter AHBWLOGBWPL, // Log2 of ^ parameter LINELEN, // Number of bits in cacheline - parameter LLENPOVERAHBW // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation) + parameter LLENPOVERAHBW, // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation) + parameter READ_ONLY_CACHE )( input logic HCLK, HRESETn, // bus interface controls @@ -115,7 +116,7 @@ module ahbcacheinterface #( flopen #(`AHBW/8) HWSTRBReg(HCLK, HREADY, BusByteMaskM[`AHBW/8-1:0], HWSTRB); - buscachefsm #(BeatCountThreshold, AHBWLOGBWPL) AHBBuscachefsm( + buscachefsm #(BeatCountThreshold, AHBWLOGBWPL, READ_ONLY_CACHE) AHBBuscachefsm( .HCLK, .HRESETn, .Flush, .BusRW, .Stall, .BusCommitted, .BusStall, .CaptureEn, .SelBusBeat, .CacheBusRW, .CacheBusAck, .BeatCount, .BeatCountDelayed, .HREADY, .HTRANS, .HWRITE, .HBURST); diff --git a/src/ebu/buscachefsm.sv b/src/ebu/buscachefsm.sv index c619c9135..e0efcf3a3 100644 --- a/src/ebu/buscachefsm.sv +++ b/src/ebu/buscachefsm.sv @@ -33,7 +33,8 @@ // HCLK and clk must be the same clock! module buscachefsm #( parameter BeatCountThreshold, // Largest beat index - parameter AHBWLOGBWPL // Log2 of BEATSPERLINE + parameter AHBWLOGBWPL, // Log2 of BEATSPERLINE + parameter READ_ONLY_CACHE )( input logic HCLK, input logic HRESETn, @@ -121,7 +122,7 @@ module buscachefsm #( (CurrState == DATA_PHASE) | (CurrState == CACHE_FETCH & ~HREADY) | (CurrState == CACHE_WRITEBACK & ~HREADY); - assign BusCommitted = CurrState != ADR_PHASE; + assign BusCommitted = (CurrState != ADR_PHASE) & ~(READ_ONLY_CACHE & CurrState == MEM3); // AHB bus interface assign HTRANS = (CurrState == ADR_PHASE & HREADY & ((|BusRW) | (|CacheBusRW)) & ~Flush) | diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index be10e8007..b34001077 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -75,109 +75,139 @@ module fctrl ( logic [1:0] FResSelD; // Select one of the results that finish in the memory stage logic [2:0] FrmD, FrmE; // FP rounding mode logic [`FMTBITS-1:0] FmtD; // FP format - logic [1:0] Fmt; // format - before possible reduction + logic [1:0] Fmt, Fmt2; // format - before possible reduction logic SupportedFmt; // is the format supported + logic SupportedFmt2; // is the source format supported for fp -> fp logic FCvtIntD, FCvtIntM; // convert to integer opperation // FPU Instruction Decoder assign Fmt = Funct7D[1:0]; + assign Fmt2 = Rs2D[1:0]; // source format for fcvt fp->fp - // Note: only Fmt is checked; fcvt does not check destination format assign SupportedFmt = (Fmt == 2'b00 | (Fmt == 2'b01 & `D_SUPPORTED) | (Fmt == 2'b10 & `ZFH_SUPPORTED) | (Fmt == 2'b11 & `Q_SUPPORTED)); + assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & `D_SUPPORTED) | + (Fmt2 == 2'b10 & `ZFH_SUPPORTED) | (Fmt2 == 2'b11 & `Q_SUPPORTED)); // decode the instruction + // FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt always_comb if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt) ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // for anything other than loads and stores, check for supported format - else case(OpD) - // FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt - 7'b0000111: case(Funct3D) - 3'b010: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flw - 3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // fld - else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fld not supported - 3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flq - else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // flq not supported - 3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flh - else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // flh not supported - default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction - endcase - 7'b0100111: case(Funct3D) - 3'b010: ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsw - 3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsd - else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsd not supported - 3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsq - else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsq not supported - 3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsh - else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsh not supported - default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction - endcase - 7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0; // fmadd - 7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0; // fmsub - 7'b1001011: ControlsD = `FCTRLW'b1_0_01_10_010_0_0_0; // fnmsub - 7'b1001111: ControlsD = `FCTRLW'b1_0_01_10_011_0_0_0; // fnmadd - 7'b1010011: casez(Funct7D) - 7'b00000??: ControlsD = `FCTRLW'b1_0_01_10_110_0_0_0; // fadd - 7'b00001??: ControlsD = `FCTRLW'b1_0_01_10_111_0_0_0; // fsub - 7'b00010??: ControlsD = `FCTRLW'b1_0_01_10_100_0_0_0; // fmul - 7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_xx0_1_0_0; // fdiv - 7'b01011??: if (Rs2D == 5'b0000) ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0_0; // fsqrt - 7'b00100??: case(Funct3D) - 3'b000: ControlsD = `FCTRLW'b1_0_00_xx_000_0_0_0; // fsgnj - 3'b001: ControlsD = `FCTRLW'b1_0_00_xx_001_0_0_0; // fsgnjn - 3'b010: ControlsD = `FCTRLW'b1_0_00_xx_010_0_0_0; // fsgnjx - default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction - endcase - 7'b00101??: case(Funct3D) - 3'b000: ControlsD = `FCTRLW'b1_0_00_xx_110_0_0_0; // fmin - 3'b001: ControlsD = `FCTRLW'b1_0_00_xx_101_0_0_0; // fmax - default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction - endcase - 7'b10100??: case(Funct3D) - 3'b010: ControlsD = `FCTRLW'b0_1_00_xx_010_0_0_0; // feq - 3'b001: ControlsD = `FCTRLW'b0_1_00_xx_001_0_0_0; // flt - 3'b000: ControlsD = `FCTRLW'b0_1_00_xx_011_0_0_0; // fle - default: ControlsD = `FCTRLW'b0_0_00_xx_000__0_1_0; // non-implemented instruction - endcase - 7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000) - ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass - else if (Funct3D[1:0] == 2'b00) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.w to int reg - else if (Funct3D[1:0] == 2'b01) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.d to int reg - else ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction - 7'b1101000: case(Rs2D[1:0]) - 2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s - 2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s - 2'b10: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s - 2'b11: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s - endcase - 7'b1100000: case(Rs2D[1:0]) - 2'b00: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w - 2'b01: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu - 2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l - 2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu - endcase - 7'b1111000: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.w.x to fp reg - 7'b0100000: ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.d - 7'b1101001: case(Rs2D[1:0]) - 2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d - 2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d - 2'b10: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d - 2'b11: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d - endcase - 7'b1100001: case(Rs2D[1:0]) - 2'b00: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w - 2'b01: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu - 2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l - 2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu - endcase - 7'b1111001: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.d.x to fp reg - 7'b0100001: ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.s - default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction - endcase - default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction - endcase + else begin + ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // default: non-implemented instruction + /* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed + case(OpD) + 7'b0000111: case(Funct3D) + 3'b010: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flw + 3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // fld + 3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flq + 3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flh + endcase + 7'b0100111: case(Funct3D) + 3'b010: ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsw + 3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsd + 3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsq + 3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsh + endcase + 7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0; // fmadd + 7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0; // fmsub + 7'b1001011: ControlsD = `FCTRLW'b1_0_01_10_010_0_0_0; // fnmsub + 7'b1001111: ControlsD = `FCTRLW'b1_0_01_10_011_0_0_0; // fnmadd + 7'b1010011: casez(Funct7D) + 7'b00000??: ControlsD = `FCTRLW'b1_0_01_10_110_0_0_0; // fadd + 7'b00001??: ControlsD = `FCTRLW'b1_0_01_10_111_0_0_0; // fsub + 7'b00010??: ControlsD = `FCTRLW'b1_0_01_10_100_0_0_0; // fmul + 7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_xx0_1_0_0; // fdiv + 7'b01011??: if (Rs2D == 5'b0000) ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0_0; // fsqrt + 7'b00100??: case(Funct3D) + 3'b000: ControlsD = `FCTRLW'b1_0_00_xx_000_0_0_0; // fsgnj + 3'b001: ControlsD = `FCTRLW'b1_0_00_xx_001_0_0_0; // fsgnjn + 3'b010: ControlsD = `FCTRLW'b1_0_00_xx_010_0_0_0; // fsgnjx + endcase + 7'b00101??: case(Funct3D) + 3'b000: ControlsD = `FCTRLW'b1_0_00_xx_110_0_0_0; // fmin + 3'b001: ControlsD = `FCTRLW'b1_0_00_xx_101_0_0_0; // fmax + endcase + 7'b10100??: case(Funct3D) + 3'b010: ControlsD = `FCTRLW'b0_1_00_xx_010_0_0_0; // feq + 3'b001: ControlsD = `FCTRLW'b0_1_00_xx_001_0_0_0; // flt + 3'b000: ControlsD = `FCTRLW'b0_1_00_xx_011_0_0_0; // fle + endcase + 7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000) + ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass + else if (Funct3D == 3'b000 & Rs2D == 5'b00000) + ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.w / fmv.x.d to int register + 7'b111100?: if (Funct3D == 3'b000 & Rs2D == 5'b00000) + ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.w.x / fmv.d.x to fp reg + 7'b0100000: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b00) + ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.(d/q/h) + 7'b0100001: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b01) + ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.(s/h/q) + // coverage off + // Not covered in testing because rv64gc does not support half or quad precision + 7'b0100010: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b10) + ControlsD = `FCTRLW'b1_0_01_00_010_0_0_0; // fcvt.h.(s/d/q) + 7'b0100011: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b11) + ControlsD = `FCTRLW'b1_0_01_00_011_0_0_0; // fcvt.q.(s/h/d) + // coverage on + 7'b1101000: case(Rs2D) + 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s + 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s + 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s + 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s + endcase + 7'b1100000: case(Rs2D) + 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w + 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu + 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l + 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu + endcase + 7'b1101001: case(Rs2D) + 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d + 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d + 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d + 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d + endcase + 7'b1100001: case(Rs2D) + 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w + 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu + 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l + 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu + endcase + // coverage off + // Not covered in testing because rv64gc does not support half or quad precision + 7'b1101010: case(Rs2D) + 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.h.w w->h + 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.h.wu wu->h + 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.h.l l->h + 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.h.lu lu->h + endcase + 7'b1100010: case(Rs2D) + 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.h h->w + 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.h h->wu + 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.h h->l + 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.h h->lu + endcase + 7'b1101011: case(Rs2D) + 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.q.w w->q + 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.q.wu wu->q + 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.q.l l->q + 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.q.lu lu->q + endcase + 7'b1100011: case(Rs2D) + 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.q q->w + 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.q q->wu + 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.q q->l + 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.q q->lu + endcase + // coverage on + endcase + endcase + end + /* verilator lint_on CASEINCOMPLETE */ // unswizzle control bits assign #1 {FRegWriteD, FWriteIntD, FResSelD, PostProcSelD, OpCtrlD, FDivStartD, IllegalFPUInstrD, FCvtIntD} = ControlsD; @@ -303,7 +333,5 @@ module fctrl ( flopenrc #(4) MWCtrlReg(clk, reset, FlushW, ~StallW, {FRegWriteM, FResSelM, FCvtIntM}, {FRegWriteW, FResSelW, FCvtIntW}); - - //assign FCvtIntW = (FResSelW == 2'b01); - + endmodule diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index cf3a22c1f..11efacffa 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -36,7 +36,7 @@ module hazard ( input logic FCvtIntStallD, FPUStallD, input logic DivBusyE, FDivBusyE, input logic EcallFaultM, BreakpointFaultM, - input logic WFIStallM, + input logic wfiM, IntPendingM, // Stall & flush outputs output logic StallF, StallD, StallE, StallM, StallW, output logic FlushD, FlushE, FlushM, FlushW @@ -45,6 +45,12 @@ module hazard ( logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause; logic LatestUnstalledD, LatestUnstalledE, LatestUnstalledM, LatestUnstalledW; logic FlushDCause, FlushECause, FlushMCause, FlushWCause; + + logic WFIStallM, WFIInterruptedM; + + // WFI logic + assign WFIStallM = wfiM & ~IntPendingM; // WFI waiting for an interrupt or timeout + assign WFIInterruptedM = wfiM & IntPendingM; // WFI detects a pending interrupt. Retire WFI; trap if interrupt is enabled. // stalls and flushes // loads: stall for one cycle if the subsequent instruction depends on the load @@ -68,7 +74,7 @@ module hazard ( assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPWrongE; assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE)); assign FlushMCause = TrapM | RetM | CSRWriteFenceM; - assign FlushWCause = TrapM; + assign FlushWCause = TrapM & ~WFIInterruptedM; // Stall causes // Most data depenency stalls are identified in the decode stage @@ -88,7 +94,9 @@ module hazard ( assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause); // Stall each stage for cause or if the next stage is stalled + // coverage off: StallFCause is always 0 assign #1 StallF = StallFCause | StallD; + // coverage on assign #1 StallD = StallDCause | StallE; assign #1 StallE = StallECause | StallM; assign #1 StallM = StallMCause | StallW; diff --git a/src/ieu/alu.sv b/src/ieu/alu.sv index c4e0f3906..43df83b60 100644 --- a/src/ieu/alu.sv +++ b/src/ieu/alu.sv @@ -37,14 +37,13 @@ module alu #(parameter WIDTH=32) ( input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction input logic [2:0] ZBBSelect, // ZBB mux select signal input logic [2:0] Funct3, // For BMU decoding - input logic [1:0] CompFlags, // Comparator flags input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage - output logic [WIDTH-1:0] Result, // ALU result + output logic [WIDTH-1:0] ALUResult, // ALU result output logic [WIDTH-1:0] Sum); // Sum of operands // CondInvB = ~B when subtracting, B otherwise. Shift = shift result. SLT/U = result of a slt/u instruction. // FullResult = ALU result before adjusting for a RV64 w-suffix instruction. - logic [WIDTH-1:0] CondMaskInvB, Shift, FullResult, ALUResult; // Intermediate Signals + logic [WIDTH-1:0] CondMaskInvB, Shift, FullResult, PreALUResult; // Intermediate Signals logic [WIDTH-1:0] CondMaskB; // Result of B mask select mux logic [WIDTH-1:0] CondShiftA; // Result of A shifted select mux logic [WIDTH-1:0] CondExtA; // Result of Zero Extend A select mux @@ -84,16 +83,16 @@ module alu #(parameter WIDTH=32) ( end // Support RV64I W-type addw/subw/addiw/shifts that discard upper 32 bits and sign-extend 32-bit result to 64 bits - if (WIDTH == 64) assign ALUResult = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult; - else assign ALUResult = FullResult; + if (WIDTH == 64) assign PreALUResult = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult; + else assign PreALUResult = FullResult; // Final Result B instruction select mux if (`ZBC_SUPPORTED | `ZBS_SUPPORTED | `ZBA_SUPPORTED | `ZBB_SUPPORTED) begin : bitmanipalu bitmanipalu #(WIDTH) balu(.A, .B, .W64, .BSelect, .ZBBSelect, - .Funct3, .CompFlags, .BALUControl, .ALUResult, .FullResult, - .CondMaskB, .CondShiftA, .Result); + .Funct3, .LT,.LTU, .BALUControl, .PreALUResult, .FullResult, + .CondMaskB, .CondShiftA, .ALUResult); end else begin - assign Result = ALUResult; + assign ALUResult = PreALUResult; assign CondMaskB = B; assign CondShiftA = A; end diff --git a/src/ieu/bmu/bitmanipalu.sv b/src/ieu/bmu/bitmanipalu.sv index 07c7e5343..228b23132 100644 --- a/src/ieu/bmu/bitmanipalu.sv +++ b/src/ieu/bmu/bitmanipalu.sv @@ -35,12 +35,13 @@ module bitmanipalu #(parameter WIDTH=32) ( input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction input logic [2:0] ZBBSelect, // ZBB mux select signal input logic [2:0] Funct3, // Funct3 field of opcode indicates operation to perform - input logic [1:0] CompFlags, // Comparator flags + input logic LT, // less than flag + input logic LTU, // less than unsigned flag input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage - input logic [WIDTH-1:0] ALUResult, FullResult, // ALUResult, FullResult signals + input logic [WIDTH-1:0] PreALUResult, FullResult,// PreALUResult, FullResult signals output logic [WIDTH-1:0] CondMaskB, // B is conditionally masked for ZBS instructions output logic [WIDTH-1:0] CondShiftA, // A is conditionally shifted for ShAdd instructions - output logic [WIDTH-1:0] Result); // Result + output logic [WIDTH-1:0] ALUResult); // Result logic [WIDTH-1:0] ZBBResult, ZBCResult; // ZBB, ZBC Result logic [WIDTH-1:0] MaskB; // BitMask of B @@ -84,16 +85,16 @@ module bitmanipalu #(parameter WIDTH=32) ( // ZBB Unit if (`ZBB_SUPPORTED) begin: zbb - zbb #(WIDTH) ZBB(.A, .RevA, .B, .ALUResult, .W64, .lt(CompFlags[0]), .ZBBSelect, .ZBBResult); + zbb #(WIDTH) ZBB(.A, .RevA, .B, .W64, .LT, .LTU, .BUnsigned(Funct3[0]), .ZBBSelect, .ZBBResult); end else assign ZBBResult = 0; // Result Select Mux always_comb case (BSelect) // 00: ALU, 01: ZBA/ZBS, 10: ZBB, 11: ZBC - 2'b00: Result = ALUResult; - 2'b01: Result = FullResult; // NOTE: We don't use ALUResult because ZBA/ZBS instructions don't sign extend the MSB of the right-hand word. - 2'b10: Result = ZBBResult; - 2'b11: Result = ZBCResult; + 2'b00: ALUResult = PreALUResult; + 2'b01: ALUResult = FullResult; // NOTE: We don't use ALUResult because ZBA/ZBS instructions don't sign extend the MSB of the right-hand word. + 2'b10: ALUResult = ZBBResult; + 2'b11: ALUResult = ZBCResult; endcase endmodule diff --git a/src/ieu/bmu/bmuctrl.sv b/src/ieu/bmu/bmuctrl.sv index 90d031a14..d1fa909d2 100644 --- a/src/ieu/bmu/bmuctrl.sv +++ b/src/ieu/bmu/bmuctrl.sv @@ -48,7 +48,6 @@ module bmuctrl( output logic [1:0] BSelectE, // Indicates if ZBA_ZBB_ZBC_ZBS instruction in one-hot encoding output logic [2:0] ZBBSelectE, // ZBB mux select signal output logic BRegWriteE, // Indicates if it is a R type B instruction in Execute - output logic BComparatorSignedE, // Indicates if comparator signed in Execute Stage output logic [2:0] BALUControlE // ALU Control signals for B instructions in Execute Stage ); @@ -56,7 +55,6 @@ module bmuctrl( logic [2:0] Funct3D; // Funct3 field in Decode stage logic [6:0] Funct7D; // Funct7 field in Decode stage logic [4:0] Rs2D; // Rs2 source register in Decode stage - logic BComparatorSignedD; // Indicates if comparator signed (max, min instruction) in Decode Stage logic RotateD; // Indicates if rotate instruction in Decode Stage logic MaskD; // Indicates if zbs instruction in Decode Stage logic PreShiftD; // Indicates if sh1add, sh2add, sh3add instruction in Decode Stage @@ -101,8 +99,10 @@ module bmuctrl( BMUControlsD = `BMUCTRLW'b000_10_001_1_1_0_1_0_0_0_0_0; // sign extend instruction else if ((Rs2D[4:2]==3'b000) & ~(Rs2D[1] & Rs2D[0])) BMUControlsD = `BMUCTRLW'b000_10_000_1_1_0_1_0_0_0_0_0; // count instruction - 17'b0110011_0000100_100: if (`XLEN == 32) - BMUControlsD = `BMUCTRLW'b000_10_001_1_1_0_1_0_0_0_0_0; // zexth (rv32) +// // coverage off: This case can't occur in RV64 +// 17'b0110011_0000100_100: if (`XLEN == 32) +// BMUControlsD = `BMUCTRLW'b000_10_001_1_1_0_1_0_0_0_0_0; // zexth (rv32) +// // coverage on 17'b0110011_0100000_111: BMUControlsD = `BMUCTRLW'b111_01_111_1_0_0_1_1_0_0_0_0; // andn 17'b0110011_0100000_110: BMUControlsD = `BMUCTRLW'b110_01_111_1_0_0_1_1_0_0_0_0; // orn 17'b0110011_0100000_100: BMUControlsD = `BMUCTRLW'b100_01_111_1_0_0_1_1_0_0_0_0; // xnor @@ -110,10 +110,10 @@ module bmuctrl( BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // rev8 17'b0010011_0010100_101: if (Rs2D[4:0] == 5'b00111) BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // orc.b - 17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_0_0_0_0_0; // max - 17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_0_0_0_0_0; // maxu - 17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_0_0_0_0_0; // min - 17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_0_0_0_0_0; // minu + 17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_1_0_0_0_0; // max + 17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_1_0_0_0_0; // maxu + 17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_1_0_0_0_0; // min + 17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_1_0_0_0_0; // minu endcase if (`XLEN==32) casez({OpD, Funct7D, Funct3D}) @@ -172,12 +172,9 @@ module bmuctrl( // Pack BALUControl Signals assign BALUControlD = {RotateD, MaskD, PreShiftD}; - // Comparator should perform signed comparison when min/max instruction. We have overlap in funct3 with some branch instructions so we use opcode to differentiate betwen min/max and branches - assign BComparatorSignedD = (Funct3D[2]^Funct3D[0]) & ~OpD[6]; - // Choose ALUSelect brom BMU for BMU operations, Funct3 for IEU operations, or 0 for addition assign ALUSelectD = BALUOpD ? BALUSelectD : (ALUOpD ? Funct3D : 3'b000); // BMU Execute stage pipieline control register - flopenrc#(10) controlregBMU(clk, reset, FlushE, ~StallE, {BSelectD, ZBBSelectD, BRegWriteD, BComparatorSignedD, BALUControlD}, {BSelectE, ZBBSelectE, BRegWriteE, BComparatorSignedE, BALUControlE}); + flopenrc#(9) controlregBMU(clk, reset, FlushE, ~StallE, {BSelectD, ZBBSelectD, BRegWriteD, BALUControlD}, {BSelectE, ZBBSelectE, BRegWriteE, BALUControlE}); endmodule diff --git a/src/ieu/bmu/clmul.sv b/src/ieu/bmu/clmul.sv index 904c64238..cf3e1c6b1 100644 --- a/src/ieu/bmu/clmul.sv +++ b/src/ieu/bmu/clmul.sv @@ -30,20 +30,20 @@ `include "wally-config.vh" module clmul #(parameter WIDTH=32) ( - input logic [WIDTH-1:0] A, B, // Operands + input logic [WIDTH-1:0] X, Y, // Operands output logic [WIDTH-1:0] ClmulResult); // ZBS result - logic [(WIDTH*WIDTH)-1:0] s; // intermediary signals for carry-less multiply + logic [(WIDTH*WIDTH)-1:0] S; // intermediary signals for carry-less multiply integer i,j; always_comb begin for (i=0;i 32, because all other + // possible values for instr16[12:10] are covered by branches above. XLEN !> 32 + // will never occur in rv64gc so this branch can not be covered else begin // illegal instruction IllegalCompInstrD = 1; InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap end + // coverage on 5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j 5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz 5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index 2a411a737..c1556daeb 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -251,7 +251,7 @@ module ifu ( .NextSet(PCSpillNextF[11:0]), .PAdr(PCPF), .CacheCommitted(CacheCommittedF), .InvalidateCache(InvalidateICacheM)); - ahbcacheinterface #(WORDSPERLINE, LOGBWPL, LINELEN, LLENPOVERAHBW) + ahbcacheinterface #(WORDSPERLINE, LOGBWPL, LINELEN, LLENPOVERAHBW, 1) ahbcacheinterface(.HCLK(clk), .HRESETn(~reset), .HRDATA, .Flush(FlushD), .CacheBusRW, .HSIZE(IFUHSIZE), .HBURST(IFUHBURST), .HTRANS(IFUHTRANS), .HWSTRB(), diff --git a/src/lsu/lsu.sv b/src/lsu/lsu.sv index e3adc00f5..f2e147f00 100644 --- a/src/lsu/lsu.sv +++ b/src/lsu/lsu.sv @@ -149,7 +149,7 @@ module lsu ( // MMU include PMP and is needed if any privileged supported ///////////////////////////////////////////////////////////////////////////////////////////// - if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED + if(`VIRTMEM_SUPPORTED) begin : hptw hptw hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF, .DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM, .FlushW, .DCacheStallM, .SATP_REGW, .PCSpillF, @@ -275,7 +275,7 @@ module lsu ( .FetchBuffer, .CacheBusRW, .CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0)); - ahbcacheinterface #(.BEATSPERLINE(BEATSPERLINE), .AHBWLOGBWPL(AHBWLOGBWPL), .LINELEN(LINELEN), .LLENPOVERAHBW(LLENPOVERAHBW)) ahbcacheinterface( + ahbcacheinterface #(.BEATSPERLINE(BEATSPERLINE), .AHBWLOGBWPL(AHBWLOGBWPL), .LINELEN(LINELEN), .LLENPOVERAHBW(LLENPOVERAHBW), .READ_ONLY_CACHE(0)) ahbcacheinterface( .HCLK(clk), .HRESETn(~reset), .Flush(FlushW), .HRDATA, .HWDATA(LSUHWDATA), .HWSTRB(LSUHWSTRB), .HSIZE(LSUHSIZE), .HBURST(LSUHBURST), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HREADY(LSUHREADY), diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index 1478b5fc0..db142de5f 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -55,7 +55,7 @@ module csr #(parameter input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode input logic [1:0] PrivilegeModeW, // current privilege mode - input logic [`LOG_XLEN-1:0] CauseM, // Trap cause + input logic [3:0] CauseM, // Trap cause input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode // inputs for performance counters input logic LoadStallD, @@ -79,7 +79,7 @@ module csr #(parameter // outputs from CSRs output logic [1:0] STATUS_MPP, output logic STATUS_SPP, STATUS_TSR, STATUS_TVM, - output logic [`XLEN-1:0] MEDELEG_REGW, + output logic [15:0] MEDELEG_REGW, output logic [`XLEN-1:0] SATP_REGW, output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, output logic STATUS_MIE, STATUS_SIE, @@ -106,8 +106,10 @@ module csr #(parameter logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW; logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM; logic CSRMWriteM, CSRSWriteM, CSRUWriteM; + logic UngatedCSRMWriteM; logic WriteFRMM, WriteFFLAGSM; - logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextCauseM, NextMtvalM; + logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM; + logic [4:0] NextCauseM; logic [11:0] CSRAdrM; logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM; logic InsufficientCSRPrivilegeM; @@ -153,7 +155,7 @@ module csr #(parameter logic VectoredM; logic [`XLEN-1:0] TVecPlusCauseM; assign VectoredM = InterruptM & (TVecM[1:0] == 2'b01); - assign TVecPlusCauseM = {TVecAlignedM[`XLEN-1:6], CauseM[3:0], 2'b00}; // 64-byte alignment allows concatenation rather than addition + assign TVecPlusCauseM = {TVecAlignedM[`XLEN-1:6], CauseM, 2'b00}; // 64-byte alignment allows concatenation rather than addition mux2 #(`XLEN) trapvecmux(TVecAlignedM, TVecPlusCauseM, VectoredM, TrapVectorM); end else assign TrapVectorM = TVecAlignedM; @@ -196,11 +198,12 @@ module csr #(parameter assign CSRAdrM = InstrM[31:20]; assign UnalignedNextEPCM = TrapM ? ((wfiM & IntPendingM) ? PCM+4 : PCM) : CSRWriteValM; assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[`XLEN-1:1], 1'b0} : {UnalignedNextEPCM[`XLEN-1:2], 2'b00}; // 3.1.15 alignment - assign NextCauseM = TrapM ? {InterruptM, {(`XLEN-`LOG_XLEN-1){1'b0}}, CauseM}: CSRWriteValM; + assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[`XLEN-1], CSRWriteValM[3:0]}; assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM; - assign CSRMWriteM = CSRWriteM & (PrivilegeModeW == `M_MODE); - assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW); - assign CSRUWriteM = CSRWriteM; + assign UngatedCSRMWriteM = CSRWriteM & (PrivilegeModeW == `M_MODE); + assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM; + assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW) & InstrValidNotFlushedM; + assign CSRUWriteM = CSRWriteM & InstrValidNotFlushedM; assign MTrapM = TrapM & (NextPrivilegeModeM == `M_MODE); assign STrapM = TrapM & (NextPrivilegeModeM == `S_MODE) & `S_SUPPORTED; @@ -208,7 +211,7 @@ module csr #(parameter // CSRs /////////////////////////////////////////// - csri csri(.clk, .reset, .InstrValidNotFlushedM, + csri csri(.clk, .reset, .CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM, .MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt, .MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable); @@ -222,8 +225,8 @@ module csr #(parameter .STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TVM, .STATUS_FS, .BigEndianM); - csrm csrm(.clk, .reset, .InstrValidNotFlushedM, - .CSRMWriteM, .MTrapM, .CSRAdrM, + csrm csrm(.clk, .reset, + .UngatedCSRMWriteM, .CSRMWriteM, .MTrapM, .CSRAdrM, .NextEPCM, .NextCauseM, .NextMtvalM, .MSTATUS_REGW, .MSTATUSH_REGW, .CSRWriteValM, .CSRMReadValM, .MTVEC_REGW, .MEPC_REGW, .MCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW, @@ -233,7 +236,7 @@ module csr #(parameter if (`S_SUPPORTED) begin:csrs - csrs csrs(.clk, .reset, .InstrValidNotFlushedM, + csrs csrs(.clk, .reset, .CSRSWriteM, .STrapM, .CSRAdrM, .NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW, .STATUS_TVM, .MCOUNTEREN_TM(MCOUNTEREN_REGW[1]), diff --git a/src/privileged/csri.sv b/src/privileged/csri.sv index a6fddbd0e..0a62b2174 100644 --- a/src/privileged/csri.sv +++ b/src/privileged/csri.sv @@ -35,7 +35,6 @@ module csri #(parameter SIE = 12'h104, SIP = 12'h144) ( input logic clk, reset, - input logic InstrValidNotFlushedM, input logic CSRMWriteM, CSRSWriteM, input logic [`XLEN-1:0] CSRWriteValM, input logic [11:0] CSRAdrM, @@ -50,10 +49,10 @@ module csri #(parameter logic STIP; // Interrupt Write Enables - assign WriteMIPM = CSRMWriteM & (CSRAdrM == MIP) & InstrValidNotFlushedM; - assign WriteMIEM = CSRMWriteM & (CSRAdrM == MIE) & InstrValidNotFlushedM; - assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP) & InstrValidNotFlushedM; - assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE) & InstrValidNotFlushedM; + assign WriteMIPM = CSRMWriteM & (CSRAdrM == MIP); + assign WriteMIEM = CSRMWriteM & (CSRAdrM == MIE); + assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP); + assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE); // Interrupt Pending and Enable Registers // MEIP, MTIP, MSIP are read-only diff --git a/src/privileged/csrm.sv b/src/privileged/csrm.sv index daf7e1012..f0e5f00db 100644 --- a/src/privileged/csrm.sv +++ b/src/privileged/csrm.sv @@ -69,20 +69,20 @@ module csrm #(parameter DSCRATCH1 = 12'h7B3, // Constants ZERO = {(`XLEN){1'b0}}, - MEDELEG_MASK = ~(ZERO | `XLEN'b1 << 11), + MEDELEG_MASK = 16'hB3FF, MIDELEG_MASK = 12'h222 // we choose to not make machine interrupts delegable ) ( input logic clk, reset, - input logic InstrValidNotFlushedM, - input logic CSRMWriteM, MTrapM, + input logic UngatedCSRMWriteM, CSRMWriteM, MTrapM, input logic [11:0] CSRAdrM, - input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW, + input logic [`XLEN-1:0] NextEPCM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW, + input logic [4:0] NextCauseM, input logic [`XLEN-1:0] CSRWriteValM, input logic [11:0] MIP_REGW, MIE_REGW, output logic [`XLEN-1:0] CSRMReadValM, MTVEC_REGW, output logic [`XLEN-1:0] MEPC_REGW, output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW, - output logic [`XLEN-1:0] MEDELEG_REGW, + output logic [15:0] MEDELEG_REGW, output logic [11:0] MIDELEG_REGW, output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], @@ -91,8 +91,7 @@ module csrm #(parameter ); logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW; - logic [`XLEN-1:0] MSCRATCH_REGW; - logic [`XLEN-1:0] MCAUSE_REGW, MTVAL_REGW; + logic [`XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; @@ -112,13 +111,13 @@ module csrm #(parameter else assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01); - assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & InstrValidNotFlushedM & ~ADDRLocked[i]; + assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~ADDRLocked[i]; flopenr #(`PA_BITS-2) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM[`PA_BITS-3:0], PMPADDR_ARRAY_REGW[i]); if (`XLEN==64) begin - assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & InstrValidNotFlushedM & ~CFGLocked[i]; + assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~CFGLocked[i]; flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]); end else begin - assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & InstrValidNotFlushedM & ~CFGLocked[i]; + assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~CFGLocked[i]; flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]); end end @@ -133,30 +132,30 @@ module csrm #(parameter assign MHARTID_REGW = 0; // Write machine Mode CSRs - assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS) & InstrValidNotFlushedM; - assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & InstrValidNotFlushedM & (`XLEN==32); - assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC) & InstrValidNotFlushedM; - assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG) & InstrValidNotFlushedM; - assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG) & InstrValidNotFlushedM; - assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH) & InstrValidNotFlushedM; - assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC)) & InstrValidNotFlushedM; - assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE)) & InstrValidNotFlushedM; - assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL)) & InstrValidNotFlushedM; - assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN) & InstrValidNotFlushedM; - assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT) & InstrValidNotFlushedM; + assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS); + assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH)& (`XLEN==32); + assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC); + assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG); + assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG); + assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH); + assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC)); + assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE)); + assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL)); + assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN); + assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT); - assign IllegalCSRMWriteReadonlyM = CSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID); + assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID); // CSRs flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); if (`S_SUPPORTED) begin:deleg // DELEG registers should exist - flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK, MEDELEG_REGW); - flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW); + flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW); + flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW); end else assign {MEDELEG_REGW, MIDELEG_REGW} = 0; flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW); flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW); - flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW); + flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, {NextCauseM[4], {(`XLEN-5){1'b0}}, NextCauseM[3:0]}, MCAUSE_REGW); if(`QEMU) assign MTVAL_REGW = `XLEN'b0; // MTVAL tied to 0 in QEMU configuration else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW); flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW); @@ -192,7 +191,7 @@ module csrm #(parameter MSTATUS: CSRMReadValM = MSTATUS_REGW; MSTATUSH: CSRMReadValM = MSTATUSH_REGW; MTVEC: CSRMReadValM = MTVEC_REGW; - MEDELEG: CSRMReadValM = MEDELEG_REGW; + MEDELEG: CSRMReadValM = {{(`XLEN-16){1'b0}}, MEDELEG_REGW}; MIDELEG: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIDELEG_REGW}; MIP: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIP_REGW}; MIE: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIE_REGW}; diff --git a/src/privileged/csrs.sv b/src/privileged/csrs.sv index 3d75ef73e..e085232a6 100644 --- a/src/privileged/csrs.sv +++ b/src/privileged/csrs.sv @@ -45,10 +45,10 @@ module csrs #(parameter STIMECMPH = 12'h15D, SATP = 12'h180) ( input logic clk, reset, - input logic InstrValidNotFlushedM, input logic CSRSWriteM, STrapM, input logic [11:0] CSRAdrM, - input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW, + input logic [`XLEN-1:0] NextEPCM, NextMtvalM, SSTATUS_REGW, + input logic [4:0] NextCauseM, input logic STATUS_TVM, input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear input logic [`XLEN-1:0] CSRWriteValM, @@ -72,28 +72,26 @@ module csrs #(parameter logic WriteSSCRATCHM, WriteSEPCM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic WriteSTIMECMPM, WriteSTIMECMPHM; - logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW; - logic [`XLEN-1:0] SCAUSE_REGW; + logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW; logic [63:0] STIMECMP_REGW; // write enables - // *** can InstrValidNotFlushed be factored out of all these writes into CSRWriteM? - assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & InstrValidNotFlushedM; - assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & InstrValidNotFlushedM; - assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & InstrValidNotFlushedM; - assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & InstrValidNotFlushedM; - assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & InstrValidNotFlushedM; - assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & InstrValidNotFlushedM; - assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & InstrValidNotFlushedM; - assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & InstrValidNotFlushedM; - assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & InstrValidNotFlushedM; - assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & (`XLEN == 32) & InstrValidNotFlushedM; + assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS); + assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC); + assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH); + assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)); + assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)); + assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)); + assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM); + assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN); + assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM); + assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & (`XLEN == 32); // CSRs flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); - flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW); + flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(`XLEN-5){1'b0}}, NextCauseM[3:0]}, SCAUSE_REGW); flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); if (`VIRTMEM_SUPPORTED) flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); diff --git a/src/privileged/csru.sv b/src/privileged/csru.sv index d8c405cb5..e474e5967 100644 --- a/src/privileged/csru.sv +++ b/src/privileged/csru.sv @@ -51,9 +51,8 @@ module csru #(parameter logic SetOrWriteFFLAGSM; // Write enables - //assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & InstrValidNotFlushedM; - assign WriteFRMM = (CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FRM | CSRAdrM == FCSR)) & InstrValidNotFlushedM; - assign WriteFFLAGSM = (CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & InstrValidNotFlushedM; + assign WriteFRMM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FRM | CSRAdrM == FCSR); + assign WriteFFLAGSM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FFLAGS | CSRAdrM == FCSR); // Write Values assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0]; diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index 1975db10e..ca3d35717 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -93,11 +93,11 @@ module privileged ( output logic BigEndianM, // Use big endian in current privilege mode // Fault outputs output logic BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire - output logic WFIStallM // Stall in Memory stage for WFI until interrupt or timeout + output logic wfiM, IntPendingM // Stall in Memory stage for WFI until interrupt pending or timeout ); - logic [`LOG_XLEN-1:0] CauseM; // trap cause - logic [`XLEN-1:0] MEDELEG_REGW; // exception delegation CSR + logic [3:0] CauseM; // trap cause + logic [15:0] MEDELEG_REGW; // exception delegation CSR logic [11:0] MIDELEG_REGW; // interrupt delegation CSR logic sretM, mretM; // supervisor / machine return instruction logic IllegalCSRAccessM; // Illegal access to CSR @@ -110,8 +110,6 @@ module privileged ( logic [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return logic DelegateM; // trap should be delegated - logic wfiM; // wait for interrupt instruction - logic IntPendingM; // interrupt is pending, even if not enabled. ends wfi logic InterruptM; // interrupt occuring logic ExceptionM; // Memory stage instruction caused a fault @@ -156,7 +154,7 @@ module privileged ( .mretM, .sretM, .PrivilegeModeW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .STATUS_MIE, .STATUS_SIE, .InstrValidM, .CommittedM, .CommittedF, - .TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .WFIStallM, .CauseM); + .TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM); endmodule diff --git a/src/privileged/trap.sv b/src/privileged/trap.sv index d50b5fb48..b6e99f2e0 100644 --- a/src/privileged/trap.sv +++ b/src/privileged/trap.sv @@ -38,7 +38,7 @@ module trap ( input logic wfiM, // wait for interrupt instruction input logic [1:0] PrivilegeModeW, // current privilege mode input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, // interrupt pending, enabled, and delegate CSRs - input logic [`XLEN-1:0] MEDELEG_REGW, // exception delegation SR + input logic [15:0] MEDELEG_REGW, // exception delegation SR input logic STATUS_MIE, STATUS_SIE, // machine/supervisor interrupt enables input logic InstrValidM, // current instruction is valid, not flushed input logic CommittedM, CommittedF, // LSU/IFU has committed to a bus operation that can't be interrupted @@ -48,8 +48,7 @@ module trap ( output logic ExceptionM, // exception is occurring output logic IntPendingM, // Interrupt is pending, might occur if enabled output logic DelegateM, // Delegate trap to supervisor handler - output logic WFIStallM, // Stall due to WFI instruction - output logic [`LOG_XLEN-1:0] CauseM // trap cause + output logic [3:0] CauseM // trap cause ); logic MIntGlobalEnM, SIntGlobalEnM; // Global interupt enables @@ -72,9 +71,8 @@ module trap ( assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW); assign ValidIntsM = {12{~Committed}} & EnabledIntsM; assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request. - assign DelegateM = `S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM[3:0]] : MEDELEG_REGW[CauseM]) & + assign DelegateM = `S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) & (PrivilegeModeW == `U_MODE | PrivilegeModeW == `S_MODE); - assign WFIStallM = wfiM & ~IntPendingM; /////////////////////////////////////////// // Trigger Traps and RET @@ -109,7 +107,7 @@ module trap ( else if (IllegalInstrFaultM) CauseM = 2; else if (InstrMisalignedFaultM) CauseM = 0; else if (BreakpointFaultM) CauseM = 3; - else if (EcallFaultM) CauseM = {{(`LOG_XLEN-4){1'b0}}, {2'b10}, PrivilegeModeW}; + else if (EcallFaultM) CauseM = {2'b10, PrivilegeModeW}; else if (LoadMisalignedFaultM) CauseM = 4; else if (StoreAmoMisalignedFaultM) CauseM = 6; else if (LoadPageFaultM) CauseM = 13; diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index 343cf1fdb..81f1997af 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -106,7 +106,7 @@ module wallypipelinedcore ( logic [1:0] PrivilegeModeW; logic [`XLEN-1:0] PTE; logic [1:0] PageType; - logic sfencevmaM, WFIStallM; + logic sfencevmaM; logic SelHPTW; // PMA checker signals @@ -162,7 +162,8 @@ module wallypipelinedcore ( logic CommittedF; logic BranchD, BranchE, JumpD, JumpE; logic DCacheStallM, ICacheStallF; - + logic wfiM, IntPendingM; + // instruction fetch unit: PC, branch prediction, instruction cache ifu ifu(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, @@ -265,7 +266,7 @@ module wallypipelinedcore ( .FCvtIntStallD, .FPUStallD, .DivBusyE, .FDivBusyE, .EcallFaultM, .BreakpointFaultM, - .WFIStallM, + .wfiM, .IntPendingM, // Stall & flush outputs .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW); @@ -292,13 +293,14 @@ module wallypipelinedcore ( .PrivilegeModeW, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .WFIStallM, .BigEndianM); + .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM); end else begin assign CSRReadValW = 0; assign UnalignedPCNextF = PC2NextF; assign RetM = 0; assign TrapM = 0; - assign WFIStallM = 0; + assign wfiM = 0; + assign IntPendingM = 0; assign sfencevmaM = 0; assign BigEndianM = 0; end diff --git a/testbench/common/wallyTracer.sv b/testbench/common/wallyTracer.sv index 4df1956ad..221c8d7f8 100644 --- a/testbench/common/wallyTracer.sv +++ b/testbench/common/wallyTracer.sv @@ -162,6 +162,7 @@ module wallyTracer(rvviTrace rvvi); CSRArray[12'h143] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; CSRArray[12'h142] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; CSRArray[12'h144] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW & & 12'h222 & testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW; + CSRArray[12'h14D] = testbench.dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // user CSRs CSRArray[12'h001] = testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; CSRArray[12'h002] = testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW; @@ -211,6 +212,7 @@ module wallyTracer(rvviTrace rvvi); CSRArray[12'h143] = CSRArrayOld[12'h143]; CSRArray[12'h142] = CSRArrayOld[12'h142]; CSRArray[12'h144] = CSRArrayOld[12'h144]; + CSRArray[12'h14D] = CSRArrayOld[12'h14D]; // user CSRs CSRArray[12'h001] = CSRArrayOld[12'h001]; CSRArray[12'h002] = CSRArrayOld[12'h002]; @@ -329,6 +331,7 @@ module wallyTracer(rvviTrace rvvi); CSRArrayOld[12'h143] = CSRArray[12'h143]; CSRArrayOld[12'h142] = CSRArray[12'h142]; CSRArrayOld[12'h144] = CSRArray[12'h144]; + CSRArrayOld[12'h14D] = CSRArray[12'h14D]; // user CSRs CSRArrayOld[12'h001] = CSRArray[12'h001]; CSRArrayOld[12'h002] = CSRArray[12'h002]; @@ -376,6 +379,7 @@ module wallyTracer(rvviTrace rvvi); assign #2 CSR_W[12'h143] = (CSRArrayOld[12'h143] != CSRArray[12'h143]) ? 1 : 0; assign #2 CSR_W[12'h142] = (CSRArrayOld[12'h142] != CSRArray[12'h142]) ? 1 : 0; assign #2 CSR_W[12'h144] = (CSRArrayOld[12'h144] != CSRArray[12'h144]) ? 1 : 0; + assign #2 CSR_W[12'h14D] = (CSRArrayOld[12'h14D] != CSRArray[12'h14D]) ? 1 : 0; assign #2 CSR_W[12'h001] = (CSRArrayOld[12'h001] != CSRArray[12'h001]) ? 1 : 0; assign #2 CSR_W[12'h002] = (CSRArrayOld[12'h002] != CSRArray[12'h002]) ? 1 : 0; assign #2 CSR_W[12'h003] = (CSRArrayOld[12'h003] != CSRArray[12'h003]) ? 1 : 0; @@ -412,6 +416,7 @@ module wallyTracer(rvviTrace rvvi); assign rvvi.csr_wb[0][0][12'h143] = CSR_W[12'h143]; assign rvvi.csr_wb[0][0][12'h142] = CSR_W[12'h142]; assign rvvi.csr_wb[0][0][12'h144] = CSR_W[12'h144]; + assign rvvi.csr_wb[0][0][12'h14D] = CSR_W[12'h14D]; assign rvvi.csr_wb[0][0][12'h001] = CSR_W[12'h001]; assign rvvi.csr_wb[0][0][12'h002] = CSR_W[12'h002]; assign rvvi.csr_wb[0][0][12'h003] = CSR_W[12'h003]; @@ -448,6 +453,7 @@ module wallyTracer(rvviTrace rvvi); assign rvvi.csr[0][0][12'h143] = CSRArray[12'h143]; assign rvvi.csr[0][0][12'h142] = CSRArray[12'h142]; assign rvvi.csr[0][0][12'h144] = CSRArray[12'h144]; + assign rvvi.csr[0][0][12'h14D] = CSRArray[12'h14D]; assign rvvi.csr[0][0][12'h001] = CSRArray[12'h001]; assign rvvi.csr[0][0][12'h002] = CSRArray[12'h002]; assign rvvi.csr[0][0][12'h003] = CSRArray[12'h003]; diff --git a/testbench/testbench-fp.sv b/testbench/testbench-fp.sv index d1f6f9b63..f250e8035 100644 --- a/testbench/testbench-fp.sv +++ b/testbench/testbench-fp.sv @@ -1,7 +1,8 @@ -/////////////////////////////////////////// + 64 bit conversions to the to-be-tested list @@ -270,27 +270,27 @@ module testbenchfp; end if (`D_SUPPORTED) begin // if double precision is supported if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested - Tests = {Tests, f64rv32cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b01}; - end - if (`XLEN == 64) begin // if 64-bit integers are being supported - Tests = {Tests, f64rv64cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b01}; - end - end - end + Tests = {Tests, f64rv32cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b01}; + end + if (`XLEN == 64) begin // if 64-bit integers are being supported + Tests = {Tests, f64rv64cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b01}; + end + end + end if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversions are being tested if(`F_SUPPORTED) begin // if single precision is supported // add the 64 <-> 32 bit conversions to the to-be-tested list @@ -397,27 +397,27 @@ module testbenchfp; end if (`F_SUPPORTED) begin // if single precision being supported if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested - Tests = {Tests, f32rv32cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b00}; - end - if (`XLEN == 64) begin // if 64-bit integers are supported - Tests = {Tests, f32rv64cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b00}; - end - end - end + Tests = {Tests, f32rv32cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b00}; + end + if (`XLEN == 64) begin // if 64-bit integers are supported + Tests = {Tests, f32rv64cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b00}; + end + end + end if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversion is being tested if(`ZFH_SUPPORTED) begin // add the 32 <-> 16 bit conversions to the to-be-tested list @@ -508,27 +508,27 @@ module testbenchfp; end if (`ZFH_SUPPORTED) begin // if half precision supported if (TEST === "cvtint"| TEST === "all") begin // if in conversions are being tested - Tests = {Tests, f16rv32cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b10}; - end - if (`XLEN == 64) begin // if 64-bit integers are supported - Tests = {Tests, f16rv64cvtint}; - // add the op-codes for these tests to the op-code list - OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; - WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; - // add what unit is used and the fmt to their lists (one for each test) - for(int i = 0; i<20; i++) begin - Unit = {Unit, `CVTINTUNIT}; - Fmt = {Fmt, 2'b10}; - end - end - end + Tests = {Tests, f16rv32cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b10}; + end + if (`XLEN == 64) begin // if 64-bit integers are supported + Tests = {Tests, f16rv64cvtint}; + // add the op-codes for these tests to the op-code list + OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL}; + WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1}; + // add what unit is used and the fmt to their lists (one for each test) + for(int i = 0; i<20; i++) begin + Unit = {Unit, `CVTINTUNIT}; + Fmt = {Fmt, 2'b10}; + end + end + end if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested // add the correct tests/op-ctrls/unit/fmt to their lists Tests = {Tests, f16cmp}; @@ -656,7 +656,8 @@ module testbenchfp; end // extract the inputs (X, Y, Z, SrcA) and the output (Ans, AnsFlg) from the current test vector - readvectors readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]), .VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA, + readvectors readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]), + .VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA, .Xs, .Ys, .Zs, .Unit(UnitVal), .Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal), .Xm, .Ym, .Zm, .DivStart, @@ -680,7 +681,7 @@ module testbenchfp; /////////////////////////////////////////////////////////////////////////////////////////////// // instantiate devices under test - if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "all") begin : fma + if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "sub" | TEST === "all") begin : fma fma fma(.Xs(Xs), .Ys(Ys), .Zs(Zs), .Xe(Xe), .Ye(Ye), .Ze(Ze), .Xm(Xm), .Ym(Ym), .Zm(Zm), @@ -1331,4 +1332,4 @@ module readvectors ( .Xm, .Ym, .Zm, .XNaN, .YNaN, .ZNaN, .XSNaN, .YSNaN, .ZSNaN, .XSubnorm, .XZero, .YZero, .ZZero, .XInf, .YInf, .ZInf, .XEn, .YEn, .ZEn, .XExpMax); -endmodule \ No newline at end of file +endmodule diff --git a/testbench/testbench-linux-imperas.sv b/testbench/testbench-linux-imperas.sv index 00167e5fd..d3d71626f 100644 --- a/testbench/testbench-linux-imperas.sv +++ b/testbench/testbench-linux-imperas.sv @@ -413,10 +413,11 @@ module testbench; end end - always @(dut.core.MTimerInt) void'(rvvi.net_push("MTimerInterrupt", dut.core.MTimerInt)); - always @(dut.core.MExtInt) void'(rvvi.net_push("MExternalInterrupt", dut.core.MExtInt)); - always @(dut.core.SExtInt) void'(rvvi.net_push("SExternalInterrupt", dut.core.SExtInt)); - always @(dut.core.MSwInt) void'(rvvi.net_push("MSWInterrupt", dut.core.MSwInt)); + always @(dut.core.MTimerInt) void'(rvvi.net_push("MTimerInterrupt", dut.core.MTimerInt)); + always @(dut.core.MExtInt) void'(rvvi.net_push("MExternalInterrupt", dut.core.MExtInt)); + always @(dut.core.SExtInt) void'(rvvi.net_push("SExternalInterrupt", dut.core.SExtInt)); + always @(dut.core.MSwInt) void'(rvvi.net_push("MSWInterrupt", dut.core.MSwInt)); + always @(dut.core.priv.priv.csr.csrs.csrs.STimerInt) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csrs.csrs.STimerInt)); final begin void'(rvviRefShutdown()); diff --git a/testbench/testbench.sv b/testbench/testbench.sv index f07cfef12..2bc3622c1 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -28,10 +28,10 @@ `include "wally-config.vh" `include "tests.vh" -`define PrintHPMCounters 1 -`define BPRED_LOGGER 1 -`define I_CACHE_ADDR_LOGGER 1 -`define D_CACHE_ADDR_LOGGER 1 +`define PrintHPMCounters 0 +`define BPRED_LOGGER 0 +`define I_CACHE_ADDR_LOGGER 0 +`define D_CACHE_ADDR_LOGGER 0 module testbench; parameter DEBUG=0; @@ -169,7 +169,8 @@ logic [3:0] dummy; logic InitializingMemories; integer ResetCount, ResetThreshold; logic InReset; - + logic Begin; + // instantiate device to be tested assign GPIOIN = 0; assign UARTSin = 1; @@ -417,7 +418,7 @@ logic [3:0] dummy; if(`PrintHPMCounters & `ZICOUNTERS_SUPPORTED) begin : HPMCSample integer HPMCindex; logic StartSampleFirst; - logic StartSampleDelayed; + logic StartSampleDelayed, BeginDelayed; logic EndSampleFirst, EndSampleDelayed; logic [`XLEN-1:0] InitialHPMCOUNTERH[`COUNTERS-1:0]; @@ -476,8 +477,11 @@ logic [3:0] dummy; assign StartSampleFirst = InReset; flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed); assign StartSample = StartSampleFirst & ~ StartSampleDelayed; - assign EndSample = DCacheFlushStart & ~DCacheFlushDone; + + flop #(1) BeginReg(clk, StartSampleFirst, BeginDelayed); + assign Begin = StartSampleFirst & ~ BeginDelayed; + end always @(negedge clk) begin @@ -528,7 +532,7 @@ logic [3:0] dummy; // initialize the branch predictor - if (`BPRED_SUPPORTED == 1) begin + if (`BPRED_SUPPORTED) begin integer adrindex; always @(*) begin @@ -551,55 +555,63 @@ logic [3:0] dummy; end - if (`I_CACHE_ADDR_LOGGER == 1) begin + if (`ICACHE_SUPPORTED && `I_CACHE_ADDR_LOGGER) begin int file; string LogFile; logic resetD, resetEdge; + logic Enable; + assign Enable = ~dut.core.StallD & ~dut.core.FlushD & dut.core.ifu.bus.icache.CacheRWF[1] & ~reset; flop #(1) ResetDReg(clk, reset, resetD); assign resetEdge = ~reset & resetD; initial begin LogFile = $psprintf("ICache.log"); file = $fopen(LogFile, "w"); + $fwrite(file, "BEGIN %s\n", memfilename); end + string HitMissString; + assign HitMissString = dut.core.ifu.bus.icache.icache.CacheHit ? "H" : "M"; always @(posedge clk) begin if(resetEdge) $fwrite(file, "TRAIN\n"); - if(StartSample) $fwrite(file, "BEGIN %s\n", memfilename); - if(~dut.core.StallD & ~dut.core.FlushD) begin - $fwrite(file, "%h R\n", dut.core.ifu.PCPF); + if(Begin) $fwrite(file, "BEGIN %s\n", memfilename); + if(Enable) begin // only log i cache reads + $fwrite(file, "%h R %s\n", dut.core.ifu.PCPF, HitMissString); end if(EndSample) $fwrite(file, "END %s\n", memfilename); end end - if (`D_CACHE_ADDR_LOGGER == 1) begin + if (`DCACHE_SUPPORTED && `D_CACHE_ADDR_LOGGER) begin int file; string LogFile; logic resetD, resetEdge; + string HitMissString; flop #(1) ResetDReg(clk, reset, resetD); assign resetEdge = ~reset & resetD; + assign HitMissString = dut.core.lsu.bus.dcache.dcache.CacheHit ? "H" : "M"; initial begin LogFile = $psprintf("DCache.log"); file = $fopen(LogFile, "w"); + $fwrite(file, "BEGIN %s\n", memfilename); end always @(posedge clk) begin if(resetEdge) $fwrite(file, "TRAIN\n"); - if(StartSample) $fwrite(file, "BEGIN %s\n", memfilename); + if(Begin) $fwrite(file, "BEGIN %s\n", memfilename); if(~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin if(dut.core.lsu.bus.dcache.CacheRWM == 2'b10) begin - $fwrite(file, "%h R\n", dut.core.lsu.PAdrM); + $fwrite(file, "%h R %s\n", dut.core.lsu.PAdrM, HitMissString); end else if (dut.core.lsu.bus.dcache.CacheRWM == 2'b01) begin - $fwrite(file, "%h W\n", dut.core.lsu.PAdrM); + $fwrite(file, "%h W %s\n", dut.core.lsu.PAdrM, HitMissString); end else if (dut.core.lsu.bus.dcache.CacheAtomicM[1] == 1'b1) begin // *** This may change - $fwrite(file, "%h A\n", dut.core.lsu.PAdrM); + $fwrite(file, "%h A %s\n", dut.core.lsu.PAdrM, HitMissString); end else if (dut.core.lsu.bus.dcache.FlushDCache) begin - $fwrite(file, "%h F\n", dut.core.lsu.PAdrM); + $fwrite(file, "%h F %s\n", dut.core.lsu.PAdrM, HitMissString); end end if(EndSample) $fwrite(file, "END %s\n", memfilename); end end - if (`BPRED_SUPPORTED == 1) begin + if (`BPRED_SUPPORTED) begin if (`BPRED_LOGGER) begin string direction; int file; diff --git a/testbench/testbench_imperas.sv b/testbench/testbench_imperas.sv index f63c640d7..56ca763af 100644 --- a/testbench/testbench_imperas.sv +++ b/testbench/testbench_imperas.sv @@ -198,10 +198,12 @@ module testbench; end - always @(dut.core.MTimerInt) void'(rvvi.net_push("MTimerInterrupt", dut.core.MTimerInt)); - always @(dut.core.MExtInt) void'(rvvi.net_push("MExternalInterrupt", dut.core.MExtInt)); - always @(dut.core.SExtInt) void'(rvvi.net_push("SExternalInterrupt", dut.core.SExtInt)); - always @(dut.core.MSwInt) void'(rvvi.net_push("MSWInterrupt", dut.core.MSwInt)); + always @(dut.core.MTimerInt) void'(rvvi.net_push("MTimerInterrupt", dut.core.MTimerInt)); + always @(dut.core.MExtInt) void'(rvvi.net_push("MExternalInterrupt", dut.core.MExtInt)); + always @(dut.core.SExtInt) void'(rvvi.net_push("SExternalInterrupt", dut.core.SExtInt)); + always @(dut.core.MSwInt) void'(rvvi.net_push("MSWInterrupt", dut.core.MSwInt)); + always @(dut.core.priv.priv.csr.csrs.csrs.STimerInt) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csrs.csrs.STimerInt)); + final begin void'(rvviRefShutdown()); diff --git a/testbench/tests.vh b/testbench/tests.vh index 79f100d4f..7f5ad4d0d 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -47,7 +47,9 @@ string tvpaths[] = '{ "ieu", "ebu", "csrwrites", - "priv" + "priv", + "ifu", + "fpu" }; string coremark[] = '{ diff --git a/tests/coverage/Makefile b/tests/coverage/Makefile index 7d4552af2..b2a2544d3 100644 --- a/tests/coverage/Makefile +++ b/tests/coverage/Makefile @@ -17,7 +17,7 @@ all: $(OBJECTS) # Change many things if bit width isn't 64 %.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile - riscv64-unknown-elf-gcc -g -o $@ -march=rv64gc_zba_zbb_zbc_zbs -mabi=lp64 -mcmodel=medany \ + riscv64-unknown-elf-gcc -g -o $@ -march=rv64gqc_zba_zbb_zbc_zbs_zfh -mabi=lp64 -mcmodel=medany \ -nostartfiles -T../../examples/link/link.ld $< riscv64-unknown-elf-objdump -S $@ > $@.objdump riscv64-unknown-elf-elf2hex --bit-width 64 --input $@ --output $@.memfile diff --git a/tests/coverage/fpu.S b/tests/coverage/fpu.S new file mode 100644 index 000000000..a349ac606 --- /dev/null +++ b/tests/coverage/fpu.S @@ -0,0 +1,90 @@ +/////////////////////////////////////////// +// fpu.S +// +// Written: David_Harris@hmc.edu 28 March 2023 +// +// Purpose: Test coverage for FPU +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +// load code to initalize stack, handle interrupts, terminate +#include "WALLY-init-lib.h" + +main: + + #bseti t0, zero, 14 # turn on FPU + csrs mstatus, t0 + + # Test legal instructions not covered elsewhere + flq ft0, 0(a0) + flh ft0, 8(a0) + fsq ft0, 0(a0) + fsh ft0, 8(a0) + + # Tests for fpu/fctrl.sv + fcvt.h.s ft1, ft0 + fcvt.q.s ft2, ft0 + fcvt.h.w ft3, a0 + fcvt.h.wu ft3, a0 + fcvt.h.l ft3, a0 + fcvt.h.lu ft3, a0 + fcvt.w.h a0, ft3 + fcvt.wu.h a0, ft3 + fcvt.l.h a0, ft3 + fcvt.lu.h a0, ft3 + fcvt.q.w ft3, a0 + fcvt.q.wu ft3, a0 + fcvt.q.l ft3, a0 + fcvt.q.lu ft3, a0 + fcvt.w.q a0, ft3 + fcvt.wu.q a0, ft3 + fcvt.l.q a0, ft3 + fcvt.lu.q a0, ft3 + + + // Tests verfying that half and quad floating point convertion instructions are not supported by rv64gc + # fcvt.h.d ft3, ft0 // Somehow this instruction is taking the route on line 124 + // idea: enable the Q extension for this to work properly? A: Q and halfs not supported in rv64gc + # fcvt.h.w ft3, a0 + # fcvt.w.h a0, ft0 + # fcvt.q.w ft3, a0 + # fcvt.w.q a0, ft0 + # fcvt.q.d ft3, ft0 + + .word 0x38007553 // Testing the all False case for 119 - funct7 under, op = 101 0011 + .word 0x40000053 // Line 145 All False Test case - illegal instruction? + .word 0xd0400053 // Line 156 All False Test case - illegal instruction? + .word 0xc0400053 // Line 162 All False Test case - illegal instruction? + .word 0xd2400053 // Line 168 All False Test case - illegal instruction? + .word 0xc2400053 // Line 174 All False Test case - illegal instruction? + + # Test illegal instructions are detected + .word 0x00000007 // illegal floating-point load (bad Funct3) + .word 0x00000027 // illegal floating-point store (bad Funct3) + .word 0x58F00053 // illegal fsqrt (bad Rs2D) + .word 0x20007053 // illegal fsgnj (bad Funct3) + .word 0x28007053 // illegal fmin/max (bad Funct3) + .word 0xA0007053 // illegal fcmp (bad Funct3) + .word 0xE0007053 // illegal fclass/fmv (bad Funct3) + .word 0xF0007053 // illegal fmv (bad Funct3) + .word 0x43007053 // illegal fcvt.d.* (bad Rs2D) + .word 0x42207053 // illegal fcvt.d.* (bad Rs2D[1]) + + j done + diff --git a/tests/coverage/ieu.S b/tests/coverage/ieu.S index e1b239371..3fd56686f 100644 --- a/tests/coverage/ieu.S +++ b/tests/coverage/ieu.S @@ -28,6 +28,11 @@ main: + # Division test (having trouble with buildroot) + li x11, 0x384000 + li x12, 0x1c2000 + divuw x9, x11, x12 + # Test clz with all bits being 0 li t0, 0 clz t1, t0 @@ -61,5 +66,6 @@ main: .word 0x6080101B // Illegal BMU similar to count word .word 0x6030101B // Illegal BMU similar to count word + j done diff --git a/tests/coverage/ifu.S b/tests/coverage/ifu.S new file mode 100644 index 000000000..9cde14ce2 --- /dev/null +++ b/tests/coverage/ifu.S @@ -0,0 +1,54 @@ +/////////////////////////////////////////// +// ifu.S +// +// Written: sriley@g.hmc.edu 28 March 2023 +// +// Purpose: Test coverage for IFU +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +// load code to initalize stack, handle interrupts, terminate +#include "WALLY-init-lib.h" + +main: + # turn floating point on + li t0, 0x2000 + csrs mstatus, t0 + + # calling compressed floating point load double instruction + //.hword 0x2000 // CL type compressed floating-point ld-->funct3,imm,rs1',imm,rd',op + // binary version 0000 0000 0000 0000 0010 0000 0000 0000 + mv s0, sp + c.fld fs0, 0(s0) + + c.fsd fs0, 0(s0) + + // c.fldsp fs0, 0 + .hword 0x2002 + + // c.fsdsp fs0, 0 + .hword 0xA002 + + //# Illegal compressed instruction with op = 01, instr[15:10] = 100111, and 0's everywhere else + //.hword 0x9C01 + + # Line Illegal compressed instruction + .hword 0x9C41 + + j done diff --git a/tests/coverage/priv.S b/tests/coverage/priv.S index 3aa3aea5c..c4e9e302d 100644 --- a/tests/coverage/priv.S +++ b/tests/coverage/priv.S @@ -36,4 +36,79 @@ main: addi t0, zero, 0 csrr t0, stimecmp + + # satp write with mstatus.TVM = 1 + bseti t0, zero, 20 + csrs mstatus, t0 + csrw satp, zero + + # STIMECMP from S mode + li t0, 1 + ecall # enter S-mode + csrw stimecmp, zero + li t0, 3 + ecall # return to M-mode + csrsi mcounteren, 2 # mcounteren_tm = 1 + li t0, 1 + ecall # supervisor mode again + csrw stimecmp, zero + li t0, 3 + ecall # machine mode again + + + + # Test write to STVAL, SCAUSE, SEPC, and STIMECMP CSRs + li t0, 0 + csrw stval, t0 + csrw scause, t0 + csrw sepc, t0 + csrw stimecmp, t0 + csrw scounteren, zero + csrw satp, zero + + + # Switch to machine mode + li a0, 3 + ecall + # Testing the HPMCOUNTERM performance counter: writing + # Base address is 2816 (MHPMCOUNTERBASE) + # There are 32 HPMCOUNTER registers + csrw 2816, t0 + csrw 2817, t0 + csrw 2818, t0 + csrw 2819, t0 + csrw 2820, t0 + csrw 2821, t0 + csrw 2822, t0 + csrw 2823, t0 + csrw 2824, t0 + csrw 2825, t0 + csrw 2826, t0 + csrw 2827, t0 + csrw 2828, t0 + csrw 2829, t0 + csrw 2830, t0 + csrw 2831, t0 + csrw 2832, t0 + csrw 2833, t0 + csrw 2834, t0 + csrw 2835, t0 + csrw 2836, t0 + csrw 2837, t0 + csrw 2838, t0 + csrw 2839, t0 + csrw 2840, t0 + csrw 2841, t0 + csrw 2842, t0 + csrw 2843, t0 + csrw 2844, t0 + csrw 2845, t0 + csrw 2846, t0 + csrw 2847, t0 + + # Testing the HPMCOUNTERM performance counter: reading + csrr t0, 2817 j done + + + diff --git a/tests/fp/combined_IF_vectors/IF_vectors/README b/tests/fp/combined_IF_vectors/IF_vectors/README new file mode 100644 index 000000000..bfbf368dd --- /dev/null +++ b/tests/fp/combined_IF_vectors/IF_vectors/README @@ -0,0 +1,4 @@ +This folder holds the archtest and testfloat vectors necessary fo evaluating performance +of standalone intdiv vs combined IFdivsqrt + +to generate vectors, uncomment line 8 in create_all_vectors.sh \ No newline at end of file diff --git a/tests/fp/combined_IF_vectors/create_IF_vectors.sh b/tests/fp/combined_IF_vectors/create_IF_vectors.sh new file mode 100755 index 000000000..d6b83f599 --- /dev/null +++ b/tests/fp/combined_IF_vectors/create_IF_vectors.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# create test vectors for stand alone int + +./extract_testfloat_vectors.py +./extract_arch_vectors.py + +# to create tvs for evaluation of combined IFdivsqrt +#./combined_IF_vectors/create_IF_vectors.sh \ No newline at end of file diff --git a/tests/fp/combined_IF_vectors/extract_arch_vectors.py b/tests/fp/combined_IF_vectors/extract_arch_vectors.py new file mode 100755 index 000000000..c80c7a843 --- /dev/null +++ b/tests/fp/combined_IF_vectors/extract_arch_vectors.py @@ -0,0 +1,251 @@ +#! /usr/bin/python3 + +# author: Alessandro Maiuolo +# contact: amaiuolo@g.hmc.edu +# date created: 3-29-2023 + +# extract all arch test vectors +import os +wally = os.popen('echo $WALLY').read().strip() + +def ext_bits(my_string): + target_len = 32 # we want 128 bits, div by 4 bc hex notation + zeroes_to_add = target_len - len(my_string) + return zeroes_to_add*"0" + my_string + +def twos_comp(b, x): + if b == 32: + return hex(0x100000000 - int(x,16))[2:] + elif b == 64: + return hex(0x10000000000000000 - int(x,16))[2:] + else: + return "UNEXPECTED_BITSIZE" + +def unpack_rf(packed): + bin_u = bin(int(packed, 16))[2:].zfill(8) # translate to binary + flags = hex(int(bin_u[3:],2))[2:].zfill(2) + rounding_mode = hex(int(bin_u[:3],2))[2:] + return flags, rounding_mode + +# rounding mode dictionary +round_dict = { + "rne":"0", + "rnm":"4", + "ru":"3", + "rz":"1", + "rd":"2", + "dyn":"7" +} + +# fcsr dictionary +fcsr_dict = { + "0":"rne", + "128":"rnm", + "96":"ru", + "32":"rz", + "64":"rd", + "224":"dyn" +} + +print("creating arch test vectors") + +class Config: + def __init__(self, bits, letter, op, filt, op_code): + self.bits = bits + self.letter = letter + self.op = op + self.filt = filt + self.op_code = op_code + +def create_vectors(my_config): + suite_folder_num = my_config.bits + if my_config.bits == 64 and my_config.letter == "F": suite_folder_num = 32 + source_dir1 = "{}/addins/riscv-arch-test/riscv-test-suite/rv{}i_m/{}/src/".format(wally, suite_folder_num, my_config.letter) + source_dir2 = "{}/tests/riscof/work/riscv-arch-test/rv{}i_m/{}/src/".format(wally, my_config.bits, my_config.letter) + dest_dir = "{}/tests/fp/combined_IF_vectors/IF_vectors/".format(wally) + all_vectors1 = os.listdir(source_dir1) + + filt_vectors1 = [v for v in all_vectors1 if my_config.filt in v] + # print(filt_vectors1) + filt_vectors2 = [v + "/ref/Reference-sail_c_simulator.signature" for v in all_vectors1 if my_config.filt in v] + + # iterate through all vectors + for i in range(len(filt_vectors1)): + vector1 = filt_vectors1[i] + vector2 = filt_vectors2[i] + operation = my_config.op_code + rounding_mode = "X" + flags = "XX" + # use name to create our new tv + dest_file = open("{}cvw_{}_{}.tv".format(dest_dir, my_config.bits, vector1[:-2]), 'a') + # open vectors + src_file1 = open(source_dir1 + vector1,'r') + src_file2 = open(source_dir2 + vector2,'r') + # for each test in the vector + reading = True + src_file2.readline() #skip first bc junk + # print(my_config.bits, my_config.letter) + if my_config.letter == "F" and my_config.bits == 64: + reading = True + # print("trigger 64F") + #skip first 2 lines bc junk + src_file2.readline() + while reading: + # get answer and flags from Ref...signature + # answers are before deadbeef (first line of 4) + # flags are after deadbeef (third line of 4) + answer = src_file2.readline().strip() + deadbeef = src_file2.readline().strip() + # print(answer) + if not (answer == "e7d4b281" and deadbeef == "6f5ca309"): # if there is still stuff to read + # get flags + packed = src_file2.readline().strip()[6:] + flags, rounding_mode = unpack_rf(packed) + # skip 00000000 buffer + src_file2.readline() + + # parse through .S file + detected = False + done = False + op1val = "0" + op2val = "0" + while not (detected or done): + # print("det1") + line = src_file1.readline() + # print(line) + if "op1val" in line: + # print("det2") + # parse line + op1val = line.split("op1val")[1].split("x")[1].split(";")[0] + if my_config.op != "fsqrt": # sqrt doesn't have two input vals + op2val = line.split("op2val")[1].split("x")[1].strip() + if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there + else: + op2val = 32*"X" + # go to next test in vector + detected = True + elif "RVTEST_CODE_END" in line: + done = True + # put it all together + if not done: + translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()), flags, rounding_mode) + dest_file.write(translation + "\n") + else: + # print("read false") + reading = False + elif my_config.letter == "M" and my_config.bits == 64: + reading = True + #skip first 2 lines bc junk + src_file2.readline() + while reading: + # print("trigger 64M") + # get answer from Ref...signature + # answers span two lines and are reversed + answer2 = src_file2.readline().strip() + answer1 = src_file2.readline().strip() + answer = answer1 + answer2 + # print(answer1,answer2) + if not (answer2 == "e7d4b281" and answer1 == "6f5ca309"): # if there is still stuff to read + # parse through .S file + detected = False + done = False + op1val = "0" + op2val = "0" + while not (detected or done): + # print("det1") + line = src_file1.readline() + # print(line) + if "op1val" in line: + # print("det2") + # parse line + op1val = line.split("op1val")[1].split("x")[1].split(";")[0] + if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling + op1val = twos_comp(my_config.bits, op1val) + if my_config.op != "fsqrt": # sqrt doesn't have two input vals, unnec here but keeping for later + op2val = line.split("op2val")[1].split("x")[1].strip() + if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there + if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling + op2val = twos_comp(my_config.bits, op2val) + # go to next test in vector + detected = True + elif "RVTEST_CODE_END" in line: + done = True + # ints don't have flags + flags = "XX" + # put it all together + if not done: + translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()), flags.strip(), rounding_mode) + dest_file.write(translation + "\n") + else: + # print("read false") + reading = False + else: + while reading: + # get answer and flags from Ref...signature + answer = src_file2.readline() + # print(answer) + packed = src_file2.readline()[6:] + # print(packed) + if len(packed.strip())>0: # if there is still stuff to read + # print("packed") + # parse through .S file + detected = False + done = False + op1val = "0" + op2val = "0" + while not (detected or done): + # print("det1") + line = src_file1.readline() + # print(line) + if "op1val" in line: + # print("det2") + # parse line + op1val = line.split("op1val")[1].split("x")[1].split(";")[0] + if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling + op1val = twos_comp(my_config.bits, op1val) + if my_config.op != "fsqrt": # sqrt doesn't have two input vals + op2val = line.split("op2val")[1].split("x")[1].strip() + if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there + if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling + op2val = twos_comp(my_config.bits, op2val) + # go to next test in vector + detected = True + elif "RVTEST_CODE_END" in line: + done = True + # rounding mode for float + if not done and (my_config.op == "fsqrt" or my_config.op == "fdiv"): + flags, rounding_mode = unpack_rf(packed) + + # put it all together + if not done: + translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()), flags, rounding_mode) + dest_file.write(translation + "\n") + else: + # print("read false") + reading = False + print("out") + dest_file.close() + src_file1.close() + src_file2.close() + +config_list = [ +Config(32, "M", "div", "div_", 0), +Config(32, "F", "fdiv", "fdiv", 1), +Config(32, "F", "fsqrt", "fsqrt", 2), +Config(32, "M", "rem", "rem-", 3), +Config(32, "M", "divu", "divu-", 4), +Config(32, "M", "remu", "remu-", 5), +Config(64, "M", "div", "div-", 0), +Config(64, "F", "fdiv", "fdiv", 1), +Config(64, "F", "fsqrt", "fsqrt", 2), +Config(64, "M", "rem", "rem-", 3), +Config(64, "M", "divu", "divu-", 4), +Config(64, "M", "remu", "remu-", 5), +Config(64, "M", "divw", "divw-", 6), +Config(64, "M", "divuw", "divuw-", 7), +Config(64, "M", "remw", "remw-", 8), +Config(64, "M", "remuw", "remuw-", 9) +] + +for c in config_list: + create_vectors(c) \ No newline at end of file diff --git a/tests/fp/combined_IF_vectors/extract_testfloat_vectors.py b/tests/fp/combined_IF_vectors/extract_testfloat_vectors.py new file mode 100755 index 000000000..07047be25 --- /dev/null +++ b/tests/fp/combined_IF_vectors/extract_testfloat_vectors.py @@ -0,0 +1,79 @@ +#! /usr/bin/python3 +# extract sqrt and float div testfloat vectors + +# author: Alessandro Maiuolo +# contact: amaiuolo@g.hmc.edu +# date created: 3-29-2023 + +import os +wally = os.popen('echo $WALLY').read().strip() +# print(wally) + +def ext_bits(my_string): + target_len = 32 # we want 128 bits, div by 4 bc hex notation + zeroes_to_add = target_len - len(my_string) + return zeroes_to_add*"0" + my_string + +# rounding mode dictionary +round_dict = { + "rne":"0", + "rnm":"4", + "ru":"3", + "rz":"1", + "rd":"2", + "dyn":"7" +} + + +print("creating testfloat div test vectors") + +source_dir = "{}/tests/fp/vectors/".format(wally) +dest_dir = "{}/tests/fp/combined_IF_vectors/IF_vectors/".format(wally) +all_vectors = os.listdir(source_dir) + +div_vectors = [v for v in all_vectors if "div" in v] + +# iterate through all float div vectors +for vector in div_vectors: + # use name to determine configs + config_list = vector.split(".")[0].split("_") + operation = "1" #float div + rounding_mode = round_dict[str(config_list[2])] + # use name to create our new tv + dest_file = open(dest_dir + "cvw_" + vector, 'a') + # open vector + src_file = open(source_dir + vector,'r') + # for each test in the vector + for i in src_file.readlines(): + translation = "" # this stores the test that we are currently working on + [input_1, input_2, answer, flags] = i.split("_") # separate inputs, answer, and flags + # put it all together, strip nec for removing \n on the end of the flags + translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(input_1), ext_bits(input_2), ext_bits(answer), flags.strip(), rounding_mode) + dest_file.write(translation + "\n") + dest_file.close() + src_file.close() + + +print("creating testfloat sqrt test vectors") + +sqrt_vectors = [v for v in all_vectors if "sqrt" in v] + +# iterate through all float div vectors +for vector in sqrt_vectors: + # use name to determine configs + config_list = vector.split(".")[0].split("_") + operation = "2" #sqrt + rounding_mode = round_dict[str(config_list[2])] + # use name to create our new tv + dest_file = open(dest_dir + "cvw_" + vector, 'a') + # open vector + src_file = open(source_dir + vector,'r') + # for each test in the vector + for i in src_file.readlines(): + translation = "" # this stores the test that we are currently working on + [input_1, answer, flags] = i.split("_") # separate inputs, answer, and flags + # put it all together, strip nec for removing \n on the end of the flags + translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(input_1), "X"*32, ext_bits(answer), flags.strip(), rounding_mode) + dest_file.write(translation + "\n") + dest_file.close() + src_file.close() \ No newline at end of file diff --git a/tests/fp/create_all_vectors.sh b/tests/fp/create_all_vectors.sh index f1ba3625c..38cfd555a 100755 --- a/tests/fp/create_all_vectors.sh +++ b/tests/fp/create_all_vectors.sh @@ -3,3 +3,6 @@ mkdir -p vectors ./create_vectors.sh ./remove_spaces.sh + +# to create tvs for evaluation of combined IFdivsqrt +#./combined_IF_vectors/create_IF_vectors.sh \ No newline at end of file diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-01.reference_output index a9c3da2c0..fb24280ad 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-01.reference_output @@ -53,7 +53,7 @@ 8000000b # mcause value from m ext interrupt 00000000 # mtval for mext interrupt (0x0) 00001880 # masked out mstatus.MPP = 11, mstatus.MPIE = 1, and mstatus.MIE = 0 -fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable) +0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable) 00000222 # mideleg after attempted write of all 1's (only some bits are writeable) # skipping instruction address fault since they're impossible with compressed instrs enabled 00000001 # mcause from an instruction access fault 00000000 # mtval of faulting instruction address (0x0) diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-s-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-s-01.reference_output index e57184719..9dbdd8337 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-s-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-s-01.reference_output @@ -48,7 +48,7 @@ 00000009 # scause from S mode ecall 00000000 # stval of ecall (*** defined to be zero for now) 00000800 # masked out mstatus.mpp = 1, mstatus.MPIE = 0, and mstatus.MIE = 0 -fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable) +0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable) 00000222 # mideleg after attempted write of all 1's (only some bits are writeable) 0000000b # scause from M mode ecall 00000000 # stval of ecall (*** defined to be zero for now) diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-u-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-u-01.reference_output index 5c6d8378d..b19a0c21e 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-u-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-u-01.reference_output @@ -45,7 +45,7 @@ 00000008 # scause from U mode ecall 00000000 # stval of ecall (*** defined to be zero for now) 00000000 # masked out mstatus.mpp = 0, mstatus.MPIE = 0, and mstatus.MIE = 0 -fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable) +0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable) 00000222 # mideleg after attempted write of all 1's (only some bits are writeable) 0000000b # scause from M mode ecall 00000000 # stval of ecall (*** defined to be zero for now) diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-01.reference_output index 78e096cee..39ec3ad42 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-01.reference_output @@ -108,8 +108,8 @@ 00000000 00001880 # masked out mstatus.MPP = 11, mstatus.MPIE = 1, and mstatus.MIE = 0 00000000 -fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable) -ffffffff +0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable) +00000000 00000222 # mideleg after attempted write of all 1's (only some bits are writeable) 00000000 # skipping instruction address fault since they're impossible with compressed instrs enabled 00000001 # mcause from an instruction access fault diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-s-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-s-01.reference_output index dc5acb4d6..4c3031eb2 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-s-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-s-01.reference_output @@ -98,8 +98,8 @@ 00000000 00000800 # masked out mstatus.mpp = 1, mstatus.MPIE = 0, and mstatus.MIE = 0 00000000 -fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable) -ffffffff +0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable) +00000000 00000222 # mideleg after attempted write of all 1's (only some bits are writeable) 00000000 0000000b # scause from M mode ecall diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-u-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-u-01.reference_output index 7afec5268..2d1d16d27 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-u-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-u-01.reference_output @@ -92,8 +92,8 @@ 00000000 00000000 # masked out mstatus.mpp = 0, mstatus.MPIE = 0, and mstatus.MIE = 0 00000000 -fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable) -ffffffff +0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable) +00000000 00000222 # mideleg after attempted write of all 1's (only some bits are writeable) 00000000 0000000b # scause from M mode ecall