Project Full coverage report
Current view: Cores-VeeR-EL2—Cores-VeeR-EL2—design—lsu—el2_lsu_addrcheck.sv Coverage Hit Total
Test Date: 21-11-2024 Toggle 53.1% 26 49
Test: all Branch 0.0% 0 0

            Line data    Source code
       1              : // SPDX-License-Identifier: Apache-2.0
       2              : // Copyright 2020 Western Digital Corporation or its affiliates.
       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              : // $Id$
      18              : //
      19              : //
      20              : // Owner:
      21              : // Function: Checks the memory map for the address
      22              : // Comments:
      23              : //
      24              : //********************************************************************************
      25              : module el2_lsu_addrcheck
      26              : import el2_pkg::*;
      27              : #(
      28              : `include "el2_param.vh"
      29              :  )(
      30     69840565 :    input logic          lsu_c2_m_clk,              // clock
      31          338 :    input logic          rst_l,                     // reset
      32              : 
      33       593287 :    input logic [31:0]   start_addr_d,              // start address for lsu
      34       593313 :    input logic [31:0]   end_addr_d,                // end address for lsu
      35       477872 :    input el2_lsu_pkt_t lsu_pkt_d,                 // packet in d
      36            0 :    input logic [31:0]   dec_tlu_mrac_ff,           // CSR read
      37      1446243 :    input logic [3:0]    rs1_region_d,              // address rs operand [31:28]
      38              : 
      39       475446 :    input logic [31:0]   rs1_d,                     // address rs operand
      40              : 
      41        36448 :    output logic         is_sideeffects_m,          // is sideffects space
      42       614422 :    output logic         addr_in_dccm_d,            // address in dccm
      43           12 :    output logic         addr_in_pic_d,             // address in pic
      44       614789 :    output logic         addr_external_d,           // address in external
      45              : 
      46           70 :    output logic         access_fault_d,            // access fault
      47           10 :    output logic         misaligned_fault_d,        // misaligned
      48            0 :    output logic [3:0]   exc_mscause_d,             // mscause for access/misaligned faults
      49              : 
      50            0 :    output logic         fir_dccm_access_error_d,   // Fast interrupt dccm access error
      51            0 :    output logic         fir_nondccm_access_error_d,// Fast interrupt dccm access error
      52              : 
      53       164871 :     input logic lsu_pmp_error_start,
      54       164871 :     input logic lsu_pmp_error_end,
      55              : 
      56              :    // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
      57              :    /*verilator coverage_off*/
      58              :    input  logic         scan_mode                  // Scan mode
      59              :    /*verilator coverage_on*/
      60              : );
      61              : 
      62              : 
      63            0 :    logic        non_dccm_access_ok;
      64        56839 :    logic        is_sideeffects_d, is_aligned_d;
      65       614422 :    logic        start_addr_in_dccm_d, end_addr_in_dccm_d;
      66       614450 :    logic        start_addr_in_dccm_region_d, end_addr_in_dccm_region_d;
      67           12 :    logic        start_addr_in_pic_d, end_addr_in_pic_d;
      68       614450 :    logic        start_addr_in_pic_region_d, end_addr_in_pic_region_d;
      69       822670 :    logic [4:0]  csr_idx;
      70         5862 :    logic        addr_in_iccm;
      71       614450 :    logic        start_addr_dccm_or_pic;
      72       614442 :    logic        base_reg_dccm_or_pic;
      73            8 :    logic        unmapped_access_fault_d, mpu_access_fault_d, picm_access_fault_d, regpred_access_fault_d;
      74           10 :    logic        regcross_misaligned_fault_d, sideeffect_misaligned_fault_d;
      75            0 :    logic [3:0]  access_fault_mscause_d;
      76            0 :    logic [3:0]  misaligned_fault_mscause_d;
      77              : 
      78              :    if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable
      79              :       // Start address check
      80              :       rvrangecheck #(.CCM_SADR(pt.DCCM_SADR),
      81              :                      .CCM_SIZE(pt.DCCM_SIZE)) start_addr_dccm_rangecheck (
      82              :          .addr(start_addr_d[31:0]),
      83              :          .in_range(start_addr_in_dccm_d),
      84              :          .in_region(start_addr_in_dccm_region_d)
      85              :       );
      86              : 
      87              :       // End address check
      88              :       rvrangecheck #(.CCM_SADR(pt.DCCM_SADR),
      89              :                      .CCM_SIZE(pt.DCCM_SIZE)) end_addr_dccm_rangecheck (
      90              :          .addr(end_addr_d[31:0]),
      91              :          .in_range(end_addr_in_dccm_d),
      92              :          .in_region(end_addr_in_dccm_region_d)
      93              :       );
      94              :    end else begin: Gen_dccm_disable // block: Gen_dccm_enable
      95              :       assign start_addr_in_dccm_d = '0;
      96              :       assign start_addr_in_dccm_region_d = '0;
      97              :       assign end_addr_in_dccm_d = '0;
      98              :       assign end_addr_in_dccm_region_d = '0;
      99              :    end
     100              : 
     101              :    if (pt.ICCM_ENABLE == 1) begin : check_iccm
     102              :       assign addr_in_iccm =  (start_addr_d[31:28] == pt.ICCM_REGION);
     103              :    end else begin
     104              :      assign addr_in_iccm = 1'b0;
     105              :    end
     106              : 
     107              :    // PIC memory check
     108              :    // Start address check
     109              :    rvrangecheck #(.CCM_SADR(pt.PIC_BASE_ADDR),
     110              :                   .CCM_SIZE(pt.PIC_SIZE)) start_addr_pic_rangecheck (
     111              :       .addr(start_addr_d[31:0]),
     112              :       .in_range(start_addr_in_pic_d),
     113              :       .in_region(start_addr_in_pic_region_d)
     114              :    );
     115              : 
     116              :    // End address check
     117              :    rvrangecheck #(.CCM_SADR(pt.PIC_BASE_ADDR),
     118              :                   .CCM_SIZE(pt.PIC_SIZE)) end_addr_pic_rangecheck (
     119              :       .addr(end_addr_d[31:0]),
     120              :       .in_range(end_addr_in_pic_d),
     121              :       .in_region(end_addr_in_pic_region_d)
     122              :    );
     123              : 
     124              :    assign start_addr_dccm_or_pic  = start_addr_in_dccm_region_d | start_addr_in_pic_region_d;
     125              :    assign base_reg_dccm_or_pic    = (|((rs1_region_d[3:0] == pt.DCCM_REGION) & pt.DCCM_ENABLE)) | (rs1_region_d[3:0] == pt.PIC_REGION);
     126              :    assign addr_in_dccm_d          = (start_addr_in_dccm_d & end_addr_in_dccm_d);
     127              :    assign addr_in_pic_d           = (start_addr_in_pic_d & end_addr_in_pic_d);
     128              : 
     129              :    assign addr_external_d   = ~(start_addr_in_dccm_region_d | start_addr_in_pic_region_d);
     130              :    assign csr_idx[4:0]       = {start_addr_d[31:28], 1'b1};
     131              :    assign is_sideeffects_d = dec_tlu_mrac_ff[csr_idx] & ~(start_addr_in_dccm_region_d | start_addr_in_pic_region_d | addr_in_iccm) & lsu_pkt_d.valid & (lsu_pkt_d.store | lsu_pkt_d.load);  //every region has the 2 LSB indicating ( 1: sideeffects/no_side effects, and 0: cacheable ). Ignored in internal regions
     132              :    assign is_aligned_d    = (lsu_pkt_d.word & (start_addr_d[1:0] == 2'b0)) |
     133              :                                                             (lsu_pkt_d.half & (start_addr_d[0] == 1'b0)) |
     134              :                                                             lsu_pkt_d.by;
     135              : 
     136            0 :    logic ACCESS0_STARTOK;
     137            0 :    logic ACCESS1_STARTOK;
     138            0 :    logic ACCESS2_STARTOK;
     139            0 :    logic ACCESS3_STARTOK;
     140            0 :    logic ACCESS4_STARTOK;
     141            0 :    logic ACCESS5_STARTOK;
     142            0 :    logic ACCESS6_STARTOK;
     143            0 :    logic ACCESS7_STARTOK;
     144            0 :    logic ACCESS0_ENDOK;
     145            0 :    logic ACCESS1_ENDOK;
     146            0 :    logic ACCESS2_ENDOK;
     147            0 :    logic ACCESS3_ENDOK;
     148            0 :    logic ACCESS4_ENDOK;
     149            0 :    logic ACCESS5_ENDOK;
     150            0 :    logic ACCESS6_ENDOK;
     151            0 :    logic ACCESS7_ENDOK;
     152              : 
     153              :    assign ACCESS0_STARTOK = pt.DATA_ACCESS_ENABLE0 & ((start_addr_d[31:0] | pt.DATA_ACCESS_MASK0)) == (pt.DATA_ACCESS_ADDR0 | pt.DATA_ACCESS_MASK0);
     154              :    assign ACCESS1_STARTOK = pt.DATA_ACCESS_ENABLE1 & ((start_addr_d[31:0] | pt.DATA_ACCESS_MASK1)) == (pt.DATA_ACCESS_ADDR1 | pt.DATA_ACCESS_MASK1);
     155              :    assign ACCESS2_STARTOK = pt.DATA_ACCESS_ENABLE2 & ((start_addr_d[31:0] | pt.DATA_ACCESS_MASK2)) == (pt.DATA_ACCESS_ADDR2 | pt.DATA_ACCESS_MASK2);
     156              :    assign ACCESS3_STARTOK = pt.DATA_ACCESS_ENABLE3 & ((start_addr_d[31:0] | pt.DATA_ACCESS_MASK3)) == (pt.DATA_ACCESS_ADDR3 | pt.DATA_ACCESS_MASK3);
     157              :    assign ACCESS4_STARTOK = pt.DATA_ACCESS_ENABLE4 & ((start_addr_d[31:0] | pt.DATA_ACCESS_MASK4)) == (pt.DATA_ACCESS_ADDR4 | pt.DATA_ACCESS_MASK4);
     158              :    assign ACCESS5_STARTOK = pt.DATA_ACCESS_ENABLE5 & ((start_addr_d[31:0] | pt.DATA_ACCESS_MASK5)) == (pt.DATA_ACCESS_ADDR5 | pt.DATA_ACCESS_MASK5);
     159              :    assign ACCESS6_STARTOK = pt.DATA_ACCESS_ENABLE6 & ((start_addr_d[31:0] | pt.DATA_ACCESS_MASK6)) == (pt.DATA_ACCESS_ADDR6 | pt.DATA_ACCESS_MASK6);
     160              :    assign ACCESS7_STARTOK = pt.DATA_ACCESS_ENABLE7 & ((start_addr_d[31:0] | pt.DATA_ACCESS_MASK7)) == (pt.DATA_ACCESS_ADDR7 | pt.DATA_ACCESS_MASK7);
     161              :    assign ACCESS0_ENDOK   = pt.DATA_ACCESS_ENABLE0 & ((end_addr_d[31:0]   | pt.DATA_ACCESS_MASK0)) == (pt.DATA_ACCESS_ADDR0 | pt.DATA_ACCESS_MASK0);
     162              :    assign ACCESS1_ENDOK   = pt.DATA_ACCESS_ENABLE1 & ((end_addr_d[31:0]   | pt.DATA_ACCESS_MASK1)) == (pt.DATA_ACCESS_ADDR1 | pt.DATA_ACCESS_MASK1);
     163              :    assign ACCESS2_ENDOK   = pt.DATA_ACCESS_ENABLE2 & ((end_addr_d[31:0]   | pt.DATA_ACCESS_MASK2)) == (pt.DATA_ACCESS_ADDR2 | pt.DATA_ACCESS_MASK2);
     164              :    assign ACCESS3_ENDOK   = pt.DATA_ACCESS_ENABLE3 & ((end_addr_d[31:0]   | pt.DATA_ACCESS_MASK3)) == (pt.DATA_ACCESS_ADDR3 | pt.DATA_ACCESS_MASK3);
     165              :    assign ACCESS4_ENDOK   = pt.DATA_ACCESS_ENABLE4 & ((end_addr_d[31:0]   | pt.DATA_ACCESS_MASK4)) == (pt.DATA_ACCESS_ADDR4 | pt.DATA_ACCESS_MASK4);
     166              :    assign ACCESS5_ENDOK   = pt.DATA_ACCESS_ENABLE5 & ((end_addr_d[31:0]   | pt.DATA_ACCESS_MASK5)) == (pt.DATA_ACCESS_ADDR5 | pt.DATA_ACCESS_MASK5);
     167              :    assign ACCESS6_ENDOK   = pt.DATA_ACCESS_ENABLE6 & ((end_addr_d[31:0]   | pt.DATA_ACCESS_MASK6)) == (pt.DATA_ACCESS_ADDR6 | pt.DATA_ACCESS_MASK6);
     168              :    assign ACCESS7_ENDOK   = pt.DATA_ACCESS_ENABLE7 & ((end_addr_d[31:0]   | pt.DATA_ACCESS_MASK7)) == (pt.DATA_ACCESS_ADDR7 | pt.DATA_ACCESS_MASK7);
     169              : 
     170              :   if (pt.PMP_ENTRIES == 0) begin
     171              :    assign non_dccm_access_ok = (~(|{pt.DATA_ACCESS_ENABLE0,pt.DATA_ACCESS_ENABLE1,pt.DATA_ACCESS_ENABLE2,pt.DATA_ACCESS_ENABLE3,pt.DATA_ACCESS_ENABLE4,pt.DATA_ACCESS_ENABLE5,pt.DATA_ACCESS_ENABLE6,pt.DATA_ACCESS_ENABLE7})) |
     172              :                                (( ACCESS0_STARTOK|
     173              :                                   ACCESS1_STARTOK|
     174              :                                   ACCESS2_STARTOK|
     175              :                                   ACCESS3_STARTOK|
     176              :                                   ACCESS4_STARTOK|
     177              :                                   ACCESS5_STARTOK|
     178              :                                   ACCESS6_STARTOK|
     179              :                                  ACCESS7_STARTOK)   &
     180              :                                 ( ACCESS0_ENDOK|
     181              :                                   ACCESS1_ENDOK|
     182              :                                   ACCESS2_ENDOK|
     183              :                                   ACCESS3_ENDOK|
     184              :                                   ACCESS4_ENDOK|
     185              :                                   ACCESS5_ENDOK|
     186              :                                   ACCESS6_ENDOK|
     187              :                                  ACCESS7_ENDOK));
     188              :   end
     189              : 
     190              :    // Access fault logic
     191              :    // 0. Unmapped local memory : Addr in dccm region but not in dccm offset OR Addr in picm region but not in picm offset OR DCCM -> PIC cross when DCCM/PIC in same region
     192              :    // 1. Uncorrectable (double bit) ECC error
     193              :    // 3. Address is not in a populated non-dccm region
     194              :    // 5. Region predication access fault: Base Address in DCCM/PIC and Final address in non-DCCM/non-PIC region or vice versa
     195              :    // 6. Ld/St access to picm are not word aligned or word size
     196              :    assign regpred_access_fault_d  = (start_addr_dccm_or_pic ^ base_reg_dccm_or_pic);                   // 5. Region predication access fault: Base Address in DCCM/PIC and Final address in non-DCCM/non-PIC region or vice versa
     197              :    assign picm_access_fault_d     = (addr_in_pic_d & ((start_addr_d[1:0] != 2'b0) | ~lsu_pkt_d.word));                                               // 6. Ld/St access to picm are not word aligned or word size
     198              : 
     199              :    if (pt.DCCM_ENABLE & (pt.DCCM_REGION == pt.PIC_REGION)) begin
     200              :       assign unmapped_access_fault_d = ((start_addr_in_dccm_region_d & ~(start_addr_in_dccm_d | start_addr_in_pic_d)) |   // 0. Addr in dccm/pic region but not in dccm/pic offset
     201              :                                         (end_addr_in_dccm_region_d & ~(end_addr_in_dccm_d | end_addr_in_pic_d))       |   // 0. Addr in dccm/pic region but not in dccm/pic offset
     202              :                                         (start_addr_in_dccm_d & end_addr_in_pic_d)                                    |   // 0. DCCM -> PIC cross when DCCM/PIC in same region
     203              :                                         (start_addr_in_pic_d  & end_addr_in_dccm_d));                                     // 0. DCCM -> PIC cross when DCCM/PIC in same region
     204              :     if (pt.PMP_ENTRIES > 0) begin
     205              :       assign mpu_access_fault_d   = (lsu_pmp_error_start | lsu_pmp_error_end);                                         // X. Address is in blocked region
     206              :     end else begin
     207              :       assign mpu_access_fault_d   = (~start_addr_in_dccm_region_d & ~non_dccm_access_ok);                              // 3. Address is not in a populated non-dccm region
     208              :     end
     209              :    end else begin
     210              :       assign unmapped_access_fault_d = ((start_addr_in_dccm_region_d & ~start_addr_in_dccm_d)                              |   // 0. Addr in dccm region but not in dccm offset
     211              :                                         (end_addr_in_dccm_region_d & ~end_addr_in_dccm_d)                                  |   // 0. Addr in dccm region but not in dccm offset
     212              :                                         (start_addr_in_pic_region_d & ~start_addr_in_pic_d)                                |   // 0. Addr in picm region but not in picm offset
     213              :                                         (end_addr_in_pic_region_d & ~end_addr_in_pic_d));                                      // 0. Addr in picm region but not in picm offset
     214              :     if (pt.PMP_ENTRIES > 0) begin
     215              :       assign mpu_access_fault_d   = (lsu_pmp_error_start | lsu_pmp_error_end);                                              // X. Address is in blocked region
     216              :     end else begin
     217              :       assign mpu_access_fault_d   = (~start_addr_in_pic_region_d & ~start_addr_in_dccm_region_d & ~non_dccm_access_ok);     // 3. Address is not in a populated non-dccm region
     218              :     end
     219              :    end
     220              : 
     221              :    assign access_fault_d = (unmapped_access_fault_d | mpu_access_fault_d | picm_access_fault_d | regpred_access_fault_d) & lsu_pkt_d.valid & ~lsu_pkt_d.dma;
     222              :    assign access_fault_mscause_d[3:0] = unmapped_access_fault_d ? 4'h2 : mpu_access_fault_d ? 4'h3 : regpred_access_fault_d ? 4'h5 : picm_access_fault_d ? 4'h6 : 4'h0;
     223              : 
     224              :    // Misaligned happens due to 2 reasons
     225              :    // 0. Region cross
     226              :    // 1. sideeffects access which are not aligned
     227              :    assign regcross_misaligned_fault_d = (start_addr_d[31:28] != end_addr_d[31:28]);
     228              :    assign sideeffect_misaligned_fault_d = (is_sideeffects_d & ~is_aligned_d);
     229              :    assign misaligned_fault_d = (regcross_misaligned_fault_d | (sideeffect_misaligned_fault_d & addr_external_d)) & lsu_pkt_d.valid & ~lsu_pkt_d.dma;
     230              :    assign misaligned_fault_mscause_d[3:0] = regcross_misaligned_fault_d ? 4'h2 : sideeffect_misaligned_fault_d ? 4'h1 : 4'h0;
     231              : 
     232              :    assign exc_mscause_d[3:0] = misaligned_fault_d ? misaligned_fault_mscause_d[3:0] : access_fault_mscause_d[3:0];
     233              : 
     234              :    // Fast interrupt error logic
     235              :    assign fir_dccm_access_error_d    = ((start_addr_in_dccm_region_d & ~start_addr_in_dccm_d) |
     236              :                                                                                 (end_addr_in_dccm_region_d   & ~end_addr_in_dccm_d)) & lsu_pkt_d.valid & lsu_pkt_d.fast_int;
     237              :    assign fir_nondccm_access_error_d = ~(start_addr_in_dccm_region_d & end_addr_in_dccm_region_d) & lsu_pkt_d.valid & lsu_pkt_d.fast_int;
     238              : 
     239              :    rvdff #(.WIDTH(1))   is_sideeffects_mff (.din(is_sideeffects_d), .dout(is_sideeffects_m), .clk(lsu_c2_m_clk), .*);
     240              : 
     241              : endmodule // el2_lsu_addrcheck