diff --git a/src/lsu/lsu.sv b/src/lsu/lsu.sv index 8c9ff05f7..aeadec262 100644 --- a/src/lsu/lsu.sv +++ b/src/lsu/lsu.sv @@ -185,7 +185,9 @@ module lsu import cvw::*; #(parameter cvw_t P) ( ///////////////////////////////////////////////////////////////////////////////////////////// if(P.ZICSR_SUPPORTED == 1) begin : dmmu logic DisableTranslation; // During HPTW walk or D$ flush disable virtual memory address translation + logic WriteAccessM; assign DisableTranslation = SelHPTW | FlushDCacheM; + assign WriteAccessM = PreLSURWM[0] | (|CMOpM); mmu #(.P(P), .TLB_ENTRIES(P.DTLB_ENTRIES), .IMMU(0)) dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]), @@ -197,7 +199,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw. .UpdateDA(DataUpdateDAM), .AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0), - .WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]), + .WriteAccessM, .ReadAccessM(PreLSURWM[1]), .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); end else begin // No MMU, so no PMA/page faults and no address translation diff --git a/tests/custom/simple/Makefile b/tests/custom/simple/Makefile index f85aedd5c..2c8c2bdab 100644 --- a/tests/custom/simple/Makefile +++ b/tests/custom/simple/Makefile @@ -4,7 +4,7 @@ ROOT := .. LIBRARY_DIRS := ${ROOT}/crt0 LIBRARY_FILES := crt0 -MARCH :=-march=rv64imfdc +MARCH :=-march=rv64imfdczicbom MABI :=-mabi=lp64d LINKER := ${ROOT}/linker8000-0000.x LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles -Wl,-Map=$(TARGET).map diff --git a/tests/custom/simple/cbom.s b/tests/custom/simple/cbom.s new file mode 100644 index 000000000..2cd90949a --- /dev/null +++ b/tests/custom/simple/cbom.s @@ -0,0 +1,351 @@ +# Written: ross1728@gmail.com Rose Thompson 17 August 2023 +# Modified: +# Purpose: Tests the 3 Zicbom cache instructions which all operate on cacheline +# granularity blocks of memory. Invalidate: Clears valid and dirty bits +# and does not write back. Clean: Writes back dirty cacheline if needed +# and clears dirty bit. Does NOT clear valid bit. Flush: Cleans and then +# Invalidates. These operations apply to all caches in the memory system. +# The tests are divided into three parts one for the data cache, instruction cache +# and checks to verify the uncached regions of memory cause exceptions. +# ----------- +# Copyright (c) 2020. RISC-V International. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause +# ----------- +# +# This assembly file tests the fence.i instruction of the RISC-V Zifencei extension. +# + +.section .text +.globl CBOMTest +.type CBOMTest, @function +CBOMTest: + # *** TODO + # first need to discover the length of the cacheline. + # for now assume it is 64 bytes + + addi sp, sp, -16 + sd s0, 0(sp) + sd ra, 8(sp) + + la s0, signature + + ################################################################################ + # INVALIDATE D$ + ################################################################################ + + # theory of operation + # 1. Read several cachelines of data from memory into the d cache and copy to a second region of memory + # 2. Then verify the second region has the same data + # 3. Invalidate the second region + # 4. Verify the second region has the original invalid data + # DON'T batch each step. We want to see the transition between cachelines. The current should be invalidated + # but the next should have the copied data. + + # step 1 +CBOMTest_inval_step1: + la a0, SourceData + la a1, Destination1 + li a2, 64 + jal ra, memcpy8 + + # step 2 +CBOMTest_inval_step2: + la a0, SourceData + la a1, Destination1 + li a2, 64 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + # step 3 +CBOMTest_inval_step3: + la a1, Destination1 + cbo.inval (a1) + # step 4 (should be Invalid) + la a0, DeadBeafData1 + la a1, Destination1 + li a2, 8 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + # step 4 next line (should still be valid) +CBOMTest_inval_step4: + la a0, SourceData+64 + la a1, Destination1+64 + li a2, 8 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + # step 3 (Invalidate all remaining lines) +CBOMTest_inval_step3_all: + la a1, Destination1+64 + cbo.inval (a1) + cbo.inval (a1) # verify invalidating an already non present line does not cause an issue. + la a1, Destination1+128 + cbo.inval (a1) + la a1, Destination1+192 + cbo.inval (a1) + la a1, Destination1+256 + cbo.inval (a1) + la a1, Destination1+320 + cbo.inval (a1) + la a1, Destination1+384 + cbo.inval (a1) + la a1, Destination1+448 + cbo.inval (a1) + + # step 4 All should be invalid +CBOMTest_inval_step4_all: + la a0, DeadBeafData1 + la a1, Destination1 + li a2, 64 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + ################################################################################ + # Clean D$ + ################################################################################ + + # theory of operation + # 1. Read several cachelines of data from memory into the d cache and copy to a second region of memory + # 2. Then verify the second region has the same data + # 3. Invalidate the second region + # 4. Verify the second region has the original invalid data + # 5. Repeat step 1 + # 6. Clean cachelines + # 7. Verify the second region has the same data + # 8. Invalidate the second region + # 9. Verify again but this time it should contain the same data + # DON'T batch each step. We want to see the transition between cachelines. The current should be invalidated + # but the next should have the copied data. + + # step 1 +CBOMTest_clean_step1: + la a0, SourceData + la a1, Destination2 + li a2, 64 + jal ra, memcpy8 + + # step 2 +CBOMTest_clean_step2: + la a0, SourceData + la a1, Destination2 + li a2, 64 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + # step 3 +CBOMTest_clean_step3: + la a1, Destination2 + cbo.inval (a1) + la a1, Destination2+64 + cbo.inval (a1) + la a1, Destination2+128 + cbo.inval (a1) + la a1, Destination2+192 + cbo.inval (a1) + la a1, Destination2+256 + cbo.inval (a1) + la a1, Destination2+320 + cbo.inval (a1) + la a1, Destination2+384 + cbo.inval (a1) + la a1, Destination2+448 + cbo.inval (a1) + + # step 4 All should be invalid +CBOMTest_clean_step4: + la a0, DeadBeafData1 + la a1, Destination2 + li a2, 64 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + # step 5 +CBOMTest_clean_step5: + la a0, SourceData + la a1, Destination2 + li a2, 64 + jal ra, memcpy8 + + # step 6 only clean 1 line +CBOMTest_clean_step6: + la a1, Destination2 + cbo.clean (a1) + + # step 7 only check that 1 line +CBOMTest_clean_step7: + la a0, SourceData + la a1, Destination2 + li a2, 8 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + # step 8 invalidate that 1 line and the next +CBOMTest_clean_step8: + la a1, Destination2 + cbo.inval (a1) + la a1, Destination2+64 + cbo.inval (a1) + + # step 9 that 1 line should contain the valid data +CBOMTest_clean_step9_line1: + la a0, SourceData + la a1, Destination2 + li a2, 8 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + # step 9 the next should contain the invalid data +CBOMTest_clean_step9_line2: + la a0, DeadBeafData1 + la a1, Destination2+64 + li a2, 8 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + # step 5 # now recopy the one we just corrupted +CBOMTest_clean_step5_recopy_line2: + la a0, SourceData+64 + la a1, Destination2+64 + li a2, 8 + jal ra, memcpy8 + + # step 6 # clean the remaining +CBOMTest_clean_step6_clean_all: + la a1, Destination2+64 + cbo.clean (a1) + la a1, Destination2+128 + cbo.clean (a1) + la a1, Destination2+192 + cbo.clean (a1) + la a1, Destination2+256 + cbo.clean (a1) + la a1, Destination2+320 + cbo.clean (a1) + la a1, Destination2+384 + cbo.clean (a1) + la a1, Destination2+448 + cbo.clean (a1) + + # step 8 # invalidate all remaining +CBOMTest_clean_step7_invalidate_all: + la a1, Destination2 + cbo.inval (a1) + la a1, Destination2+64 + cbo.inval (a1) + la a1, Destination2+128 + cbo.inval (a1) + la a1, Destination2+192 + cbo.inval (a1) + la a1, Destination2+256 + cbo.inval (a1) + la a1, Destination2+320 + cbo.inval (a1) + la a1, Destination2+384 + cbo.inval (a1) + la a1, Destination2+448 + cbo.inval (a1) + + # step 9 # check all +CBOMTest_clean_step9_check_all: + la a0, SourceData + la a1, Destination2 + li a2, 64 + jal ra, memcmp8 + sd a0, 0(s0) # should be -1 + addi s0, s0, 8 + + ld s0, 0(sp) + ld ra, 8(sp) + addi sp, sp, 16 + ret + + +.section .text +.type memcpy8, @function +memcpy8: + # a0 is the source + # a1 is the dst + # a2 is the number of 8 byte words + mv t0, a0 + mv t1, a1 + li t2, 0 +memcpy8_loop: + ld t3, 0(t0) + sd t3, 0(t1) + addi t0, t0, 8 + addi t1, t1, 8 + addi t2, t2, 1 + blt t2, a2, memcpy8_loop + ret + +.section .text +.type memcmp8, @function +# returns which index mismatch, -1 if none +memcmp8: + # a0 is the source1 + # a1 is the source2 + # a2 is the number of 8 byte words + mv t0, a0 + mv t1, a1 + li t2, 0 +memcmp8_loop: + ld t3, 0(t0) + ld t4, 0(t1) + bne t3, t4, memcmp8_ne + addi t0, t0, 8 + addi t1, t1, 8 + addi t2, t2, 1 + blt t2, a2, memcmp8_loop + li a0, -1 + ret +memcmp8_ne: + mv a0, t2 + ret + + + +.data +.align 7 + +DeadBeafData1: + .fill 64, 8, 0xdeadbeefdeadbeef +SourceData: + .int 0, 1, 2, 3, 4, 5, 6, 7 + .int 8, 9, 10, 11, 12, 13, 14, 15 + .int 16, 17, 18, 19, 20, 21, 22, 23 + .int 24, 25, 26, 27, 28, 29, 30, 31 + .int 32, 33, 34, 35, 36, 37, 38, 39 + .int 40, 41, 42, 43, 44, 45, 46, 47 + .int 48, 49, 50, 51, 52, 53, 54, 55 + .int 56, 57, 58, 59, 60, 61, 62, 63 + .int 64, 65, 66, 67, 68, 69, 70, 71 + .int 72, 73, 74, 75, 76, 77, 79, 79 + .int 80, 81, 82, 83, 84, 85, 86, 87 + .int 88, 89, 90, 91, 92, 93, 94, 95 + .int 96, 97, 98, 99, 100, 101, 102, 103 + .int 104, 105, 106, 107, 108, 109, 110, 111 + .int 112, 113, 114, 115, 116, 117, 118, 119 + .int 120, 121, 122, 123, 124, 125, 126, 127 + +Destination1: + .fill 64, 8, 0xdeadbeefdeadbeef +Destination2: + .fill 64, 8, 0xdeadbeefdeadbeef +Destination3: + .fill 64, 8, 0xdeadbeefdeadbeef +Destination4: + .fill 64, 8, 0xdeadbeefdeadbeef + +signature: + .fill 16, 8, 0x0bad0bad0bad0bad + diff --git a/tests/custom/simple/header.h b/tests/custom/simple/header.h index 973bdd59a..a237e8c17 100644 --- a/tests/custom/simple/header.h +++ b/tests/custom/simple/header.h @@ -12,4 +12,5 @@ void global_hist_3_space_test(); void global_hist_4_space_test(); void global_hist_6_space_test(); void oneLoopTest(); +void CBOMTest(); #endif diff --git a/tests/custom/simple/main.c b/tests/custom/simple/main.c index bebd96f6b..d1af33ab1 100644 --- a/tests/custom/simple/main.c +++ b/tests/custom/simple/main.c @@ -8,7 +8,8 @@ int main(){ global_hist_3_space_test(); global_hist_2_space_test(); global_hist_1_space_test(); - global_hist_0_space_test(); + global_hist_0_space_test(); + CBOMTest(); int res = 1; if (res < 0) { fail();