Merge pull request #540 from davidharrishmc/dev

Fix Timer Interrupt Issue #530 and coverage/tlbNAPOT tests #457
This commit is contained in:
Rose Thompson 2023-12-21 12:30:06 -08:00 committed by GitHub
commit b701cbf823
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 89 additions and 48 deletions

View File

@ -35,7 +35,7 @@ localparam XLEN = 32'd32;
// IEEE 754 compliance // IEEE 754 compliance
localparam IEEE754 = 0; localparam IEEE754 = 0;
localparam MISA = (32'h00000104 | 1 << 1 | 1 << 20 | 1 << 18 | 1 << 12 | 1 << 0 | 1 <<3 | 1 << 5); localparam MISA = (32'h00000104 | 1 << 20 | 1 << 18 | 1 << 12 | 1 << 0 | 1 <<3 | 1 << 5);
localparam ZICSR_SUPPORTED = 1; localparam ZICSR_SUPPORTED = 1;
localparam ZIFENCEI_SUPPORTED = 1; localparam ZIFENCEI_SUPPORTED = 1;
localparam COUNTERS = 12'd32; localparam COUNTERS = 12'd32;

View File

@ -34,7 +34,7 @@ localparam XLEN = 32'd64;
localparam IEEE754 = 0; localparam IEEE754 = 0;
// MISA RISC-V configuration per specification // MISA RISC-V configuration per specification
localparam MISA = (32'h00000104 | 1 << 1 | 1 << 5 | 1 << 3 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0); localparam MISA = (32'h00000104 | 1 << 5 | 1 << 3 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0);
localparam ZICSR_SUPPORTED = 1; localparam ZICSR_SUPPORTED = 1;
localparam ZIFENCEI_SUPPORTED = 1; localparam ZIFENCEI_SUPPORTED = 1;
localparam COUNTERS = 12'd32; localparam COUNTERS = 12'd32;

View File

@ -17,7 +17,7 @@ all: riscoftests memfiles coveragetests
wally-riscv-arch-test: wallyriscoftests memfiles wally-riscv-arch-test: wallyriscoftests memfiles
coverage: coverage: cov/rv64gc_arch64i.ucdb
#make -C ../tests/coverage --jobs #make -C ../tests/coverage --jobs
#iter-elf.bash --cover --search ../tests/coverage #iter-elf.bash --cover --search ../tests/coverage
vcover merge -out cov/cov.ucdb cov/rv64gc_arch64i.ucdb cov/rv64gc*.ucdb -logfile cov/log vcover merge -out cov/cov.ucdb cov/rv64gc_arch64i.ucdb cov/rv64gc*.ucdb -logfile cov/log

View File

@ -51,9 +51,13 @@
--override cpu/unaligned=T # Zicclsm (should be true) --override cpu/unaligned=T # Zicclsm (should be true)
--override cpu/ignore_non_leaf_DAU=1 --override cpu/ignore_non_leaf_DAU=1
--override cpu/wfi_is_nop=T --override cpu/wfi_is_nop=T
--override cpu/misa_Extensions_mask=0x0 --override cpu/misa_Extensions_mask=0x0 # MISA not writable
--override cpu/Sstc=T --override cpu/Sstc=T
# unsuccessfully attempt to add B extension (DH 12/21/23)
#--override cpu/add_Extensions="B"
#--override cpu/misa_Extensions=0x0014112F
# Enable SVADU hardware update of A/D bits when menvcfg.ADUE=1 # Enable SVADU hardware update of A/D bits when menvcfg.ADUE=1
--override cpu/Svadu=T --override cpu/Svadu=T
#--override cpu/updatePTEA=F #--override cpu/updatePTEA=F

View File

