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