1package xiangshan.backend.fu 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utility.DataHoldBypass 7import utils.OptionWrapper 8import xiangshan._ 9import xiangshan.backend.rob.RobPtr 10import xiangshan.frontend.{FtqPtr, PreDecodeInfo} 11import xiangshan.backend.datapath.DataConfig._ 12 13class FuncUnitCtrlInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 14 val fuOpType = FuOpType() 15 val robIdx = new RobPtr 16 val pdest = UInt(PhyRegIdxWidth.W) 17 val rfWen = OptionWrapper(cfg.writeIntRf, Bool()) 18 val fpWen = OptionWrapper(cfg.writeFpRf, Bool()) 19 val vecWen = OptionWrapper(cfg.writeVecRf, Bool()) 20 val flushPipe = OptionWrapper(cfg.flushPipe, Bool()) 21 val preDecode = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo) 22 val ftqIdx = OptionWrapper(cfg.needPc || cfg.replayInst, new FtqPtr) 23 val ftqOffset = OptionWrapper(cfg.needPc || cfg.replayInst, UInt(log2Up(PredictWidth).W)) 24 val predictInfo = OptionWrapper(cfg.hasRedirect, new Bundle { 25 val target = UInt(VAddrData().dataWidth.W) 26 val taken = Bool() 27 }) 28 val fpu = OptionWrapper(cfg.needFPUCtrl, new FPUCtrlSignals) 29} 30 31class FuncUnitCtrlOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 32 val robIdx = new RobPtr 33 val pdest = UInt(PhyRegIdxWidth.W) // Todo: use maximum of pregIdxWidth of different pregs 34 val rfWen = OptionWrapper(cfg.writeIntRf, Bool()) 35 val fpWen = OptionWrapper(cfg.writeFpRf, Bool()) 36 val vecWen = OptionWrapper(cfg.writeVecRf, Bool()) 37 val exceptionVec = OptionWrapper(cfg.exceptionOut.nonEmpty, ExceptionVec()) 38 val flushPipe = OptionWrapper(cfg.flushPipe, Bool()) 39 val replay = OptionWrapper(cfg.replayInst, Bool()) 40 val preDecode = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo) 41 val fpu = OptionWrapper(cfg.needFPUCtrl, new FPUCtrlSignals) // only used in FMA 42} 43 44class FuncUnitDataInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 45 val src = MixedVec(cfg.genSrcDataVec) 46 val imm = UInt(cfg.dataBits.W) 47 val pc = OptionWrapper(cfg.needPc, UInt(VAddrData().dataWidth.W)) 48} 49 50class FuncUnitDataOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 51 val data = UInt(cfg.dataBits.W) 52 val fflags = OptionWrapper(cfg.writeFflags, UInt(5.W)) 53 val pc = OptionWrapper(cfg.isFence, UInt(VAddrData().dataWidth.W)) 54 val redirect = OptionWrapper(cfg.hasRedirect, ValidIO(new Redirect)) 55} 56 57class FuncUnitInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 58 val ctrl = new FuncUnitCtrlInput(cfg) 59 val data = new FuncUnitDataInput(cfg) 60} 61 62class FuncUnitOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 63 val ctrl = new FuncUnitCtrlOutput(cfg) 64 val res = new FuncUnitDataOutput(cfg) 65} 66 67class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 68 val flush = Flipped(ValidIO(new Redirect)) 69 val in = Flipped(DecoupledIO(new FuncUnitInput(cfg))) 70 val out = DecoupledIO(new FuncUnitOutput(cfg)) 71 val csrio = if (cfg.isCsr) Some(new CSRFileIO) else None 72 val fenceio = if (cfg.isFence) Some(new FenceIO) else None 73 val frm = if (cfg.needSrcFrm) Some(Input(UInt(3.W))) else None 74} 75 76abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends XSModule { 77 val io = IO(new FuncUnitIO(cfg)) 78 79 // should only be used in non-piped fu 80 def connectNonPipedCtrlSingal: Unit = { 81 io.out.bits.ctrl.robIdx := DataHoldBypass(io.in.bits.ctrl.robIdx, io.in.fire) 82 io.out.bits.ctrl.pdest := DataHoldBypass(io.in.bits.ctrl.pdest, io.in.fire) 83 io.out.bits.ctrl.preDecode.foreach(_ := DataHoldBypass(io.in.bits.ctrl.preDecode.get, io.in.fire)) 84 io.out.bits.ctrl.fpu .foreach(_ := DataHoldBypass(io.in.bits.ctrl.fpu.get, io.in.fire)) 85 } 86} 87 88/** 89 * @author LinJiaWei, Yinan Xu 90 */ 91trait HasPipelineReg { this: FuncUnit => 92 def latency: Int 93 94 require(latency > 0) 95 96 val validVec = io.in.valid +: Seq.fill(latency)(RegInit(false.B)) 97 val rdyVec = Seq.fill(latency)(Wire(Bool())) :+ io.out.ready 98 val ctrlVec = io.in.bits.ctrl +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl))) 99 val dataVec = io.in.bits.data +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.data))) 100 101 val robIdxVec = ctrlVec.map(_.robIdx) 102 val pcVec = dataVec.map(_.pc) 103 104 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 105 val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(io.flush)) 106 107 for (i <- 0 until latency) { 108 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 109 } 110 111 for (i <- 1 until latency) { 112 when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){ 113 validVec(i) := validVec(i - 1) 114 ctrlVec(i) := ctrlVec(i - 1) 115 dataVec(i) := dataVec(i - 1) 116 }.elsewhen(flushVec(i) || rdyVec(i)){ 117 validVec(i) := false.B 118 } 119 } 120 121 io.in.ready := rdyVec.head 122 io.out.valid := validVec.last 123 io.out.bits.res.pc.zip(pcVec.last).foreach { case (l, r) => l := r } 124 io.out.bits.ctrl := ctrlVec.last 125 126 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 127 128 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 129 next, 130 regEnable(i) 131 ) 132 133 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 134 135 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 136 137 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 138 139 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 140 141 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 142 143} 144 145 146