@ -37,17 +37,17 @@ module adrdecs import cvw::*; #(parameter cvw_t P) (
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111); localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
// Determine which region of physical memory (if any) is being accessed // Determine which region of physical memory (if any) is being accessed
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[11]); adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[1]);
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[10]); adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[2]);
adrdec #(P.PA_BITS) ddr4dec(PhysicalAddress, P.EXT_MEM_BASE[P.PA_BITS-1:0], P.EXT_MEM_RANGE[P.PA_BITS-1:0], P.EXT_MEM_SUPPORTED, AccessRWXC, Size, SUPPORTED_SIZE, SelRegions[9]); adrdec #(P.PA_BITS) ddr4dec(PhysicalAddress, P.EXT_MEM_BASE[P.PA_BITS-1:0], P.EXT_MEM_RANGE[P.PA_BITS-1:0], P.EXT_MEM_SUPPORTED, AccessRWXC, Size, SUPPORTED_SIZE, SelRegions[3]);
adrdec #(P.PA_BITS) bootromdec(PhysicalAddress, P.BOOTROM_BASE[P.PA_BITS-1:0], P.BOOTROM_RANGE[P.PA_BITS-1:0], P.BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[8]); adrdec #(P.PA_BITS) bootromdec(PhysicalAddress, P.BOOTROM_BASE[P.PA_BITS-1:0], P.BOOTROM_RANGE[P.PA_BITS-1:0], P.BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[4]);
adrdec #(P.PA_BITS) uncoreramdec(PhysicalAddress, P.UNCORE_RAM_BASE[P.PA_BITS-1:0], P.UNCORE_RAM_RANGE[P.PA_BITS-1:0], P.UNCORE_RAM_SUPPORTED, AccessRWXC, Size, SUPPORTED_SIZE, SelRegions[7]); adrdec #(P.PA_BITS) uncoreramdec(PhysicalAddress, P.UNCORE_RAM_BASE[P.PA_BITS-1:0], P.UNCORE_RAM_RANGE[P.PA_BITS-1:0], P.UNCORE_RAM_SUPPORTED, AccessRWXC, Size, SUPPORTED_SIZE, SelRegions[5]);
adrdec #(P.PA_BITS) clintdec(PhysicalAddress, P.CLINT_BASE[P.PA_BITS-1:0], P.CLINT_RANGE[P.PA_BITS-1:0], P.CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[6]); adrdec #(P.PA_BITS) clintdec(PhysicalAddress, P.CLINT_BASE[P.PA_BITS-1:0], P.CLINT_RANGE[P.PA_BITS-1:0], P.CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[6]);
adrdec #(P.PA_BITS) gpiodec(PhysicalAddress, P.GPIO_BASE[P.PA_BITS-1:0], P.GPIO_RANGE[P.PA_BITS-1:0], P.GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[5]); adrdec #(P.PA_BITS) gpiodec(PhysicalAddress, P.GPIO_BASE[P.PA_BITS-1:0], P.GPIO_RANGE[P.PA_BITS-1:0], P.GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[7]);
adrdec #(P.PA_BITS) uartdec(PhysicalAddress, P.UART_BASE[P.PA_BITS-1:0], P.UART_RANGE[P.PA_BITS-1:0], P.UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[4]); adrdec #(P.PA_BITS) uartdec(PhysicalAddress, P.UART_BASE[P.PA_BITS-1:0], P.UART_RANGE[P.PA_BITS-1:0], P.UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[8]);
adrdec #(P.PA_BITS) plicdec(PhysicalAddress, P.PLIC_BASE[P.PA_BITS-1:0], P.PLIC_RANGE[P.PA_BITS-1:0], P.PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[3]); adrdec #(P.PA_BITS) plicdec(PhysicalAddress, P.PLIC_BASE[P.PA_BITS-1:0], P.PLIC_RANGE[P.PA_BITS-1:0], P.PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[9]);
adrdec #(P.PA_BITS) sdcdec(PhysicalAddress, P.SDC_BASE[P.PA_BITS-1:0], P.SDC_RANGE[P.PA_BITS-1:0], P.SDC_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE & 4'b1100, SelRegions[2]); adrdec #(P.PA_BITS) sdcdec(PhysicalAddress, P.SDC_BASE[P.PA_BITS-1:0], P.SDC_RANGE[P.PA_BITS-1:0], P.SDC_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE & 4'b1100, SelRegions[10]);
adrdec #(P.PA_BITS) spidec(PhysicalAddress, P.SPI_BASE[P.PA_BITS-1:0], P.SPI_RANGE[P.PA_BITS-1:0], P.SPI_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[1]); adrdec #(P.PA_BITS) spidec(PhysicalAddress, P.SPI_BASE[P.PA_BITS-1:0], P.SPI_RANGE[P.PA_BITS-1:0], P.SPI_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[11]);
assign SelRegions[0] = ~|(SelRegions[11:1]); // none of the regions are selected assign SelRegions[0] = ~|(SelRegions[11:1]); // none of the regions are selected
endmodule endmodule

View File

