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