mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge pull request #540 from davidharrishmc/dev
Fix Timer Interrupt Issue #530 and coverage/tlbNAPOT tests #457
This commit is contained in:
commit
b701cbf823
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user