@ -58,18 +58,18 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWXC, Size, SelRegions); adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWXC, Size, SelRegions);
// Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable // Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable
assign CacheableRegion = SelRegions[9] | SelRegions[8] | SelRegions[7]; // exclusion-tag: unused-cachable assign CacheableRegion = SelRegions[3] | SelRegions[4] | SelRegions[5]; // exclusion-tag: unused-cachable
assign Cacheable = (PBMemoryType == 2'b00) ? CacheableRegion : 0; assign Cacheable = (PBMemoryType == 2'b00) ? CacheableRegion : 0;
// Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly // Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly
// I/O is nonidempotent. PBMT can override PMA; NC is idempotent and IO is non-idempotent // I/O is nonidempotent. PBMT can override PMA; NC is idempotent and IO is non-idempotent
assign IdempotentRegion = SelRegions[11] | SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7]; // exclusion-tag: unused-idempotent assign IdempotentRegion = SelRegions[1] | SelRegions[2] | SelRegions[3] | SelRegions[4] | SelRegions[5]; // exclusion-tag: unused-idempotent
assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01); assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01);
// Atomic operations are only allowed on RAM // Atomic operations are only allowed on RAM
assign AtomicAllowed = SelRegions[11] | SelRegions[9] | SelRegions[7]; // exclusion-tag: unused-idempotent assign AtomicAllowed = SelRegions[1] | SelRegions[3] | SelRegions[5]; // exclusion-tag: unused-idempotent
// Check if tightly integrated memories are selected // Check if tightly integrated memories are selected
assign SelTIM = SelRegions[11] | SelRegions[10]; // exclusion-tag: unused-idempotent assign SelTIM = SelRegions[1] | SelRegions[2]; // exclusion-tag: unused-idempotent
// Detect access faults // Detect access faults
assign PMAAccessFault = (SelRegions[0]) & AccessRWXC | AtomicAccessM & ~AtomicAllowed; assign PMAAccessFault = (SelRegions[0]) & AccessRWXC | AtomicAccessM & ~AtomicAllowed;

View File

@ -91,7 +91,7 @@ module uncore import cvw::*; #(parameter cvw_t P)(
adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions);
// unswizzle HSEL signals // unswizzle HSEL signals
assign {HSELDTIM, HSELIROM, HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELEXTSDC, HSELSPI} = HSELRegions[11:1]; assign {HSELSPI, HSELEXTSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1];
// AHB -> APB bridge // AHB -> APB bridge
ahbapbbridge #(P, 5) ahbapbbridge ( ahbapbbridge #(P, 5) ahbapbbridge (
@ -180,7 +180,7 @@ module uncore import cvw::*; #(parameter cvw_t P)(
// device is ready. Hense this register must be selectively enabled by HREADY. // device is ready. Hense this register must be selectively enabled by HREADY.
// However on reset None must be seleted. // However on reset None must be seleted.
flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1, flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1,
{HSELDTIMD, HSELIROMD, HSELEXTD, HSELBootRomD, HSELRamD, {HSELSPID, HSELEXTSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD,
HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELEXTSDCD, HSELSPID, HSELNoneD}); HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD});
flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED); flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED);
endmodule endmodule

View File

@ -205,12 +205,12 @@ module testbench;
end end
always @(dut.core.MTimerInt) void'(rvvi.net_push("MTimerInterrupt", dut.core.MTimerInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[7]) void'(rvvi.net_push("MTimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[7]));
always @(dut.core.MExtInt) void'(rvvi.net_push("MExternalInterrupt", dut.core.MExtInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[11]) void'(rvvi.net_push("MExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[11]));
always @(dut.core.SExtInt) void'(rvvi.net_push("SExternalInterrupt", dut.core.SExtInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[9]) void'(rvvi.net_push("SExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[9]));
always @(dut.core.MSwInt) void'(rvvi.net_push("MSWInterrupt", dut.core.MSwInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[3]) void'(rvvi.net_push("MSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[3]));
always @(dut.core.priv.priv.csr.csrs.csrs.STimerInt) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csrs.csrs.STimerInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[1]) void'(rvvi.net_push("SSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[1]));
always @(dut.core.priv.priv.csr.csri.MIP_REGW[5]) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[5]));
final begin final begin
void'(rvviRefShutdown()); void'(rvviRefShutdown());

View File

@ -432,11 +432,12 @@ module testbench;
end end
end end
always @(dut.core.MTimerInt) void'(rvvi.net_push("MTimerInterrupt", dut.core.MTimerInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[7]) void'(rvvi.net_push("MTimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[7]));
always @(dut.core.MExtInt) void'(rvvi.net_push("MExternalInterrupt", dut.core.MExtInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[11]) void'(rvvi.net_push("MExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[11]));
always @(dut.core.SExtInt) void'(rvvi.net_push("SExternalInterrupt", dut.core.SExtInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[9]) void'(rvvi.net_push("SExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[9]));
always @(dut.core.MSwInt) void'(rvvi.net_push("MSWInterrupt", dut.core.MSwInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[3]) void'(rvvi.net_push("MSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[3]));
always @(dut.core.priv.priv.csr.csrs.csrs.STimerInt) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csrs.csrs.STimerInt)); always @(dut.core.priv.priv.csr.csri.MIP_REGW[1]) void'(rvvi.net_push("SSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[1]));
always @(dut.core.priv.priv.csr.csri.MIP_REGW[5]) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[5]));
final begin final begin
void'(rvviRefShutdown()); void'(rvviRefShutdown());

View File

@ -51,9 +51,11 @@ main:
jal a1, looptest jal a1, looptest
li a2, 0x40215240 # Test properly formed pages with 1 in PPN[3] that are not NAPOT li a2, 0x40215240 # Test properly formed pages with 1 in PPN[3] that are not NAPOT
jal a1, looptest jal a1, looptest
# li t4, 0x1000 # address step size li t4, 0x1000 # address step size
# li a2, 0x80216000 # Test NAPOT pages li a2, 0x80216000 # Test NAPOT pages
# jal a1, looptest jal a1, looptest
li a0, 3 # switch back to machine mode because code at 0x80000000 may not have clean page table entry
ecall
j done j done
looptest: looptest:
@ -62,30 +64,64 @@ looptest:
li t3, 35 # Max amount of Loops = 34 li t3, 35 # Max amount of Loops = 34
li t5, 0x8082 # return instruction opcode li t5, 0x8082 # return instruction opcode
loop: bge t2, t3, looptesti # exit loop if i >= loops loop: bge t2, t3, finished # exit loop if i >= loops
sw t5, 0(t0) # store a return at this address to exercise DTLB sw t5, 0(t0) # store a return at this address to exercise DTLB
lw t1, 0(t0) # read it back lw t1, 0(t0) # read it back
fence.i # synchronize with I$ fence.i # synchronize with I$
jal changetoipfhandler # set up trap handler to return from instruction page fault if necessary
jalr ra, t0 # jump to the return statement to exercise the ITLB jalr ra, t0 # jump to the return statement to exercise the ITLB
jal changetodefaulthandler
add t0, t0, t4 add t0, t0, t4
addi t2, t2, 1 addi t2, t2, 1
j loop j loop
looptesti:
mv t0, a2 # base address
li t2, 0 # i = 0
fence.i # synchronize with I$
# Exercise itlb by jumping to each of the return statements
loopi: bge t2, t3, finished # exit loop if i >= loops
jalr ra, t0 # jump to the return statement to exercise the ITLB
add t0, t0, t4
addi t2, t2, 1
j loopi
finished: finished:
jr a1 jr a1
changetoipfhandler:
li a0, 3
ecall # switch to machine mode
la a0, ipf_handler
csrw mtvec, a0 # point to new handler
li a0, 1
ecall # switch back to supervisor mode
ret
changetodefaulthandler:
li a0, 3
ecall # switch to machine mode
la a0, trap_handler
csrw mtvec, a0 # point to new handler
li a0, 1
ecall # switch back to supervisor mode
ret
instructionpagefaulthandler:
csrw mepc, ra # go back to calling function
mret
.align 4 # trap handlers must be aligned to multiple of 4
ipf_handler:
# Load trap handler stack pointer tp
csrrw tp, mscratch, tp # swap MSCRATCH and tp
sd t0, 0(tp) # Save t0 and t1 on the stack
sd t1, -8(tp)
csrr t0, mcause # Check the cause
li t1, 8 # is it an ecall trap?
andi t0, t0, 0xFC # if CAUSE = 8, 9, or 11
beq t0, t1, ecall # yes, take ecall
csrr t0, mcause
li t1, 12 # is it an instruction page fault
beq t0, t1, ipf # yes, return to calling function
j trap_return
ipf:
csrw mepc, ra # return to calling function
ld t1, -8(tp) # restore t1 and t0
ld t0, 0(tp)
csrrw tp, mscratch, tp # restore tp
mret # return from trap
.data .data
.align 16 .align 16