package ifu import include._ import lib._ import chisel3._ import chisel3.util._ class el2_ifu_bp_ctl extends Module with el2_lib { val io = IO (new Bundle { val clk = Input(Bool()) val active_clk = Input(Bool()) val rst_l = Input(Bool()) val ic_hit_f = Input(Bool()) val ifc_fetch_addr_f = Input(UInt(32.W)) val ifc_fetch_req_f = Input(Bool()) // Fetch request generated by the IFC // Decode packet containing information if its a brnach or not val dec_tlu_br0_r_pkt = Input(new el2_br_tlu_pkt_t) val exu_i0_br_fghr_r = Input(UInt(BHT_GHR_SIZE.W)) // Updated GHR from the exu val exu_i0_br_index_r = Input(UInt((BTB_ADDR_HI-BTB_ADDR_LO).W)) // Way from where the btb got a hit val dec_tlu_flush_lower_wb = Input(Bool()) val dec_tlu_flush_leak_one_wb = Input(Bool()) val dec_tlu_bpred_disable = Input(Bool()) // Exu misprediction packet val exu_mp_pkt = Input(new el2_predict_pkt_t) val exu_mp_eghr = Input(UInt(BHT_GHR_SIZE.W)) val exu_mp_fghr = Input(UInt(BHT_GHR_SIZE.W)) val exu_mp_index = Input(UInt((BTB_ADDR_HI-BTB_ADDR_LO).W)) // Misprediction index val exu_mp_btag = Input(UInt(BTB_BTAG_SIZE.W)) val exu_flush_final = Input(Bool()) val ifu_bp_hit_taken_f = Output(Bool()) val ifu_bp_btb_target_f = Output(UInt(31.W)) val ifu_bp_inst_mask_f = Output(Bool()) val ifu_bp_fghr_f = Output(UInt(BHT_GHR_SIZE.W)) val ifu_bp_way_f = Output(UInt(2.W)) val ifu_bp_ret_f = Output(UInt(2.W)) val ifu_bp_hist1_f = Output(UInt(2.W)) val ifu_bp_hist0_f = Output(UInt(2.W)) val ifu_bp_pc4_f = Output(UInt(2.W)) val ifu_bp_valid_f = Output(UInt(2.W)) val ifu_bp_poffset_f = Output(UInt(12.W)) }) io.ifu_bp_hit_taken_f := 0.U io.ifu_bp_btb_target_f := 0.U io.ifu_bp_inst_mask_f := 0.U io.ifu_bp_fghr_f := 0.U io.ifu_bp_way_f := 0.U io.ifu_bp_ret_f := 0.U io.ifu_bp_hist1_f := 0.U io.ifu_bp_hist0_f := 0.U io.ifu_bp_pc4_f := 0.U io.ifu_bp_valid_f := 0.U io.ifu_bp_poffset_f := 0.U val TAG_START = 16+BTB_BTAG_SIZE val PC4 = 4 val BOFF = 3 val CALL = 2 val RET = 1 val BV = 0 val LRU_SIZE = BTB_ARRAY_DEPTH val NUM_BHT_LOOP = if(BHT_ARRAY_DEPTH > 16) 16 else BHT_ARRAY_DEPTH val NUM_BHT_LOOP_INNER_HI = if(BHT_ARRAY_DEPTH > 16) BHT_ADDR_LO+3 else BHT_ADDR_HI val NUM_BHT_LOOP_OUTER_LO = if(BHT_ARRAY_DEPTH > 16) BHT_ADDR_LO+4 else BHT_ADDR_LO val BHT_NO_ADDR_MATCH = BHT_ARRAY_DEPTH <= 16 val leak_one_f = WireInit(Bool(), 0.U) val exu_mp_valid = io.exu_mp_pkt.misp & ~leak_one_f val exu_mp_boffset = io.exu_mp_pkt.boffset val exu_mp_pc4 = io.exu_mp_pkt.pc4 val exu_mp_call = io.exu_mp_pkt.pcall val exu_mp_ret = io.exu_mp_pkt.pret val exu_mp_ja = io.exu_mp_pkt.pja val exu_mp_way = io.exu_mp_pkt.way val exu_mp_hist = io.exu_mp_pkt.hist val exu_mp_tgt = io.exu_mp_pkt.toffset val exu_mp_addr = io.exu_mp_index val exu_mp_ataken = io.exu_mp_pkt.ataken // LM: Its a commit or update packet val dec_tlu_br0_v_wb = io.dec_tlu_br0_r_pkt.valid val dec_tlu_br0_hist_wb = io.dec_tlu_br0_r_pkt.hist val dec_tlu_br0_addr_wb = io.exu_i0_br_index_r val dec_tlu_br0_error_wb = io.dec_tlu_br0_r_pkt.br_error val dec_tlu_br0_middle_wb = io.dec_tlu_br0_r_pkt.middle val dec_tlu_br0_way_wb = io.dec_tlu_br0_r_pkt.way val dec_tlu_br0_start_error_wb = io.dec_tlu_br0_r_pkt.br_start_error val exu_i0_br_fghr_wb = io.exu_i0_br_fghr_r val fetch_rd_tag_p1_f = WireInit(UInt(BTB_BTAG_SIZE.W), 0.U) val fetch_rd_tag_f = WireInit(UInt(BTB_BTAG_SIZE.W), 0.U) val bht_dir_f = WireInit(UInt(2.W), 0.U) val dec_tlu_error_wb = WireInit(Bool(), 0.U) val btb_error_addr_wb = WireInit(UInt((BTB_ADDR_HI-BTB_ADDR_LO).W), 0.U) val btb_bank0_rd_data_way0_f = WireInit(UInt((TAG_START+1).W), 0.U) val btb_bank0_rd_data_way1_f = WireInit(UInt((TAG_START+1).W), 0.U) val btb_bank0_rd_data_way0_p1_f = WireInit(UInt((TAG_START+1).W), 0.U) val btb_bank0_rd_data_way1_p1_f = WireInit(UInt((TAG_START+1).W), 0.U) val dec_tlu_way_wb = WireInit(Bool(), 0.U) // Hash the first PC val btb_rd_addr_f = el2_btb_addr_hash(io.ifc_fetch_addr_f) // Second pc = pc +4 val fetch_addr_p1_f = io.ifc_fetch_addr_f + 4.U // Hash the second pc val btb_rd_addr_p1_f = el2_btb_addr_hash(fetch_addr_p1_f) // TODO val btb_sel_f = Cat(~bht_dir_f(0),bht_dir_f(0)) // Checking of the pc is a multiple of 4, if it is fetch-start will be "01" val fetch_start_f = Cat(io.ifc_fetch_addr_f(1),~io.ifc_fetch_addr_f(1)) // If there is an error write-back from the dec check if the current pc is equal to the write-bcak pc val branch_error_collision_f = dec_tlu_error_wb & (btb_error_addr_wb === btb_rd_addr_f) val branch_error_collision_p1_f = dec_tlu_error_wb & (btb_error_addr_wb === btb_rd_addr_p1_f) // If there is an error write back but the address are from different bank val branch_error_bank_conflict_f = branch_error_collision_f & dec_tlu_error_wb val branch_error_bank_conflict_p1_f = branch_error_collision_p1_f & dec_tlu_error_wb // There is a misprediction and the exu is writing back val fetch_mp_collision_f = (io.exu_mp_btag === fetch_rd_tag_f) & exu_mp_valid & io.ifc_fetch_req_f & (exu_mp_addr === btb_rd_addr_f) val fetch_mp_collision_p1_f = (io.exu_mp_btag === fetch_rd_tag_p1_f) & exu_mp_valid & io.ifc_fetch_req_f & (exu_mp_addr === btb_rd_addr_p1_f) val leak_one_f_d1 = RegNext(leak_one_f, init = 0.U) val dec_tlu_way_wb_f = RegNext(dec_tlu_way_wb, init = 0.U) val exu_mp_way_f = RegNext(exu_mp_way, init = 0.U) val exu_flush_final_d1 = RegNext(io.exu_flush_final, init = 0.U) // TODO leak_one_f := (io.dec_tlu_flush_leak_one_wb & io.dec_tlu_flush_lower_wb) | (leak_one_f_d1 & io.dec_tlu_flush_lower_wb) // For a tag to match the branch should be valid tag should match and a fetch request should be generated val tag_match_way0_f = btb_bank0_rd_data_way0_f(BV) & (btb_bank0_rd_data_way0_f(TAG_START,17) === fetch_rd_tag_f) & ~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & ~leak_one_f val tag_match_way1_f = btb_bank0_rd_data_way1_f(BV) & (btb_bank0_rd_data_way1_f(TAG_START,17) === fetch_rd_tag_f) & ~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & ~leak_one_f val tag_match_way0_p1_f = btb_bank0_rd_data_way0_p1_f(BV) & (btb_bank0_rd_data_way0_p1_f(TAG_START,17) === fetch_rd_tag_p1_f) & ~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & ~leak_one_f val tag_match_way1_p1_f = btb_bank0_rd_data_way1_p1_f(BV) & (btb_bank0_rd_data_way1_p1_f(TAG_START,17) === fetch_rd_tag_p1_f) & ~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & ~leak_one_f } object ifu_bp extends App { println((new chisel3.stage.ChiselStage).emitVerilog(new el2_ifu_bp_ctl())) }