FTB中fallThroughErr逻辑梳理

  1. FTB Bank读取阶段断言检查
  • 在读取FTB条目时,验证预测的fallThrough地址是否超出范围(必须保证指令块的结束地址不超过预测范围)
// Check if the entry read by ftbBank is legal.
for (n <- 0 to numWays - 1) {
val req_pc_reg = RegEnable(io.req_pc.bits, 0.U.asTypeOf(io.req_pc.bits), io.req_pc.valid)
val req_pc_reg_lower = Cat(0.U(1.W), req_pc_reg(instOffsetBits + log2Ceil(PredictWidth) - 1, instOffsetBits))
val ftbEntryEndLowerwithCarry = Cat(read_entries(n).carry, read_entries(n).pftAddr)
val fallThroughErr = req_pc_reg_lower + PredictWidth.U >= ftbEntryEndLowerwithCarry
when(read_entries(n).valid && total_hits(n) && io.s1_fire) {
assert(fallThroughErr, s"FTB read sram entry in way${n} fallThrough address error!")
}
}
  1. 流水线S2阶段的地址校验
  • 检查起始地址(startLower)是否大于等于结束地址(endLowerwithCarry)
  • 或者结束地址是否超出预测块范围(startLower + PredictWidth)
val real_s2_startLower        = Cat(0.U(1.W), real_s2_pc(instOffsetBits + log2Ceil(PredictWidth) - 1, instOffsetBits))
val real_s2_endLowerwithCarry = Cat(real_s2_ftb_entry.carry, real_s2_ftb_entry.pftAddr)
val real_s2_fallThroughErr =
real_s2_startLower >= real_s2_endLowerwithCarry || real_s2_endLowerwithCarry > (real_s2_startLower + PredictWidth.U)
  1. 流水线S3阶段的最终校验
  • 校验地址
val fallThroughErr =
s3_pc_startLower >= s3_ftb_entry_endLowerwithCarry || s3_ftb_entry_endLowerwithCarry > (s3_pc_startLower + PredictWidth.U)
XSError(
s3_ftb_entry_dup(0).valid && s3_hit_dup(0) && io.s3_fire(0) && fallThroughErr,
"FTB read sram entry in s3 fallThrough address error!"
)
  1. FTB更新写入校验
  • 在更新FTB时校验写入地址
val ftb_write_fallThrough = ftb_write.entry.getFallThrough(write_pc)
when(write_valid) {
assert(write_pc + (FetchWidth * 4).U >= ftb_write_fallThrough, s"FTB write_entry fallThrough address error!")
}