PMP and G value
Created by: masgia
From the specs:
In general, the PMP grain is 2^G+2 bytes and must be the same across all PMP regions. When G ≥ 1, the NA4 mode is not selectable. When G ≥ 2 and pmpcfg_i.A[1] is set, i.e. the mode is NAPOT, then bits pmpaddr_i[G-2:0] read as all ones. When G ≥ 1 and pmpcfg_i.A[1] is clear, i.e. the mode is OFF or TOR, then bits pmpaddr_i[G-1:0] read as all zeros.
While in csr_registers.sv
// PMPADDR
// Important: we only support granularity 8 bytes (G=2)
// -> last bit of pmpaddr must be set 0/1 based on the mode:
// NA4, NAPOT: 1
// TOR, OFF: 0
riscv::CSR_PMPADDR0: csr_rdata = {10'b0, pmpaddr_q[0][riscv::PLEN-3:1], (pmpcfg_q[0].addr_mode[1] == 1'b1 ? 1'b1 : 1'b0)};
8-bytes granularity would correspond to G=1 in my understanding. Moreover, if the code is consistent with the rule which states that pmpaddr[G-2:0] read as all ones, it is not compliant with the one which states that pmpaddr[G-1:0] read as all zeros (it should be the last 2 bits, not the last one).
Also, it looks like NA4 is selectable. I can write pmpcfg.a=NA4, and the PMP implementation behaves accordingly. For example, with the following configuration pmpcfg0.r = 1; pmpcfg0.w = 1; pmpcfg0.x = 0; pmpcfg0.a = 2; // NA4 pmpcfg0.o = 0; pmpcfg0.l = 0; pmpaddr0=0x40000000; I can read and write address 0x40000000 but I get an exception when accessing address 0x40000004.