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