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