diff --git a/doc/03_reference/coverage_plan.rst b/doc/03_reference/coverage_plan.rst index 85278ba6..ee95dd21 100644 --- a/doc/03_reference/coverage_plan.rst +++ b/doc/03_reference/coverage_plan.rst @@ -280,6 +280,11 @@ PMP * Access close to PMP region modification that allows/disallows that access. +* ``pmp_wr_exec_region`` - Explores behaviour around adding executable regions when MML is enabled. + Cross of current region configuration with region configuration that is being written and RLB setting. + It only considers regions that aren't currently executable with writes attempted to make them executable. + Non MML configurations are not sampled. + CSRs ^^^^ Basic read/write functionality must be tested on all implemented CSRs. diff --git a/dv/uvm/core_ibex/fcov/core_ibex_pmp_fcov_if.sv b/dv/uvm/core_ibex/fcov/core_ibex_pmp_fcov_if.sv index 9bfcff54..f1802c76 100644 --- a/dv/uvm/core_ibex/fcov/core_ibex_pmp_fcov_if.sv +++ b/dv/uvm/core_ibex/fcov/core_ibex_pmp_fcov_if.sv @@ -138,12 +138,20 @@ interface core_ibex_pmp_fcov_if import ibex_pkg::*; #( for (genvar i_region = 0; i_region < PMPNumRegions; i_region += 1) begin : g_pmp_region_fcov pmp_priv_bits_e pmp_region_priv_bits; + pmp_priv_bits_e pmp_region_priv_bits_wr; assign pmp_region_priv_bits = pmp_priv_bits_e'({csr_pmp_mseccfg.mml, csr_pmp_cfg[i_region].lock, csr_pmp_cfg[i_region].exec, csr_pmp_cfg[i_region].write, csr_pmp_cfg[i_region].read}); + assign pmp_region_priv_bits_wr = + pmp_priv_bits_e'({csr_pmp_mseccfg.mml, + cs_registers_i.g_pmp_registers.pmp_cfg_wdata[i_region].lock, + cs_registers_i.g_pmp_registers.pmp_cfg_wdata[i_region].exec, + cs_registers_i.g_pmp_registers.pmp_cfg_wdata[i_region].write, + cs_registers_i.g_pmp_registers.pmp_cfg_wdata[i_region].read}); + // Do the permission check for Data channel with the privilege level from Instruction channels. // This way we can check the effect of mstatus.mprv changing privilege levels for LSU related // operations. @@ -431,6 +439,33 @@ interface core_ibex_pmp_fcov_if import ibex_pkg::*; #( csr_pmp_cfg[i_region].lock && cs_registers_i.g_pmp_registers.g_pmp_csrs[i_region].u_pmp_addr_csr.wr_en_i && csr_pmp_mseccfg.rlb) + + // Only sample this cross when we attempt to write to a PMP config that doesn't currently + // allow execution with MML enabled + pmp_wr_exec_region : + cross pmp_region_priv_bits, pmp_region_priv_bits_wr, csr_pmp_mseccfg.rlb iff + (fcov_csr_write && + csr_pmp_mseccfg.mml && + cs_registers_i.csr_we_int && + cs_registers_i.csr_addr == (CSR_OFF_PMP_CFG + (i_region[11:0] >> 2)) && + ((!pmp_region_priv_bits[2] && pmp_region_priv_bits != MML_XM_XU) || + pmp_region_priv_bits inside {MML_WRM_WRU, MML_RM_RU})) { + + // Only interested in MML configuration + ignore_bins non_mml_in = binsof(pmp_region_priv_bits) with (!pmp_region_priv_bits[4]); + + ignore_bins non_mml_out = + binsof(pmp_region_priv_bits_wr) with (!pmp_region_priv_bits_wr[4]); + + // Only interested in starting configs that weren't executable so ignore executable + // regions + ignore_bins from_exec_bins = binsof(pmp_region_priv_bits) intersect {MML_XU, MML_XRU, + MML_XWRU, MML_XM_XU, MML_XM, MML_XRM, MML_XRM_XU}; + + // Only interested in writes that give executable regions so ignore non executable regions + ignore_bins to_non_exec_bins = binsof(pmp_region_priv_bits_wr) intersect {MML_NONE, + MML_RU, MML_WRM_RU, MML_WRU, MML_WRM_WRU, MML_L, MML_RM, MML_WRM, MML_RM_RU}; + } endgroup `DV_FCOV_INSTANTIATE_CG(pmp_region_cg, en_pmp_fcov)