提交 22e06089 编写于 作者: L Lingrui98

ubtb: wrap meta bank and data bank

上级 e7d4886b
......@@ -73,206 +73,169 @@ class MicroBTB extends BasePredictor
val pred = UInt(2.W)
}
@chiselName
class UBTBMetaBank(nWays: Int) extends XSModule {
val io = IO(new Bundle {
val wen = Input(Bool())
val wWay = Input(UInt(log2Up(nWays).W))
val wdata = Input(new MicroBTBMeta)
val rtag = Input(UInt(tagSize.W))
val rdata = Output(new MetaOutput)
val hit_and_taken = Output(Bool())
val hit_ohs = Output(Vec(nWays, Bool()))
val hit_way = Output(UInt(log2Up(nWays).W))
val allocatable_way = Valid(UInt(log2Up(nWays).W))
val rWay = Input(UInt(log2Up(nWays).W))
val rpred = Output(UInt(2.W))
})
val mem = Mem(nWays, new MicroBTBMeta)
val rentries = VecInit((0 until nWays) map (i => mem(i)))
val hit_ohs = VecInit(rentries map (e => e.valid && e.tag === io.rtag))
io.hit_and_taken := VecInit(rentries map (e => e.valid && e.tag === io.rtag && e.pred(1))).asUInt.orR
val hit_way = OHToUInt(hit_ohs)
//val hit_entry = rentries(hit_way)
val hit_entry = ParallelMux(hit_ohs zip rentries)
io.hit_ohs := hit_ohs
io.hit_way := hit_way
io.rdata.is_Br := hit_entry.is_Br
io.rdata.is_RVC := hit_entry.is_RVC
io.rdata.pred := hit_entry.pred
val entry_emptys = VecInit(rentries.map(e => !e.valid))
val allocatable = ParallelOR(entry_emptys)
io.allocatable_way.bits := PriorityEncoder(entry_emptys)
io.allocatable_way.valid := allocatable
io.rpred := rentries(io.rWay).pred
when (io.wen) {
mem.write(io.wWay, io.wdata)
}
}
@chiselName
class UBTBDataBank(nWays: Int) extends XSModule {
val io = IO(new Bundle {
val wen = Input(Bool())
val wWay = Input(UInt(log2Up(nWays).W))
val wdata = Input(new MicroBTBEntry)
val rOHs = Input(Vec(nWays, Bool()))
val rdata = Output(new MicroBTBEntry)
})
val mem = Mem(nWays, new MicroBTBEntry)
val rentries = VecInit((0 until nWays) map (i => mem(i)))
// io.rdata := rentries(io.rWay)
io.rdata := ParallelMux(io.rOHs zip rentries)
when (io.wen) {
mem.write(io.wWay, io.wdata)
}
}
val metaBanks = Seq.fill(PredictWidth)(Module(new UBTBMetaBank(nWays)))
val dataBanks = Seq.fill(PredictWidth)(Module(new UBTBDataBank(nWays)))
val metas = VecInit(metaBanks.map(_.io))
val datas = VecInit(dataBanks.map(_.io))
val uBTBMeta = VecInit(metas.map(m => m.rdata))
val uBTB = VecInit(datas.map(d => d.rdata))
val do_reset = RegInit(true.B)
val reset_way = RegInit(0.U(log2Ceil(nWays).W))
when (do_reset) { reset_way := reset_way + 1.U }
when (reset_way === (nWays-1).U) { do_reset := false.B }
//uBTB read
//tag is packet aligned
val packetAlignedPC = packetAligned(io.pc.bits)
val read_valid = io.pc.valid
val read_req_tag = getTag(packetAlignedPC)
class ReadRespEntry extends XSBundle
class ReadResp extends XSBundle
{
val is_RVC = Bool()
val target = UInt(VAddrBits.W)
val valid = Bool()
val taken = Bool()
val target = UInt(VAddrBits.W)
val is_RVC = Bool()
val is_Br = Bool()
}
val read_resp = Wire(Vec(PredictWidth,new ReadRespEntry))
(0 until PredictWidth).map{ b => metas(b).rtag := read_req_tag }
val read_hit_ohs = (0 until PredictWidth).map{ b => metas(b).hit_ohs }
val read_hit_vec = VecInit(read_hit_ohs.map{oh => ParallelOR(oh).asBool})
val read_hit_ways = (0 until PredictWidth).map{ b => metas(b).hit_way }
(0 until PredictWidth).map(b => datas(b).rOHs := read_hit_ohs(b))
val uBTBMeta_resp = VecInit((0 until PredictWidth).map(b => metas(b).rdata))
val btb_resp = VecInit((0 until PredictWidth).map(b => datas(b).rdata))
class UBTBBank(val nWays: Int) extends XSModule with HasIFUConst {
val io = IO(new Bundle {
val read_pc = Flipped(Valid(UInt(VAddrBits.W)))
val read_resp = Output(new ReadResp)
val read_hit = Output(Bool())
val to_write_way = Output(UInt(log2Ceil(nWays).W))
for(i <- 0 until PredictWidth){
// do not need to decide whether to produce results\
read_resp(i).valid := io.inMask(i)
read_resp(i).taken := read_resp(i).valid && metas(i).hit_and_taken
read_resp(i).is_Br := read_resp(i).valid && uBTBMeta_resp(i).is_Br
read_resp(i).target := Cat(io.pc.bits(VAddrBits-1, lowerBitsSize+instOffsetBits), btb_resp(i).asUInt, 0.U(instOffsetBits.W))
read_resp(i).is_RVC := read_resp(i).valid && uBTBMeta_resp(i).is_RVC
val update_way = Input(UInt(log2Ceil(nWays).W))
val update_read_pred = Output(UInt(2.W))
out_ubtb_br_info.hits(i) := read_hit_vec(i)
}
val update_write_meta = Flipped(Valid(new MicroBTBMeta))
val update_write_data = Flipped(Valid(new MicroBTBEntry))
})
val meta = Module(new AsyncDataModuleTemplate(new MicroBTBMeta, nWays, nWays, 1))
val data = Module(new AsyncDataModuleTemplate(new MicroBTBEntry, nWays, nWays, 1))
//TODO: way alloc algorithm
def alloc_way(valids:UInt ,meta_tags:UInt,req_tag:UInt) = {
val way = Wire(UInt(log2Up(BtbWays).W))
val all_valid = valids.andR.asBool
val tags = Cat(meta_tags,req_tag)
val l = log2Ceil(nWays)
val nChunks = (tags.getWidth + l - 1) / l
val chunks = (0 until nChunks) map { i =>
tags(min((i+1)*l, tags.getWidth)-1, i*l)
for (w <- 0 until nWays) {
meta.io.raddr(w) := w.U
data.io.raddr(w) := w.U
}
way := Mux(all_valid,chunks.reduce(_^_),PriorityEncoder(~valids))
way
}
meta.io.waddr(0) := io.update_way
meta.io.wen(0) := io.update_write_meta.valid
meta.io.wdata(0) := io.update_write_meta.bits
data.io.waddr(0) := io.update_way
data.io.wen(0) := io.update_write_data.valid
data.io.wdata(0) := io.update_write_data.bits
val rmetas = meta.io.rdata
val rdatas = data.io.rdata
val packetAlignedPC = packetAligned(io.read_pc.bits)
val read_tag = getTag(io.read_pc.bits)
val hits = VecInit(rmetas.map(m => m.valid && m.tag === read_tag))
val takens = VecInit(rmetas.map(m => m.pred(1)))
val hit_oh = hits.asUInt
val hit_and_taken = VecInit((hits zip takens) map {case (h, t) => h && t}).asUInt.orR
val hit_meta = ParallelMux(hits zip rmetas)
val hit_data = ParallelMux(hits zip rdatas)
val target = Cat(io.read_pc.bits(VAddrBits-1, lowerBitsSize+instOffsetBits), hit_data.lower, 0.U(instOffsetBits.W))
val emptys = rmetas.map(m => !m.valid)
val allocatable = VecInit(emptys).asUInt.orR
val empty_way = ParallelPriorityEncoder(emptys)
val hit_way = OHToUInt(hit_oh)
val random_way = LFSR64()(log2Ceil(nWays)-1,0)
io.to_write_way := Mux(hit_oh.orR, hit_way, Mux(allocatable, empty_way, random_way))
val ren = io.read_pc.valid
io.read_resp.valid := ren
io.read_resp.is_RVC := ren && hit_meta.is_RVC
io.read_resp.is_Br := ren && hit_meta.is_Br
io.read_resp.taken := ren && hit_and_taken
io.read_resp.target := target
io.read_hit := ren && hit_oh.orR
io.update_read_pred := rmetas(io.update_way).pred
}
val ubtbBanks = Seq.fill(PredictWidth)(Module(new UBTBBank(nWays)))
val banks = VecInit(ubtbBanks.map(_.io))
val read_resps = VecInit(banks.map(b => b.read_resp))
val alloc_ways = (0 until PredictWidth).map{ b =>
Mux(metas(b).allocatable_way.valid, metas(b).allocatable_way.bits, LFSR64()(log2Ceil(nWays)-1,0))}
(0 until PredictWidth).map(i => out_ubtb_br_info.writeWay(i) := Mux(read_hit_vec(i).asBool,read_hit_ways(i),alloc_ways(i)))
for (b <- 0 until PredictWidth) {
banks(b).read_pc.valid := io.pc.valid && io.inMask(b)
banks(b).read_pc.bits := io.pc.bits
out_ubtb_br_info.writeWay(b) := banks(b).to_write_way
out_ubtb_br_info.hits(b) := banks(b).read_hit
//response
//only when hit and instruction valid and entry valid can output data
for(i <- 0 until PredictWidth)
{
io.out.targets(i) := read_resp(i).target
io.out.hits(i) := read_resp(i).valid && read_hit_vec(i)
io.out.takens(i) := read_resp(i).taken
io.out.is_RVC(i) := read_resp(i).is_RVC
io.out.brMask(i) := read_resp(i).is_Br
//only when hit and instruction valid and entry valid can output data
io.out.targets(b) := read_resps(b).target
io.out.hits(b) := banks(b).read_hit
io.out.takens(b) := read_resps(b).taken
io.out.is_RVC(b) := read_resps(b).is_RVC
io.out.brMask(b) := read_resps(b).is_Br
}
val do_reset = RegInit(true.B)
val reset_way = RegInit(0.U(log2Ceil(nWays).W))
when (do_reset) { reset_way := reset_way + 1.U }
when (reset_way === (nWays-1).U) { do_reset := false.B }
//uBTB update
//backend should send fetch pc to update
val u = io.update.bits
val update_packet_pc = packetAligned(u.ftqPC)
val update_pcs = VecInit((0 until PredictWidth).map(i => update_packet_pc + (i << instOffsetBits).U))
val update_write_ways = VecInit(u.metas.map(_.ubtbWriteWay))
val update_hits = u.metas.map(_.ubtbHits)
val update_takens = u.takens
val update_bank = u.cfiIndex.bits
val update_tag = getTag(update_packet_pc)
val update_target = u.target
val update_target_lower = update_target(lowerBitsSize-1+instOffsetBits, instOffsetBits)
val update_target_lower = u.target(lowerBitsSize-1+instOffsetBits, instOffsetBits)
// only when taken should we update target
val entry_write_valid = io.update.valid && u.valids(u.cfiIndex.bits) && u.takens(u.cfiIndex.bits)
val data_write_valids =
VecInit((0 until PredictWidth).map(i =>
io.update.valid && u.valids(i) && u.takens(i)))
val meta_write_valids =
VecInit((0 until PredictWidth).map(i => io.update.valid && u.valids(i) && (u.br_mask(i) || u.takens(i))))
for (b <- 0 until PredictWidth) {
datas(b).wen := do_reset || (entry_write_valid && b.U === update_bank)
datas(b).wWay := Mux(do_reset, reset_way, update_write_ways(u.cfiIndex.bits))
datas(b).wdata := Mux(do_reset, 0.U.asTypeOf(new MicroBTBEntry), update_target_lower.asTypeOf(new MicroBTBEntry))
}
VecInit((0 until PredictWidth).map(i =>
io.update.valid && u.valids(i) && (u.br_mask(i) || u.takens(i))))
val new_preds =
VecInit((0 until PredictWidth).map(i =>
Mux(!update_hits(i), Mux(update_takens(i),3.U,0.U),
satUpdate(banks(i).update_read_pred,2,update_takens(i)))))
val new_preds = VecInit((0 until PredictWidth).map(i =>
Mux(!update_hits(i),
Mux(update_takens(i),3.U,0.U),
satUpdate( metas(i).rpred,2,update_takens(i)))))
//write the uBTBMeta
(0 until PredictWidth).map(i => metas(i).rWay := update_write_ways(i))
val update_write_metas = Wire(Vec(PredictWidth, new MicroBTBMeta))
val update_write_datas = Wire(Vec(PredictWidth, new MicroBTBEntry))
for (i <- 0 until PredictWidth) {
update_write_metas(i).is_Br := u.br_mask(i)
update_write_metas(i).is_RVC := u.rvc_mask(i)
update_write_metas(i).valid := true.B
update_write_metas(i).tag := update_tag
update_write_metas(i).pred := new_preds(i)
}
update_write_datas(i).lower := update_target_lower
}
for (b <- 0 until PredictWidth) {
metas(b).wen := do_reset || meta_write_valids(b)
metas(b).wWay := Mux(do_reset, reset_way, update_write_ways(b))
metas(b).wdata := Mux(do_reset, 0.U.asTypeOf(new MicroBTBMeta), update_write_metas(b))
banks(b).update_way := update_write_ways(b)
banks(b).update_write_meta.valid := do_reset || meta_write_valids(b)
banks(b).update_write_meta.bits :=
Mux(do_reset, 0.U.asTypeOf(new MicroBTBMeta), update_write_metas(b))
banks(b).update_write_data.valid := do_reset || data_write_valids(b)
banks(b).update_write_data.bits :=
Mux(do_reset, 0.U.asTypeOf(new MicroBTBEntry), update_write_datas(b))
}
if (BPUDebug && debug) {
val update_pcs = VecInit((0 until PredictWidth).map(i => update_packet_pc + (i << instOffsetBits).U))
val update_bank = u.cfiIndex.bits
val read_valid = io.pc.valid
val read_req_tag = getTag(io.pc.bits)
val read_hit_vec = VecInit(banks.map(b => b.read_hit))
val read_hit_ways = VecInit(banks.map(b => b.to_write_way))
XSDebug(read_valid,"uBTB read req: pc:0x%x, tag:%x \n",io.pc.bits,read_req_tag)
XSDebug(read_valid,"uBTB read resp: read_hit_vec:%b, \n",read_hit_vec.asUInt)
for(i <- 0 until PredictWidth) {
XSDebug(read_valid,"bank(%d) hit:%d way:%d valid:%d is_RVC:%d taken:%d isBr:%d target:0x%x alloc_way:%d\n",
i.U, read_hit_vec(i), read_hit_ways(i), read_resp(i).valid, read_resp(i).is_RVC,
read_resp(i).taken, read_resp(i).is_Br, read_resp(i).target, out_ubtb_br_info.writeWay(i))
XSDebug(entry_write_valid && (i.U === update_bank),
i.U, read_hit_vec(i), read_hit_ways(i), read_resps(i).valid, read_resps(i).is_RVC,
read_resps(i).taken, read_resps(i).is_Br, read_resps(i).target, out_ubtb_br_info.writeWay(i))
XSDebug(data_write_valids(i),
"uBTB update data(%d): update | pc:0x%x | update hits:%b | update_write_way:%d | update_lower 0x%x\n ",
i.U, update_pcs(i), update_hits(i), update_write_ways(i), update_target_lower(lowerBitsSize-1,0))
XSDebug(meta_write_valids(i), "uBTB update meta(%d): update_taken:%d | old_pred:%b | new_pred:%b | br:%d | rvc:%d | update_tag:%x\n",
i.U, update_takens(i), metas(i).rpred, new_preds(i), u.br_mask(i), u.rvc_mask(i), update_tag)
i.U, update_takens(i), banks(i).update_read_pred, new_preds(i), u.br_mask(i), u.rvc_mask(i), update_tag)
}
}
if (extended_stat) {
val update_target = u.target
val high_identical = update_target(VAddrBits-1, lowerBitsSize) =/= update_packet_pc(VAddrBits-1, lowerBitsSize)
XSDebug(io.update.valid, "extended_stat: identical %d\n", high_identical)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册