Project Full coverage report
Current view: Cores-VeeR-EL2—Cores-VeeR-EL2—design—dec—el2_dec_pmp_ctl.sv Coverage Hit Total
Test Date: 21-11-2024 Toggle 78.1% 25 32
Test: all Branch 0.0% 0 0

            Line data    Source code
       1              : // SPDX-License-Identifier: Apache-2.0
       2              : // Copyright 2023 Antmicro <www.antmicro.com>
       3              : //
       4              : // Licensed under the Apache License, Version 2.0 (the "License");
       5              : // you may not use this file except in compliance with the License.
       6              : // You may obtain a copy of the License at
       7              : //
       8              : // http://www.apache.org/licenses/LICENSE-2.0
       9              : //
      10              : // Unless required by applicable law or agreed to in writing, software
      11              : // distributed under the License is distributed on an "AS IS" BASIS,
      12              : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13              : // See the License for the specific language governing permissions and
      14              : // limitations under the License.
      15              : 
      16              : 
      17              : //********************************************************************************
      18              : // el2_dec_pmp_ctl.sv
      19              : //
      20              : //
      21              : // Function: Physical Memory Protection CSRs
      22              : // Comments:
      23              : //
      24              : //********************************************************************************
      25              : 
      26              : module el2_dec_pmp_ctl
      27              :   import el2_pkg::*;
      28              : #(
      29              : `include "el2_param.vh"
      30              :  )
      31              :   (
      32     69840565 :    input logic clk,
      33     69840565 :    input logic free_l2clk,
      34     69840565 :    input logic csr_wr_clk,
      35          338 :    input logic rst_l,
      36        42288 :    input logic        dec_csr_wen_r_mod,  // csr write enable at wb
      37          542 :    input logic [11:0] dec_csr_wraddr_r,   // write address for csr
      38         1686 :    input logic [31:0] dec_csr_wrdata_r,   // csr write data at wb
      39         1000 :    input logic [11:0] dec_csr_rdaddr_d,   // read address for csr
      40              : 
      41          896 :    input logic csr_pmpcfg,
      42          802 :    input logic csr_pmpaddr0,
      43           16 :    input logic csr_pmpaddr16,
      44           10 :    input logic csr_pmpaddr32,
      45           14 :    input logic csr_pmpaddr48,
      46              : 
      47            2 :    input logic dec_pause_state, // Paused
      48          108 :    input logic dec_tlu_pmu_fw_halted, // pmu/fw halted
      49          120 :    input logic internal_dbg_halt_timers, // debug halted
      50              : 
      51              : `ifdef RV_SMEPMP
      52            2 :    input el2_mseccfg_pkt_t mseccfg,
      53              : `endif
      54              : 
      55          262 :    output logic [31:0] dec_pmp_rddata_d,  // pmp CSR read data
      56         1738 :    output logic        dec_pmp_read_d,    // pmp CSR address match
      57              : 
      58            0 :    output el2_pmp_cfg_pkt_t pmp_pmpcfg  [pt.PMP_ENTRIES],
      59              :    output logic [31:0]      pmp_pmpaddr [pt.PMP_ENTRIES],
      60              : 
      61              :    // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
      62              :    /*verilator coverage_off*/
      63              :    input  logic        scan_mode
      64              :    /*verilator coverage_on*/
      65              :    );
      66              : 
      67          500 :    logic wr_pmpcfg_r;
      68          100 :    logic [3:0] wr_pmpcfg_group;
      69              : 
      70          544 :    logic wr_pmpaddr0_sel;
      71            0 :    logic wr_pmpaddr16_sel;
      72            0 :    logic wr_pmpaddr32_sel;
      73            0 :    logic wr_pmpaddr48_sel;
      74          544 :    logic wr_pmpaddr_r;
      75            0 :    logic [1:0] wr_pmpaddr_quarter;
      76            0 :    logic [5:0] wr_pmpaddr_address;
      77              : 
      78          334 :    logic [3:0] pmp_quarter_rdaddr;
      79          354 :    logic [31:0] pmp_pmpcfg_rddata;
      80              : 
      81              :    // ----------------------------------------------------------------------
      82              : 
      83            0 :    logic [pt.PMP_ENTRIES-1:0] entry_lock_eff;  // Effective entry lock
      84              :    for (genvar r = 0; r < pt.PMP_ENTRIES; r++) begin : g_pmpcfg_lock
      85              : `ifdef RV_SMEPMP
      86              :    // Smepmp allow modifying locked entries when mseccfg.RLB is set
      87              :    assign entry_lock_eff[r] = pmp_pmpcfg[r].lock & ~mseccfg.RLB;
      88              : `else
      89              :    assign entry_lock_eff[r] = pmp_pmpcfg[r].lock;
      90              : `endif
      91              :    end
      92              : 
      93              :    // ----------------------------------------------------------------------
      94              :    // PMPCFGx (RW)
      95              :    // [31:24] : PMP entry (x*4 + 3) configuration
      96              :    // [23:16] : PMP entry (x*4 + 2) configuration
      97              :    // [15:8] : PMP entry (x*4 + 1) configuration
      98              :    //  [7:0] : PMP entry (x*4 + 0) configuration
      99              : 
     100              :    localparam PMPCFG       = 12'h3a0;
     101              : 
     102              :    assign wr_pmpcfg_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:4] == PMPCFG[11:4]);
     103              :    assign wr_pmpcfg_group = dec_csr_wraddr_r[3:0]; // selects group of 4 pmpcfg entries (group 1 -> entries 4-7; up to 16 groups)
     104              : 
     105              :    for (genvar entry_idx = 0; entry_idx < pt.PMP_ENTRIES; entry_idx++) begin : gen_pmpcfg_ff
     106              :       logic [7:0] raw_wdata;
     107              :       logic [7:0] csr_wdata;
     108              : 
     109              :       // PMPCFG fields are WARL. Mask out bits 6:5 during write.
     110              :       // When Smepmp is disabled R=0 and W=1 combination is illegal mask out W
     111              :       // when R is cleared.
     112              :       assign raw_wdata = dec_csr_wrdata_r[(entry_idx[1:0]*8)+7:(entry_idx[1:0]*8)+0];
     113              : `ifdef RV_SMEPMP
     114              :       assign csr_wdata = raw_wdata & 8'b10011111;
     115              : `else
     116              :       assign csr_wdata = raw_wdata[0] ? (raw_wdata & 8'b10011111) : (raw_wdata & 8'b10011101);
     117              : `endif
     118              : 
     119              :       rvdffe #(8) pmpcfg_ff (.*, .clk(free_l2clk),
     120              :                           .en(wr_pmpcfg_r & (wr_pmpcfg_group == entry_idx[5:2]) & (~entry_lock_eff[entry_idx])),
     121              :                           .din(csr_wdata),
     122              :                           .dout(pmp_pmpcfg[entry_idx]));
     123              :    end
     124              : 
     125              :    // ----------------------------------------------------------------------
     126              :    // PMPADDRx (RW)
     127              :    // [31:0] : PMP entry (x) address selector (word addressing)
     128              :    //
     129              :    // NOTE: VeeR-EL2 uses 32-bit physical addressing, register bits 31:30 mapping
     130              :    //       to bits 33:32 of the physical address are always set to 0. (WARL)
     131              : 
     132              :    localparam  PMPADDR0      = 12'h3b0;
     133              :    localparam PMPADDR16      = 12'h3c0;
     134              :    localparam PMPADDR32      = 12'h3d0;
     135              :    localparam PMPADDR48      = 12'h3e0;
     136              : 
     137              :    assign wr_pmpaddr0_sel  = dec_csr_wraddr_r[11:4] ==  PMPADDR0[11:4];
     138              :    assign wr_pmpaddr16_sel = dec_csr_wraddr_r[11:4] == PMPADDR16[11:4];
     139              :    assign wr_pmpaddr32_sel = dec_csr_wraddr_r[11:4] == PMPADDR32[11:4];
     140              :    assign wr_pmpaddr48_sel = dec_csr_wraddr_r[11:4] == PMPADDR48[11:4];
     141              :    assign wr_pmpaddr_r = dec_csr_wen_r_mod & (wr_pmpaddr0_sel | wr_pmpaddr16_sel | wr_pmpaddr32_sel | wr_pmpaddr48_sel);
     142              : 
     143              :    assign wr_pmpaddr_quarter[0] = wr_pmpaddr16_sel | wr_pmpaddr48_sel;
     144              :    assign wr_pmpaddr_quarter[1] = wr_pmpaddr32_sel | wr_pmpaddr48_sel;
     145              :    assign wr_pmpaddr_address = {wr_pmpaddr_quarter, dec_csr_wraddr_r[3:0]}; // entry address
     146              : 
     147              :    for (genvar entry_idx = 0; entry_idx < pt.PMP_ENTRIES; entry_idx++) begin : gen_pmpaddr_ff
     148              :       logic pmpaddr_lock;
     149              :       logic pmpaddr_lock_next;
     150              :       if (entry_idx+1 < pt.PMP_ENTRIES)
     151              :          assign pmpaddr_lock_next = entry_lock_eff[entry_idx+1] & pmp_pmpcfg[entry_idx+1].mode == TOR;
     152              :       else
     153              :          assign pmpaddr_lock_next = 1'b0;
     154              :       assign pmpaddr_lock = entry_lock_eff[entry_idx] | pmpaddr_lock_next;
     155              :       assign pmp_pmpaddr[entry_idx][31:30] = 2'b00;
     156              :       rvdffe #(30) pmpaddr_ff (.*, .clk(free_l2clk),
     157              :                           .en(wr_pmpaddr_r & (wr_pmpaddr_address == entry_idx)
     158              :                               & (~pmpaddr_lock)),
     159              :                           .din(dec_csr_wrdata_r[29:0]),
     160              :                           .dout(pmp_pmpaddr[entry_idx][29:0]));
     161              :    end
     162              : 
     163              :    // CSR read mux
     164              : 
     165              :    assign pmp_quarter_rdaddr     = dec_csr_rdaddr_d[3:0];
     166              :    assign pmp_pmpcfg_rddata      = { pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h3}],
     167              :                                      pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h2}],
     168              :                                      pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h1}],
     169              :                                      pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h0}]
     170              :                                      };
     171              :    assign dec_pmp_read_d         = csr_pmpcfg | csr_pmpaddr0 | csr_pmpaddr16 | csr_pmpaddr32 | csr_pmpaddr48;
     172              :    assign dec_pmp_rddata_d[31:0] = ( ({32{csr_pmpcfg}}    & pmp_pmpcfg_rddata) |
     173              :                                      ({32{csr_pmpaddr0}}  & pmp_pmpaddr[{2'h0, pmp_quarter_rdaddr}]) |
     174              :                                      ({32{csr_pmpaddr16}} & pmp_pmpaddr[{2'h1, pmp_quarter_rdaddr}]) |
     175              :                                      ({32{csr_pmpaddr32}} & pmp_pmpaddr[{2'h2, pmp_quarter_rdaddr}]) |
     176              :                                      ({32{csr_pmpaddr48}} & pmp_pmpaddr[{2'h3, pmp_quarter_rdaddr}])
     177              :                                      );
     178              : 
     179              : endmodule // dec_pmp_ctl