xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/PcTargetMem.scala (revision b03c55a5df5dc8793cb44b42dd60141566e57e78)
1package xiangshan.backend
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
7import utility._
8import xiangshan._
9import xiangshan.backend.datapath.DataConfig.VAddrData
10import xiangshan.frontend.{FtqPtr, FtqToCtrlIO, Ftq_RF_Components}
11
12class PcTargetMem(params: BackendParams)(implicit p: Parameters) extends LazyModule {
13  override def shouldBeInlined: Boolean = false
14
15  lazy val module = new PcTargetMemImp(this)(p, params)
16}
17
18class PcTargetMemImp(override val wrapper: PcTargetMem)(implicit p: Parameters, params: BackendParams) extends LazyModuleImp(wrapper) with HasXSParameter {
19
20  require(params.numTargetReadPort == params.numPcMemReadPort, "The EXUs which need PC must be the same as the EXUs which need Target PC.")
21  private val numTargetMemRead = params.numTargetReadPort + params.numPcMemReadPort
22
23  val io = IO(new PcTargetMemIO())
24  private val readValid = io.toDataPath.fromDataPathValid
25
26  private def hasRen: Boolean = true
27  private val targetMem = Module(new SyncDataModuleTemplate(new PcTargetMemEntry, FtqSize, numTargetMemRead, 1, hasRen = hasRen))
28  private val targetPCVec : Vec[UInt] = Wire(Vec(params.numTargetReadPort, UInt(VAddrData().dataWidth.W)))
29  private val pcVec       : Vec[UInt] = Wire(Vec(params.numPcMemReadPort, UInt(VAddrData().dataWidth.W)))
30
31  private val wdata = Wire(new PcTargetMemEntry)
32  wdata.addr := io.fromFrontendFtq.pc_mem_wdata
33  wdata.flag := io.fromFrontendFtq.pc_mem_waddr.flag
34
35  targetMem.io.wen.head := GatedValidRegNext(io.fromFrontendFtq.pc_mem_wen)
36  targetMem.io.waddr.head := RegEnable(io.fromFrontendFtq.pc_mem_waddr.value, io.fromFrontendFtq.pc_mem_wen)
37  targetMem.io.wdata.head := RegEnable(wdata, io.fromFrontendFtq.pc_mem_wen)
38  private val rdataVec = targetMem.io.rdata
39
40  private val newestEn: Bool = io.fromFrontendFtq.newest_entry_en
41  private val newestTarget: UInt = io.fromFrontendFtq.newest_entry_target
42
43  // The FtqPtr is used to compare with read ptr since its arrival(T), so it needs to be holded and bypassed.
44  private val currentNewestFtqPtr = DataHoldBypass(io.fromFrontendFtq.newest_entry_ptr, newestEn)
45  // The newest target will be used at T+1, so there is no need to bypass it.
46  private val currentNewestTarget = RegEnable(io.fromFrontendFtq.newest_entry_target, newestEn)
47  private val targetReadPtrVec = 0 until params.numTargetReadPort map { i =>
48    RegEnable(io.toDataPath.fromDataPathFtqPtr(i), io.toDataPath.fromDataPathValid(i))
49  }
50
51  for (i <- 0 until params.numTargetReadPort) {
52    val targetPtr = io.toDataPath.fromDataPathFtqPtr(i)
53    // target pc stored in next entry
54    targetMem.io.ren.get(i) := readValid(i)
55    targetMem.io.raddr(i) := (targetPtr + 1.U).value
56
57    val hitNewestFtqPtr = RegEnable(targetPtr === currentNewestFtqPtr, false.B, readValid(i))
58    targetPCVec(i) := MuxCase(
59      default = Fill(VAddrBits, 1.U(1.W)), // use all 1s as invalid predict jump target
60      mapping = Seq(
61        hitNewestFtqPtr -> currentNewestTarget,
62        (rdataVec(i).flag === targetReadPtrVec(i).flag) -> rdataVec(i).addr.startAddr,
63      )
64    )
65  }
66
67  for (i <- 0 until params.numPcMemReadPort) {
68    val pcAddr = io.toDataPath.fromDataPathFtqPtr(i)
69    val offset = io.toDataPath.fromDataPathFtqOffset(i)
70    // pc stored in this entry
71    targetMem.io.ren.get(i + params.numTargetReadPort) := readValid(i)
72    targetMem.io.raddr(i + params.numTargetReadPort) := pcAddr.value
73    pcVec(i) := targetMem.io.rdata(i + params.numTargetReadPort).addr.getPc(RegEnable(offset, readValid(i)))
74  }
75
76  io.toDataPath.toDataPathTargetPC := targetPCVec
77  io.toDataPath.toDataPathPC := pcVec
78}
79
80class PcToDataPathIO(params: BackendParams)(implicit p: Parameters) extends XSBundle {
81  //Ftq
82  val fromDataPathValid = Input(Vec(params.numPcMemReadPort, Bool()))
83  val fromDataPathFtqPtr = Input(Vec(params.numPcMemReadPort, new FtqPtr))
84  val fromDataPathFtqOffset = Input(Vec(params.numPcMemReadPort, UInt(log2Up(PredictWidth).W)))
85  //Target PC
86  val toDataPathTargetPC = Output(Vec(params.numTargetReadPort, UInt(VAddrData().dataWidth.W)))
87  //PC
88  val toDataPathPC = Output(Vec(params.numPcMemReadPort, UInt(VAddrData().dataWidth.W)))
89}
90
91class PcTargetMemIO()(implicit p: Parameters, params: BackendParams) extends XSBundle {
92  //from frontend
93  val fromFrontendFtq = Flipped(new FtqToCtrlIO)
94  //to backend
95  val toDataPath = new PcToDataPathIO(params)
96}
97
98class PcTargetMemEntry(implicit p: Parameters) extends XSBundle {
99  val addr = new Ftq_RF_Components
100  val flag = Bool()
101}
102