Project Full coverage report
Current view: Cores-VeeR-EL2—Cores-VeeR-EL2—design—ifu—el2_ifu_ifc_ctl.sv Coverage Hit Total
Test Date: 21-11-2024 Toggle 97.6% 40 41
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              : // el2_ifu_ifc_ctl.sv
      18              : // Function: Fetch pipe control
      19              : //
      20              : // Comments:
      21              : //********************************************************************************
      22              : 
      23              : module el2_ifu_ifc_ctl
      24              : import el2_pkg::*;
      25              : #(
      26              : `include "el2_param.vh"
      27              :  )
      28              :   (
      29     69840565 :    input logic clk,                         // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
      30     69840565 :    input logic free_l2clk,                  // Clock always.                  Through one clock header.  For flops with    second header built in.
      31              : 
      32          338 :    input logic rst_l, // reset enable, from core pin
      33              :    // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
      34              :    /*verilator coverage_off*/
      35              :    input logic scan_mode, // scan
      36              :    /*verilator coverage_on*/
      37              : 
      38      6782653 :    input logic ic_hit_f,      // Icache hit
      39      5908764 :    input logic ifu_ic_mb_empty, // Miss buffer empty
      40              : 
      41      5986539 :    input logic ifu_fb_consume1,  // Aligner consumed 1 fetch buffer
      42      1761739 :    input logic ifu_fb_consume2,  // Aligner consumed 2 fetch buffers
      43              : 
      44          232 :    input logic dec_tlu_flush_noredir_wb, // Don't fetch on flush
      45       673974 :    input logic exu_flush_final, // FLush
      46       227566 :    input logic [31:1] exu_flush_path_final, // Flush path
      47              : 
      48      3170544 :    input logic ifu_bp_hit_taken_f, // btb hit, select the target path
      49       518479 :    input logic [31:1] ifu_bp_btb_target_f, //  predicted target PC
      50              : 
      51           16 :    input logic ic_dma_active, // IC DMA active, stop fetching
      52      2632580 :    input logic ic_write_stall, // IC is writing, stop fetching
      53           26 :    input logic dma_iccm_stall_any, // force a stall in the fetch pipe for DMA ICCM access
      54              : 
      55            0 :    input logic [31:0]  dec_tlu_mrac_ff ,   // side_effect and cacheable for each region
      56              : 
      57          443 :    output logic [31:1] ifc_fetch_addr_f, // fetch addr F
      58          443 :    output logic [31:1] ifc_fetch_addr_bf, // fetch addr BF
      59              : 
      60      3714536 :    output logic  ifc_fetch_req_f,  // fetch request valid F
      61              : 
      62       614908 :    output logic  ifu_pmu_fetch_stall, // pmu event measuring fetch stall
      63              : 
      64          375 :    output logic                       ifc_fetch_uncacheable_bf,      // The fetch request is uncacheable space. BF stage
      65      3714574 :    output logic                      ifc_fetch_req_bf,              // Fetch request. Comes with the address.  BF stage
      66          568 :    output logic                       ifc_fetch_req_bf_raw,          // Fetch request without some qualifications. Used for clock-gating. BF stage
      67           84 :    output logic                       ifc_iccm_access_bf,            // This request is to the ICCM. Do not generate misses to the bus.
      68            2 :    output logic                       ifc_region_acc_fault_bf,       // Access fault. in ICCM region but offset is outside defined ICCM.
      69              : 
      70       640547 :    output logic  ifc_dma_access_ok // fetch is not accessing the ICCM, DMA can proceed
      71              : 
      72              : 
      73              :    );
      74              : 
      75          443 :    logic [31:1]  fetch_addr_bf;
      76          445 :    logic [31:1]  fetch_addr_next;
      77       445816 :    logic [3:0]   fb_write_f, fb_write_ns;
      78              : 
      79      1083954 :    logic     fb_full_f_ns, fb_full_f;
      80          605 :    logic     fb_right, fb_right2, fb_left, wfm, idle;
      81      5885178 :    logic     sel_last_addr_bf, sel_next_addr_bf;
      82      8567842 :    logic     miss_f, miss_a;
      83           26 :    logic     flush_fb, dma_iccm_stall_any_f;
      84          790 :    logic     mb_empty_mod, goto_idle, leave_idle;
      85      3661454 :    logic     fetch_bf_en;
      86       626520 :    logic         line_wrap;
      87       472249 :    logic         fetch_addr_next_1;
      88              : 
      89              :    // FSM assignment
      90              :     typedef enum logic [1:0] { IDLE  = 2'b00 ,
      91              :                                FETCH = 2'b01 ,
      92              :                                STALL = 2'b10 ,
      93              :                                WFM   = 2'b11   } state_t ;
      94          560 :    state_t state      ;
      95          560 :    state_t next_state ;
      96              : 
      97           42 :    logic     dma_stall;
      98              :    assign dma_stall = ic_dma_active | dma_iccm_stall_any_f;
      99              : 
     100              : 
     101              : 
     102              :    // Fetch address mux
     103              :    // - flush
     104              :    // - Miss *or* flush during WFM (icache miss buffer is blocking)
     105              :    // - Sequential
     106              : 
     107              : if(pt.BTB_ENABLE==1) begin : genblock1
     108              :    logic sel_btb_addr_bf;
     109              : 
     110              :    assign sel_last_addr_bf = ~exu_flush_final & (~ifc_fetch_req_f | ~ic_hit_f);
     111              :    assign sel_btb_addr_bf  = ~exu_flush_final & ifc_fetch_req_f & ifu_bp_hit_taken_f & ic_hit_f;
     112              :    assign sel_next_addr_bf = ~exu_flush_final & ifc_fetch_req_f & ~ifu_bp_hit_taken_f & ic_hit_f;
     113              : 
     114              : 
     115              :    assign fetch_addr_bf[31:1] = ( ({31{exu_flush_final}} &  exu_flush_path_final[31:1]) | // FLUSH path
     116              :                   ({31{sel_last_addr_bf}} & ifc_fetch_addr_f[31:1]) | // MISS path
     117              :                   ({31{sel_btb_addr_bf}} & {ifu_bp_btb_target_f[31:1]})| // BTB target
     118              :                   ({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path
     119              : 
     120              : 
     121              : end // if (pt.BTB_ENABLE=1)
     122              :    else begin
     123              :    assign sel_last_addr_bf = ~exu_flush_final & (~ifc_fetch_req_f | ~ic_hit_f);
     124              :    assign sel_next_addr_bf = ~exu_flush_final & ifc_fetch_req_f & ic_hit_f;
     125              : 
     126              : 
     127              :    assign fetch_addr_bf[31:1] = ( ({31{exu_flush_final}} &  exu_flush_path_final[31:1]) | // FLUSH path
     128              :                   ({31{sel_last_addr_bf}} & ifc_fetch_addr_f[31:1]) | // MISS path
     129              :                   ({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path
     130              : 
     131              : end
     132              :    assign fetch_addr_next[31:1] = {({ifc_fetch_addr_f[31:2]} + 30'b1), fetch_addr_next_1 };
     133              :    assign line_wrap = (fetch_addr_next[pt.ICACHE_TAG_INDEX_LO] ^ ifc_fetch_addr_f[pt.ICACHE_TAG_INDEX_LO]);
     134              : 
     135              :    assign fetch_addr_next_1 = line_wrap ? 1'b0 : ifc_fetch_addr_f[1];
     136              : 
     137              :    assign ifc_fetch_req_bf_raw = ~idle;
     138              :    assign ifc_fetch_req_bf =  ifc_fetch_req_bf_raw &
     139              : 
     140              :                  ~(fb_full_f_ns & ~(ifu_fb_consume2 | ifu_fb_consume1)) &
     141              :                  ~dma_stall &
     142              :                  ~ic_write_stall &
     143              :                  ~dec_tlu_flush_noredir_wb;
     144              : 
     145              : 
     146              :    assign fetch_bf_en = exu_flush_final | ifc_fetch_req_f;
     147              : 
     148              :    assign miss_f = ifc_fetch_req_f & ~ic_hit_f & ~exu_flush_final;
     149              : 
     150              :    assign mb_empty_mod = (ifu_ic_mb_empty | exu_flush_final) & ~dma_stall & ~miss_f & ~miss_a;
     151              : 
     152              :    // Halt flushes and takes us to IDLE
     153              :    assign goto_idle = exu_flush_final & dec_tlu_flush_noredir_wb;
     154              :    // If we're in IDLE, and we get a flush, goto FETCH
     155              :    assign leave_idle = exu_flush_final & ~dec_tlu_flush_noredir_wb & idle;
     156              : 
     157              : //.i 7
     158              : //.o 2
     159              : //.ilb state[1] state[0] reset_delayed miss_f mb_empty_mod  goto_idle leave_idle
     160              : //.ob next_state[1] next_state[0]
     161              : //.type fr
     162              : //
     163              : //# fetch 01, stall 10, wfm 11, idle 00
     164              : //-- 1---- 01
     165              : //-- 0--1- 00
     166              : //00 0--00 00
     167              : //00 0--01 01
     168              : //
     169              : //01 01-0- 11
     170              : //01 00-0- 01
     171              : //
     172              : //11 0-10- 01
     173              : //11 0-00- 11
     174              : 
     175              :    assign next_state[1] = (~state[1] & state[0] & miss_f & ~goto_idle) |
     176              :               (state[1] & ~mb_empty_mod & ~goto_idle);
     177              : 
     178              :    assign next_state[0] = (~goto_idle & leave_idle) | (state[0] & ~goto_idle);
     179              : 
     180              :    assign flush_fb = exu_flush_final;
     181              : 
     182              :    // model fb write logic to mass balance the fetch buffers
     183              :    assign fb_right = ( ifu_fb_consume1 & ~ifu_fb_consume2 & (~ifc_fetch_req_f | miss_f)) | // Consumed and no new fetch
     184              :               (ifu_fb_consume2 &  ifc_fetch_req_f); // Consumed 2 and new fetch
     185              : 
     186              : 
     187              :    assign fb_right2 = (ifu_fb_consume2 & (~ifc_fetch_req_f | miss_f)); // Consumed 2 and no new fetch
     188              : 
     189              :    assign fb_left = ifc_fetch_req_f & ~(ifu_fb_consume1 | ifu_fb_consume2) & ~miss_f;
     190              : 
     191              : // CBH
     192              :    assign fb_write_ns[3:0] = ( ({4{(flush_fb)}} & 4'b0001) |
     193              :                    ({4{~flush_fb & fb_right }} & {1'b0, fb_write_f[3:1]}) |
     194              :                    ({4{~flush_fb & fb_right2}} & {2'b0, fb_write_f[3:2]}) |
     195              :                    ({4{~flush_fb & fb_left  }} & {fb_write_f[2:0], 1'b0}) |
     196              :                    ({4{~flush_fb & ~fb_right & ~fb_right2 & ~fb_left}}  & fb_write_f[3:0]));
     197              : 
     198              : 
     199              :    assign fb_full_f_ns = fb_write_ns[3];
     200              : 
     201              :    assign idle     = state      == IDLE  ;
     202              :    assign wfm      = state      == WFM   ;
     203              : 
     204              :    rvdffie #(10) fbwrite_ff (.*, .clk(free_l2clk),
     205              :                           .din( {dma_iccm_stall_any, miss_f, ifc_fetch_req_bf, next_state[1:0], fb_full_f_ns, fb_write_ns[3:0]}),
     206              :                           .dout({dma_iccm_stall_any_f, miss_a, ifc_fetch_req_f, state[1:0], fb_full_f, fb_write_f[3:0]}));
     207              : 
     208              :    assign ifu_pmu_fetch_stall = wfm |
     209              :                 (ifc_fetch_req_bf_raw &
     210              :                 ( (fb_full_f & ~(ifu_fb_consume2 | ifu_fb_consume1 | exu_flush_final)) |
     211              :                   dma_stall));
     212              : 
     213              : 
     214              : 
     215              :    assign ifc_fetch_addr_bf[31:1] = fetch_addr_bf[31:1];
     216              : 
     217              :    rvdffpcie #(31) faddrf1_ff  (.*, .en(fetch_bf_en), .din(fetch_addr_bf[31:1]), .dout(ifc_fetch_addr_f[31:1]));
     218              : 
     219              : 
     220              :  if (pt.ICCM_ENABLE)  begin : genblock2
     221              :    logic iccm_acc_in_region_bf;
     222              :    logic iccm_acc_in_range_bf;
     223              :    rvrangecheck #( .CCM_SADR    (pt.ICCM_SADR),
     224              :                    .CCM_SIZE    (pt.ICCM_SIZE) ) iccm_rangecheck (
     225              :                                      .addr     ({ifc_fetch_addr_bf[31:1],1'b0}) ,
     226              :                                      .in_range (iccm_acc_in_range_bf) ,
     227              :                                      .in_region(iccm_acc_in_region_bf)
     228              :                                      );
     229              : 
     230              :    assign ifc_iccm_access_bf = iccm_acc_in_range_bf ;
     231              : 
     232              :   assign ifc_dma_access_ok = ( (~ifc_iccm_access_bf |
     233              :                  (fb_full_f & ~(ifu_fb_consume2 | ifu_fb_consume1)) |
     234              :                  (wfm  & ~ifc_fetch_req_bf) |
     235              :                  idle ) & ~exu_flush_final) |
     236              :                   dma_iccm_stall_any_f;
     237              : 
     238              :   assign ifc_region_acc_fault_bf = ~iccm_acc_in_range_bf & iccm_acc_in_region_bf ;
     239              :  end
     240              :  else  begin
     241              :    assign ifc_iccm_access_bf = 1'b0 ;
     242              :    assign ifc_dma_access_ok  = 1'b0 ;
     243              :    assign ifc_region_acc_fault_bf  = 1'b0 ;
     244              :  end
     245              : 
     246              :    assign ifc_fetch_uncacheable_bf =  ~dec_tlu_mrac_ff[{ifc_fetch_addr_bf[31:28] , 1'b0 }]  ; // bit 0 of each region description is the cacheable bit
     247              : 
     248              : endmodule // el2_ifu_ifc_ctl
     249              :