mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-06-27 17:01:20 -04:00
Support PMP granularity G > 0 in PMP registers
This commit is contained in:
parent
97f5ea0fd1
commit
90b4337a49
6 changed files with 43 additions and 28 deletions
|
@ -103,6 +103,7 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||
// when compressed instructions are supported, there can't be misaligned instructions
|
||||
localparam MEDELEG_MASK = P.ZCA_SUPPORTED ? 16'hB3FE : 16'hB3FF;
|
||||
localparam MIDELEG_MASK = 12'h222; // we choose to not make machine interrupts delegable
|
||||
localparam Gm1 = P.PMP_G > 0 ? P.PMP_G - 1 : 0; // max(G-1, 0)
|
||||
|
||||
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
||||
genvar i;
|
||||
|
@ -112,6 +113,7 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||
logic [7:0] CSRPMPWriteValM[P.PMP_ENTRIES-1:0];
|
||||
logic [7:0] CSRPMPLegalizedWriteValM[P.PMP_ENTRIES-1:0];
|
||||
logic [1:0] CSRPMPWRLegalizedWriteValM[P.PMP_ENTRIES-1:0];
|
||||
logic CSRPMPA0LegalizedWriteValM[P.PMP_ENTRIES-1:0];
|
||||
logic [P.PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
|
||||
for(i=0; i<P.PMP_ENTRIES; i++) begin
|
||||
// when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR
|
||||
|
@ -133,7 +135,8 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||
end
|
||||
|
||||
assign CSRPMPWRLegalizedWriteValM[i] = {(CSRPMPWriteValM[i][1] & CSRPMPWriteValM[i][0]), CSRPMPWriteValM[i][0]}; // legalize WR fields (reserved 10 written as 00)
|
||||
assign CSRPMPLegalizedWriteValM[i] = {CSRPMPWriteValM[i][7], 2'b00, CSRPMPWriteValM[i][4:2], CSRPMPWRLegalizedWriteValM[i]};
|
||||
assign CSRPMPA0LegalizedWriteValM[i] = (P.PMP_G > 0) & CSRPMPWriteValM[i][4] | CSRPMPWriteValM[i][3]; // if G > 0, when trying to write A = NA4 (10), actually write A = NAPOT (11)
|
||||
assign CSRPMPLegalizedWriteValM[i] = {CSRPMPWriteValM[i][7], 2'b00, CSRPMPWriteValM[i][4], CSRPMPA0LegalizedWriteValM[i], CSRPMPWriteValM[i][2], CSRPMPWRLegalizedWriteValM[i]};
|
||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRPMPLegalizedWriteValM[i], PMPCFG_ARRAY_REGW[i]);
|
||||
end
|
||||
end
|
||||
|
@ -217,13 +220,23 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
|||
// Read machine mode CSRs
|
||||
// verilator lint_off WIDTH
|
||||
logic [5:0] entry;
|
||||
logic [P.XLEN-1:0] pmpaddr; // correct for grain size and PMP mode
|
||||
logic napot;
|
||||
always_comb begin
|
||||
entry = '0;
|
||||
CSRMReadValM = '0;
|
||||
pmpaddr = '0;
|
||||
napot = 0;
|
||||
IllegalCSRMAccessM = !(P.S_SUPPORTED) & (CSRAdrM == MEDELEG | CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode
|
||||
if ($unsigned(CSRAdrM) >= PMPADDR0 & $unsigned(CSRAdrM) < PMPADDR0 + P.PMP_ENTRIES) // reading a PMP entry
|
||||
CSRMReadValM = {{(P.XLEN-(P.PA_BITS-2)){1'b0}}, PMPADDR_ARRAY_REGW[CSRAdrM - PMPADDR0]};
|
||||
else if ($unsigned(CSRAdrM) >= PMPCFG0 & $unsigned(CSRAdrM) < PMPCFG0 + P.PMP_ENTRIES/4 & (P.XLEN==32 | CSRAdrM[0] == 0)) begin
|
||||
if ($unsigned(CSRAdrM) >= PMPADDR0 & $unsigned(CSRAdrM) < PMPADDR0 + P.PMP_ENTRIES) begin // reading a PMP entry
|
||||
pmpaddr = {{(P.XLEN-(P.PA_BITS-2)){1'b0}}, PMPADDR_ARRAY_REGW[CSRAdrM - PMPADDR0]}; // raw value in PMP registers
|
||||
if (P.PMP_G > 0) begin // bottom bits read as 0/1 depending on mode
|
||||
napot = PMPCFG_ARRAY_REGW[CSRAdrM - PMPADDR0][4]; // read from corresponding pmpcfg register, indicating NAPOT mode
|
||||
if ((P.PMP_G > 1) & napot) pmpaddr = {pmpaddr[P.XLEN-1:Gm1], {Gm1 {1'b1}}}; // in NAPOT, bottom G-1 bits read as all 1s
|
||||
else if (!napot) pmpaddr = {pmpaddr[P.XLEN-1:P.PMP_G], {P.PMP_G{1'b0}}}; // in TOR/OFF, bottom G bits read as 0s
|
||||
end
|
||||
CSRMReadValM = pmpaddr;
|
||||
end else if ($unsigned(CSRAdrM) >= PMPCFG0 & $unsigned(CSRAdrM) < PMPCFG0 + P.PMP_ENTRIES/4 & (P.XLEN==32 | CSRAdrM[0] == 0)) begin
|
||||
// only odd-numbered PMPCFG entries exist in RV64
|
||||
if (P.XLEN==64) begin
|
||||
entry = ({CSRAdrM[11:1], 1'b0} - PMPCFG0)*4; // disregard odd entries in RV64
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
|
||||
module riscvassertions import cvw::*; #(parameter cvw_t P);
|
||||
initial begin
|
||||
//$display("PMPG = %d LLEN = %d !ZCA = %b PMPENTRIES = %d !ICS = %b", P.PMP_G, P.ICACHE_LINELENINBITS, !P.ZCA_SUPPORTED, P.PMP_ENTRIES, !P.ICACHE_SUPPORTED);
|
||||
assert (P.PMP_ENTRIES == 0 | P.PMP_ENTRIES==16 | P.PMP_ENTRIES==64) else $fatal(1, "Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64");
|
||||
assert (P.PMP_G > 0 | P.XLEN == 32) else $fatal(1, "RV64 requires PMP_G at least 1 to avoid checking for 8-byte accesses to 4-byte region");
|
||||
assert (P.PMP_G >= $clog2(P.DCACHE_LINELENINBITS)-2 | !P.ZICCLSM_SUPPORTED | P.PMP_ENTRIES == 0) else $fatal(1, "Systems that support misaligned data with PMP must have grain size of at least one cache line so accesses that span grains will also cause spills");
|
||||
assert (P.PMP_G >= $clog2(P.ICACHE_LINELENINBITS)-2 | !P.ZCA_SUPPORTED | P.PMP_ENTRIES == 0 | !P.ICACHE_SUPPORTED) else $fatal(1, "Systems that support compressed instructions with PMP must have grain size of at least one cache line so fetches that span grains will also cause spills");
|
||||
assert (P.PMP_G > 0 | P.XLEN == 32 | P.PMP_ENTRIES == 0) else $fatal(1, "RV64 requires PMP_G at least 1 to avoid checking for 8-byte accesses to 4-byte region");
|
||||
assert ((P.PMP_G >= $clog2(P.DCACHE_LINELENINBITS/8)-2) | !P.ZICCLSM_SUPPORTED | P.PMP_ENTRIES == 0) else $fatal(1, "Systems that support misaligned data with PMP must have grain size of at least one cache line so accesses that span grains will also cause spills");
|
||||
assert ((P.PMP_G >= $clog2(P.ICACHE_LINELENINBITS/8)-2) | !P.ZCA_SUPPORTED | (P.PMP_ENTRIES == 0) | !P.ICACHE_SUPPORTED) else $fatal(1, "Systems that support compressed instructions with PMP must have grain size of at least one cache line so fetches that span grains will also cause spills");
|
||||
assert (P.PMP_G < P.PA_BITS-2 | P.PMP_ENTRIES == 0) else $fatal(1, "PMP granularity must be less than the number of physical address bits");
|
||||
assert (P.IDIV_BITSPERCYCLE == 1 | P.IDIV_BITSPERCYCLE==2 | P.IDIV_BITSPERCYCLE==4) else $fatal(1, "Illegal number of divider bits/cycle: IDIV_BITSPERCYCLE must be 1, 2, or 4");
|
||||
assert (P.F_SUPPORTED | !P.D_SUPPORTED) else $fatal(1, "Can't support double fp (D) without supporting float (F)");
|
||||
assert (P.D_SUPPORTED | !P.Q_SUPPORTED) else $fatal(1, "Can't support quad fp (Q) without supporting double (D)");
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
0fffffff
|
||||
0ffffff0 # writeback of value written to PMPADDR0, less trailing 4 bits for G = 4
|
||||
20040000
|
||||
2004003f
|
||||
20040030
|
||||
20040080
|
||||
20040080
|
||||
20040084
|
||||
200400c0
|
||||
2004013f
|
||||
2fffffff
|
||||
20040130
|
||||
2ffffff0
|
||||
0009001f
|
||||
0018900c
|
||||
0018980c
|
||||
1f000000
|
||||
0018900c
|
||||
200400c0
|
||||
0018980c
|
||||
200400c7
|
||||
00000005
|
||||
00000bad
|
||||
00600dbb
|
||||
|
|
|
@ -73,7 +73,7 @@ test_cases:
|
|||
|
||||
# write pmpcfg regs with the information in the table above. this should also write the value of these registers to the output.
|
||||
.4byte 0x0, 0x0009001F, write_pmpcfg_0 # write pmpcfg0, output 0x0009001F
|
||||
.4byte 0x1, 0x0018900C, write_pmpcfg_1 # write pmpcfg1, output 0x0018900C
|
||||
.4byte 0x1, 0x0018900C, write_pmpcfg_1 # write pmpcfg1, output 0x0018980C because NA4 reads as NAPOT with G > 0
|
||||
# pmpcfg2 is zeroed out, so it doesn't need a write
|
||||
.4byte 0x3, 0x1F000000, write_pmpcfg_3 # write pmpcfg3, output 0x1F000000
|
||||
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
0fffffff # Test 12.3.2.2.1: writeback of value written to PMPADDR0
|
||||
0ffffff0 # Test 12.3.2.2.1: writeback of value written to PMPADDR0, less trailing 4 bits for G = 4
|
||||
00000000
|
||||
20040000 # writeback of value written to PMPADDR1
|
||||
20040000 # writeback of value written to PMPADDR1, less trailing 4 bits for G = 4
|
||||
00000000
|
||||
2004003f # writeback of value written to PMPADDR2
|
||||
20040030 # writeback of value written to PMPADDR2, less trailing 4 bits for G = 4
|
||||
00000000
|
||||
20040080 # writeback of value written to PMPADDR3
|
||||
20040080 # writeback of value written to PMPADDR3, less trailing 4 bits for G = 4
|
||||
00000000
|
||||
20040084 # writeback of value written to PMPADDR4
|
||||
20040080 # writeback of value written to PMPADDR4, less trailing 4 bits for G = 4
|
||||
00000000
|
||||
200400c0 # writeback of value written to PMPADDR5
|
||||
200400c0 # writeback of value written to PMPADDR5, less trailing 4 bits for G = 4
|
||||
00000000
|
||||
2004013f # writeback of value written to PMPADDR6
|
||||
20040130 # writeback of value written to PMPADDR6, less trailing 4 bits for G = 4
|
||||
00000000
|
||||
2fffffff # writeback of value written to PMPADDR15
|
||||
2ffffff0 # writeback of value written to PMPADDR15, less trailing 4 bits for G = 4
|
||||
00000000
|
||||
0009001f # writeback of value written to PMPCFG0
|
||||
0018900c
|
||||
0018980c
|
||||
00000000 # writeback of value written to PMPCFG2
|
||||
1f000000
|
||||
0009001f # old value of PMPCFG0 after failed write to locked out region
|
||||
0018900c
|
||||
200400c0 # old value of PMPADDR5 after failed write to locked out region
|
||||
0018980c
|
||||
200400c7 # old value of PMPADDR5 after failed write to locked out region
|
||||
00000000
|
||||
00000005 # Test 12.3.2.2.2: read test with access fault to region with L=1, R=0
|
||||
00000000
|
||||
|
|
|
@ -71,7 +71,7 @@ test_cases:
|
|||
.8byte 0xF, 0x2FFFFFFF, write_pmpaddr_15 # | 15 | 0x2FFFFFFF | 1F | 0 | NAPOT | 1 | 1 | 1 | Main mem 80000000-FFFFFFFF RWX|
|
||||
|
||||
# write pmpcfg regs with the information in the table above. this should also write the value of these registers to the output.
|
||||
.8byte 0x0, 0x0018900C0009001F, write_pmpcfg_0 # write pmpcfg0, output 0x0018900C0009001F
|
||||
.8byte 0x0, 0x0018900C0009001F, write_pmpcfg_0 # write pmpcfg0, output 0x0018980C0009001F because NA4 writes as NAPOT
|
||||
.8byte 0x2, 0x1F00000000000000, write_pmpcfg_2 # write pmpcfg2, output 0x1F00000000000000
|
||||
|
||||
# write known values to memory where W=0. This should be possible since we're in machine mode.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue