IMC miss-state update

This commit is contained in:
waleed-lm 2020-10-23 10:54:41 +05:00
parent 714ccd7092
commit 23bed5142c
13 changed files with 51267 additions and 51118 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val exu_mp_index = Input(UInt((BTB_ADDR_HI-BTB_ADDR_LO+1).W)) // Misprediction index
val exu_mp_btag = Input(UInt(BTB_BTAG_SIZE.W))
val exu_flush_final = Input(Bool())
// Signals to the IFU containing information about brnach
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())
@ -41,11 +41,11 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
})
val TAG_START = 16+BTB_BTAG_SIZE
val PC4 = 4
val BOFF = 3
val CALL = 2
val RET = 1
val BV = 0
val PC4 = 4 // Branch = pc + 4 (BTB Index)
val BOFF = 3 // Branch offset (BTB Index)
val CALL = 2 // Branch CALL (BTB Index)
val RET = 1 // Branch RET (BTB Index)
val BV = 0 // Branch Valid (BTB Index)
val LRU_SIZE = BTB_ARRAY_DEPTH
val NUM_BHT_LOOP = if(BHT_ARRAY_DEPTH > 16) 16 else BHT_ARRAY_DEPTH
@ -115,8 +115,10 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
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
// Hashing the PC to generate the index for the btb
val fetch_rd_tag_f = if(BTB_BTAG_FOLD) el2_btb_tag_hash_fold(io.ifc_fetch_addr_f) else el2_btb_tag_hash(io.ifc_fetch_addr_f)
val fetch_rd_tag_p1_f = if(BTB_BTAG_FOLD) el2_btb_tag_hash_fold(Cat(fetch_addr_p1_f,0.U)) else el2_btb_tag_hash(Cat(fetch_addr_p1_f,0.U))
// 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)
@ -126,19 +128,22 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val exu_mp_way_f = withClock(io.active_clk) {RegNext(exu_mp_way, init = 0.U)}
val exu_flush_final_d1 = withClock(io.active_clk) {RegNext(io.exu_flush_final, init = 0.U)}
// TODO
// If there is a flush from the lower pipe wait until the flush gets deasserted from the (decode) side
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
// Also there should be no bank conflict or leak-one
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
!(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & !leak_one_f
// Similar to the way-0 -> way-1
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
!(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & !leak_one_f
// Similar to above matches
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
// Similar to above matches
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
@ -149,18 +154,19 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val tag_match_way1_expanded_f = Cat(tag_match_way1_f & (btb_bank0_rd_data_way1_f(BOFF) ^ btb_bank0_rd_data_way1_f(PC4)),
tag_match_way1_f & !(btb_bank0_rd_data_way1_f(BOFF) ^ btb_bank0_rd_data_way1_f(PC4)))
val tag_match_way0_expanded_p1_f = Cat(tag_match_way0_p1_f & (btb_bank0_rd_data_way0_p1_f(BOFF) ^ btb_bank0_rd_data_way0_p1_f(PC4)),
tag_match_way0_p1_f & !(btb_bank0_rd_data_way0_p1_f(BOFF) ^ btb_bank0_rd_data_way0_p1_f(PC4)))
val tag_match_way1_expanded_p1_f = Cat(tag_match_way1_p1_f & (btb_bank0_rd_data_way1_p1_f(BOFF) ^ btb_bank0_rd_data_way1_p1_f(PC4)),
tag_match_way1_p1_f & !(btb_bank0_rd_data_way1_p1_f(BOFF) ^ btb_bank0_rd_data_way1_p1_f(PC4)))
// Final hit calculation
val wayhit_f = tag_match_way0_expanded_f | tag_match_way1_expanded_f
val wayhit_p1_f = tag_match_way0_expanded_p1_f | tag_match_way1_expanded_p1_f
// Chopping off the ways that had a hitbtb_vbank0_rd_data_f
// Chopping off the ways that had a hit btb_vbank0_rd_data_f
// e-> Lower half o-> Upper half
val btb_bank0e_rd_data_f = Mux1H(Seq(tag_match_way0_expanded_f(0).asBool->btb_bank0_rd_data_way0_f,
tag_match_way1_expanded_f(0).asBool->btb_bank0_rd_data_way1_f))
@ -170,23 +176,42 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val btb_bank0e_rd_data_p1_f = Mux1H(Seq(tag_match_way0_expanded_p1_f(0).asBool->btb_bank0_rd_data_way0_p1_f,
tag_match_way1_expanded_p1_f(0).asBool->btb_bank0_rd_data_way1_p1_f))
// Making virtual banks, made bit 1 of the pc to check
// Making virtual banks, made from pc-bit(1) if it comes from a multiple of 4 we get the lower half of the bank
// and the upper half of the bank-0 in vbank 1
val btb_vbank0_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0)->btb_bank0e_rd_data_f,
io.ifc_fetch_addr_f(0)->btb_bank0o_rd_data_f))
val btb_vbank1_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0)->btb_bank0o_rd_data_f,
io.ifc_fetch_addr_f(0)->btb_bank0e_rd_data_p1_f))
// Implimenting the LRU for a 2-way BTB
// Branch prediction info is sent with the 2byte lane associated with the end of the branch.
// Cases
// BANK1 BANK0
// -------------------------------
// | : | : |
// -------------------------------
// <------------> : PC4 branch, offset, should be in B1 (indicated on [2])
// <------------> : PC4 branch, no offset, indicate PC4, VALID, HIST on [1]
// <------------> : PC4 branch, offset, indicate PC4, VALID, HIST on [0]
// <------> : PC2 branch, offset, indicate VALID, HIST on [1]
// <------> : PC2 branch, no offset, indicate VALID, HIST on [0]
// Make an LRU value with execution mis-prediction
val mp_wrindex_dec = 1.U << exu_mp_addr
// Make an LRU value with current read pc
val fetch_wrindex_dec = 1.U << btb_rd_addr_f
//io.test1 := fetch_wrindex_dec
val fetch_wrindex_p1_dec = 1.U << btb_rd_addr_p1_f
//io.test2 := fetch_wrindex_p1_dec
val mp_wrlru_b0 = mp_wrindex_dec & Fill(LRU_SIZE, exu_mp_valid)
val vwayhit_f = Mux1H(Seq(~io.ifc_fetch_addr_f(0).asBool->wayhit_f,
io.ifc_fetch_addr_f(0).asBool->Cat(wayhit_p1_f(0), wayhit_f(1)))) & Cat(eoc_mask, 1.U(1.W))
// Make an LRU value with current read pc + 4
val fetch_wrindex_p1_dec = 1.U << btb_rd_addr_p1_f
// Checking if the mis-prediction was valid or not and make a new LRU value
val mp_wrlru_b0 = mp_wrindex_dec & Fill(LRU_SIZE, exu_mp_valid)
val vwayhit_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0).asBool->wayhit_f,
io.ifc_fetch_addr_f(0).asBool->Cat(wayhit_p1_f(0), wayhit_f(1)))) & Cat(eoc_mask, 1.U(1.W))
// Is the update of the lru valid or not
val lru_update_valid_f = (vwayhit_f(0) | vwayhit_f(1)) & io.ifc_fetch_req_f & !leak_one_f
val fetch_wrlru_b0 = fetch_wrindex_dec & Fill(LRU_SIZE, lru_update_valid_f)
@ -194,43 +219,57 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val btb_lru_b0_hold = ~mp_wrlru_b0 & ~fetch_wrlru_b0
// If there is a collision the use the mis-predicted value as output and update accordingly
val use_mp_way = fetch_mp_collision_f
val use_mp_way_p1 = fetch_mp_collision_p1_f
val btb_lru_b0_ns = Mux1H(Seq(~exu_mp_way.asBool->mp_wrlru_b0,
tag_match_way0_f.asBool->fetch_wrlru_b0,
tag_match_way0_p1_f.asBool->fetch_wrlru_p1_b0)) | btb_lru_b0_hold & btb_lru_b0_f
// Calculate the lru next value and flop it
val btb_lru_b0_ns = Mux1H(Seq(!exu_mp_way.asBool -> mp_wrlru_b0,
tag_match_way0_f.asBool -> fetch_wrlru_b0,
tag_match_way0_p1_f.asBool -> fetch_wrlru_p1_b0)) | btb_lru_b0_hold & btb_lru_b0_f
val btb_lru_rd_f = Mux(use_mp_way.asBool, exu_mp_way_f, (fetch_wrindex_dec & btb_lru_b0_f).orR)
val btb_lru_rd_p1_f = Mux(use_mp_way_p1.asBool, exu_mp_way_f, (fetch_wrindex_p1_dec & btb_lru_b0_f).orR)
// Similar to the vbank make vlru
val btb_vlru_rd_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0) -> Cat(btb_lru_rd_f, btb_lru_rd_f),
io.ifc_fetch_addr_f(0).asBool -> Cat(btb_lru_rd_p1_f, btb_lru_rd_f)))
val tag_match_vway1_expanded_f = Mux1H(Seq(~io.ifc_fetch_addr_f(0).asBool->tag_match_way1_expanded_f,
io.ifc_fetch_addr_f(0).asBool->Cat(tag_match_way1_expanded_p1_f(0),tag_match_way1_expanded_f(1))))
// virtual way depending on pc value
val tag_match_vway1_expanded_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0).asBool->tag_match_way1_expanded_f,
io.ifc_fetch_addr_f(0).asBool->Cat(tag_match_way1_expanded_p1_f(0),tag_match_way1_expanded_f(1))))
val way_raw = tag_match_vway1_expanded_f | (~vwayhit_f & btb_vlru_rd_f)
io.ifu_bp_way_f := tag_match_vway1_expanded_f | (~vwayhit_f & btb_vlru_rd_f)
// update the lru
btb_lru_b0_f := RegEnable(btb_lru_b0_ns, init = 0.U, (io.ifc_fetch_req_f|exu_mp_valid).asBool)
// Checking if the end of line is near
val eoc_near = io.ifc_fetch_addr_f(ICACHE_BEAT_ADDR_HI-1, 2).andR
// Mask according to eoc-near and make the hit-final
eoc_mask := !eoc_near | (~io.ifc_fetch_addr_f(1,0)).orR()
val btb_sel_data_f = WireInit(UInt(16.W), init = 0.U)
val hist1_raw = WireInit(UInt(2.W), init = 0.U)
// Filteing out portion of BTB read after virtual banking
// Entry -> tag[pt.BTB_BTAG_SIZE-1:0], toffset[11:0], pc4, boffset, call, ret, valid
val btb_rd_tgt_f = btb_sel_data_f(15,4)
val btb_rd_pc4_f = btb_sel_data_f(3)
val btb_rd_call_f = btb_sel_data_f(1)
val btb_rd_ret_f = btb_sel_data_f(0)
// This is 1-index shifted to that of the btb-data-read so we have 1-bit shifted
btb_sel_data_f := Mux1H(Seq(btb_sel_f(1).asBool-> btb_vbank1_rd_data_f(16,1),
btb_sel_f(0).asBool-> btb_vbank0_rd_data_f(16,1)))
// No lower flush or bp-disabple and a fetch request is generated with virtual way hit
io.ifu_bp_hit_taken_f := (vwayhit_f & hist1_raw).orR & io.ifc_fetch_req_f & !leak_one_f_d1 & !io.dec_tlu_bpred_disable
// If the prediction is a call or ret btb entry then do not check the bht just force a taken with data from the RAS
val bht_force_taken_f = Cat( btb_vbank1_rd_data_f(CALL) | btb_vbank1_rd_data_f(RET) ,
btb_vbank0_rd_data_f(CALL) | btb_vbank0_rd_data_f(RET))
@ -240,31 +279,38 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val bht_bank0_rd_data_f =WireInit(UInt(2.W), 0.U)
val bht_bank0_rd_data_p1_f =WireInit(UInt(2.W), 0.U)
// Depending on pc make the virtual bank as commented above
val bht_vbank0_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0).asBool->bht_bank0_rd_data_f,
io.ifc_fetch_addr_f(0).asBool->bht_bank1_rd_data_f))
val bht_vbank1_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0).asBool->bht_bank1_rd_data_f,
io.ifc_fetch_addr_f(0).asBool->bht_bank0_rd_data_p1_f))
// Direction containing data of both banks direction
bht_dir_f := Cat((bht_force_taken_f(1) | bht_vbank1_rd_data_f(1)) & bht_valid_f(1),
(bht_force_taken_f(0) | bht_vbank0_rd_data_f(1)) & bht_valid_f(0))
// If the branch is taken then pass btb sel else 0
io.ifu_bp_inst_mask_f := (io.ifu_bp_hit_taken_f & btb_sel_f(1)) | !io.ifu_bp_hit_taken_f
// Bank explination
// hist 1 shows both banks direction
hist1_raw := bht_force_taken_f | Cat(bht_vbank1_rd_data_f(1), bht_vbank0_rd_data_f(1))
// hist 0 shows the both bank strength
val hist0_raw = Cat(bht_vbank1_rd_data_f(0), bht_vbank0_rd_data_f(0))
// pc4: if the branch is pc+4
val pc4_raw = Cat(vwayhit_f(1) & btb_vbank1_rd_data_f(PC4),
vwayhit_f(0) & btb_vbank0_rd_data_f(PC4))
// Its a call call or ret branch
val pret_raw = Cat(vwayhit_f(1) & !btb_vbank1_rd_data_f(CALL) & btb_vbank1_rd_data_f(RET),
vwayhit_f(0) & !btb_vbank0_rd_data_f(CALL) & btb_vbank0_rd_data_f(RET))
//GHR
val num_valids = bht_valid_f(1) +& bht_valid_f(0) // countones
// count number of 1's in bht_valid
val num_valids = bht_valid_f(1) +& bht_valid_f(0)
// To calculate a merged ghr meaning the is a overlapping 1 in sel and dir
val final_h = (btb_sel_f & bht_dir_f).orR
val fghr = WireInit(UInt(BHT_GHR_SIZE.W), 0.U)
@ -275,15 +321,17 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val exu_flush_ghr = io.exu_mp_fghr
val fghr_ns = Wire(UInt(BHT_GHR_SIZE.W))
// If there is a exu-flush use its ghr
// If there is a hit and a fetch then use the merged-ghr
// If there is no hit or fetch then hold value
fghr_ns := Mux1H(Seq(exu_flush_final_d1.asBool->exu_flush_ghr,
(!exu_flush_final_d1 & io.ifc_fetch_req_f & io.ic_hit_f & !leak_one_f_d1).asBool -> merged_ghr,
(!exu_flush_final_d1 & io.ifc_fetch_req_f & io.ic_hit_f & !leak_one_f_d1).asBool -> merged_ghr,
(!exu_flush_final_d1 & !(io.ifc_fetch_req_f & io.ic_hit_f & !leak_one_f_d1)).asBool -> fghr))
fghr := withClock(io.active_clk) {RegNext(fghr_ns, init = 0.U)}
io.ifu_bp_fghr_f := fghr
io.ifu_bp_way_f := way_raw
io.ifu_bp_hist1_f := hist1_raw
io.ifu_bp_hist0_f := hist0_raw
io.ifu_bp_pc4_f := pc4_raw
@ -291,8 +339,9 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
io.ifu_bp_valid_f := vwayhit_f & ~Fill(2, io.dec_tlu_bpred_disable)
io.ifu_bp_ret_f := pret_raw
// block fetch to calculate if there is a hit with fetch request and a taken branch then compute the branch offset
val bloc_f = Cat((bht_dir_f(0) & !fetch_start_f(0)) | (!bht_dir_f(0) & fetch_start_f(0)),
(bht_dir_f(0) & fetch_start_f(0)) | (!bht_dir_f(0) & !fetch_start_f(0)))
(bht_dir_f(0) & fetch_start_f(0)) | (!bht_dir_f(0) & !fetch_start_f(0)))
val use_fa_plus = !bht_dir_f(0) & io.ifc_fetch_addr_f(0) & !btb_rd_pc4_f
@ -302,17 +351,20 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val ifc_fetch_adder_prior = RegEnable(io.ifc_fetch_addr_f(30,1), 0.U, (io.ifc_fetch_req_f & !io.ifu_bp_hit_taken_f & io.ic_hit_f).asBool)
io.ifu_bp_poffset_f := btb_rd_tgt_f
val adder_pc_in_f = Mux1H(Seq(use_fa_plus.asBool -> fetch_addr_p1_f,
btb_fg_crossing_f.asBool -> ifc_fetch_adder_prior,
(!btb_fg_crossing_f & !use_fa_plus).asBool-> io.ifc_fetch_addr_f(30,1)))
// Calculate the branch target by adding the offset
val bp_btb_target_adder_f = rvbradder(Cat(adder_pc_in_f(29,0),bp_total_branch_offset_f, 0.U), Cat(btb_rd_tgt_f,0.U))
val rets_out = Wire(Vec(RET_STACK_SIZE, UInt(32.W)))
rets_out := (0 until RET_STACK_SIZE).map(i=>0.U)
// Final target if its a RET then pop else take the target pc
io.ifu_bp_btb_target_f := Mux((btb_rd_ret_f & !btb_rd_call_f & rets_out(0)(0)).asBool,
rets_out(0)(31,1),bp_btb_target_adder_f(31,1))
rets_out(0)(31,1),bp_btb_target_adder_f(31,1))
// Return stack
val bp_rs_call_target_f = rvbradder(Cat(adder_pc_in_f(29,0),bp_total_branch_offset_f, 0.U), Cat(Fill(11, 0.U),~btb_rd_pc4_f, 0.U))
@ -323,6 +375,7 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
val rsenable = (0 until RET_STACK_SIZE).map(i=> if(i==0) !rs_hold else if(i==RET_STACK_SIZE-1) rs_push else rs_push | rs_pop)
// Make the input of the RAS
val rets_in = (0 until RET_STACK_SIZE).map(i=> if(i==0)
Mux1H(Seq(rs_push.asBool -> Cat(bp_rs_call_target_f(31,1),1.U),
rs_pop.asBool -> rets_out(1)))
@ -330,24 +383,31 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
else Mux1H(Seq(rs_push.asBool->rets_out(i-1),
rs_pop.asBool ->rets_out(i+1))))
// Make flops for poping the data
rets_out := (0 until RET_STACK_SIZE).map(i=>RegEnable(rets_in(i),0.U,rsenable(i).asBool))
val btb_valid = exu_mp_valid & (!dec_tlu_error_wb)
val btb_wr_tag = io.exu_mp_btag
// Making the data to write into the BTB according the structure discribed above
val btb_wr_data = Cat(btb_wr_tag, exu_mp_tgt, exu_mp_pc4, exu_mp_boffset, exu_mp_call | exu_mp_ja, exu_mp_ret | exu_mp_ja, btb_valid)
val exu_mp_valid_write = exu_mp_valid & exu_mp_ataken
// Enable for write on each way
val btb_wr_en_way0 = ((!exu_mp_way) & exu_mp_valid_write & (!dec_tlu_error_wb)) | ((!dec_tlu_way_wb) & dec_tlu_error_wb)
val btb_wr_en_way1 = (exu_mp_way & exu_mp_valid_write & (!dec_tlu_error_wb)) | (dec_tlu_way_wb & dec_tlu_error_wb)
// Writing is always done from dec or exu check if the dec have a valid data
val btb_wr_addr = Mux(dec_tlu_error_wb.asBool , btb_error_addr_wb, exu_mp_addr)
val middle_of_bank = exu_mp_pc4 ^ exu_mp_boffset
// Enable the clk enable according to the exu misprediction where it is not a RAS
val bht_wr_en0 = Fill(2, exu_mp_valid & !exu_mp_call & !exu_mp_ret & !exu_mp_ja) & Cat(middle_of_bank, ~middle_of_bank)
val bht_wr_en2 = Fill(2, dec_tlu_br0_v_wb) & Cat(dec_tlu_br0_middle_wb, ~dec_tlu_br0_middle_wb)
val bht_wr_data0 = exu_mp_hist
val bht_wr_data2 = dec_tlu_br0_hist_wb
// Hash each read and write address
val mp_hashed = el2_btb_ghr_hash(Cat(exu_mp_addr,0.U(2.W)), io.exu_mp_eghr)
val br0_hashed_wb = el2_btb_ghr_hash(Cat(dec_tlu_br0_addr_wb,0.U(2.W)), exu_i0_br_fghr_wb)
val bht_rd_addr_hashed_f = el2_btb_ghr_hash(Cat(btb_rd_addr_f,0.U(2.W)), fghr)
@ -367,36 +427,41 @@ class el2_ifu_bp_ctl extends Module with el2_lib with RequireAsyncReset {
btb_bank0_rd_data_way0_f := Mux1H((0 until LRU_SIZE).map(i=>(btb_rd_addr_f===i.U).asBool->btb_bank0_rd_data_way0_out(i)))
btb_bank0_rd_data_way1_f := Mux1H((0 until LRU_SIZE).map(i=>(btb_rd_addr_f===i.U).asBool->btb_bank0_rd_data_way1_out(i)))
// BTB read muxing
btb_bank0_rd_data_way0_p1_f := Mux1H((0 until LRU_SIZE).map(i=>(btb_rd_addr_p1_f===i.U).asBool->btb_bank0_rd_data_way0_out(i)))
btb_bank0_rd_data_way1_p1_f := Mux1H((0 until LRU_SIZE).map(i=>(btb_rd_addr_p1_f===i.U).asBool->btb_bank0_rd_data_way1_out(i)))
val bht_bank_clken = Wire(Vec(2, Vec(BHT_ARRAY_DEPTH/NUM_BHT_LOOP, Bool())))
for(i<-0 until 2; k<- 0 until (BHT_ARRAY_DEPTH/NUM_BHT_LOOP)){
// Checking if there is a write enable with address for the BHT
bht_bank_clken(i)(k) := (bht_wr_en0(i) & ((bht_wr_addr0(BHT_ADDR_HI-BHT_ADDR_LO,NUM_BHT_LOOP_OUTER_LO-2)===k.U) | BHT_NO_ADDR_MATCH.B)) |
(bht_wr_en2(i) & ((bht_wr_addr2(BHT_ADDR_HI-BHT_ADDR_LO,NUM_BHT_LOOP_OUTER_LO-2)===k.U) | BHT_NO_ADDR_MATCH.B))
}
// Writing data into the BHT (DEC-side) or (EXU-side)
val bht_bank_wr_data = (0 until 2).map(i=>(0 until BHT_ARRAY_DEPTH/NUM_BHT_LOOP).map(k=>(0 until NUM_BHT_LOOP).map(j=>
Mux((bht_wr_en2(i)&(bht_wr_addr2(NUM_BHT_LOOP_INNER_HI-BHT_ADDR_LO,0)===j.U)&(bht_wr_addr2(BHT_ADDR_HI-BHT_ADDR_LO,NUM_BHT_LOOP_OUTER_LO-BHT_ADDR_LO)===k.U)|BHT_NO_ADDR_MATCH.B).asBool, bht_wr_data2, bht_wr_data0))))
val bht_bank_sel = Wire(Vec(2, Vec(BHT_ARRAY_DEPTH/NUM_BHT_LOOP, Vec(NUM_BHT_LOOP, Bool()))))
// We have a 2 way bht with BHT_ARRAY_DEPTH/NUM_BHT_LOOP blocks and NUM_BHT_LOOP->offset in each block
// Make enables of each flop according to the address dividing the address in 2-blocks upper block for BHT-Block and
// the lower block for the offset and run this on both of the ways
for(i<-0 until 2; k<-0 until BHT_ARRAY_DEPTH/NUM_BHT_LOOP; j<- 0 until NUM_BHT_LOOP){
bht_bank_sel(i)(k)(j) := (bht_wr_en0(i) & (bht_wr_addr0(NUM_BHT_LOOP_INNER_HI-BHT_ADDR_LO,0)===j.asUInt) & ((bht_wr_addr0(BHT_ADDR_HI-BHT_ADDR_LO, NUM_BHT_LOOP_OUTER_LO-BHT_ADDR_LO)===k.asUInt) | BHT_NO_ADDR_MATCH.B)) |
(bht_wr_en2(i) & (bht_wr_addr2(NUM_BHT_LOOP_INNER_HI-BHT_ADDR_LO,0)===j.asUInt) & ((bht_wr_addr2(BHT_ADDR_HI-BHT_ADDR_LO, NUM_BHT_LOOP_OUTER_LO-BHT_ADDR_LO)===k.asUInt) | BHT_NO_ADDR_MATCH.B))
}
// Reading the BHT with i->way, k->block and the j->offset
val bht_bank_rd_data_out = Wire(Vec(2, Vec(BHT_ARRAY_DEPTH, UInt(2.W))))
for(i<-0 until 2; k<-0 until BHT_ARRAY_DEPTH/NUM_BHT_LOOP; j<-0 until NUM_BHT_LOOP){
bht_bank_rd_data_out(i)((16*k)+j) := RegEnable(bht_bank_wr_data(i)(k)(j), 0.U, bht_bank_sel(i)(k)(j) & bht_bank_clken(i)(k))
}
// Make the final read mux
bht_bank0_rd_data_f := Mux1H((0 until BHT_ARRAY_DEPTH).map(i=>(bht_rd_addr_f===i.U).asBool->bht_bank_rd_data_out(0)(i)))
bht_bank1_rd_data_f := Mux1H((0 until BHT_ARRAY_DEPTH).map(i=>(bht_rd_addr_f===i.U).asBool->bht_bank_rd_data_out(1)(i)))
bht_bank0_rd_data_p1_f := Mux1H((0 until BHT_ARRAY_DEPTH).map(i=>(bht_rd_addr_p1_f===i.U).asBool->bht_bank_rd_data_out(0)(i)))
}
object ifu_bp extends App {

View File

@ -22,6 +22,31 @@ class mem_ctl_bundle extends Bundle with el2_lib{
val dec_tlu_fence_i_wb = Input(Bool())
val ifu_bp_hit_taken_f = Input(Bool())
val ifu_bp_inst_mask_f = Input(Bool())
val ifu_axi_arready = Input(Bool())
val ifu_axi_rvalid = Input(Bool())
val ifu_axi_rid = Input(UInt(IFU_BUS_TAG.W))
val ifu_axi_rdata = Input(UInt(64.W))
val ifu_axi_rresp = Input(UInt(2.W))
val ifu_bus_clk_en = Input(Bool())
val dma_iccm_req = Input(Bool())
val dma_mem_addr = Input(UInt(32.W))
val dma_mem_sz = Input(UInt(3.W))
val dma_mem_write = Input(Bool())
val dma_mem_wdata = Input(UInt(64.W))
val dma_mem_tag = Input(UInt(3.W))
val ic_rd_data = Input(UInt(64.W))
val ic_debug_rd_data = Input(UInt(71.W))
val ictag_debug_rd_data = Input(UInt(26.W))
val ic_eccerr = Input(UInt(ICACHE_BANKS_WAY.W))
val ic_parerr = Input(UInt(ICACHE_BANKS_WAY.W))
val ic_rd_hit = Input(UInt(ICACHE_NUM_WAYS.W))
val ic_tag_perr = Input(Bool())
val iccm_rd_data = Input(UInt(64.W))
val iccm_rd_data_ecc = Input(UInt(78.W))
val ifu_fetch_val = Input(UInt(2.W))
val dec_tlu_ic_diag_pkt = Input(new el2_cache_debug_pkt_t)
val ifu_miss_state_idle = Output(Bool())
val ifu_ic_mb_empty = Output(Bool())
val ic_dma_active = Output(Bool())
@ -48,7 +73,6 @@ class mem_ctl_bundle extends Bundle with el2_lib{
val ifu_axi_wlast = Output(Bool())
val ifu_axi_bready = Output(Bool())
val ifu_axi_arvalid = Output(Bool())
val ifu_axi_arready = Input(Bool())
val ifu_axi_arid = Output(UInt(IFU_BUS_TAG.W))
val ifu_axi_araddr = Output(UInt(32.W))
val ifu_axi_arregion = Output(UInt(4.W))
@ -59,18 +83,7 @@ class mem_ctl_bundle extends Bundle with el2_lib{
val ifu_axi_arcache = Output(UInt(4.W))
val ifu_axi_arprot = Output(UInt(3.W))
val ifu_axi_arqos = Output(UInt(4.W))
val ifu_axi_rvalid = Input(Bool())
val ifu_axi_rready = Output(Bool())
val ifu_axi_rid = Input(UInt(IFU_BUS_TAG.W))
val ifu_axi_rdata = Input(UInt(64.W))
val ifu_axi_rresp = Input(UInt(2.W))
val ifu_bus_clk_en = Input(Bool())
val dma_iccm_req = Input(Bool())
val dma_mem_addr = Input(UInt(32.W))
val dma_mem_sz = Input(UInt(3.W))
val dma_mem_write = Input(Bool())
val dma_mem_wdata = Input(UInt(64.W))
val dma_mem_tag = Input(UInt(3.W))
val iccm_dma_ecc_error = Output(Bool())
val iccm_dma_rvalid = Output(Bool())
val iccm_dma_rdata = Output(UInt(64.W))
@ -80,29 +93,19 @@ class mem_ctl_bundle extends Bundle with el2_lib{
val ic_wr_en = Output(UInt(ICACHE_NUM_WAYS.W))
val ic_rd_en = Output(Bool())
val ic_wr_data = Output(Vec(ICACHE_BANKS_WAY, UInt(71.W)))
val ic_rd_data = Input(UInt(64.W))
val ic_debug_rd_data = Input(UInt(71.W))
val ictag_debug_rd_data = Input(UInt(26.W))
val ic_debug_wr_data = Output(UInt(71.W))
val ifu_ic_debug_rd_data = Output(UInt(71.W))
val ic_eccerr = Input(UInt(ICACHE_BANKS_WAY.W))
val ic_parerr = Input(UInt(ICACHE_BANKS_WAY.W))
val ic_debug_addr = Output(UInt((ICACHE_INDEX_HI-2).W))
val ic_debug_rd_en = Output(Bool())
val ic_debug_wr_en = Output(Bool())
val ic_debug_tag_array = Output(Bool())
val ic_debug_way = Output(UInt(ICACHE_NUM_WAYS.W))
val ic_tag_valid = Output(UInt(ICACHE_NUM_WAYS.W))
val ic_rd_hit = Input(UInt(ICACHE_NUM_WAYS.W))
val ic_tag_perr = Input(Bool())
val iccm_rw_addr = Output(UInt((ICCM_BITS-1).W))
val iccm_wren = Output(Bool())
val iccm_rden = Output(Bool())
val iccm_wr_data = Output(UInt(78.W))
val iccm_wr_size = Output(UInt(3.W))
val iccm_rd_data = Input(UInt(64.W))
val iccm_rd_data_ecc = Input(UInt(78.W))
val ifu_fetch_val = Input(UInt(2.W))
val ic_hit_f = Output(Bool())
val ic_access_fault_f = Output(Bool())
val ic_access_fault_type_f = Output(UInt(2.W))
@ -115,7 +118,6 @@ class mem_ctl_bundle extends Bundle with el2_lib{
val ic_data_f = Output(UInt(32.W))
val ic_premux_data = Output(UInt(64.W))
val ic_sel_premux_data = Output(Bool())
val dec_tlu_ic_diag_pkt = Input(new el2_cache_debug_pkt_t)
val dec_tlu_core_ecc_disable = Input(Bool())
val ifu_ic_debug_rd_data_valid = Output(Bool())
val iccm_buf_correct_ecc = Output(Bool())
@ -535,6 +537,7 @@ class el2_ifu_mem_ctl extends Module with el2_lib {
val bus_ifu_bus_clk_en_ff = withClock(io.free_clk){RegNext(bus_ifu_bus_clk_en, 0.U)}
scnd_miss_req_q := withClock(io.free_clk){RegNext(scnd_miss_req_in, 0.U)}
val scnd_miss_req_ff2 = withClock(io.free_clk){RegNext(scnd_miss_req, 0.U)}
scnd_miss_req := scnd_miss_req_q & (!io.exu_flush_final)
val bus_cmd_req_hold = WireInit(Bool(), false.B)
val ifu_bus_cmd_valid = WireInit(Bool(), false.B)
val bus_cmd_beat_count = WireInit(UInt(ICACHE_BEAT_BITS.W), 0.U)