// SPDX-License-Identifier: Apache-2.0 // Copyright 2019 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. //******************************************************************************** // $Id$ // // // Owner: // Function: lsu interface with interface queue // Comments: // //******************************************************************************** // Function to do 8 to 3 bit encoding function automatic logic [2:0] f_Enc8to3; input logic [7:0] Dec_value; logic [2:0] Enc_value; Enc_value[0] = Dec_value[1] | Dec_value[3] | Dec_value[5] | Dec_value[7]; Enc_value[1] = Dec_value[2] | Dec_value[3] | Dec_value[6] | Dec_value[7]; Enc_value[2] = Dec_value[4] | Dec_value[5] | Dec_value[6] | Dec_value[7]; return Enc_value[2:0]; endfunction // f_Enc8to3 module lsu_bus_buffer import swerv_types::*; ( input logic clk, input logic rst_l, input logic scan_mode, input logic dec_tlu_non_blocking_disable, // disable non block input logic dec_tlu_wb_coalescing_disable, // disable write buffer coalescing input logic dec_tlu_ld_miss_byp_wb_disable, // disable ld miss bypass of the write buffer input logic dec_tlu_sideeffect_posted_disable, // disable posted writes to sideeffect addr to the bus // various clocks needed for the bus reads and writes input logic lsu_c1_dc3_clk, input logic lsu_c1_dc4_clk, input logic lsu_c1_dc5_clk, input logic lsu_c2_dc3_clk, input logic lsu_c2_dc4_clk, input logic lsu_c2_dc5_clk, input logic lsu_freeze_c1_dc2_clk, input logic lsu_freeze_c1_dc3_clk, input logic lsu_freeze_c2_dc2_clk, input logic lsu_freeze_c2_dc3_clk, input logic lsu_bus_ibuf_c1_clk, input logic lsu_bus_obuf_c1_clk, input logic lsu_bus_buf_c1_clk, input logic lsu_free_c2_clk, input logic lsu_busm_clk, input lsu_pkt_t lsu_pkt_dc1, // lsu packet flowing down the pipe input lsu_pkt_t lsu_pkt_dc2, // lsu packet flowing down the pipe input lsu_pkt_t lsu_pkt_dc3, // lsu packet flowing down the pipe input lsu_pkt_t lsu_pkt_dc4, // lsu packet flowing down the pipe input lsu_pkt_t lsu_pkt_dc5, // lsu packet flowing down the pipe input logic [31:0] lsu_addr_dc2, // lsu address flowing down the pipe input logic [31:0] end_addr_dc2, // lsu address flowing down the pipe input logic [31:0] lsu_addr_dc5, // lsu address flowing down the pipe input logic [31:0] end_addr_dc5, // lsu address flowing down the pipe input logic [31:0] store_data_dc5, // store data flowing down the pipe input logic no_word_merge_dc5, // dc5 store doesn't need to wait in ibuf since it will not coalesce input logic no_dword_merge_dc5, // dc5 store doesn't need to wait in ibuf since it will not coalesce input logic lsu_busreq_dc2, // bus request is in dc2 output logic lsu_busreq_dc3, // bus request is in dc2 output logic lsu_busreq_dc4, // bus request is in dc4 output logic lsu_busreq_dc5, // bus request is in dc5 input logic ld_full_hit_dc2, // load can get all its byte from a write buffer entry input logic flush_dc2_up, // flush input logic flush_dc3, // flush input logic flush_dc4, // flush input logic flush_dc5, // flush input logic lsu_freeze_dc3, input logic dec_tlu_cancel_e4, // cancel the bus load in dc4 and reset the freeze input logic lsu_commit_dc5, // lsu instruction in dc5 commits input logic is_sideeffects_dc2, // lsu attribute is side_effects input logic is_sideeffects_dc5, // lsu attribute is side_effects input logic ldst_dual_dc1, // load/store is unaligned at 32 bit boundary input logic ldst_dual_dc2, // load/store is unaligned at 32 bit boundary input logic ldst_dual_dc3, // load/store is unaligned at 32 bit boundary input logic ldst_dual_dc4, // load/store is unaligned at 32 bit boundary input logic ldst_dual_dc5, // load/store is unaligned at 32 bit boundary input logic [7:0] ldst_byteen_ext_dc2, output logic ld_freeze_dc3, // load goes to external and asserts freeze output logic lsu_bus_buffer_pend_any, // bus buffer has a pending bus entry output logic lsu_bus_buffer_full_any, // bus buffer is full output logic lsu_bus_buffer_empty_any, // bus buffer is empty output logic ld_bus_error_dc3, // bus error in dc3 output logic [31:0] ld_bus_error_addr_dc3, // address of the bus error output logic [31:0] ld_bus_data_dc3, // the Dc3 load data from bus output logic [3:0] ld_byte_hit_buf_lo, ld_byte_hit_buf_hi, // Byte enables for forwarding data output logic [31:0] ld_fwddata_buf_lo, ld_fwddata_buf_hi, // load forwarding data output logic lsu_imprecise_error_load_any, // imprecise load bus error output logic lsu_imprecise_error_store_any, // imprecise store bus error output logic [31:0] lsu_imprecise_error_addr_any, // address of the imprecise error // Non-blocking loads input logic dec_nonblock_load_freeze_dc2, output logic lsu_nonblock_load_valid_dc3, // there is an external load -> put in the cam output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_dc3, // the tag of the external non block load output logic lsu_nonblock_load_inv_dc5, // invalidate signal for the cam entry for non block loads output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_dc5, // tag of the enrty which needs to be invalidated output logic lsu_nonblock_load_data_valid, // the non block is valid - sending information back to the cam output logic lsu_nonblock_load_data_error, // non block load has an error output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // the tag of the non block load sending the data/error output logic [31:0] lsu_nonblock_load_data, // Data of the non block load // PMU events output logic lsu_pmu_bus_trxn, output logic lsu_pmu_bus_misaligned, output logic lsu_pmu_bus_error, output logic lsu_pmu_bus_busy, // AXI Write Channels output logic lsu_axi_awvalid, input logic lsu_axi_awready, output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_awid, output logic [31:0] lsu_axi_awaddr, output logic [3:0] lsu_axi_awregion, output logic [7:0] lsu_axi_awlen, output logic [2:0] lsu_axi_awsize, output logic [1:0] lsu_axi_awburst, output logic lsu_axi_awlock, output logic [3:0] lsu_axi_awcache, output logic [2:0] lsu_axi_awprot, output logic [3:0] lsu_axi_awqos, output logic lsu_axi_wvalid, input logic lsu_axi_wready, output logic [63:0] lsu_axi_wdata, output logic [7:0] lsu_axi_wstrb, output logic lsu_axi_wlast, input logic lsu_axi_bvalid, output logic lsu_axi_bready, input logic [1:0] lsu_axi_bresp, input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_bid, // AXI Read Channels output logic lsu_axi_arvalid, input logic lsu_axi_arready, output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_arid, output logic [31:0] lsu_axi_araddr, output logic [3:0] lsu_axi_arregion, output logic [7:0] lsu_axi_arlen, output logic [2:0] lsu_axi_arsize, output logic [1:0] lsu_axi_arburst, output logic lsu_axi_arlock, output logic [3:0] lsu_axi_arcache, output logic [2:0] lsu_axi_arprot, output logic [3:0] lsu_axi_arqos, input logic lsu_axi_rvalid, output logic lsu_axi_rready, input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_rid, input logic [63:0] lsu_axi_rdata, input logic [1:0] lsu_axi_rresp, input logic lsu_axi_rlast, input logic lsu_bus_clk_en, input logic lsu_bus_clk_en_q ); `include "global.h" // For Ld: IDLE -> WAIT -> CMD -> RESP -> DONE -> IDLE // For St: IDLE -> WAIT -> CMD -> RESP(?) -> IDLE typedef enum logic [2:0] {IDLE=3'b000, WAIT=3'b001, CMD=3'b010, RESP=3'b011, DONE=3'b100} state_t; localparam DEPTH = `RV_LSU_NUM_NBLOAD; localparam DEPTH_LOG2 = `RV_LSU_NUM_NBLOAD_WIDTH; localparam TIMER = 8; // This can be only power of 2 localparam TIMER_LOG2 = (TIMER < 2) ? 1 : $clog2(TIMER); localparam TIMER_MAX = (TIMER == 0) ? TIMER_LOG2'(0) : TIMER_LOG2'(TIMER - 1); // Maximum value of timer logic [3:0] ldst_byteen_hi_dc2, ldst_byteen_lo_dc2; logic [DEPTH-1:0] ld_addr_hitvec_lo, ld_addr_hitvec_hi; logic [3:0][DEPTH-1:0] ld_byte_hitvec_lo, ld_byte_hitvec_hi; logic [3:0][DEPTH-1:0] ld_byte_hitvecfn_lo, ld_byte_hitvecfn_hi; logic ld_addr_ibuf_hit_lo, ld_addr_ibuf_hit_hi; logic [3:0] ld_byte_ibuf_hit_lo, ld_byte_ibuf_hit_hi; logic [3:0] ldst_byteen_dc5; logic [7:0] ldst_byteen_ext_dc5; logic [3:0] ldst_byteen_hi_dc5, ldst_byteen_lo_dc5; logic [31:0] store_data_hi_dc5, store_data_lo_dc5; logic ldst_samedw_dc5; logic lsu_nonblock_load_valid_dc4,lsu_nonblock_load_valid_dc5; logic [31:0] lsu_nonblock_load_data_hi, lsu_nonblock_load_data_lo, lsu_nonblock_data_unalgn; logic [1:0] lsu_nonblock_addr_offset; logic [1:0] lsu_nonblock_sz; logic lsu_nonblock_load_data_valid_hi, lsu_nonblock_load_data_valid_lo; logic lsu_nonblock_load_data_error_hi, lsu_nonblock_load_data_error_lo; logic lsu_nonblock_unsign, lsu_nonblock_dual; logic dec_nonblock_load_freeze_dc3; logic ld_precise_bus_error; logic [DEPTH_LOG2-1:0] lsu_imprecise_error_load_tag; logic [31:0] ld_block_bus_data; logic [DEPTH-1:0] CmdPtr0Dec, CmdPtr1Dec; logic [DEPTH_LOG2-1:0] CmdPtr0, CmdPtr1; logic [DEPTH_LOG2-1:0] WrPtr0_dc3, WrPtr0_dc4, WrPtr0_dc5; logic [DEPTH_LOG2-1:0] WrPtr1_dc3, WrPtr1_dc4, WrPtr1_dc5; logic found_wrptr0, found_wrptr1, found_cmdptr0, found_cmdptr1; logic [3:0] buf_numvld_any, buf_numvld_wrcmd_any, buf_numvld_pend_any, buf_numvld_cmd_any; logic bus_sideeffect_pend; logic bus_coalescing_disable; logic ld_freeze_en, ld_freeze_rst; logic FreezePtrEn; logic [DEPTH_LOG2-1:0] FreezePtr; logic bus_addr_match_pending; logic bus_cmd_sent, bus_cmd_ready; logic bus_wcmd_sent, bus_wdata_sent; logic bus_rsp_read, bus_rsp_write; logic [LSU_BUS_TAG-1:0] bus_rsp_read_tag, bus_rsp_write_tag; logic bus_rsp_read_error, bus_rsp_write_error; logic [63:0] bus_rsp_rdata; // Bus buffer signals state_t [DEPTH-1:0] buf_state; logic [DEPTH-1:0][2:0] buf_state_out; logic [DEPTH-1:0][1:0] buf_sz; logic [DEPTH-1:0][31:0] buf_addr; logic [DEPTH-1:0][3:0] buf_byteen; logic [DEPTH-1:0] buf_sideeffect; logic [DEPTH-1:0] buf_write; logic [DEPTH-1:0] buf_unsign; logic [DEPTH-1:0] buf_dual; logic [DEPTH-1:0] buf_samedw; logic [DEPTH-1:0] buf_nomerge; logic [DEPTH-1:0] buf_dualhi; logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_dualtag; logic [DEPTH-1:0] buf_nb; logic [DEPTH-1:0] buf_error; logic [DEPTH-1:0][31:0] buf_data; logic [DEPTH-1:0][DEPTH-1:0] buf_age, buf_age_younger, buf_age_temp; state_t [DEPTH-1:0] buf_nxtstate; logic [DEPTH-1:0] buf_rst; logic [DEPTH-1:0] buf_state_en; logic [DEPTH-1:0] buf_cmd_state_bus_en; logic [DEPTH-1:0] buf_resp_state_bus_en; logic [DEPTH-1:0] buf_state_bus_en; logic [DEPTH-1:0] buf_dual_in; logic [DEPTH-1:0] buf_samedw_in; logic [DEPTH-1:0] buf_nomerge_in; logic [DEPTH-1:0] buf_nb_in; logic [DEPTH-1:0] buf_sideeffect_in; logic [DEPTH-1:0] buf_unsign_in; logic [DEPTH-1:0][1:0] buf_sz_in; logic [DEPTH-1:0] buf_write_in; logic [DEPTH-1:0] buf_wr_en; logic [DEPTH-1:0] buf_dualhi_in; logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_dualtag_in; logic [DEPTH-1:0][3:0] buf_byteen_in; logic [DEPTH-1:0][31:0] buf_addr_in; logic [DEPTH-1:0][31:0] buf_data_in; logic [DEPTH-1:0] buf_error_en; logic [DEPTH-1:0] buf_data_en; logic [DEPTH-1:0][DEPTH-1:0] buf_age_in; logic [DEPTH-1:0][DEPTH-1:0] buf_ageQ; // Input buffer signals logic ibuf_valid; logic ibuf_dual; logic ibuf_samedw; logic ibuf_nomerge; logic [DEPTH_LOG2-1:0] ibuf_tag; logic [DEPTH_LOG2-1:0] ibuf_dualtag; logic ibuf_nb; logic ibuf_sideeffect; logic ibuf_unsign; logic ibuf_write; logic [1:0] ibuf_sz; logic [3:0] ibuf_byteen; logic [31:0] ibuf_addr; logic [31:0] ibuf_data; logic [TIMER_LOG2-1:0] ibuf_timer; logic ibuf_byp; logic ibuf_wr_en; logic ibuf_rst; logic ibuf_force_drain; logic ibuf_drain_vld; logic [DEPTH-1:0] ibuf_drainvec_vld; logic [DEPTH_LOG2-1:0] ibuf_tag_in; logic [DEPTH_LOG2-1:0] ibuf_dualtag_in; logic [1:0] ibuf_sz_in; logic [31:0] ibuf_addr_in; logic [3:0] ibuf_byteen_in; logic [31:0] ibuf_data_in; logic [TIMER_LOG2-1:0] ibuf_timer_in; logic [3:0] ibuf_byteen_out; logic [31:0] ibuf_data_out; logic ibuf_merge_en, ibuf_merge_in; // Output buffer signals logic obuf_valid; logic obuf_write; logic obuf_sideeffect; logic [31:0] obuf_addr; logic [63:0] obuf_data; logic [1:0] obuf_sz; logic [7:0] obuf_byteen; logic obuf_merge; logic obuf_cmd_done, obuf_data_done; logic [LSU_BUS_TAG-1:0] obuf_tag0; logic [LSU_BUS_TAG-1:0] obuf_tag1; logic ibuf_buf_byp; logic obuf_force_wr_en; logic obuf_wr_wait; logic obuf_wr_en, obuf_wr_enQ; logic obuf_rst; logic obuf_write_in; logic obuf_sideeffect_in; logic [31:0] obuf_addr_in; logic [63:0] obuf_data_in; logic [1:0] obuf_sz_in; logic [7:0] obuf_byteen_in; logic obuf_merge_in; logic obuf_cmd_done_in, obuf_data_done_in; logic [LSU_BUS_TAG-1:0] obuf_tag0_in; logic [LSU_BUS_TAG-1:0] obuf_tag1_in; logic obuf_merge_en; logic [TIMER_LOG2-1:0] obuf_wr_timer, obuf_wr_timer_in; logic [7:0] obuf_byteen0_in, obuf_byteen1_in; logic [63:0] obuf_data0_in, obuf_data1_in; logic lsu_axi_awvalid_q, lsu_axi_awready_q; logic lsu_axi_wvalid_q, lsu_axi_wready_q; logic lsu_axi_arvalid_q, lsu_axi_arready_q; logic lsu_axi_bvalid_q, lsu_axi_bready_q; logic lsu_axi_rvalid_q, lsu_axi_rready_q; logic [LSU_BUS_TAG-1:0] lsu_axi_bid_q, lsu_axi_rid_q; logic [1:0] lsu_axi_bresp_q, lsu_axi_rresp_q; logic [63:0] lsu_axi_rdata_q; //------------------------------------------------------------------------------ // Load forwarding logic start //------------------------------------------------------------------------------ // Buffer hit logic for bus load forwarding assign ldst_byteen_hi_dc2[3:0] = ldst_byteen_ext_dc2[7:4]; assign ldst_byteen_lo_dc2[3:0] = ldst_byteen_ext_dc2[3:0]; for (genvar i=0; i 4'b0) & (obuf_wr_timer < TIMER_MAX)) ? (obuf_wr_timer + 1'b1) : obuf_wr_timer); assign obuf_force_wr_en = lsu_busreq_dc2 & ~lsu_busreq_dc3 & ~lsu_busreq_dc4 & ~lsu_busreq_dc5 & ~ibuf_valid & (buf_numvld_cmd_any[3:0] == 4'b1) & (lsu_addr_dc2[31:2] != buf_addr[CmdPtr0][31:2]); // Entry in dc2 can't merge with entry going to obuf and there is no entry in between assign ibuf_buf_byp = ibuf_byp & (buf_numvld_pend_any[3:0] == 4'b0) & ~ldst_dual_dc5 & lsu_pkt_dc5.store; assign obuf_wr_en = (lsu_bus_clk_en & ((ibuf_buf_byp & lsu_commit_dc5) | ((buf_state[CmdPtr0] == CMD) & found_cmdptr0 & ~buf_cmd_state_bus_en[CmdPtr0] & (~(buf_dual[CmdPtr0] & buf_samedw[CmdPtr0] & ~buf_write[CmdPtr0]) | found_cmdptr1 | buf_nomerge[CmdPtr0] | obuf_force_wr_en)))) & (bus_cmd_ready | ~obuf_valid) & ~obuf_wr_wait & ~bus_sideeffect_pend & ~bus_addr_match_pending; assign obuf_rst = bus_cmd_sent & ~obuf_wr_en; assign obuf_write_in = ibuf_buf_byp ? lsu_pkt_dc5.store : buf_write[CmdPtr0]; assign obuf_sideeffect_in = ibuf_buf_byp ? is_sideeffects_dc5 : buf_sideeffect[CmdPtr0]; assign obuf_addr_in[31:0] = ibuf_buf_byp ? lsu_addr_dc5[31:0] : buf_addr[CmdPtr0]; assign obuf_sz_in[1:0] = ibuf_buf_byp ? {lsu_pkt_dc5.word, lsu_pkt_dc5.half} : buf_sz[CmdPtr0]; assign obuf_merge_in = obuf_merge_en; assign obuf_tag0_in[LSU_BUS_TAG-1:0] = ibuf_buf_byp ? LSU_BUS_TAG'(WrPtr0_dc5) : LSU_BUS_TAG'(CmdPtr0); assign obuf_tag1_in[LSU_BUS_TAG-1:0] = LSU_BUS_TAG'(CmdPtr1); assign obuf_cmd_done_in = ~(obuf_wr_en | obuf_rst) & (obuf_cmd_done | bus_wcmd_sent); assign obuf_data_done_in = ~(obuf_wr_en | obuf_rst) & (obuf_data_done | bus_wdata_sent); assign obuf_byteen0_in[7:0] = ibuf_buf_byp ? (lsu_addr_dc5[2] ? {ldst_byteen_lo_dc5[3:0],4'b0} : {4'b0,ldst_byteen_lo_dc5[3:0]}) : (buf_addr[CmdPtr0][2] ? {buf_byteen[CmdPtr0],4'b0} : {4'b0,buf_byteen[CmdPtr0]}); assign obuf_byteen1_in[7:0] = buf_addr[CmdPtr1][2] ? {buf_byteen[CmdPtr1],4'b0} : {4'b0,buf_byteen[CmdPtr1]}; assign obuf_data0_in[63:0] = ibuf_buf_byp ? (lsu_addr_dc5[2] ? {store_data_lo_dc5[31:0],32'b0} : {32'b0,store_data_lo_dc5[31:0]}) : (buf_addr[CmdPtr0][2] ? {buf_data[CmdPtr0],32'b0} : {32'b0,buf_data[CmdPtr0]}); assign obuf_data1_in[63:0] = buf_addr[CmdPtr1][2] ? {buf_data[CmdPtr1],32'b0} : {32'b0,buf_data[CmdPtr1]}; for (genvar i=0 ;i<8; i++) begin assign obuf_byteen_in[i] = obuf_byteen0_in[i] | (obuf_merge_en & obuf_byteen1_in[i]); assign obuf_data_in[(8*i)+7:(8*i)] = (obuf_merge_en & obuf_byteen1_in[i]) ? obuf_data1_in[(8*i)+7:(8*i)] : obuf_data0_in[(8*i)+7:(8*i)]; end // No store obuf merging for AXI since all stores are sent non-posted. Can't track the second id right now assign obuf_merge_en = (CmdPtr0 != CmdPtr1) & found_cmdptr0 & found_cmdptr1 & (buf_state[CmdPtr0] == CMD) & (buf_state[CmdPtr1] == CMD) & ~buf_cmd_state_bus_en[CmdPtr0] & ~buf_sideeffect[CmdPtr0] & (~buf_write[CmdPtr0] & buf_dual[CmdPtr0] & ~buf_dualhi[CmdPtr0] & buf_samedw[CmdPtr0]); // CmdPtr0/CmdPtr1 are for same load which is within a DW rvdff #(.WIDTH(1)) obuf_wren_ff (.din(obuf_wr_en), .dout(obuf_wr_enQ), .clk(lsu_busm_clk), .*); rvdff #(.WIDTH(1)) obuf_cmd_done_ff (.din(obuf_cmd_done_in), .dout(obuf_cmd_done), .clk(lsu_busm_clk), .*); rvdff #(.WIDTH(1)) obuf_data_done_ff (.din(obuf_data_done_in), .dout(obuf_data_done), .clk(lsu_busm_clk), .*); rvdffsc #(.WIDTH(1)) obuf_valid_ff (.din(1'b1), .dout(obuf_valid), .en(obuf_wr_en), .clear(obuf_rst), .clk(lsu_busm_clk), .*); rvdffs #(.WIDTH(LSU_BUS_TAG)) obuf_tag0ff (.din(obuf_tag0_in), .dout(obuf_tag0), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); rvdffs #(.WIDTH(LSU_BUS_TAG)) obuf_tag1ff (.din(obuf_tag1_in), .dout(obuf_tag1), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); rvdffs #(.WIDTH(1)) obuf_mergeff (.din(obuf_merge_in), .dout(obuf_merge), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); rvdffs #(.WIDTH(1)) obuf_writeff (.din(obuf_write_in), .dout(obuf_write), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); rvdffs #(.WIDTH(1)) obuf_sideeffectff (.din(obuf_sideeffect_in), .dout(obuf_sideeffect), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); rvdffs #(.WIDTH(2)) obuf_szff (.din(obuf_sz_in[1:0]), .dout(obuf_sz), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); rvdffe #(.WIDTH(32)) obuf_addrff (.din(obuf_addr_in[31:0]), .dout(obuf_addr), .en(obuf_wr_en), .*); rvdffs #(.WIDTH(8)) obuf_byteenff (.din(obuf_byteen_in[7:0]), .dout(obuf_byteen), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); rvdffe #(.WIDTH(64)) obuf_dataff (.din(obuf_data_in[63:0]), .dout(obuf_data), .en(obuf_wr_en), .*); rvdff #(.WIDTH(TIMER_LOG2)) obuf_timerff (.din(obuf_wr_timer_in), .dout(obuf_wr_timer), .clk(lsu_busm_clk), .*); //------------------------------------------------------------------------------ // Output buffer logic ends here //------------------------------------------------------------------------------ // Find the entry to allocate and entry to send always_comb begin WrPtr0_dc3[DEPTH_LOG2-1:0] = '0; WrPtr1_dc3[DEPTH_LOG2-1:0] = '0; found_wrptr0 = '0; found_wrptr1 = '0; // Find first write pointer for (int i=0; i= (DEPTH-1)); assign lsu_bus_buffer_empty_any = ~(|buf_state[DEPTH-1:0]) & ~ibuf_valid & ~obuf_valid; // Freeze logic assign FreezePtrEn = lsu_busreq_dc3 & lsu_pkt_dc3.load & ld_freeze_dc3; assign ld_freeze_en = (is_sideeffects_dc2 | dec_nonblock_load_freeze_dc2 | dec_tlu_non_blocking_disable) & lsu_busreq_dc2 & lsu_pkt_dc2.load & ~lsu_freeze_dc3 & ~flush_dc2_up & ~ld_full_hit_dc2; always_comb begin ld_freeze_rst = flush_dc3 | (dec_tlu_cancel_e4 & ld_freeze_dc3); for (int i=0; i> (8*buf_addr[FreezePtr][1:0])); assign ld_precise_bus_error = (buf_error[FreezePtr] | (buf_dual[FreezePtr] & buf_error[buf_dualtag[FreezePtr]])) & ~buf_write[FreezePtr] & buf_rst[FreezePtr] & lsu_freeze_dc3 & ld_freeze_rst & ~flush_dc3; // Don't give bus error for interrupts assign ld_bus_error_addr_dc3[31:0] = buf_addr[FreezePtr][31:0]; // Non blocking ports assign lsu_nonblock_load_valid_dc3 = lsu_busreq_dc3 & lsu_pkt_dc3.valid & lsu_pkt_dc3.load & ~flush_dc3 & ~dec_nonblock_load_freeze_dc3 & ~lsu_freeze_dc3 & ~dec_tlu_non_blocking_disable; assign lsu_nonblock_load_tag_dc3[DEPTH_LOG2-1:0] = WrPtr0_dc3[DEPTH_LOG2-1:0]; assign lsu_nonblock_load_inv_dc5 = lsu_nonblock_load_valid_dc5 & ~lsu_commit_dc5; assign lsu_nonblock_load_inv_tag_dc5[DEPTH_LOG2-1:0] = WrPtr0_dc5[DEPTH_LOG2-1:0]; // dc5 tag needs to be accurate even if there is no invalidate always_comb begin lsu_nonblock_load_data_valid_lo = '0; lsu_nonblock_load_data_valid_hi = '0; lsu_nonblock_load_data_error_lo = '0; lsu_nonblock_load_data_error_hi = '0; lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0] = '0; lsu_nonblock_load_data_lo[31:0] = '0; lsu_nonblock_load_data_hi[31:0] = '0; for (int i=0; i> 8*lsu_nonblock_addr_offset[1:0]); assign lsu_nonblock_load_data_valid = lsu_nonblock_load_data_valid_lo & (~lsu_nonblock_dual | lsu_nonblock_load_data_valid_hi); assign lsu_nonblock_load_data_error = lsu_nonblock_load_data_error_lo | (lsu_nonblock_dual & lsu_nonblock_load_data_error_hi); assign lsu_nonblock_load_data = ({32{ lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b00)}} & {24'b0,lsu_nonblock_data_unalgn[7:0]}) | ({32{ lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b01)}} & {16'b0,lsu_nonblock_data_unalgn[15:0]}) | ({32{~lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b00)}} & {{24{lsu_nonblock_data_unalgn[7]}}, lsu_nonblock_data_unalgn[7:0]}) | ({32{~lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b01)}} & {{16{lsu_nonblock_data_unalgn[15]}},lsu_nonblock_data_unalgn[15:0]}) | ({32{(lsu_nonblock_sz[1:0] == 2'b10)}} & lsu_nonblock_data_unalgn[31:0]); // Determine if there is a pending return to sideeffect load/store always_comb begin bus_sideeffect_pend = obuf_valid & obuf_sideeffect & dec_tlu_sideeffect_posted_disable; for (int i=0; i