1984 lines
91 KiB
Systemverilog
1984 lines
91 KiB
Systemverilog
//********************************************************************************
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright 2020 Western Digital Corporation or its affiliates.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//********************************************************************************
|
|
|
|
|
|
//********************************************************************************
|
|
// Function: Icache , iccm control
|
|
// BFF -> F1 -> F2 -> A
|
|
//********************************************************************************
|
|
|
|
module el2_ifu_mem_ctl
|
|
import el2_pkg::*;
|
|
#(
|
|
`include "el2_param.vh"
|
|
) (
|
|
input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK.
|
|
input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
|
|
input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in.
|
|
input logic rst_l, // reset, active low
|
|
|
|
input logic exu_flush_final, // Flush from the pipeline., includes flush lower
|
|
input logic dec_tlu_flush_lower_wb, // Flush lower from the pipeline.
|
|
input logic dec_tlu_flush_err_wb, // Flush from the pipeline due to perr.
|
|
input logic dec_tlu_i0_commit_cmt, // committed i0 instruction
|
|
input logic dec_tlu_force_halt, // force halt.
|
|
|
|
input logic [31:1] ifc_fetch_addr_bf, // Fetch Address byte aligned always. F1 stage.
|
|
input logic ifc_fetch_uncacheable_bf, // The fetch request is uncacheable space. F1 stage
|
|
input logic ifc_fetch_req_bf, // Fetch request. Comes with the address. F1 stage
|
|
input logic ifc_fetch_req_bf_raw, // Fetch request without some qualifications. Used for clock-gating. F1 stage
|
|
input logic ifc_iccm_access_bf, // This request is to the ICCM. Do not generate misses to the bus.
|
|
input logic ifc_region_acc_fault_bf, // Access fault. in ICCM region but offset is outside defined ICCM.
|
|
input logic ifc_dma_access_ok, // It is OK to give dma access to the ICCM. (ICCM is not busy this cycle).
|
|
input logic dec_tlu_fence_i_wb, // Fence.i instruction is committing. Clear all Icache valids.
|
|
input logic ifu_bp_hit_taken_f, // Branch is predicted taken. Kill the fetch next cycle.
|
|
|
|
input logic ifu_bp_inst_mask_f, // tell ic which valids to kill because of a taken branch, right justified
|
|
|
|
output logic ifu_miss_state_idle, // No icache misses are outstanding.
|
|
output logic ifu_ic_mb_empty, // Continue with normal fetching. This does not mean that miss is finished.
|
|
output logic ic_dma_active , // In the middle of servicing dma request to ICCM. Do not make any new requests.
|
|
output logic ic_write_stall, // Stall fetch the cycle we are writing the cache.
|
|
|
|
/// PMU signals
|
|
output logic ifu_pmu_ic_miss, // IC miss event
|
|
output logic ifu_pmu_ic_hit, // IC hit event
|
|
output logic ifu_pmu_bus_error, // Bus error event
|
|
output logic ifu_pmu_bus_busy, // Bus busy event
|
|
output logic ifu_pmu_bus_trxn, // Bus transaction
|
|
|
|
//-------------------------- IFU AXI signals--------------------------
|
|
// AXI Write Channels
|
|
output logic ifu_axi_awvalid,
|
|
output logic [pt.IFU_BUS_TAG-1:0] ifu_axi_awid,
|
|
output logic [ 31:0] ifu_axi_awaddr,
|
|
output logic [ 3:0] ifu_axi_awregion,
|
|
output logic [ 7:0] ifu_axi_awlen,
|
|
output logic [ 2:0] ifu_axi_awsize,
|
|
output logic [ 1:0] ifu_axi_awburst,
|
|
output logic ifu_axi_awlock,
|
|
output logic [ 3:0] ifu_axi_awcache,
|
|
output logic [ 2:0] ifu_axi_awprot,
|
|
output logic [ 3:0] ifu_axi_awqos,
|
|
|
|
output logic ifu_axi_wvalid,
|
|
output logic [63:0] ifu_axi_wdata,
|
|
output logic [ 7:0] ifu_axi_wstrb,
|
|
output logic ifu_axi_wlast,
|
|
|
|
output logic ifu_axi_bready,
|
|
|
|
// AXI Read Channels
|
|
output logic ifu_axi_arvalid,
|
|
input logic ifu_axi_arready,
|
|
output logic [pt.IFU_BUS_TAG-1:0] ifu_axi_arid,
|
|
output logic [ 31:0] ifu_axi_araddr,
|
|
output logic [ 3:0] ifu_axi_arregion,
|
|
output logic [ 7:0] ifu_axi_arlen,
|
|
output logic [ 2:0] ifu_axi_arsize,
|
|
output logic [ 1:0] ifu_axi_arburst,
|
|
output logic ifu_axi_arlock,
|
|
output logic [ 3:0] ifu_axi_arcache,
|
|
output logic [ 2:0] ifu_axi_arprot,
|
|
output logic [ 3:0] ifu_axi_arqos,
|
|
|
|
input logic ifu_axi_rvalid,
|
|
output logic ifu_axi_rready,
|
|
input logic [pt.IFU_BUS_TAG-1:0] ifu_axi_rid,
|
|
input logic [ 63:0] ifu_axi_rdata,
|
|
input logic [ 1:0] ifu_axi_rresp,
|
|
|
|
input logic ifu_bus_clk_en,
|
|
|
|
|
|
input logic dma_iccm_req, // dma iccm command (read or write)
|
|
input logic [31:0] dma_mem_addr, // dma address
|
|
input logic [ 2:0] dma_mem_sz, // size
|
|
input logic dma_mem_write, // write
|
|
input logic [63:0] dma_mem_wdata, // write data
|
|
input logic [ 2:0] dma_mem_tag, // DMA Buffer entry number
|
|
|
|
output logic iccm_dma_ecc_error, // Data read from iccm has an ecc error
|
|
output logic iccm_dma_rvalid, // Data read from iccm is valid
|
|
output logic [63:0] iccm_dma_rdata, // dma data read from iccm
|
|
output logic [ 2:0] iccm_dma_rtag, // Tag of the DMA req
|
|
output logic iccm_ready, // iccm ready to accept new command.
|
|
|
|
|
|
// I$ & ITAG Ports
|
|
output logic [31:1] ic_rw_addr, // Read/Write addresss to the Icache.
|
|
output logic [pt.ICACHE_NUM_WAYS-1:0] ic_wr_en, // Icache write enable, when filling the Icache.
|
|
output logic ic_rd_en, // Icache read enable.
|
|
|
|
output logic [pt.ICACHE_BANKS_WAY-1:0] [70:0] ic_wr_data, // Data to fill to the Icache. With ECC
|
|
input logic [63:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
|
|
input logic [70:0] ic_debug_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
|
|
input logic [25:0] ictag_debug_rd_data, // Debug icache tag.
|
|
output logic [70:0] ic_debug_wr_data, // Debug wr cache.
|
|
output logic [70:0] ifu_ic_debug_rd_data, // debug data read
|
|
|
|
|
|
input logic [pt.ICACHE_BANKS_WAY-1:0] ic_eccerr, //
|
|
input logic [pt.ICACHE_BANKS_WAY-1:0] ic_parerr,
|
|
|
|
output logic [ pt.ICACHE_INDEX_HI:3] ic_debug_addr, // Read/Write addresss to the Icache.
|
|
output logic ic_debug_rd_en, // Icache debug rd
|
|
output logic ic_debug_wr_en, // Icache debug wr
|
|
output logic ic_debug_tag_array, // Debug tag array
|
|
output logic [pt.ICACHE_NUM_WAYS-1:0] ic_debug_way, // Debug way. Rd or Wr.
|
|
|
|
|
|
output logic [pt.ICACHE_NUM_WAYS-1:0] ic_tag_valid, // Valid bits when accessing the Icache. One valid bit per way. F2 stage
|
|
|
|
input logic [pt.ICACHE_NUM_WAYS-1:0] ic_rd_hit, // Compare hits from Icache tags. Per way. F2 stage
|
|
input logic ic_tag_perr, // Icache Tag parity error
|
|
|
|
// ICCM ports
|
|
output logic [pt.ICCM_BITS-1:1] iccm_rw_addr, // ICCM read/write address.
|
|
output logic iccm_wren, // ICCM write enable (through the DMA)
|
|
output logic iccm_rden, // ICCM read enable.
|
|
output logic [ 77:0] iccm_wr_data, // ICCM write data.
|
|
output logic [ 2:0] iccm_wr_size, // ICCM write location within DW.
|
|
|
|
input logic [63:0] iccm_rd_data, // Data read from ICCM.
|
|
input logic [77:0] iccm_rd_data_ecc, // Data + ECC read from ICCM.
|
|
input logic [1:0] ifu_fetch_val,
|
|
// IFU control signals
|
|
output logic ic_hit_f, // Hit in Icache(if Icache access) or ICCM access( ICCM always has ic_hit_f)
|
|
output logic [1:0] ic_access_fault_f, // Access fault (bus error or ICCM access in region but out of offset range).
|
|
output logic [1:0] ic_access_fault_type_f, // Access fault types
|
|
output logic iccm_rd_ecc_single_err, // This fetch has a single ICCM ecc error.
|
|
output logic [1:0] iccm_rd_ecc_double_err, // This fetch has a double ICCM ecc error.
|
|
output logic ic_error_start, // This has any I$ errors ( data/tag/ecc/parity )
|
|
|
|
output logic ifu_async_error_start, // Or of the sb iccm, and all the icache errors sent to aligner to stop
|
|
output logic iccm_dma_sb_error, // Single Bit ECC error from a DMA access
|
|
output logic [1:0] ic_fetch_val_f, // valid bytes for fetch. To the Aligner.
|
|
output logic [31:0] ic_data_f, // Data read from Icache or ICCM. To the Aligner.
|
|
output logic [63:0] ic_premux_data, // Premuxed data to be muxed with Icache data
|
|
output logic ic_sel_premux_data, // Select premux data.
|
|
|
|
///// Debug
|
|
input el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt, // Icache/tag debug read/write packet
|
|
input logic dec_tlu_core_ecc_disable, // disable the ecc checking and flagging
|
|
output logic ifu_ic_debug_rd_data_valid, // debug data valid.
|
|
output logic iccm_buf_correct_ecc,
|
|
output logic iccm_correction_state,
|
|
|
|
|
|
input logic scan_mode
|
|
);
|
|
|
|
// Create different defines for ICACHE and ICCM enable combinations
|
|
|
|
localparam NUM_OF_BEATS = 8;
|
|
|
|
|
|
|
|
logic [ 31:3] ifu_ic_req_addr_f;
|
|
logic uncacheable_miss_in;
|
|
logic uncacheable_miss_ff;
|
|
|
|
|
|
|
|
logic bus_ifu_wr_en;
|
|
logic bus_ifu_wr_en_ff;
|
|
logic bus_ifu_wr_en_ff_q;
|
|
logic bus_ifu_wr_en_ff_wo_err;
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] bus_ic_wr_en;
|
|
|
|
logic reset_tag_valid_for_miss;
|
|
|
|
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status;
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_mb_in;
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_rep_new;
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_mb_ff;
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_new;
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_hit_new;
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_new_w_debug;
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] tagv_mb_in;
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] tagv_mb_ff;
|
|
|
|
|
|
logic ifu_wr_data_comb_err;
|
|
logic ifu_byp_data_err_new;
|
|
logic [ 1:0] ifu_byp_data_err_f;
|
|
logic ifu_wr_cumulative_err_data;
|
|
logic ifu_wr_cumulative_err;
|
|
logic ifu_wr_data_comb_err_ff;
|
|
logic scnd_miss_index_match;
|
|
|
|
|
|
logic ifc_dma_access_q_ok;
|
|
logic ifc_iccm_access_f;
|
|
logic ifc_region_acc_fault_f;
|
|
logic ifc_region_acc_fault_final_f;
|
|
logic [ 1:0] ifc_bus_acc_fault_f;
|
|
logic ic_act_miss_f;
|
|
logic ic_miss_under_miss_f;
|
|
logic ic_ignore_2nd_miss_f;
|
|
logic ic_act_hit_f;
|
|
logic miss_pending;
|
|
logic [31:1] imb_in, imb_ff;
|
|
logic [31:pt.ICACHE_BEAT_ADDR_HI+1] miss_addr_in, miss_addr;
|
|
logic miss_wrap_f;
|
|
logic flush_final_f;
|
|
logic ifc_fetch_req_f;
|
|
logic ifc_fetch_req_f_raw;
|
|
logic fetch_req_f_qual;
|
|
logic ifc_fetch_req_qual_bf;
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] replace_way_mb_any;
|
|
logic last_beat;
|
|
logic reset_beat_cnt;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:3] ic_req_addr_bits_hi_3;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:3] ic_wr_addr_bits_hi_3;
|
|
logic [ 31:1] ifu_fetch_addr_int_f;
|
|
logic [ 31:1] ifu_ic_rw_int_addr;
|
|
logic crit_wd_byp_ok_ff;
|
|
logic ic_crit_wd_rdy_new_ff;
|
|
logic [ 79:0] ic_byp_data_only_pre_new;
|
|
logic [ 79:0] ic_byp_data_only_new;
|
|
logic ic_byp_hit_f;
|
|
logic ic_valid;
|
|
logic ic_valid_ff;
|
|
logic reset_all_tags;
|
|
logic ic_valid_w_debug;
|
|
|
|
logic [pt.ICACHE_NUM_WAYS-1:0] ifu_tag_wren, ifu_tag_wren_ff;
|
|
logic [pt.ICACHE_NUM_WAYS-1:0] ic_debug_tag_wr_en;
|
|
logic [pt.ICACHE_NUM_WAYS-1:0] ifu_tag_wren_w_debug;
|
|
logic [pt.ICACHE_NUM_WAYS-1:0] ic_debug_way_ff;
|
|
logic ic_debug_rd_en_ff;
|
|
logic fetch_bf_f_c1_clken;
|
|
logic fetch_bf_f_c1_clk;
|
|
logic debug_c1_clken;
|
|
logic debug_c1_clk;
|
|
|
|
logic reset_ic_in;
|
|
logic reset_ic_ff;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:1] vaddr_f;
|
|
logic [31:1] ifu_status_wr_addr;
|
|
logic sel_mb_addr;
|
|
logic sel_mb_addr_ff;
|
|
logic sel_mb_status_addr;
|
|
logic [63:0] ic_final_data;
|
|
|
|
logic [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] ifu_ic_rw_int_addr_ff;
|
|
logic [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] ifu_status_wr_addr_ff;
|
|
logic [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] ifu_ic_rw_int_addr_w_debug;
|
|
logic [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] ifu_status_wr_addr_w_debug;
|
|
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_new_ff;
|
|
logic way_status_wr_en_ff;
|
|
logic [pt.ICACHE_TAG_DEPTH-1:0][pt.ICACHE_STATUS_BITS-1:0] way_status_out;
|
|
logic [1:0] ic_debug_way_enc;
|
|
|
|
logic [pt.IFU_BUS_TAG-1:0] ifu_bus_rid_ff;
|
|
|
|
logic fetch_req_icache_f;
|
|
logic fetch_req_iccm_f;
|
|
logic ic_iccm_hit_f;
|
|
logic fetch_uncacheable_ff;
|
|
logic way_status_wr_en;
|
|
logic sel_byp_data;
|
|
logic sel_ic_data;
|
|
logic sel_iccm_data;
|
|
logic ic_rd_parity_final_err;
|
|
logic ic_act_miss_f_delayed;
|
|
logic bus_ifu_wr_data_error;
|
|
logic bus_ifu_wr_data_error_ff;
|
|
logic way_status_wr_en_w_debug;
|
|
logic ic_debug_tag_val_rd_out;
|
|
logic ifu_pmu_ic_miss_in;
|
|
logic ifu_pmu_ic_hit_in;
|
|
logic ifu_pmu_bus_error_in;
|
|
logic ifu_pmu_bus_trxn_in;
|
|
logic ifu_pmu_bus_busy_in;
|
|
logic ic_debug_ict_array_sel_in;
|
|
logic ic_debug_ict_array_sel_ff;
|
|
logic debug_data_clken;
|
|
logic last_data_recieved_in;
|
|
logic last_data_recieved_ff;
|
|
|
|
logic ifu_bus_rvalid;
|
|
logic ifu_bus_rvalid_ff;
|
|
logic ifu_bus_rvalid_unq_ff;
|
|
logic ifu_bus_arready_unq;
|
|
logic ifu_bus_arready_unq_ff;
|
|
logic ifu_bus_arvalid;
|
|
logic ifu_bus_arvalid_ff;
|
|
logic ifu_bus_arready;
|
|
logic ifu_bus_arready_ff;
|
|
logic [63:0] ifu_bus_rdata_ff;
|
|
logic [1:0] ifu_bus_rresp_ff;
|
|
logic ifu_bus_rsp_valid;
|
|
logic ifu_bus_rsp_ready;
|
|
logic [pt.IFU_BUS_TAG-1:0] ifu_bus_rsp_tag;
|
|
logic [63:0] ifu_bus_rsp_rdata;
|
|
logic [1:0] ifu_bus_rsp_opc;
|
|
|
|
logic [pt.ICACHE_NUM_BEATS-1:0] write_fill_data;
|
|
logic [pt.ICACHE_NUM_BEATS-1:0] wr_data_c1_clk;
|
|
logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_valid_in;
|
|
logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_valid;
|
|
logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_error_in;
|
|
logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_error;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:1] byp_fetch_index;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_0;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_1;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:3] byp_fetch_index_inc;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_inc_0;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_inc_1;
|
|
logic miss_buff_hit_unq_f;
|
|
logic stream_hit_f;
|
|
logic stream_miss_f;
|
|
logic stream_eol_f;
|
|
logic crit_byp_hit_f;
|
|
logic [pt.IFU_BUS_TAG-1:0] other_tag;
|
|
logic [(2*pt.ICACHE_NUM_BEATS)-1:0][31:0] ic_miss_buff_data;
|
|
logic [63:0] ic_miss_buff_half;
|
|
logic scnd_miss_req, scnd_miss_req_q;
|
|
logic scnd_miss_req_in;
|
|
|
|
|
|
logic [ pt.ICCM_BITS-1:2] iccm_ecc_corr_index_ff;
|
|
logic [ pt.ICCM_BITS-1:2] iccm_ecc_corr_index_in;
|
|
logic [ 38:0] iccm_ecc_corr_data_ff;
|
|
logic iccm_ecc_write_status;
|
|
logic iccm_rd_ecc_single_err_ff;
|
|
logic iccm_error_start; // start the error fsm
|
|
logic perr_state_en;
|
|
logic miss_state_en;
|
|
|
|
logic busclk;
|
|
logic busclk_force;
|
|
logic busclk_reset;
|
|
logic bus_ifu_bus_clk_en_ff;
|
|
logic bus_ifu_bus_clk_en;
|
|
|
|
logic ifc_bus_ic_req_ff_in;
|
|
logic ifu_bus_cmd_valid;
|
|
logic ifu_bus_cmd_ready;
|
|
|
|
logic bus_inc_data_beat_cnt;
|
|
logic bus_reset_data_beat_cnt;
|
|
logic bus_hold_data_beat_cnt;
|
|
|
|
logic bus_inc_cmd_beat_cnt;
|
|
logic bus_reset_cmd_beat_cnt_0;
|
|
logic bus_reset_cmd_beat_cnt_secondlast;
|
|
logic bus_hold_cmd_beat_cnt;
|
|
|
|
logic [pt.ICACHE_BEAT_BITS-1:0] bus_new_data_beat_count;
|
|
logic [pt.ICACHE_BEAT_BITS-1:0] bus_data_beat_count;
|
|
|
|
logic [pt.ICACHE_BEAT_BITS-1:0] bus_new_cmd_beat_count;
|
|
logic [pt.ICACHE_BEAT_BITS-1:0] bus_cmd_beat_count;
|
|
|
|
|
|
logic [pt.ICACHE_BEAT_BITS-1:0] bus_new_rd_addr_count;
|
|
logic [pt.ICACHE_BEAT_BITS-1:0] bus_rd_addr_count;
|
|
|
|
|
|
logic bus_cmd_sent;
|
|
logic bus_last_data_beat;
|
|
|
|
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] bus_wren;
|
|
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] bus_wren_last;
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] wren_reset_miss;
|
|
logic ifc_dma_access_ok_d;
|
|
logic ifc_dma_access_ok_prev;
|
|
|
|
logic bus_cmd_req_in;
|
|
logic bus_cmd_req_hold;
|
|
|
|
logic second_half_available;
|
|
logic write_ic_16_bytes;
|
|
|
|
logic ifc_region_acc_fault_final_bf;
|
|
logic ifc_region_acc_fault_memory_bf;
|
|
logic ifc_region_acc_fault_memory_f;
|
|
logic ifc_region_acc_okay;
|
|
|
|
logic iccm_correct_ecc;
|
|
logic dma_sb_err_state, dma_sb_err_state_ff;
|
|
logic two_byte_instr;
|
|
|
|
typedef enum logic [2:0] {
|
|
IDLE = 3'b000,
|
|
CRIT_BYP_OK = 3'b001,
|
|
HIT_U_MISS = 3'b010,
|
|
MISS_WAIT = 3'b011,
|
|
CRIT_WRD_RDY = 3'b100,
|
|
SCND_MISS = 3'b101,
|
|
STREAM = 3'b110,
|
|
STALL_SCND_MISS = 3'b111
|
|
} miss_state_t;
|
|
miss_state_t miss_state, miss_nxtstate;
|
|
|
|
typedef enum logic [1:0] {
|
|
ERR_STOP_IDLE = 2'b00,
|
|
ERR_FETCH1 = 2'b01,
|
|
ERR_FETCH2 = 2'b10,
|
|
ERR_STOP_FETCH = 2'b11
|
|
} err_stop_state_t;
|
|
err_stop_state_t err_stop_state, err_stop_nxtstate;
|
|
logic err_stop_state_en;
|
|
logic err_stop_fetch;
|
|
|
|
logic ic_crit_wd_rdy; // Critical fetch is ready to be bypassed.
|
|
|
|
logic ifu_bp_hit_taken_q_f;
|
|
logic ifu_bus_rvalid_unq;
|
|
logic bus_cmd_beat_en;
|
|
|
|
|
|
// ---- Clock gating section -----
|
|
// c1 clock enables
|
|
|
|
|
|
assign fetch_bf_f_c1_clken = ifc_fetch_req_bf_raw | ifc_fetch_req_f | miss_pending | exu_flush_final | scnd_miss_req;
|
|
assign debug_c1_clken = ic_debug_rd_en | ic_debug_wr_en;
|
|
// C1 - 1 clock pulse for data
|
|
|
|
rvclkhdr fetch_bf_f_c1_cgc (
|
|
.en(fetch_bf_f_c1_clken),
|
|
.l1clk(fetch_bf_f_c1_clk),
|
|
.*
|
|
);
|
|
rvclkhdr debug_c1_cgc (
|
|
.en(debug_c1_clken),
|
|
.l1clk(debug_c1_clk),
|
|
.*
|
|
);
|
|
|
|
// ------ end clock gating section ------------------------
|
|
|
|
logic [1:0] iccm_single_ecc_error;
|
|
logic dma_iccm_req_f;
|
|
assign iccm_dma_sb_error = (|iccm_single_ecc_error[1:0]) & dma_iccm_req_f;
|
|
assign ifu_async_error_start = iccm_rd_ecc_single_err | ic_error_start;
|
|
|
|
|
|
typedef enum logic [2:0] {
|
|
ERR_IDLE = 3'b000,
|
|
IC_WFF = 3'b001,
|
|
ECC_WFF = 3'b010,
|
|
ECC_CORR = 3'b011,
|
|
DMA_SB_ERR = 3'b100
|
|
} perr_state_t;
|
|
perr_state_t perr_state, perr_nxtstate;
|
|
|
|
|
|
assign ic_dma_active = iccm_correct_ecc | (perr_state == DMA_SB_ERR) | (err_stop_state == ERR_STOP_FETCH) | err_stop_fetch |
|
|
dec_tlu_flush_err_wb; // The last term is to give a error-correction a chance to finish before refetch starts
|
|
|
|
assign scnd_miss_req_in = ifu_bus_rsp_valid & bus_ifu_bus_clk_en & ifu_bus_rsp_ready &
|
|
(&bus_new_data_beat_count[pt.ICACHE_BEAT_BITS-1:0]) &
|
|
~uncacheable_miss_ff & ((miss_state == SCND_MISS) | (miss_nxtstate == SCND_MISS)) & ~exu_flush_final;
|
|
|
|
assign ifu_bp_hit_taken_q_f = ifu_bp_hit_taken_f & ic_hit_f;
|
|
|
|
//////////////////////////////////// Create Miss State Machine ///////////////////////
|
|
// Create Miss State Machine //
|
|
// Create Miss State Machine //
|
|
// Create Miss State Machine //
|
|
//////////////////////////////////// Create Miss State Machine ///////////////////////
|
|
// FIFO state machine
|
|
always_comb begin : MISS_SM
|
|
miss_nxtstate = IDLE;
|
|
miss_state_en = 1'b0;
|
|
case (miss_state)
|
|
IDLE: begin : idle
|
|
miss_nxtstate = (ic_act_miss_f & ~exu_flush_final) ? CRIT_BYP_OK : HIT_U_MISS;
|
|
miss_state_en = ic_act_miss_f & ~dec_tlu_force_halt;
|
|
end
|
|
CRIT_BYP_OK: begin : crit_byp_ok
|
|
miss_nxtstate = (dec_tlu_force_halt ) ? IDLE :
|
|
( ic_byp_hit_f & (last_data_recieved_ff | (bus_ifu_wr_en_ff & last_beat)) & uncacheable_miss_ff) ? IDLE :
|
|
( ic_byp_hit_f & ~last_data_recieved_ff & uncacheable_miss_ff) ? MISS_WAIT :
|
|
(~ic_byp_hit_f & ~exu_flush_final & (bus_ifu_wr_en_ff & last_beat) & uncacheable_miss_ff) ? CRIT_WRD_RDY :
|
|
( (bus_ifu_wr_en_ff & last_beat) & ~uncacheable_miss_ff) ? IDLE :
|
|
( ic_byp_hit_f & ~exu_flush_final & ~(bus_ifu_wr_en_ff & last_beat) & ~ifu_bp_hit_taken_q_f & ~uncacheable_miss_ff) ? STREAM :
|
|
( bus_ifu_wr_en_ff & ~exu_flush_final & ~(bus_ifu_wr_en_ff & last_beat) & ~ifu_bp_hit_taken_q_f & ~uncacheable_miss_ff) ? STREAM :
|
|
(~ic_byp_hit_f & ~exu_flush_final & (bus_ifu_wr_en_ff & last_beat) & ~uncacheable_miss_ff) ? IDLE :
|
|
( (exu_flush_final | ifu_bp_hit_taken_q_f) & ~(bus_ifu_wr_en_ff & last_beat) ) ? HIT_U_MISS : IDLE;
|
|
miss_state_en = dec_tlu_force_halt | exu_flush_final | ic_byp_hit_f | ifu_bp_hit_taken_q_f | (bus_ifu_wr_en_ff & last_beat) | (bus_ifu_wr_en_ff & ~uncacheable_miss_ff) ;
|
|
end
|
|
CRIT_WRD_RDY: begin : crit_wrd_rdy
|
|
miss_nxtstate = IDLE;
|
|
miss_state_en = exu_flush_final | flush_final_f | ic_byp_hit_f | dec_tlu_force_halt;
|
|
end
|
|
STREAM: begin : stream
|
|
miss_nxtstate = ((exu_flush_final | ifu_bp_hit_taken_q_f | stream_eol_f ) & ~(bus_ifu_wr_en_ff & last_beat) & ~dec_tlu_force_halt) ? HIT_U_MISS : IDLE ;
|
|
miss_state_en = exu_flush_final | ifu_bp_hit_taken_q_f | stream_eol_f | (bus_ifu_wr_en_ff & last_beat) | dec_tlu_force_halt ;
|
|
end
|
|
MISS_WAIT: begin : miss_wait
|
|
miss_nxtstate = (exu_flush_final & ~(bus_ifu_wr_en_ff & last_beat) & ~dec_tlu_force_halt) ? HIT_U_MISS : IDLE ;
|
|
miss_state_en = exu_flush_final | (bus_ifu_wr_en_ff & last_beat) | dec_tlu_force_halt;
|
|
end
|
|
HIT_U_MISS: begin : hit_u_miss
|
|
miss_nxtstate = ic_miss_under_miss_f & ~(bus_ifu_wr_en_ff & last_beat) & ~dec_tlu_force_halt ? SCND_MISS :
|
|
ic_ignore_2nd_miss_f & ~(bus_ifu_wr_en_ff & last_beat) & ~dec_tlu_force_halt ? STALL_SCND_MISS : IDLE ;
|
|
miss_state_en = (bus_ifu_wr_en_ff & last_beat) | ic_miss_under_miss_f | ic_ignore_2nd_miss_f | dec_tlu_force_halt;
|
|
end
|
|
SCND_MISS: begin : scnd_miss
|
|
miss_nxtstate = dec_tlu_force_halt ? IDLE :
|
|
exu_flush_final ? ((bus_ifu_wr_en_ff & last_beat) ? IDLE : HIT_U_MISS) : CRIT_BYP_OK;
|
|
miss_state_en = (bus_ifu_wr_en_ff & last_beat) | exu_flush_final | dec_tlu_force_halt;
|
|
end
|
|
STALL_SCND_MISS: begin : stall_scnd_miss
|
|
miss_nxtstate = dec_tlu_force_halt ? IDLE :
|
|
exu_flush_final ? ((bus_ifu_wr_en_ff & last_beat) ? IDLE : HIT_U_MISS) : IDLE;
|
|
miss_state_en = (bus_ifu_wr_en_ff & last_beat) | exu_flush_final | dec_tlu_force_halt;
|
|
end
|
|
default: begin : def_case
|
|
miss_nxtstate = IDLE;
|
|
miss_state_en = 1'b0;
|
|
end
|
|
endcase
|
|
end
|
|
rvdffs #(($bits(
|
|
miss_state_t
|
|
))) miss_state_ff (
|
|
.clk (active_clk),
|
|
.din (miss_nxtstate),
|
|
.dout({miss_state}),
|
|
.en (miss_state_en),
|
|
.*
|
|
);
|
|
|
|
logic sel_hold_imb;
|
|
|
|
assign miss_pending = (miss_state != IDLE);
|
|
assign crit_wd_byp_ok_ff = (miss_state == CRIT_BYP_OK) | ((miss_state == CRIT_WRD_RDY) & ~flush_final_f);
|
|
assign sel_hold_imb = (miss_pending & ~(bus_ifu_wr_en_ff & last_beat) & ~((miss_state == CRIT_WRD_RDY) & exu_flush_final) &
|
|
~((miss_state == CRIT_WRD_RDY) & crit_byp_hit_f) ) | ic_act_miss_f |
|
|
(miss_pending & (miss_nxtstate == CRIT_WRD_RDY)) ;
|
|
|
|
|
|
logic sel_hold_imb_scnd;
|
|
logic [ 31:1] imb_scnd_in;
|
|
logic [ 31:1] imb_scnd_ff;
|
|
logic uncacheable_miss_scnd_in;
|
|
logic uncacheable_miss_scnd_ff;
|
|
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] tagv_mb_scnd_in;
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] tagv_mb_scnd_ff;
|
|
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_mb_scnd_in;
|
|
logic [pt.ICACHE_STATUS_BITS-1:0] way_status_mb_scnd_ff;
|
|
|
|
assign sel_hold_imb_scnd = ((miss_state == SCND_MISS) | ic_miss_under_miss_f) & ~flush_final_f;
|
|
assign way_status_mb_scnd_in[pt.ICACHE_STATUS_BITS-1:0] = (miss_state == SCND_MISS) ? way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0] : {way_status[pt.ICACHE_STATUS_BITS-1:0]} ;
|
|
assign tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0] = (miss_state == SCND_MISS) ? tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0] : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags & ~exu_flush_final}});
|
|
assign uncacheable_miss_scnd_in = sel_hold_imb_scnd ? uncacheable_miss_scnd_ff : ifc_fetch_uncacheable_bf ;
|
|
|
|
|
|
rvdff_fpga #(1) unc_miss_scnd_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din(uncacheable_miss_scnd_in),
|
|
.dout(uncacheable_miss_scnd_ff)
|
|
);
|
|
rvdffpcie #(31) imb_f_scnd_ff (
|
|
.*,
|
|
.en (fetch_bf_f_c1_clken),
|
|
.din ({imb_scnd_in[31:1]}),
|
|
.dout({imb_scnd_ff[31:1]})
|
|
);
|
|
rvdff_fpga #(pt.ICACHE_STATUS_BITS) mb_rep_wayf2_scnd_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din({way_status_mb_scnd_in[pt.ICACHE_STATUS_BITS-1:0]}),
|
|
.dout({way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0]})
|
|
);
|
|
rvdff_fpga #(pt.ICACHE_NUM_WAYS) mb_tagv_scnd_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din({tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0]}),
|
|
.dout({tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0]})
|
|
);
|
|
|
|
|
|
|
|
|
|
assign ic_req_addr_bits_hi_3[pt.ICACHE_BEAT_ADDR_HI:3] = bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0] ;
|
|
assign ic_wr_addr_bits_hi_3[pt.ICACHE_BEAT_ADDR_HI:3] = ifu_bus_rid_ff[pt.ICACHE_BEAT_BITS-1:0] & {pt.ICACHE_BEAT_BITS{bus_ifu_wr_en_ff}};
|
|
// NOTE: Cacheline size is 16 bytes in this example.
|
|
// Tag Index Bank Offset
|
|
// [31:16] [15:5] [4] [3:0]
|
|
|
|
|
|
assign fetch_req_icache_f = ifc_fetch_req_f & ~ifc_iccm_access_f & ~ifc_region_acc_fault_final_f;
|
|
assign fetch_req_iccm_f = ifc_fetch_req_f & ifc_iccm_access_f;
|
|
|
|
assign ic_iccm_hit_f = fetch_req_iccm_f & (~miss_pending | (miss_state==HIT_U_MISS) | (miss_state==STREAM));
|
|
assign ic_byp_hit_f = (crit_byp_hit_f | stream_hit_f) & fetch_req_icache_f & miss_pending;
|
|
assign ic_act_hit_f = (|ic_rd_hit[pt.ICACHE_NUM_WAYS-1:0]) & fetch_req_icache_f & ~reset_all_tags & (~miss_pending | (miss_state==HIT_U_MISS)) & ~sel_mb_addr_ff;
|
|
assign ic_act_miss_f = (((~(|ic_rd_hit[pt.ICACHE_NUM_WAYS-1:0]) | reset_all_tags) & fetch_req_icache_f & ~miss_pending) | scnd_miss_req) & ~ifc_region_acc_fault_final_f;
|
|
assign ic_miss_under_miss_f = (~(|ic_rd_hit[pt.ICACHE_NUM_WAYS-1:0]) | reset_all_tags) & fetch_req_icache_f & (miss_state == HIT_U_MISS) &
|
|
(imb_ff[31:pt.ICACHE_TAG_INDEX_LO] != ifu_fetch_addr_int_f[31:pt.ICACHE_TAG_INDEX_LO]) & ~uncacheable_miss_ff & ~sel_mb_addr_ff & ~ifc_region_acc_fault_final_f;
|
|
assign ic_ignore_2nd_miss_f = (~(|ic_rd_hit[pt.ICACHE_NUM_WAYS-1:0]) | reset_all_tags) & fetch_req_icache_f & (miss_state == HIT_U_MISS) &
|
|
((imb_ff[31:pt.ICACHE_TAG_INDEX_LO] == ifu_fetch_addr_int_f[31:pt.ICACHE_TAG_INDEX_LO]) | uncacheable_miss_ff) ;
|
|
assign ic_hit_f = ic_act_hit_f | ic_byp_hit_f | ic_iccm_hit_f | (ifc_region_acc_fault_final_f & ifc_fetch_req_f);
|
|
|
|
assign uncacheable_miss_in = scnd_miss_req ? uncacheable_miss_scnd_ff : sel_hold_imb ? uncacheable_miss_ff : ifc_fetch_uncacheable_bf ;
|
|
assign imb_in[31:1] = scnd_miss_req ? imb_scnd_ff[31:1] : sel_hold_imb ? imb_ff[31:1] : {ifc_fetch_addr_bf[31:1]} ;
|
|
|
|
assign imb_scnd_in[31:1] = sel_hold_imb_scnd ? imb_scnd_ff[31:1] : {ifc_fetch_addr_bf[31:1]};
|
|
|
|
assign scnd_miss_index_match = (imb_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] == imb_scnd_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]) & scnd_miss_req & ~ifu_wr_cumulative_err_data;
|
|
assign way_status_mb_in[pt.ICACHE_STATUS_BITS-1:0] = (scnd_miss_req & ~scnd_miss_index_match) ? way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0] :
|
|
(scnd_miss_req & scnd_miss_index_match) ? way_status_rep_new[pt.ICACHE_STATUS_BITS-1:0] :
|
|
miss_pending ? way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0] :
|
|
{way_status[pt.ICACHE_STATUS_BITS-1:0]} ;
|
|
assign tagv_mb_in[pt.ICACHE_NUM_WAYS-1:0] = scnd_miss_req ? (tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0] | ({pt.ICACHE_NUM_WAYS {scnd_miss_index_match}} & replace_way_mb_any[pt.ICACHE_NUM_WAYS-1:0])) :
|
|
miss_pending ? tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0] : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags & ~exu_flush_final}}) ;
|
|
|
|
assign reset_ic_in = miss_pending & ~scnd_miss_req_q & (reset_all_tags | reset_ic_ff);
|
|
|
|
|
|
|
|
rvdffpcie #(31) ifu_fetch_addr_f_ff (
|
|
.*,
|
|
.en (fetch_bf_f_c1_clken),
|
|
.din ({ifc_fetch_addr_bf[31:1]}),
|
|
.dout({ifu_fetch_addr_int_f[31:1]})
|
|
);
|
|
|
|
assign vaddr_f[pt.ICACHE_BEAT_ADDR_HI:1] = ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:1];
|
|
|
|
rvdffpcie #(31) imb_f_ff (
|
|
.*,
|
|
.en (fetch_bf_f_c1_clken),
|
|
.din (imb_in[31:1]),
|
|
.dout(imb_ff[31:1])
|
|
);
|
|
rvdff_fpga #(1) unc_miss_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din(uncacheable_miss_in),
|
|
.dout(uncacheable_miss_ff)
|
|
);
|
|
|
|
|
|
assign miss_addr_in[31:pt.ICACHE_BEAT_ADDR_HI+1] = (~miss_pending ) ? imb_ff[31:pt.ICACHE_BEAT_ADDR_HI+1] :
|
|
( scnd_miss_req_q ) ? imb_scnd_ff[31:pt.ICACHE_BEAT_ADDR_HI+1] : miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1] ;
|
|
|
|
|
|
rvdfflie #(
|
|
.WIDTH(31 - pt.ICACHE_BEAT_ADDR_HI),
|
|
.LEFT (31 - pt.ICACHE_BEAT_ADDR_HI - 8)
|
|
) miss_f_ff (
|
|
.*,
|
|
.en (bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt),
|
|
.din ({miss_addr_in[31:pt.ICACHE_BEAT_ADDR_HI+1]}),
|
|
.dout({miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1]})
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
rvdff_fpga #(pt.ICACHE_STATUS_BITS) mb_rep_wayf2_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din({way_status_mb_in[pt.ICACHE_STATUS_BITS-1:0]}),
|
|
.dout({way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0]})
|
|
);
|
|
rvdff_fpga #(pt.ICACHE_NUM_WAYS) mb_tagv_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din({tagv_mb_in[pt.ICACHE_NUM_WAYS-1:0]}),
|
|
.dout({tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0]})
|
|
);
|
|
|
|
assign ifc_fetch_req_qual_bf = ifc_fetch_req_bf & ~((miss_state == CRIT_WRD_RDY) & flush_final_f) & ~stream_miss_f ;// & ~exu_flush_final ;
|
|
|
|
assign ifc_fetch_req_f = ifc_fetch_req_f_raw & ~exu_flush_final;
|
|
|
|
rvdff_fpga #(1) ifu_iccm_acc_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din(ifc_iccm_access_bf),
|
|
.dout(ifc_iccm_access_f)
|
|
);
|
|
rvdff_fpga #(1) ifu_iccm_reg_acc_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din(ifc_region_acc_fault_final_bf),
|
|
.dout(ifc_region_acc_fault_final_f)
|
|
);
|
|
rvdff_fpga #(1) rgn_acc_ff (
|
|
.*,
|
|
.clk(fetch_bf_f_c1_clk),
|
|
.clken(fetch_bf_f_c1_clken),
|
|
.rawclk(clk),
|
|
.din(ifc_region_acc_fault_bf),
|
|
.dout(ifc_region_acc_fault_f)
|
|
);
|
|
|
|
|
|
assign ifu_ic_req_addr_f[31:3] = {
|
|
miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1], ic_req_addr_bits_hi_3[pt.ICACHE_BEAT_ADDR_HI:3]
|
|
};
|
|
assign ifu_ic_mb_empty = (((miss_state == HIT_U_MISS) | (miss_state == STREAM)) & ~(bus_ifu_wr_en_ff & last_beat)) | ~miss_pending ;
|
|
assign ifu_miss_state_idle = (miss_state == IDLE);
|
|
|
|
|
|
assign sel_mb_addr = ((miss_pending & write_ic_16_bytes & ~uncacheable_miss_ff) | reset_tag_valid_for_miss) ;
|
|
assign ifu_ic_rw_int_addr[31:1] = ({31{ sel_mb_addr}} & {imb_ff[31:pt.ICACHE_BEAT_ADDR_HI+1] , ic_wr_addr_bits_hi_3[pt.ICACHE_BEAT_ADDR_HI:3] , imb_ff[2:1]}) |
|
|
({31{~sel_mb_addr}} & ifc_fetch_addr_bf[31:1] ) ;
|
|
|
|
assign sel_mb_status_addr = ((miss_pending & write_ic_16_bytes & ~uncacheable_miss_ff & last_beat & bus_ifu_wr_en_ff_q) | reset_tag_valid_for_miss) ;
|
|
assign ifu_status_wr_addr[31:1] = ({31{ sel_mb_status_addr}} & {imb_ff[31:pt.ICACHE_BEAT_ADDR_HI+1] , ic_wr_addr_bits_hi_3[pt.ICACHE_BEAT_ADDR_HI:3] , imb_ff[2:1]}) |
|
|
({31{~sel_mb_status_addr}} & ifu_fetch_addr_int_f[31:1] ) ;
|
|
|
|
|
|
assign ic_rw_addr[31:1] = ifu_ic_rw_int_addr[31:1];
|
|
|
|
|
|
if (pt.ICACHE_ECC == 1) begin : icache_ecc_1
|
|
logic [ 6:0] ic_wr_ecc;
|
|
logic [ 6:0] ic_miss_buff_ecc;
|
|
logic [141:0] ic_wr_16bytes_data;
|
|
logic [ 70:0] ifu_ic_debug_rd_data_in;
|
|
|
|
rvecc_encode_64 ic_ecc_encode_64_bus (
|
|
.din (ifu_bus_rdata_ff[63:0]),
|
|
.ecc_out(ic_wr_ecc[6:0])
|
|
);
|
|
rvecc_encode_64 ic_ecc_encode_64_buff (
|
|
.din (ic_miss_buff_half[63:0]),
|
|
.ecc_out(ic_miss_buff_ecc[6:0])
|
|
);
|
|
|
|
for (genvar i = 0; i < pt.ICACHE_BANKS_WAY; i++) begin : ic_wr_data_loop
|
|
assign ic_wr_data[i][70:0] = ic_wr_16bytes_data[((71*i)+70):(71*i)];
|
|
end
|
|
|
|
|
|
assign ic_debug_wr_data[70:0] = {dec_tlu_ic_diag_pkt.icache_wrdata[70:0]};
|
|
assign ic_error_start = ((|ic_eccerr[pt.ICACHE_BANKS_WAY-1:0]) & ic_act_hit_f) | ic_rd_parity_final_err;
|
|
|
|
|
|
|
|
assign ifu_ic_debug_rd_data_in[70:0] = ic_debug_ict_array_sel_ff ? {2'b0,ictag_debug_rd_data[25:21],32'b0,ictag_debug_rd_data[20:0],{7-pt.ICACHE_STATUS_BITS{1'b0}}, way_status[pt.ICACHE_STATUS_BITS-1:0],3'b0,ic_debug_tag_val_rd_out} :
|
|
ic_debug_rd_data[70:0];
|
|
|
|
rvdffe #(71) ifu_debug_data_ff (
|
|
.*,
|
|
.en (debug_data_clken),
|
|
.din ({ifu_ic_debug_rd_data_in[70:0]}),
|
|
.dout({ifu_ic_debug_rd_data[70:0]})
|
|
);
|
|
|
|
assign ic_wr_16bytes_data[141:0] = ifu_bus_rid_ff[0] ? {ic_wr_ecc[6:0] , ifu_bus_rdata_ff[63:0] , ic_miss_buff_ecc[6:0] , ic_miss_buff_half[63:0] } :
|
|
{ic_miss_buff_ecc[6:0] , ic_miss_buff_half[63:0] , ic_wr_ecc[6:0] , ifu_bus_rdata_ff[63:0] } ;
|
|
|
|
|
|
end else begin : icache_parity_1
|
|
logic [ 3:0] ic_wr_parity;
|
|
logic [ 3:0] ic_miss_buff_parity;
|
|
logic [135:0] ic_wr_16bytes_data;
|
|
logic [ 70:0] ifu_ic_debug_rd_data_in;
|
|
for (genvar i = 0; i < 4; i++) begin : DATA_PGEN
|
|
rveven_paritygen #(16) par_bus (
|
|
.data_in (ifu_bus_rdata_ff[((16*i)+15):(16*i)]),
|
|
.parity_out(ic_wr_parity[i])
|
|
);
|
|
rveven_paritygen #(16) par_buff (
|
|
.data_in (ic_miss_buff_half[((16*i)+15):(16*i)]),
|
|
.parity_out(ic_miss_buff_parity[i])
|
|
);
|
|
end
|
|
|
|
|
|
for (genvar i = 0; i < pt.ICACHE_BANKS_WAY; i++) begin : ic_wr_data_loop
|
|
assign ic_wr_data[i][70:0] = {3'b0, ic_wr_16bytes_data[((68*i)+67):(68*i)]};
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
assign ic_debug_wr_data[70:0] = {dec_tlu_ic_diag_pkt.icache_wrdata[70:0]};
|
|
assign ic_error_start = ((|ic_parerr[pt.ICACHE_BANKS_WAY-1:0]) & ic_act_hit_f) | ic_rd_parity_final_err;
|
|
|
|
assign ifu_ic_debug_rd_data_in[70:0] = ic_debug_ict_array_sel_ff ? {6'b0,ictag_debug_rd_data[21],32'b0,ictag_debug_rd_data[20:0],{7-pt.ICACHE_STATUS_BITS{1'b0}},way_status[pt.ICACHE_STATUS_BITS-1:0],3'b0,ic_debug_tag_val_rd_out} :
|
|
ic_debug_rd_data[70:0] ;
|
|
|
|
rvdffe #(71) ifu_debug_data_ff (
|
|
.*,
|
|
.en (debug_data_clken),
|
|
.din ({ifu_ic_debug_rd_data_in[70:0]}),
|
|
.dout({ifu_ic_debug_rd_data[70:0]})
|
|
);
|
|
|
|
assign ic_wr_16bytes_data[135:0] = ifu_bus_rid_ff[0] ? {ic_wr_parity[3:0] , ifu_bus_rdata_ff[63:0] , ic_miss_buff_parity[3:0] , ic_miss_buff_half[63:0] } :
|
|
{ic_miss_buff_parity[3:0] , ic_miss_buff_half[63:0] , ic_wr_parity[3:0] , ifu_bus_rdata_ff[63:0] } ;
|
|
|
|
end
|
|
|
|
|
|
assign ifu_wr_data_comb_err = bus_ifu_wr_data_error_ff;
|
|
assign ifu_wr_cumulative_err = (ifu_wr_data_comb_err | ifu_wr_data_comb_err_ff) & ~reset_beat_cnt;
|
|
assign ifu_wr_cumulative_err_data = ifu_wr_data_comb_err | ifu_wr_data_comb_err_ff;
|
|
|
|
|
|
assign sel_byp_data = (ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK));
|
|
assign sel_ic_data = ~(ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK) | (miss_state == MISS_WAIT)) & ~fetch_req_iccm_f & ~ifc_region_acc_fault_final_f;
|
|
|
|
if (pt.ICCM_ICACHE == 1) begin : iccm_icache
|
|
assign sel_iccm_data = fetch_req_iccm_f;
|
|
|
|
assign ic_final_data[63:0] = ({64{sel_byp_data | sel_iccm_data | sel_ic_data}} & {ic_rd_data[63:0]} ) ;
|
|
|
|
assign ic_premux_data[63:0] = ({64{sel_byp_data }} & {ic_byp_data_only_new[63:0]} ) |
|
|
({64{sel_iccm_data}} & {iccm_rd_data[63:0]});
|
|
|
|
assign ic_sel_premux_data = sel_iccm_data | sel_byp_data;
|
|
end
|
|
|
|
if (pt.ICCM_ONLY == 1) begin : iccm_only
|
|
assign sel_iccm_data = fetch_req_iccm_f;
|
|
assign ic_final_data[63:0] = ({64{sel_byp_data }} & {ic_byp_data_only_new[63:0]} ) |
|
|
({64{sel_iccm_data}} & {iccm_rd_data[63:0]});
|
|
assign ic_premux_data = '0;
|
|
assign ic_sel_premux_data = '0;
|
|
end
|
|
|
|
if (pt.ICACHE_ONLY == 1) begin : icache_only
|
|
assign ic_final_data[63:0] = ({64{sel_byp_data | sel_ic_data}} & {ic_rd_data[63:0]});
|
|
assign ic_premux_data[63:0] = ({64{sel_byp_data}} & {ic_byp_data_only_new[63:0]});
|
|
assign ic_sel_premux_data = sel_byp_data;
|
|
end
|
|
|
|
|
|
if (pt.NO_ICCM_NO_ICACHE == 1) begin : no_iccm_no_icache
|
|
assign ic_final_data[63:0] = ({64{sel_byp_data}} & {ic_byp_data_only_new[63:0]});
|
|
assign ic_premux_data = 0;
|
|
assign ic_sel_premux_data = '0;
|
|
end
|
|
|
|
|
|
assign ifc_bus_acc_fault_f[1:0] = {2{ic_byp_hit_f}} & ifu_byp_data_err_f[1:0];
|
|
assign ic_data_f[31:0] = ic_final_data[31:0];
|
|
|
|
|
|
|
|
assign fetch_req_f_qual = ic_hit_f & ~exu_flush_final;
|
|
assign ic_access_fault_f[1:0] = ({2{ifc_region_acc_fault_final_f}} | ifc_bus_acc_fault_f[1:0]) & {2{~exu_flush_final}};
|
|
assign ic_access_fault_type_f[1:0] = |iccm_rd_ecc_double_err ? 2'b01 :
|
|
ifc_region_acc_fault_f ? 2'b10 :
|
|
ifc_region_acc_fault_memory_f ? 2'b11 : 2'b00 ;
|
|
|
|
// right justified
|
|
|
|
assign ic_fetch_val_f[1] = fetch_req_f_qual & ifu_bp_inst_mask_f & ~(vaddr_f[pt.ICACHE_BEAT_ADDR_HI:1] == {pt.ICACHE_BEAT_ADDR_HI{1'b1}}) & (err_stop_state != ERR_FETCH2);
|
|
assign ic_fetch_val_f[0] = fetch_req_f_qual;
|
|
assign two_byte_instr = (ic_data_f[1:0] != 2'b11);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// Create full buffer... //
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
logic [63:0] ic_miss_buff_data_in;
|
|
assign ic_miss_buff_data_in[63:0] = ifu_bus_rsp_rdata[63:0];
|
|
|
|
for (genvar i = 0; i < pt.ICACHE_NUM_BEATS; i++) begin : wr_flop
|
|
|
|
assign write_fill_data[i] = bus_ifu_wr_en & ( (pt.IFU_BUS_TAG)'(i) == ifu_bus_rsp_tag[pt.IFU_BUS_TAG-1:0]);
|
|
|
|
rvdffe #(32) byp_data_0_ff (
|
|
.*,
|
|
.en (write_fill_data[i]),
|
|
.din (ic_miss_buff_data_in[31:0]),
|
|
.dout(ic_miss_buff_data[i*2][31:0])
|
|
);
|
|
|
|
rvdffe #(32) byp_data_1_ff (
|
|
.*,
|
|
.en (write_fill_data[i]),
|
|
.din (ic_miss_buff_data_in[63:32]),
|
|
.dout(ic_miss_buff_data[i*2+1][31:0])
|
|
);
|
|
|
|
assign ic_miss_buff_data_valid_in[i] = write_fill_data[i] ? 1'b1 : (ic_miss_buff_data_valid[i] & ~ic_act_miss_f) ;
|
|
|
|
rvdff #(1) byp_data_valid_ff (
|
|
.*,
|
|
.clk (active_clk),
|
|
.din (ic_miss_buff_data_valid_in[i]),
|
|
.dout(ic_miss_buff_data_valid[i])
|
|
);
|
|
|
|
assign ic_miss_buff_data_error_in[i] = write_fill_data[i] ? bus_ifu_wr_data_error : (ic_miss_buff_data_error[i] & ~ic_act_miss_f) ;
|
|
|
|
rvdff #(1) byp_data_error_ff (
|
|
.*,
|
|
.clk (active_clk),
|
|
.din (ic_miss_buff_data_error_in[i]),
|
|
.dout(ic_miss_buff_data_error[i])
|
|
);
|
|
end
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// New bypass ready //
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:1] bypass_index;
|
|
logic [pt.ICACHE_BEAT_ADDR_HI:3] bypass_index_5_3_inc;
|
|
logic bypass_data_ready_in;
|
|
logic ic_crit_wd_rdy_new_in;
|
|
|
|
assign bypass_index[pt.ICACHE_BEAT_ADDR_HI:1] = imb_ff[pt.ICACHE_BEAT_ADDR_HI:1];
|
|
assign bypass_index_5_3_inc[pt.ICACHE_BEAT_ADDR_HI:3] = bypass_index[pt.ICACHE_BEAT_ADDR_HI:3] + 1 ;
|
|
|
|
|
|
assign bypass_data_ready_in = ((ic_miss_buff_data_valid_in[bypass_index[pt.ICACHE_BEAT_ADDR_HI:3]] & ~bypass_index[2] & ~bypass_index[1])) |
|
|
((ic_miss_buff_data_valid_in[bypass_index[pt.ICACHE_BEAT_ADDR_HI:3]] & ~bypass_index[2] & bypass_index[1])) |
|
|
((ic_miss_buff_data_valid_in[bypass_index[pt.ICACHE_BEAT_ADDR_HI:3]] & bypass_index[2] & ~bypass_index[1])) |
|
|
((ic_miss_buff_data_valid_in[bypass_index[pt.ICACHE_BEAT_ADDR_HI:3]] & ic_miss_buff_data_valid_in[bypass_index_5_3_inc[pt.ICACHE_BEAT_ADDR_HI:3]] & bypass_index[2] & bypass_index[1])) |
|
|
((ic_miss_buff_data_valid_in[bypass_index[pt.ICACHE_BEAT_ADDR_HI:3]] & (bypass_index[pt.ICACHE_BEAT_ADDR_HI:3] == {pt.ICACHE_BEAT_ADDR_HI{1'b1}}))) ;
|
|
|
|
|
|
|
|
assign ic_crit_wd_rdy_new_in = ( bypass_data_ready_in & crit_wd_byp_ok_ff & uncacheable_miss_ff & ~exu_flush_final & ~ifu_bp_hit_taken_q_f) |
|
|
( crit_wd_byp_ok_ff & ~uncacheable_miss_ff & ~exu_flush_final & ~ifu_bp_hit_taken_q_f) |
|
|
(ic_crit_wd_rdy_new_ff & ~fetch_req_icache_f & crit_wd_byp_ok_ff & ~exu_flush_final) ;
|
|
|
|
|
|
assign byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:1] = ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:1];
|
|
assign byp_fetch_index_0[pt.ICACHE_BEAT_ADDR_HI:2] = {
|
|
ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:3], 1'b0
|
|
};
|
|
assign byp_fetch_index_1[pt.ICACHE_BEAT_ADDR_HI:2] = {
|
|
ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:3], 1'b1
|
|
};
|
|
assign byp_fetch_index_inc[pt.ICACHE_BEAT_ADDR_HI:3] = ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:3]+1'b1 ;
|
|
assign byp_fetch_index_inc_0[pt.ICACHE_BEAT_ADDR_HI:2] = {
|
|
byp_fetch_index_inc[pt.ICACHE_BEAT_ADDR_HI:3], 1'b0
|
|
};
|
|
assign byp_fetch_index_inc_1[pt.ICACHE_BEAT_ADDR_HI:2] = {
|
|
byp_fetch_index_inc[pt.ICACHE_BEAT_ADDR_HI:3], 1'b1
|
|
};
|
|
|
|
assign ifu_byp_data_err_new = (~ifu_fetch_addr_int_f[2] & ~ifu_fetch_addr_int_f[1] & ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] ) |
|
|
(~ifu_fetch_addr_int_f[2] & ifu_fetch_addr_int_f[1] & ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] ) |
|
|
( ifu_fetch_addr_int_f[2] & ~ifu_fetch_addr_int_f[1] & ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] ) |
|
|
( ifu_fetch_addr_int_f[2] & ifu_fetch_addr_int_f[1] & (ic_miss_buff_data_error[byp_fetch_index_inc[pt.ICACHE_BEAT_ADDR_HI:3]] | ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] )) ;
|
|
|
|
assign ifu_byp_data_err_f[1:0] = (ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] ) ? 2'b11 :
|
|
( ifu_fetch_addr_int_f[2] & ifu_fetch_addr_int_f[1] & ~(ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] ) & (~miss_wrap_f & ic_miss_buff_data_error[byp_fetch_index_inc[pt.ICACHE_BEAT_ADDR_HI:3]])) ? 2'b10 : 2'b00;
|
|
|
|
|
|
|
|
|
|
|
|
assign ic_byp_data_only_pre_new[79:0] = ({80{~ifu_fetch_addr_int_f[2]}} & {ic_miss_buff_data[byp_fetch_index_inc_0][15:0],ic_miss_buff_data[byp_fetch_index_1][31:0] , ic_miss_buff_data[byp_fetch_index_0][31:0]}) |
|
|
({80{ ifu_fetch_addr_int_f[2]}} & {ic_miss_buff_data[byp_fetch_index_inc_1][15:0],ic_miss_buff_data[byp_fetch_index_inc_0][31:0] , ic_miss_buff_data[byp_fetch_index_1][31:0]}) ;
|
|
|
|
assign ic_byp_data_only_new[79:0] = ~ifu_fetch_addr_int_f[1] ? {ic_byp_data_only_pre_new[79:0]} :
|
|
{16'b0,ic_byp_data_only_pre_new[79:16]} ;
|
|
|
|
assign miss_wrap_f = (imb_ff[pt.ICACHE_TAG_INDEX_LO] != ifu_fetch_addr_int_f[pt.ICACHE_TAG_INDEX_LO] ) ;
|
|
|
|
assign miss_buff_hit_unq_f = ((ic_miss_buff_data_valid[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] & ~byp_fetch_index[2] & ~byp_fetch_index[1])) |
|
|
((ic_miss_buff_data_valid[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] & ~byp_fetch_index[2] & byp_fetch_index[1])) |
|
|
((ic_miss_buff_data_valid[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] & byp_fetch_index[2] & ~byp_fetch_index[1])) |
|
|
((ic_miss_buff_data_valid[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] & ic_miss_buff_data_valid[byp_fetch_index_inc[pt.ICACHE_BEAT_ADDR_HI:3]] & byp_fetch_index[2] & byp_fetch_index[1])) |
|
|
((ic_miss_buff_data_valid[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] & (byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3] == {pt.ICACHE_BEAT_BITS{1'b1}}))) ;
|
|
|
|
assign stream_hit_f = (miss_buff_hit_unq_f & ~miss_wrap_f) & (miss_state == STREAM);
|
|
assign stream_miss_f = ~(miss_buff_hit_unq_f & ~miss_wrap_f ) & (miss_state==STREAM) & ifc_fetch_req_f;
|
|
assign stream_eol_f = (byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:2] == {pt.ICACHE_BEAT_BITS+1{1'b1}}) & ifc_fetch_req_f & stream_hit_f;
|
|
|
|
assign crit_byp_hit_f = (miss_buff_hit_unq_f ) & ((miss_state == CRIT_WRD_RDY) | (miss_state==CRIT_BYP_OK)) ;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// Figure out if you have the data to write. //
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
assign other_tag[pt.IFU_BUS_TAG-1:0] = {ifu_bus_rid_ff[pt.IFU_BUS_TAG-1:1], ~ifu_bus_rid_ff[0]};
|
|
assign second_half_available = ic_miss_buff_data_valid[other_tag];
|
|
assign write_ic_16_bytes = second_half_available & bus_ifu_wr_en_ff;
|
|
assign ic_miss_buff_half[63:0] = {
|
|
ic_miss_buff_data[{other_tag, 1'b1}], ic_miss_buff_data[{other_tag, 1'b0}]
|
|
};
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// Parity checking logic for Icache logic. //
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
assign ic_rd_parity_final_err = ic_tag_perr & ~exu_flush_final & sel_ic_data & ~(ifc_region_acc_fault_final_f | (|ifc_bus_acc_fault_f)) &
|
|
(fetch_req_icache_f & ~reset_all_tags & (~miss_pending | (miss_state==HIT_U_MISS)) & ~sel_mb_addr_ff);
|
|
|
|
logic [ pt.ICACHE_NUM_WAYS-1:0] perr_err_inv_way;
|
|
logic [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] perr_ic_index_ff;
|
|
logic perr_sel_invalidate;
|
|
logic perr_sb_write_status;
|
|
|
|
|
|
|
|
rvdffe #(
|
|
.WIDTH(pt.ICACHE_INDEX_HI - pt.ICACHE_TAG_INDEX_LO + 1),
|
|
.OVERRIDE(1)
|
|
) perr_dat_ff (
|
|
.din (ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]),
|
|
.dout(perr_ic_index_ff[pt.ICACHE_INDEX_HI : pt.ICACHE_TAG_INDEX_LO]),
|
|
.en (perr_sb_write_status),
|
|
.*
|
|
);
|
|
|
|
assign perr_err_inv_way[pt.ICACHE_NUM_WAYS-1:0] = {pt.ICACHE_NUM_WAYS{perr_sel_invalidate}};
|
|
assign iccm_correct_ecc = (perr_state == ECC_CORR);
|
|
assign dma_sb_err_state = (perr_state == DMA_SB_ERR);
|
|
assign iccm_buf_correct_ecc = iccm_correct_ecc & ~dma_sb_err_state_ff;
|
|
|
|
|
|
|
|
//////////////////////////////////// Create Parity Error State Machine ///////////////////////
|
|
// Create Parity Error State Machine //
|
|
// Create Parity Error State Machine //
|
|
// Create Parity Error State Machine //
|
|
//////////////////////////////////// Create Parity Error State Machine ///////////////////////
|
|
|
|
|
|
// FIFO state machine
|
|
always_comb begin : ERROR_SM
|
|
perr_nxtstate = ERR_IDLE;
|
|
perr_state_en = 1'b0;
|
|
perr_sb_write_status = 1'b0;
|
|
perr_sel_invalidate = 1'b0;
|
|
|
|
case (perr_state)
|
|
ERR_IDLE: begin : err_idle
|
|
perr_nxtstate = iccm_dma_sb_error ? DMA_SB_ERR : (ic_error_start & ~exu_flush_final) ? IC_WFF : ECC_WFF;
|
|
perr_state_en = (((iccm_error_start | ic_error_start) & ~dec_tlu_flush_lower_wb) | iccm_dma_sb_error) & ~dec_tlu_force_halt;
|
|
perr_sb_write_status = perr_state_en;
|
|
end
|
|
IC_WFF: begin : icache_wff // All the I$ data and/or Tag errors ( parity/ECC ) will come to this state
|
|
perr_nxtstate = ERR_IDLE;
|
|
perr_state_en = dec_tlu_flush_lower_wb | dec_tlu_force_halt;
|
|
perr_sel_invalidate = (dec_tlu_flush_err_wb & dec_tlu_flush_lower_wb);
|
|
end
|
|
ECC_WFF: begin : ecc_wff
|
|
perr_nxtstate = ((~dec_tlu_flush_err_wb & dec_tlu_flush_lower_wb ) | dec_tlu_force_halt) ? ERR_IDLE : ECC_CORR ;
|
|
perr_state_en = dec_tlu_flush_lower_wb | dec_tlu_force_halt;
|
|
end
|
|
DMA_SB_ERR: begin : dma_sb_ecc
|
|
perr_nxtstate = dec_tlu_force_halt ? ERR_IDLE : ECC_CORR;
|
|
perr_state_en = 1'b1;
|
|
end
|
|
ECC_CORR: begin : ecc_corr
|
|
perr_nxtstate = ERR_IDLE;
|
|
perr_state_en = 1'b1;
|
|
end
|
|
default: begin : def_case
|
|
perr_nxtstate = ERR_IDLE;
|
|
perr_state_en = 1'b0;
|
|
perr_sb_write_status = 1'b0;
|
|
perr_sel_invalidate = 1'b0;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
rvdffs #(($bits(
|
|
perr_state_t
|
|
))) perr_state_ff (
|
|
.clk (active_clk),
|
|
.din (perr_nxtstate),
|
|
.dout({perr_state}),
|
|
.en (perr_state_en),
|
|
.*
|
|
);
|
|
|
|
//////////////////////////////////// Create stop fetch State Machine /////////////////////////
|
|
//////////////////////////////////// Create stop fetch State Machine /////////////////////////
|
|
//////////////////////////////////// Create stop fetch State Machine /////////////////////////
|
|
//////////////////////////////////// Create stop fetch State Machine /////////////////////////
|
|
//////////////////////////////////// Create stop fetch State Machine /////////////////////////
|
|
always_comb begin : ERROR_STOP_FETCH
|
|
err_stop_nxtstate = ERR_STOP_IDLE;
|
|
err_stop_state_en = 1'b0;
|
|
err_stop_fetch = 1'b0;
|
|
iccm_correction_state = 1'b0;
|
|
|
|
case (err_stop_state)
|
|
ERR_STOP_IDLE: begin : err_stop_idle
|
|
err_stop_nxtstate = ERR_FETCH1;
|
|
err_stop_state_en = dec_tlu_flush_err_wb & (perr_state == ECC_WFF) & ~dec_tlu_force_halt;
|
|
end
|
|
ERR_FETCH1: begin : err_fetch1 // All the I$ data and/or Tag errors ( parity/ECC ) will come to this state
|
|
err_stop_nxtstate = (dec_tlu_flush_lower_wb | dec_tlu_i0_commit_cmt | dec_tlu_force_halt) ? ERR_STOP_IDLE : ((ifu_fetch_val[1:0] == 2'b11) | (ifu_fetch_val[0] & two_byte_instr)) ? ERR_STOP_FETCH : ifu_fetch_val[0] ? ERR_FETCH2 : ERR_FETCH1;
|
|
err_stop_state_en = dec_tlu_flush_lower_wb | dec_tlu_i0_commit_cmt | ifu_fetch_val[0] | ifu_bp_hit_taken_q_f | dec_tlu_force_halt;
|
|
err_stop_fetch = ((ifu_fetch_val[1:0] == 2'b11) | (ifu_fetch_val[0] & two_byte_instr)) & ~(exu_flush_final | dec_tlu_i0_commit_cmt);
|
|
iccm_correction_state = 1'b1;
|
|
|
|
end
|
|
ERR_FETCH2: begin : err_fetch2 // All the I$ data and/or Tag errors ( parity/ECC ) will come to this state
|
|
err_stop_nxtstate = (dec_tlu_flush_lower_wb | dec_tlu_i0_commit_cmt | dec_tlu_force_halt) ? ERR_STOP_IDLE : ifu_fetch_val[0] ? ERR_STOP_FETCH : ERR_FETCH2;
|
|
err_stop_state_en = dec_tlu_flush_lower_wb | dec_tlu_i0_commit_cmt | ifu_fetch_val[0] | dec_tlu_force_halt ;
|
|
err_stop_fetch = ifu_fetch_val[0] & ~exu_flush_final & ~dec_tlu_i0_commit_cmt;
|
|
iccm_correction_state = 1'b1;
|
|
|
|
end
|
|
ERR_STOP_FETCH: begin : ecc_wff
|
|
err_stop_nxtstate = ( (dec_tlu_flush_lower_wb & ~dec_tlu_flush_err_wb) | dec_tlu_i0_commit_cmt | dec_tlu_force_halt) ? ERR_STOP_IDLE : dec_tlu_flush_err_wb ? ERR_FETCH1 : ERR_STOP_FETCH ;
|
|
err_stop_state_en = dec_tlu_flush_lower_wb | dec_tlu_i0_commit_cmt | dec_tlu_force_halt;
|
|
err_stop_fetch = 1'b1;
|
|
iccm_correction_state = 1'b1;
|
|
|
|
end
|
|
default: begin : def_case
|
|
err_stop_nxtstate = ERR_STOP_IDLE;
|
|
err_stop_state_en = 1'b0;
|
|
err_stop_fetch = 1'b0;
|
|
iccm_correction_state = 1'b1;
|
|
|
|
end
|
|
endcase
|
|
end
|
|
rvdffs #(($bits(
|
|
err_stop_state_t
|
|
))) err_stop_state_ff (
|
|
.clk (active_clk),
|
|
.din (err_stop_nxtstate),
|
|
.dout({err_stop_state}),
|
|
.en (err_stop_state_en),
|
|
.*
|
|
);
|
|
|
|
|
|
|
|
assign bus_ifu_bus_clk_en = ifu_bus_clk_en;
|
|
|
|
|
|
rvclkhdr bus_clk_f (
|
|
.en(bus_ifu_bus_clk_en),
|
|
.l1clk(busclk),
|
|
.*
|
|
);
|
|
rvclkhdr bus_clk (
|
|
.en(bus_ifu_bus_clk_en | dec_tlu_force_halt),
|
|
.l1clk(busclk_force),
|
|
.*
|
|
);
|
|
|
|
assign scnd_miss_req = scnd_miss_req_q & ~exu_flush_final;
|
|
|
|
assign ifc_bus_ic_req_ff_in = (ic_act_miss_f | bus_cmd_req_hold | ifu_bus_cmd_valid) & ~dec_tlu_force_halt & ~((bus_cmd_beat_count== {pt.ICACHE_BEAT_BITS{1'b1}}) & ifu_bus_cmd_valid & ifu_bus_cmd_ready & miss_pending);
|
|
|
|
rvdff_fpga #(1) bus_ic_req_ff2 (
|
|
.*,
|
|
.clk(busclk_force),
|
|
.clken(bus_ifu_bus_clk_en | dec_tlu_force_halt),
|
|
.rawclk(clk),
|
|
.din(ifc_bus_ic_req_ff_in),
|
|
.dout(ifu_bus_cmd_valid)
|
|
);
|
|
|
|
assign bus_cmd_req_in = (ic_act_miss_f | bus_cmd_req_hold) & ~bus_cmd_sent & ~dec_tlu_force_halt ; // hold until first command sent
|
|
|
|
|
|
|
|
// AXI command signals
|
|
// Read Channel
|
|
assign ifu_axi_arvalid = ifu_bus_cmd_valid;
|
|
assign ifu_axi_arid[pt.IFU_BUS_TAG-1:0] = ((pt.IFU_BUS_TAG)'(bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0])) & {pt.IFU_BUS_TAG{ifu_bus_cmd_valid}};
|
|
assign ifu_axi_araddr[31:0] = {ifu_ic_req_addr_f[31:3], 3'b0} & {32{ifu_bus_cmd_valid}};
|
|
assign ifu_axi_arsize[2:0] = 3'b011;
|
|
assign ifu_axi_arprot[2:0] = 3'b101;
|
|
assign ifu_axi_arcache[3:0] = 4'b1111;
|
|
assign ifu_axi_arregion[3:0] = ifu_ic_req_addr_f[31:28];
|
|
assign ifu_axi_arlen[7:0] = '0;
|
|
assign ifu_axi_arburst[1:0] = 2'b01;
|
|
assign ifu_axi_arqos[3:0] = '0;
|
|
assign ifu_axi_arlock = '0;
|
|
assign ifu_axi_rready = 1'b1;
|
|
|
|
// Write Channel
|
|
assign ifu_axi_awvalid = '0;
|
|
assign ifu_axi_awid[pt.IFU_BUS_TAG-1:0] = '0;
|
|
assign ifu_axi_awaddr[31:0] = '0;
|
|
assign ifu_axi_awsize[2:0] = '0;
|
|
assign ifu_axi_awprot[2:0] = '0;
|
|
assign ifu_axi_awcache[3:0] = '0;
|
|
assign ifu_axi_awregion[3:0] = '0;
|
|
assign ifu_axi_awlen[7:0] = '0;
|
|
assign ifu_axi_awburst[1:0] = '0;
|
|
assign ifu_axi_awqos[3:0] = '0;
|
|
assign ifu_axi_awlock = '0;
|
|
|
|
assign ifu_axi_wvalid = '0;
|
|
assign ifu_axi_wstrb[7:0] = '0;
|
|
assign ifu_axi_wdata[63:0] = '0;
|
|
assign ifu_axi_wlast = '0;
|
|
assign ifu_axi_bready = '0;
|
|
|
|
|
|
assign ifu_bus_arready_unq = ifu_axi_arready;
|
|
assign ifu_bus_rvalid_unq = ifu_axi_rvalid;
|
|
assign ifu_bus_arvalid = ifu_axi_arvalid;
|
|
|
|
rvdff_fpga #(1) bus_rdy_ff (
|
|
.*,
|
|
.clk(busclk),
|
|
.clken(bus_ifu_bus_clk_en),
|
|
.rawclk(clk),
|
|
.din(ifu_bus_arready_unq),
|
|
.dout(ifu_bus_arready_unq_ff)
|
|
);
|
|
rvdff_fpga #(1) bus_rsp_vld_ff (
|
|
.*,
|
|
.clk(busclk),
|
|
.clken(bus_ifu_bus_clk_en),
|
|
.rawclk(clk),
|
|
.din(ifu_bus_rvalid_unq),
|
|
.dout(ifu_bus_rvalid_unq_ff)
|
|
);
|
|
rvdff_fpga #(1) bus_cmd_ff (
|
|
.*,
|
|
.clk(busclk),
|
|
.clken(bus_ifu_bus_clk_en),
|
|
.rawclk(clk),
|
|
.din(ifu_bus_arvalid),
|
|
.dout(ifu_bus_arvalid_ff)
|
|
);
|
|
rvdff_fpga #(2) bus_rsp_cmd_ff (
|
|
.*,
|
|
.clk(busclk),
|
|
.clken(bus_ifu_bus_clk_en),
|
|
.rawclk(clk),
|
|
.din(ifu_axi_rresp[1:0]),
|
|
.dout(ifu_bus_rresp_ff[1:0])
|
|
);
|
|
rvdff_fpga #(pt.IFU_BUS_TAG) bus_rsp_tag_ff (
|
|
.*,
|
|
.clk(busclk),
|
|
.clken(bus_ifu_bus_clk_en),
|
|
.rawclk(clk),
|
|
.din(ifu_axi_rid[pt.IFU_BUS_TAG-1:0]),
|
|
.dout(ifu_bus_rid_ff[pt.IFU_BUS_TAG-1:0])
|
|
);
|
|
rvdffe #(64) bus_data_ff (
|
|
.*,
|
|
.clk (clk),
|
|
.din (ifu_axi_rdata[63:0]),
|
|
.dout(ifu_bus_rdata_ff[63:0]),
|
|
.en (ifu_bus_clk_en & ifu_axi_rvalid)
|
|
);
|
|
|
|
assign ifu_bus_cmd_ready = ifu_axi_arready;
|
|
assign ifu_bus_rsp_valid = ifu_axi_rvalid;
|
|
assign ifu_bus_rsp_ready = ifu_axi_rready;
|
|
assign ifu_bus_rsp_tag[pt.IFU_BUS_TAG-1:0] = ifu_axi_rid[pt.IFU_BUS_TAG-1:0];
|
|
assign ifu_bus_rsp_rdata[63:0] = ifu_axi_rdata[63:0];
|
|
assign ifu_bus_rsp_opc[1:0] = {ifu_axi_rresp[1:0]};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create write signals so we can write to the miss-buffer directly from the bus.
|
|
|
|
assign ifu_bus_rvalid = ifu_bus_rsp_valid & bus_ifu_bus_clk_en;
|
|
|
|
|
|
|
|
assign ifu_bus_arready = ifu_bus_arready_unq & bus_ifu_bus_clk_en;
|
|
assign ifu_bus_arready_ff = ifu_bus_arready_unq_ff & bus_ifu_bus_clk_en_ff;
|
|
|
|
assign ifu_bus_rvalid_ff = ifu_bus_rvalid_unq_ff & bus_ifu_bus_clk_en_ff;
|
|
assign bus_cmd_sent = ifu_bus_arvalid & ifu_bus_arready & miss_pending & ~dec_tlu_force_halt;
|
|
assign bus_inc_data_beat_cnt = (bus_ifu_wr_en_ff & ~bus_last_data_beat & ~dec_tlu_force_halt);
|
|
assign bus_reset_data_beat_cnt = ic_act_miss_f | (bus_ifu_wr_en_ff & bus_last_data_beat) | dec_tlu_force_halt;
|
|
assign bus_hold_data_beat_cnt = ~bus_inc_data_beat_cnt & ~bus_reset_data_beat_cnt;
|
|
|
|
assign bus_new_data_beat_count[pt.ICACHE_BEAT_BITS-1:0] = ({pt.ICACHE_BEAT_BITS{bus_reset_data_beat_cnt}} & (pt.ICACHE_BEAT_BITS)'(0)) |
|
|
({pt.ICACHE_BEAT_BITS{bus_inc_data_beat_cnt}} & (bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0] + {{pt.ICACHE_BEAT_BITS-1{1'b0}},1'b1})) |
|
|
({pt.ICACHE_BEAT_BITS{bus_hold_data_beat_cnt}} & bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0]);
|
|
|
|
|
|
assign last_data_recieved_in = (bus_ifu_wr_en_ff & bus_last_data_beat & ~scnd_miss_req) | (last_data_recieved_ff & ~ic_act_miss_f) ;
|
|
|
|
|
|
|
|
// Request Address Count
|
|
assign bus_new_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0] = (~miss_pending ) ? imb_ff[pt.ICACHE_BEAT_ADDR_HI:3] :
|
|
( scnd_miss_req_q ) ? imb_scnd_ff[pt.ICACHE_BEAT_ADDR_HI:3] :
|
|
( bus_cmd_sent ) ? (bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0] + 3'b001) :
|
|
bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0];
|
|
|
|
rvdff_fpga #(pt.ICACHE_BEAT_BITS) bus_rd_addr_ff (
|
|
.*,
|
|
.clk(busclk_reset),
|
|
.clken(bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt),
|
|
.rawclk(clk),
|
|
.din({bus_new_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0]}),
|
|
.dout({bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0]})
|
|
);
|
|
|
|
|
|
|
|
// command beat Count
|
|
assign bus_inc_cmd_beat_cnt = ifu_bus_cmd_valid & ifu_bus_cmd_ready & miss_pending & ~dec_tlu_force_halt;
|
|
assign bus_reset_cmd_beat_cnt_0 = (ic_act_miss_f & ~uncacheable_miss_in) | dec_tlu_force_halt;
|
|
assign bus_reset_cmd_beat_cnt_secondlast = ic_act_miss_f & uncacheable_miss_in;
|
|
assign bus_hold_cmd_beat_cnt = ~bus_inc_cmd_beat_cnt & ~(ic_act_miss_f | scnd_miss_req | dec_tlu_force_halt) ;
|
|
assign bus_cmd_beat_en = bus_inc_cmd_beat_cnt | ic_act_miss_f | dec_tlu_force_halt;
|
|
|
|
assign bus_new_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0] = ({pt.ICACHE_BEAT_BITS{bus_reset_cmd_beat_cnt_0}} & (pt.ICACHE_BEAT_BITS)'(0) ) |
|
|
({pt.ICACHE_BEAT_BITS{bus_reset_cmd_beat_cnt_secondlast}} & (pt.ICACHE_BEAT_BITS)'(pt.ICACHE_SCND_LAST)) |
|
|
({pt.ICACHE_BEAT_BITS{bus_inc_cmd_beat_cnt}} & (bus_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0] + {{pt.ICACHE_BEAT_BITS-1{1'b0}}, 1'b1})) |
|
|
({pt.ICACHE_BEAT_BITS{bus_hold_cmd_beat_cnt}} & bus_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0]) ;
|
|
|
|
|
|
rvclkhdr bus_clk_reset (
|
|
.en(bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt),
|
|
.l1clk(busclk_reset),
|
|
.*
|
|
);
|
|
|
|
rvdffs_fpga #(pt.ICACHE_BEAT_BITS) bus_cmd_beat_ff (
|
|
.*,
|
|
.clk(busclk_reset),
|
|
.clken(bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt),
|
|
.rawclk(clk),
|
|
.en(bus_cmd_beat_en),
|
|
.din({bus_new_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0]}),
|
|
.dout({bus_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0]})
|
|
);
|
|
|
|
|
|
assign bus_last_data_beat = uncacheable_miss_ff ? (bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0] == {{pt.ICACHE_BEAT_BITS-1{1'b0}},1'b1}) : (&bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0]);
|
|
|
|
assign bus_ifu_wr_en = ifu_bus_rvalid & miss_pending;
|
|
assign bus_ifu_wr_en_ff = ifu_bus_rvalid_ff & miss_pending;
|
|
assign bus_ifu_wr_en_ff_q = ifu_bus_rvalid_ff & miss_pending & ~uncacheable_miss_ff & ~(|ifu_bus_rresp_ff[1:0]) & write_ic_16_bytes; // qualify with no-error conditions ;
|
|
assign bus_ifu_wr_en_ff_wo_err = ifu_bus_rvalid_ff & miss_pending & ~uncacheable_miss_ff;
|
|
|
|
|
|
rvdffie #(10) misc_ff (
|
|
.*,
|
|
.clk(free_l2clk),
|
|
.din({
|
|
ic_act_miss_f,
|
|
ifu_wr_cumulative_err,
|
|
exu_flush_final,
|
|
ic_crit_wd_rdy_new_in,
|
|
bus_ifu_bus_clk_en,
|
|
scnd_miss_req_in,
|
|
bus_cmd_req_in,
|
|
last_data_recieved_in,
|
|
ifc_dma_access_ok_d,
|
|
dma_iccm_req
|
|
}),
|
|
.dout({
|
|
ic_act_miss_f_delayed,
|
|
ifu_wr_data_comb_err_ff,
|
|
flush_final_f,
|
|
ic_crit_wd_rdy_new_ff,
|
|
bus_ifu_bus_clk_en_ff,
|
|
scnd_miss_req_q,
|
|
bus_cmd_req_hold,
|
|
last_data_recieved_ff,
|
|
ifc_dma_access_ok_prev,
|
|
dma_iccm_req_f
|
|
})
|
|
);
|
|
|
|
rvdffie #(
|
|
.WIDTH(pt.ICACHE_BEAT_BITS + 5),
|
|
.OVERRIDE(1)
|
|
) misc1_ff (
|
|
.*,
|
|
.clk(free_l2clk),
|
|
.din({
|
|
reset_ic_in,
|
|
sel_mb_addr,
|
|
bus_new_data_beat_count[pt.ICACHE_BEAT_BITS-1:0],
|
|
ifc_region_acc_fault_memory_bf,
|
|
ic_debug_rd_en,
|
|
ic_debug_rd_en_ff
|
|
}),
|
|
.dout({
|
|
reset_ic_ff,
|
|
sel_mb_addr_ff,
|
|
bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0],
|
|
ifc_region_acc_fault_memory_f,
|
|
ic_debug_rd_en_ff,
|
|
ifu_ic_debug_rd_data_valid
|
|
})
|
|
);
|
|
|
|
assign reset_tag_valid_for_miss = ic_act_miss_f_delayed & (miss_state == CRIT_BYP_OK) & ~uncacheable_miss_ff;
|
|
assign bus_ifu_wr_data_error = |ifu_bus_rsp_opc[1:0] & ifu_bus_rvalid & miss_pending;
|
|
assign bus_ifu_wr_data_error_ff = |ifu_bus_rresp_ff[1:0] & ifu_bus_rvalid_ff & miss_pending;
|
|
|
|
|
|
assign ic_crit_wd_rdy = ic_crit_wd_rdy_new_in | ic_crit_wd_rdy_new_ff;
|
|
assign last_beat = bus_last_data_beat & bus_ifu_wr_en_ff;
|
|
assign reset_beat_cnt = bus_reset_data_beat_cnt;
|
|
|
|
// DMA
|
|
// Making sure that the dma_access is allowed when we have 2 back to back dma_access_ok. Also gating with current state == idle
|
|
assign ifc_dma_access_ok_d = ifc_dma_access_ok & ~iccm_correct_ecc & ~iccm_dma_sb_error;
|
|
assign ifc_dma_access_q_ok = ifc_dma_access_ok & ~iccm_correct_ecc & ifc_dma_access_ok_prev & (perr_state == ERR_IDLE) & ~iccm_dma_sb_error;
|
|
assign iccm_ready = ifc_dma_access_q_ok;
|
|
|
|
logic [1:0] iccm_ecc_word_enable;
|
|
|
|
if (pt.ICCM_ENABLE == 1) begin : iccm_enabled
|
|
logic [ 3:2] dma_mem_addr_ff;
|
|
logic iccm_dma_rden;
|
|
|
|
logic iccm_dma_ecc_error_in;
|
|
logic [ 13:0] dma_mem_ecc;
|
|
logic [ 63:0] iccm_dma_rdata_in;
|
|
logic [ 31:0] iccm_dma_rdata_1_muxed;
|
|
logic [ 1:0][31:0] iccm_corrected_data;
|
|
logic [ 1:0][06:0] iccm_corrected_ecc;
|
|
|
|
|
|
logic [ 1:0] iccm_double_ecc_error;
|
|
|
|
|
|
logic [pt.ICCM_BITS-1:2] iccm_rw_addr_f;
|
|
|
|
logic [ 31:0] iccm_corrected_data_f_mux;
|
|
logic [ 06:0] iccm_corrected_ecc_f_mux;
|
|
logic iccm_dma_rvalid_in;
|
|
logic [ 77:0] iccm_rdmux_data;
|
|
logic iccm_rd_ecc_single_err_hold_in;
|
|
logic [ 2:0] dma_mem_tag_ff;
|
|
|
|
|
|
|
|
|
|
assign iccm_wren = (ifc_dma_access_q_ok & dma_iccm_req & dma_mem_write) | iccm_correct_ecc;
|
|
assign iccm_rden = (ifc_dma_access_q_ok & dma_iccm_req & ~dma_mem_write) | (ifc_iccm_access_bf & ifc_fetch_req_bf);
|
|
assign iccm_dma_rden = (ifc_dma_access_q_ok & dma_iccm_req & ~dma_mem_write);
|
|
assign iccm_wr_size[2:0] = {3{dma_iccm_req}} & dma_mem_sz[2:0];
|
|
|
|
rvecc_encode iccm_ecc_encode0 (
|
|
.din(dma_mem_wdata[31:0]),
|
|
.ecc_out(dma_mem_ecc[6:0])
|
|
);
|
|
|
|
rvecc_encode iccm_ecc_encode1 (
|
|
.din(dma_mem_wdata[63:32]),
|
|
.ecc_out(dma_mem_ecc[13:7])
|
|
);
|
|
|
|
assign iccm_wr_data[77:0] = (iccm_correct_ecc & ~(ifc_dma_access_q_ok & dma_iccm_req)) ? {iccm_ecc_corr_data_ff[38:0], iccm_ecc_corr_data_ff[38:0]} :
|
|
{dma_mem_ecc[13:7],dma_mem_wdata[63:32], dma_mem_ecc[6:0],dma_mem_wdata[31:0]};
|
|
|
|
assign iccm_dma_rdata_1_muxed[31:0] = dma_mem_addr_ff[2] ? iccm_corrected_data[0][31:0] : iccm_corrected_data[1][31:0] ;
|
|
assign iccm_dma_rdata_in[63:0] = iccm_dma_ecc_error_in ? {2{dma_mem_addr[31:0]}} : {iccm_dma_rdata_1_muxed[31:0], iccm_corrected_data[0]};
|
|
assign iccm_dma_ecc_error_in = |(iccm_double_ecc_error[1:0]);
|
|
|
|
rvdffe #(64) dma_data_ff (
|
|
.*,
|
|
.clk (clk),
|
|
.en (iccm_dma_rvalid_in),
|
|
.din (iccm_dma_rdata_in[63:0]),
|
|
.dout(iccm_dma_rdata[63:0])
|
|
);
|
|
rvdffie #(11) dma_misc_bits (
|
|
.*,
|
|
.clk(free_l2clk),
|
|
.din({
|
|
dma_mem_tag[2:0],
|
|
dma_mem_tag_ff[2:0],
|
|
dma_mem_addr[3:2],
|
|
iccm_dma_rden,
|
|
iccm_dma_rvalid_in,
|
|
iccm_dma_ecc_error_in
|
|
}),
|
|
.dout({
|
|
dma_mem_tag_ff[2:0],
|
|
iccm_dma_rtag[2:0],
|
|
dma_mem_addr_ff[3:2],
|
|
iccm_dma_rvalid_in,
|
|
iccm_dma_rvalid,
|
|
iccm_dma_ecc_error
|
|
})
|
|
);
|
|
|
|
assign iccm_rw_addr[pt.ICCM_BITS-1:1] = ( ifc_dma_access_q_ok & dma_iccm_req & ~iccm_correct_ecc) ? dma_mem_addr[pt.ICCM_BITS-1:1] :
|
|
(~(ifc_dma_access_q_ok & dma_iccm_req) & iccm_correct_ecc) ? {iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2],1'b0} : ifc_fetch_addr_bf[pt.ICCM_BITS-1:1] ;
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// ECC checking logic for ICCM data. //
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
logic [3:0] ic_fetch_val_int_f;
|
|
logic [3:0] ic_fetch_val_shift_right;
|
|
assign ic_fetch_val_int_f[3:0] = {2'b00, ic_fetch_val_f[1:0]};
|
|
assign ic_fetch_val_shift_right[3:0] = {ic_fetch_val_int_f << ifu_fetch_addr_int_f[1]};
|
|
|
|
assign iccm_rdmux_data[77:0] = iccm_rd_data_ecc[77:0];
|
|
for (genvar i = 0; i < 2; i++) begin : ICCM_ECC_CHECK
|
|
assign iccm_ecc_word_enable[i] = ((|ic_fetch_val_shift_right[(2*i+1):(2*i)] & ~exu_flush_final & sel_iccm_data) | iccm_dma_rvalid_in) & ~dec_tlu_core_ecc_disable;
|
|
rvecc_decode ecc_decode (
|
|
.en(iccm_ecc_word_enable[i]),
|
|
.sed_ded(1'b0), // 1 : means only detection
|
|
.din(iccm_rdmux_data[(39*i+31):(39*i)]),
|
|
.ecc_in(iccm_rdmux_data[(39*i+38):(39*i+32)]),
|
|
.dout(iccm_corrected_data[i][31:0]),
|
|
.ecc_out(iccm_corrected_ecc[i][6:0]),
|
|
.single_ecc_error(iccm_single_ecc_error[i]),
|
|
.double_ecc_error(iccm_double_ecc_error[i])
|
|
);
|
|
end
|
|
|
|
assign iccm_rd_ecc_single_err = (|iccm_single_ecc_error[1:0] ) & ifc_iccm_access_f & ifc_fetch_req_f;
|
|
assign iccm_rd_ecc_double_err[1:0] = ~ifu_fetch_addr_int_f[1] ? ({iccm_double_ecc_error[0], iccm_double_ecc_error[0]} ) & {2{ifc_iccm_access_f}} :
|
|
({iccm_double_ecc_error[1], iccm_double_ecc_error[0]} ) & {2{ifc_iccm_access_f}} ;
|
|
|
|
assign iccm_corrected_data_f_mux[31:0] = iccm_single_ecc_error[0] ? iccm_corrected_data[0] : iccm_corrected_data[1];
|
|
assign iccm_corrected_ecc_f_mux[6:0] = iccm_single_ecc_error[0] ? iccm_corrected_ecc[0] : iccm_corrected_ecc[1];
|
|
|
|
assign iccm_ecc_write_status = ((iccm_rd_ecc_single_err & ~iccm_rd_ecc_single_err_ff) & ~exu_flush_final) | iccm_dma_sb_error;
|
|
assign iccm_rd_ecc_single_err_hold_in = (iccm_rd_ecc_single_err | iccm_rd_ecc_single_err_ff) & ~exu_flush_final ;
|
|
assign iccm_error_start = iccm_rd_ecc_single_err;
|
|
assign iccm_ecc_corr_index_in[pt.ICCM_BITS-1:2] = iccm_single_ecc_error[0] ? iccm_rw_addr_f[pt.ICCM_BITS-1:2] : iccm_rw_addr_f[pt.ICCM_BITS-1:2] + 1'b1 ;
|
|
|
|
rvdffie #(pt.ICCM_BITS - 1) iccm_index_f (
|
|
.*,
|
|
.clk (free_l2clk),
|
|
.din ({iccm_rw_addr[pt.ICCM_BITS-1:2], iccm_rd_ecc_single_err_hold_in}),
|
|
.dout({iccm_rw_addr_f[pt.ICCM_BITS-1:2], iccm_rd_ecc_single_err_ff})
|
|
);
|
|
|
|
rvdffe #((39 + (pt.ICCM_BITS - 2))) ecc_dat0_ff (
|
|
.clk(clk),
|
|
.din({
|
|
iccm_corrected_ecc_f_mux[6:0],
|
|
iccm_corrected_data_f_mux[31:0],
|
|
iccm_ecc_corr_index_in[pt.ICCM_BITS-1:2]
|
|
}),
|
|
.dout({iccm_ecc_corr_data_ff[38:0], iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2]}),
|
|
.en(iccm_ecc_write_status),
|
|
.*
|
|
);
|
|
|
|
end else begin : iccm_disabled
|
|
assign iccm_dma_rvalid = 1'b0;
|
|
assign iccm_dma_ecc_error = 1'b0;
|
|
assign iccm_dma_rdata[63:0] = '0;
|
|
assign iccm_single_ecc_error = '0;
|
|
assign iccm_dma_rtag = '0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assign iccm_rd_ecc_single_err = 1'b0;
|
|
assign iccm_rd_ecc_double_err = '0;
|
|
assign iccm_rd_ecc_single_err_ff = 1'b0;
|
|
assign iccm_error_start = 1'b0;
|
|
assign iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2] = '0;
|
|
assign iccm_ecc_corr_data_ff[38:0] = '0;
|
|
assign iccm_ecc_write_status = '0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
////// ICCM signals
|
|
|
|
|
|
assign ic_rd_en = (ifc_fetch_req_bf & ~ifc_fetch_uncacheable_bf & ~ifc_iccm_access_bf &
|
|
~(((miss_state == STREAM) & ~miss_state_en) |
|
|
((miss_state == CRIT_BYP_OK) & ~miss_state_en) |
|
|
((miss_state == STALL_SCND_MISS) & ~miss_state_en) |
|
|
((miss_state == MISS_WAIT) & ~miss_state_en) |
|
|
((miss_state == CRIT_WRD_RDY) & ~miss_state_en) |
|
|
((miss_state == CRIT_BYP_OK) & miss_state_en & (miss_nxtstate == MISS_WAIT)) )) |
|
|
( ifc_fetch_req_bf & exu_flush_final & ~ifc_fetch_uncacheable_bf & ~ifc_iccm_access_bf ) ;
|
|
|
|
logic ic_real_rd_wp_unused;
|
|
assign ic_real_rd_wp_unused = (ifc_fetch_req_bf & ~ifc_iccm_access_bf & ~ifc_region_acc_fault_final_bf & ~dec_tlu_fence_i_wb & ~stream_miss_f & ~ic_act_miss_f &
|
|
~(((miss_state == STREAM) & ~miss_state_en) |
|
|
((miss_state == CRIT_BYP_OK) & ~miss_state_en & ~(miss_nxtstate == MISS_WAIT)) |
|
|
((miss_state == CRIT_BYP_OK) & miss_state_en & (miss_nxtstate == MISS_WAIT)) |
|
|
((miss_state == MISS_WAIT) & ~miss_state_en) |
|
|
((miss_state == STALL_SCND_MISS) & ~miss_state_en) |
|
|
((miss_state == CRIT_WRD_RDY) & ~miss_state_en) |
|
|
((miss_nxtstate == STREAM) & miss_state_en) |
|
|
((miss_state == SCND_MISS) & ~miss_state_en))) |
|
|
(ifc_fetch_req_bf & ~ifc_iccm_access_bf & ~ifc_region_acc_fault_final_bf & ~dec_tlu_fence_i_wb & ~stream_miss_f & exu_flush_final) ;
|
|
|
|
|
|
assign ic_wr_en[pt.ICACHE_NUM_WAYS-1:0] = bus_ic_wr_en[pt.ICACHE_NUM_WAYS-1:0] & {pt.ICACHE_NUM_WAYS{write_ic_16_bytes}};
|
|
assign ic_write_stall = write_ic_16_bytes & ~((((miss_state== CRIT_BYP_OK) | ((miss_state==STREAM) & ~(exu_flush_final | ifu_bp_hit_taken_q_f | stream_eol_f ))) & ~(bus_ifu_wr_en_ff & last_beat & ~uncacheable_miss_ff)));
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Icache status and LRU
|
|
///////////////////////////////////////////////////////////////
|
|
logic [pt.ICACHE_NUM_WAYS-1:0] ic_tag_valid_unq;
|
|
if (pt.ICACHE_ENABLE == 1) begin : icache_enabled
|
|
assign ic_valid = ~ifu_wr_cumulative_err_data & ~(reset_ic_in | reset_ic_ff) & ~reset_tag_valid_for_miss;
|
|
|
|
assign ifu_status_wr_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] = ((ic_debug_rd_en | ic_debug_wr_en ) & ic_debug_tag_array) ?
|
|
ic_debug_addr[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] :
|
|
ifu_status_wr_addr[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO];
|
|
|
|
// status
|
|
|
|
assign way_status_wr_en_w_debug = way_status_wr_en | (ic_debug_wr_en & ic_debug_tag_array);
|
|
|
|
assign way_status_new_w_debug[pt.ICACHE_STATUS_BITS-1:0] = (ic_debug_wr_en & ic_debug_tag_array) ? (pt.ICACHE_STATUS_BITS == 1) ? ic_debug_wr_data[4] : ic_debug_wr_data[6:4] :
|
|
way_status_new[pt.ICACHE_STATUS_BITS-1:0] ;
|
|
|
|
rvdffie #(
|
|
.WIDTH(pt.ICACHE_TAG_LO - pt.ICACHE_TAG_INDEX_LO + 1 + pt.ICACHE_STATUS_BITS),
|
|
.OVERRIDE(1)
|
|
) status_misc_ff (
|
|
.*,
|
|
.clk(free_l2clk),
|
|
.din({
|
|
ifu_status_wr_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO],
|
|
way_status_wr_en_w_debug,
|
|
way_status_new_w_debug[pt.ICACHE_STATUS_BITS-1:0]
|
|
}),
|
|
.dout({
|
|
ifu_status_wr_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO],
|
|
way_status_wr_en_ff,
|
|
way_status_new_ff[pt.ICACHE_STATUS_BITS-1:0]
|
|
})
|
|
);
|
|
|
|
logic [(pt.ICACHE_TAG_DEPTH/8)-1 : 0] way_status_clken;
|
|
logic [(pt.ICACHE_TAG_DEPTH/8)-1 : 0] way_status_clk;
|
|
|
|
for (genvar i = 0; i < pt.ICACHE_TAG_DEPTH / 8; i++) begin : CLK_GRP_WAY_STATUS
|
|
assign way_status_clken[i] = (ifu_status_wr_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO+3] == i );
|
|
|
|
rvclkhdr way_status_cgc (
|
|
.en(way_status_clken[i]),
|
|
.l1clk(way_status_clk[i]),
|
|
.*
|
|
);
|
|
|
|
|
|
for (genvar j = 0; j < 8; j++) begin : WAY_STATUS
|
|
rvdffs_fpga #(pt.ICACHE_STATUS_BITS) ic_way_status (
|
|
.*,
|
|
.clk(way_status_clk[i]),
|
|
.clken(way_status_clken[i]),
|
|
.rawclk(clk),
|
|
.en(((ifu_status_wr_addr_ff[pt.ICACHE_TAG_INDEX_LO+2:pt.ICACHE_TAG_INDEX_LO] == j) & way_status_wr_en_ff)),
|
|
.din(way_status_new_ff[pt.ICACHE_STATUS_BITS-1:0]),
|
|
.dout(way_status_out[8*i+j])
|
|
);
|
|
end // WAY_STATUS
|
|
end // CLK_GRP_WAY_STATUS
|
|
|
|
always_comb begin : way_status_out_mux
|
|
way_status[pt.ICACHE_STATUS_BITS-1:0] = '0;
|
|
for (int j = 0; j < pt.ICACHE_TAG_DEPTH; j++) begin : status_mux_loop
|
|
if (ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] == (pt.ICACHE_TAG_LO-pt.ICACHE_TAG_INDEX_LO)'(j)) begin : mux_out
|
|
way_status[pt.ICACHE_STATUS_BITS-1:0] = way_status_out[j];
|
|
end
|
|
end
|
|
end
|
|
|
|
assign ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] = ((ic_debug_rd_en | ic_debug_wr_en ) & ic_debug_tag_array) ?
|
|
ic_debug_addr[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] :
|
|
ifu_ic_rw_int_addr[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO];
|
|
assign ifu_tag_wren_w_debug[pt.ICACHE_NUM_WAYS-1:0] = ifu_tag_wren[pt.ICACHE_NUM_WAYS-1:0] | ic_debug_tag_wr_en[pt.ICACHE_NUM_WAYS-1:0] ;
|
|
|
|
assign ic_valid_w_debug = (ic_debug_wr_en & ic_debug_tag_array) ? ic_debug_wr_data[0] : ic_valid;
|
|
|
|
rvdffie #(pt.ICACHE_TAG_LO - pt.ICACHE_TAG_INDEX_LO + pt.ICACHE_NUM_WAYS + 1) tag_addr_ff (
|
|
.*,
|
|
.clk(free_l2clk),
|
|
.din({
|
|
ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO],
|
|
ifu_tag_wren_w_debug[pt.ICACHE_NUM_WAYS-1:0],
|
|
ic_valid_w_debug
|
|
}),
|
|
.dout({
|
|
ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO],
|
|
ifu_tag_wren_ff[pt.ICACHE_NUM_WAYS-1:0],
|
|
ic_valid_ff
|
|
})
|
|
);
|
|
|
|
|
|
logic [pt.ICACHE_NUM_WAYS-1:0] [pt.ICACHE_TAG_DEPTH-1:0] ic_tag_valid_out ;
|
|
|
|
logic [(pt.ICACHE_TAG_DEPTH/32)-1:0] [pt.ICACHE_NUM_WAYS-1:0] tag_valid_clken ;
|
|
logic [(pt.ICACHE_TAG_DEPTH/32)-1:0] [pt.ICACHE_NUM_WAYS-1:0] tag_valid_clk ;
|
|
|
|
for (genvar i = 0; i < pt.ICACHE_TAG_DEPTH / 32; i++) begin : CLK_GRP_TAG_VALID
|
|
for (genvar j = 0; j < pt.ICACHE_NUM_WAYS; j++) begin : way_clken
|
|
if (pt.ICACHE_TAG_DEPTH == 32) begin
|
|
assign tag_valid_clken[i][j] = ifu_tag_wren_ff[j] | perr_err_inv_way[j] | reset_all_tags;
|
|
end else begin
|
|
assign tag_valid_clken[i][j] = (((ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO+5] == i ) & ifu_tag_wren_ff[j] ) |
|
|
((perr_ic_index_ff [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO+5] == i ) & perr_err_inv_way[j]) | reset_all_tags);
|
|
end
|
|
|
|
|
|
rvclkhdr way_status_cgc (
|
|
.en(tag_valid_clken[i][j]),
|
|
.l1clk(tag_valid_clk[i][j]),
|
|
.*
|
|
);
|
|
|
|
|
|
for (genvar k = 0; k < 32; k++) begin : TAG_VALID
|
|
rvdffs_fpga #(1) ic_way_tagvalid_dup (
|
|
.*,
|
|
.clk(tag_valid_clk[i][j]),
|
|
.clken(tag_valid_clken[i][j]),
|
|
.rawclk(clk),
|
|
.en(((ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] == (k + 32*i)) & ifu_tag_wren_ff[j] ) |
|
|
((perr_ic_index_ff [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] == (k + 32*i)) & perr_err_inv_way[j]) | reset_all_tags),
|
|
.din(ic_valid_ff & ~reset_all_tags & ~perr_sel_invalidate),
|
|
.dout(ic_tag_valid_out[j][32*i+k])
|
|
);
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
always_comb begin : tag_valid_out_mux
|
|
ic_tag_valid_unq[pt.ICACHE_NUM_WAYS-1:0] = '0;
|
|
for (int j = 0; j < pt.ICACHE_TAG_DEPTH; j++) begin : tag_valid_loop
|
|
if (ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] == (pt.ICACHE_TAG_LO-pt.ICACHE_TAG_INDEX_LO)'(j)) begin : valid_out
|
|
for (int k = 0; k < pt.ICACHE_NUM_WAYS; k++) begin
|
|
ic_tag_valid_unq[k] |= ic_tag_valid_out[k][j];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
// four-way set associative - three bits
|
|
// each bit represents one branch point in a binary decision tree; let 1
|
|
// represent that the left side has been referenced more recently than the
|
|
// right side, and 0 vice-versa
|
|
//
|
|
// are all 4 ways valid?
|
|
// / \
|
|
// | no, use an invalid way.
|
|
// |
|
|
// |
|
|
// bit_0 == 0? state | replace ref to | next state
|
|
// / \ ------+-------- -------+-----------
|
|
// y n x00 | way_0 way_0 | _11
|
|
// / \ x10 | way_1 way_1 | _01
|
|
// bit_1 == 0? bit_2 == 0? 0x1 | way_2 way_2 | 1_0
|
|
// / \ / \ 1x1 | way_3 way_3 | 0_0
|
|
// y n y n
|
|
// / \ / \ ('x' means don't care ('_' means unchanged)
|
|
// way_0 way_1 way_2 way_3 don't care)
|
|
|
|
if (pt.ICACHE_NUM_WAYS == 4) begin: four_way_plru
|
|
assign replace_way_mb_any[3] = ( way_status_mb_ff[2] & way_status_mb_ff[0] & (&tagv_mb_ff[3:0])) |
|
|
(~tagv_mb_ff[3]& tagv_mb_ff[2] & tagv_mb_ff[1] & tagv_mb_ff[0]) ;
|
|
assign replace_way_mb_any[2] = (~way_status_mb_ff[2] & way_status_mb_ff[0] & (&tagv_mb_ff[3:0])) |
|
|
(~tagv_mb_ff[2]& tagv_mb_ff[1] & tagv_mb_ff[0]) ;
|
|
assign replace_way_mb_any[1] = ( way_status_mb_ff[1] & ~way_status_mb_ff[0] & (&tagv_mb_ff[3:0])) |
|
|
(~tagv_mb_ff[1]& tagv_mb_ff[0] ) ;
|
|
assign replace_way_mb_any[0] = (~way_status_mb_ff[1] & ~way_status_mb_ff[0] & (&tagv_mb_ff[3:0])) |
|
|
(~tagv_mb_ff[0] ) ;
|
|
|
|
assign way_status_hit_new[pt.ICACHE_STATUS_BITS-1:0] = ({3{~exu_flush_final & ic_rd_hit[0]}} & {way_status[2] , 1'b1 , 1'b1}) |
|
|
({3{~exu_flush_final & ic_rd_hit[1]}} & {way_status[2] , 1'b0 , 1'b1}) |
|
|
({3{~exu_flush_final & ic_rd_hit[2]}} & {1'b1 ,way_status[1] , 1'b0}) |
|
|
({3{~exu_flush_final & ic_rd_hit[3]}} & {1'b0 ,way_status[1] , 1'b0}) ;
|
|
|
|
assign way_status_rep_new[pt.ICACHE_STATUS_BITS-1:0] = ({3{replace_way_mb_any[0]}} & {way_status_mb_ff[2] , 1'b1 , 1'b1}) |
|
|
({3{replace_way_mb_any[1]}} & {way_status_mb_ff[2] , 1'b0 , 1'b1}) |
|
|
({3{replace_way_mb_any[2]}} & {1'b1 ,way_status_mb_ff[1] , 1'b0}) |
|
|
({3{replace_way_mb_any[3]}} & {1'b0 ,way_status_mb_ff[1] , 1'b0}) ;
|
|
end else begin : two_ways_plru
|
|
assign replace_way_mb_any[0] = (~way_status_mb_ff & tagv_mb_ff[0] & tagv_mb_ff[1]) | ~tagv_mb_ff[0];
|
|
assign replace_way_mb_any[1] = ( way_status_mb_ff & tagv_mb_ff[0] & tagv_mb_ff[1]) | ~tagv_mb_ff[1] & tagv_mb_ff[0];
|
|
assign way_status_hit_new[pt.ICACHE_STATUS_BITS-1:0] = ic_rd_hit[0];
|
|
assign way_status_rep_new[pt.ICACHE_STATUS_BITS-1:0] = replace_way_mb_any[0];
|
|
|
|
end
|
|
// Make sure to select the way_status_hit_new even when in hit_under_miss.
|
|
assign way_status_new[pt.ICACHE_STATUS_BITS-1:0] = (bus_ifu_wr_en_ff_q & last_beat ) ? way_status_rep_new[pt.ICACHE_STATUS_BITS-1:0] :
|
|
way_status_hit_new[pt.ICACHE_STATUS_BITS-1:0] ;
|
|
|
|
|
|
assign way_status_wr_en = (bus_ifu_wr_en_ff_q & last_beat) | ic_act_hit_f;
|
|
|
|
for (genvar i = 0; i < pt.ICACHE_NUM_WAYS; i++) begin : bus_wren_loop
|
|
assign bus_wren[i] = bus_ifu_wr_en_ff_q & replace_way_mb_any[i] & miss_pending;
|
|
assign bus_wren_last[i] = bus_ifu_wr_en_ff_wo_err & replace_way_mb_any[i] & miss_pending & bus_last_data_beat;
|
|
assign ifu_tag_wren[i] = bus_wren_last[i] | wren_reset_miss[i];
|
|
assign wren_reset_miss[i] = replace_way_mb_any[i] & reset_tag_valid_for_miss;
|
|
|
|
end
|
|
assign bus_ic_wr_en[pt.ICACHE_NUM_WAYS-1:0] = bus_wren[pt.ICACHE_NUM_WAYS-1:0];
|
|
|
|
|
|
end else begin : icache_disabled
|
|
assign ic_tag_valid_unq[pt.ICACHE_NUM_WAYS-1:0] = '0;
|
|
assign way_status[pt.ICACHE_STATUS_BITS-1:0] = '0;
|
|
assign replace_way_mb_any[pt.ICACHE_NUM_WAYS-1:0] = '0;
|
|
assign way_status_hit_new[pt.ICACHE_STATUS_BITS-1:0] = '0;
|
|
assign way_status_rep_new[pt.ICACHE_STATUS_BITS-1:0] = '0;
|
|
assign way_status_new[pt.ICACHE_STATUS_BITS-1:0] = '0;
|
|
assign way_status_wr_en = '0;
|
|
assign bus_wren[pt.ICACHE_NUM_WAYS-1:0] = '0;
|
|
|
|
end
|
|
|
|
assign ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0] = ic_tag_valid_unq[pt.ICACHE_NUM_WAYS-1:0] & {pt.ICACHE_NUM_WAYS{(~fetch_uncacheable_ff & ifc_fetch_req_f_raw) }} ;
|
|
assign ic_debug_tag_val_rd_out = |(ic_tag_valid_unq[pt.ICACHE_NUM_WAYS-1:0] & ic_debug_way_ff[pt.ICACHE_NUM_WAYS-1:0] & {pt.ICACHE_NUM_WAYS{ic_debug_rd_en_ff}}) ;
|
|
///////////////////////////////////////////
|
|
// PMU signals
|
|
///////////////////////////////////////////
|
|
|
|
assign ifu_pmu_ic_miss_in = ic_act_miss_f;
|
|
assign ifu_pmu_ic_hit_in = ic_act_hit_f;
|
|
assign ifu_pmu_bus_error_in = |ifc_bus_acc_fault_f;
|
|
assign ifu_pmu_bus_trxn_in = bus_cmd_sent;
|
|
assign ifu_pmu_bus_busy_in = ifu_bus_arvalid_ff & ~ifu_bus_arready_ff & miss_pending;
|
|
|
|
rvdffie #(9) ifu_pmu_sigs_ff (
|
|
.*,
|
|
.clk(free_l2clk),
|
|
.din({
|
|
ifc_fetch_uncacheable_bf,
|
|
ifc_fetch_req_qual_bf,
|
|
dma_sb_err_state,
|
|
dec_tlu_fence_i_wb,
|
|
ifu_pmu_ic_miss_in,
|
|
ifu_pmu_ic_hit_in,
|
|
ifu_pmu_bus_error_in,
|
|
ifu_pmu_bus_busy_in,
|
|
ifu_pmu_bus_trxn_in
|
|
}),
|
|
.dout({
|
|
fetch_uncacheable_ff,
|
|
ifc_fetch_req_f_raw,
|
|
dma_sb_err_state_ff,
|
|
reset_all_tags,
|
|
ifu_pmu_ic_miss,
|
|
ifu_pmu_ic_hit,
|
|
ifu_pmu_bus_error,
|
|
ifu_pmu_bus_busy,
|
|
ifu_pmu_bus_trxn
|
|
})
|
|
);
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Cache debug logic //
|
|
///////////////////////////////////////////////////////
|
|
assign ic_debug_addr[pt.ICACHE_INDEX_HI:3] = dec_tlu_ic_diag_pkt.icache_dicawics[pt.ICACHE_INDEX_HI-3:0] ;
|
|
assign ic_debug_way_enc[01:00] = dec_tlu_ic_diag_pkt.icache_dicawics[15:14];
|
|
|
|
|
|
assign ic_debug_tag_array = dec_tlu_ic_diag_pkt.icache_dicawics[16];
|
|
assign ic_debug_rd_en = dec_tlu_ic_diag_pkt.icache_rd_valid;
|
|
assign ic_debug_wr_en = dec_tlu_ic_diag_pkt.icache_wr_valid;
|
|
|
|
|
|
assign ic_debug_way[pt.ICACHE_NUM_WAYS-1:0] = {
|
|
(ic_debug_way_enc[1:0] == 2'b11),
|
|
(ic_debug_way_enc[1:0] == 2'b10),
|
|
(ic_debug_way_enc[1:0] == 2'b01),
|
|
(ic_debug_way_enc[1:0] == 2'b00)
|
|
};
|
|
|
|
assign ic_debug_tag_wr_en[pt.ICACHE_NUM_WAYS-1:0] = {pt.ICACHE_NUM_WAYS{ic_debug_wr_en & ic_debug_tag_array}} & ic_debug_way[pt.ICACHE_NUM_WAYS-1:0] ;
|
|
|
|
assign ic_debug_ict_array_sel_in = ic_debug_rd_en & ic_debug_tag_array;
|
|
|
|
rvdff_fpga #(01 + pt.ICACHE_NUM_WAYS) ifu_debug_sel_ff (
|
|
.*,
|
|
.clk(debug_c1_clk),
|
|
.clken(debug_c1_clken),
|
|
.rawclk(clk),
|
|
.din({ic_debug_ict_array_sel_in, ic_debug_way[pt.ICACHE_NUM_WAYS-1:0]}),
|
|
.dout({ic_debug_ict_array_sel_ff, ic_debug_way_ff[pt.ICACHE_NUM_WAYS-1:0]})
|
|
);
|
|
|
|
|
|
|
|
|
|
assign debug_data_clken = ic_debug_rd_en_ff;
|
|
|
|
|
|
|
|
|
|
// memory protection - equation to look identical to the LSU equation
|
|
assign ifc_region_acc_okay = (~(|{pt.INST_ACCESS_ENABLE0,pt.INST_ACCESS_ENABLE1,pt.INST_ACCESS_ENABLE2,pt.INST_ACCESS_ENABLE3,pt.INST_ACCESS_ENABLE4,pt.INST_ACCESS_ENABLE5,pt.INST_ACCESS_ENABLE6,pt.INST_ACCESS_ENABLE7})) |
|
|
(pt.INST_ACCESS_ENABLE0 & (({ifc_fetch_addr_bf[31:1],1'b0} | pt.INST_ACCESS_MASK0)) == (pt.INST_ACCESS_ADDR0 | pt.INST_ACCESS_MASK0)) |
|
|
(pt.INST_ACCESS_ENABLE1 & (({ifc_fetch_addr_bf[31:1],1'b0} | pt.INST_ACCESS_MASK1)) == (pt.INST_ACCESS_ADDR1 | pt.INST_ACCESS_MASK1)) |
|
|
(pt.INST_ACCESS_ENABLE2 & (({ifc_fetch_addr_bf[31:1],1'b0} | pt.INST_ACCESS_MASK2)) == (pt.INST_ACCESS_ADDR2 | pt.INST_ACCESS_MASK2)) |
|
|
(pt.INST_ACCESS_ENABLE3 & (({ifc_fetch_addr_bf[31:1],1'b0} | pt.INST_ACCESS_MASK3)) == (pt.INST_ACCESS_ADDR3 | pt.INST_ACCESS_MASK3)) |
|
|
(pt.INST_ACCESS_ENABLE4 & (({ifc_fetch_addr_bf[31:1],1'b0} | pt.INST_ACCESS_MASK4)) == (pt.INST_ACCESS_ADDR4 | pt.INST_ACCESS_MASK4)) |
|
|
(pt.INST_ACCESS_ENABLE5 & (({ifc_fetch_addr_bf[31:1],1'b0} | pt.INST_ACCESS_MASK5)) == (pt.INST_ACCESS_ADDR5 | pt.INST_ACCESS_MASK5)) |
|
|
(pt.INST_ACCESS_ENABLE6 & (({ifc_fetch_addr_bf[31:1],1'b0} | pt.INST_ACCESS_MASK6)) == (pt.INST_ACCESS_ADDR6 | pt.INST_ACCESS_MASK6)) |
|
|
(pt.INST_ACCESS_ENABLE7 & (({ifc_fetch_addr_bf[31:1],1'b0} | pt.INST_ACCESS_MASK7)) == (pt.INST_ACCESS_ADDR7 | pt.INST_ACCESS_MASK7));
|
|
|
|
assign ifc_region_acc_fault_memory_bf = ~ifc_iccm_access_bf & ~ifc_region_acc_okay & ifc_fetch_req_bf;
|
|
|
|
assign ifc_region_acc_fault_final_bf = ifc_region_acc_fault_bf | ifc_region_acc_fault_memory_bf;
|
|
|
|
|
|
|
|
|
|
endmodule // el2_ifu_mem_ctl
|