1package xiangshan.backend.fu 2 3import org.chipsalliance.cde.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utility._ 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 15import xiangshan.backend.fu.vector.Bundles.VType 16import xiangshan.backend.fu.wrapper.{CSRInput, CSRToDecode} 17 18class FuncUnitCtrlInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 19 val fuOpType = FuOpType() 20 val robIdx = new RobPtr 21 val pdest = UInt(PhyRegIdxWidth.W) 22 val rfWen = OptionWrapper(cfg.needIntWen, Bool()) 23 val fpWen = OptionWrapper(cfg.needFpWen, Bool()) 24 val vecWen = OptionWrapper(cfg.needVecWen, Bool()) 25 val v0Wen = OptionWrapper(cfg.needV0Wen, Bool()) 26 val vlWen = OptionWrapper(cfg.needVlWen, Bool()) 27 val flushPipe = OptionWrapper(cfg.flushPipe, Bool()) 28 val preDecode = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo) 29 val ftqIdx = OptionWrapper(cfg.needPc || cfg.replayInst || cfg.isSta || cfg.isCsr, new FtqPtr) 30 val ftqOffset = OptionWrapper(cfg.needPc || cfg.replayInst || cfg.isSta || cfg.isCsr, UInt(log2Up(PredictWidth).W)) 31 val predictInfo = OptionWrapper(cfg.needPdInfo, new Bundle { 32 val target = UInt(VAddrData().dataWidth.W) 33 val taken = Bool() 34 }) 35 val fpu = OptionWrapper(cfg.writeFflags, new FPUCtrlSignals) 36 val vpu = OptionWrapper(cfg.needVecCtrl, new VPUCtrlSignals) 37} 38 39class FuncUnitCtrlOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 40 val robIdx = new RobPtr 41 val pdest = UInt(PhyRegIdxWidth.W) // Todo: use maximum of pregIdxWidth of different pregs 42 val rfWen = OptionWrapper(cfg.needIntWen, Bool()) 43 val fpWen = OptionWrapper(cfg.needFpWen, Bool()) 44 val vecWen = OptionWrapper(cfg.needVecWen, Bool()) 45 val v0Wen = OptionWrapper(cfg.needV0Wen, Bool()) 46 val vlWen = OptionWrapper(cfg.needVlWen, Bool()) 47 val exceptionVec = OptionWrapper(cfg.exceptionOut.nonEmpty, ExceptionVec()) 48 val flushPipe = OptionWrapper(cfg.flushPipe, Bool()) 49 val replay = OptionWrapper(cfg.replayInst, Bool()) 50 val preDecode = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo) 51 val fpu = OptionWrapper(cfg.writeFflags, new FPUCtrlSignals) 52 val vpu = OptionWrapper(cfg.needVecCtrl, new VPUCtrlSignals) 53} 54 55class FuncUnitDataInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 56 val src = MixedVec(cfg.genSrcDataVec) 57 val imm = UInt(cfg.destDataBits.W) 58 val pc = OptionWrapper(cfg.needPc, UInt(VAddrData().dataWidth.W)) 59 val nextPcOffset = OptionWrapper(cfg.needPc, UInt((log2Up(PredictWidth) + 1).W)) 60 61 def getSrcVConfig : UInt = src(cfg.vconfigIdx) 62 def getSrcMask : UInt = src(cfg.maskSrcIdx) 63} 64 65class FuncUnitDataOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 66 val data = UInt(cfg.destDataBits.W) 67 val fflags = OptionWrapper(cfg.writeFflags, UInt(5.W)) 68 val vxsat = OptionWrapper(cfg.writeVxsat, Vxsat()) 69 val redirect = OptionWrapper(cfg.hasRedirect, ValidIO(new Redirect)) 70} 71 72class FuncUnitInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 73 val needCtrlPipe = cfg.latency.latencyVal.nonEmpty && (!cfg.isStd) 74 val ctrl = new FuncUnitCtrlInput(cfg) 75 val ctrlPipe = OptionWrapper(needCtrlPipe, Vec(cfg.latency.latencyVal.get + 1, new FuncUnitCtrlInput(cfg))) 76 val validPipe = OptionWrapper(needCtrlPipe, Vec(cfg.latency.latencyVal.get + 1, Bool())) 77 val data = new FuncUnitDataInput(cfg) 78 val dataPipe = OptionWrapper(needCtrlPipe, Vec(cfg.latency.latencyVal.get + 1, new FuncUnitDataInput(cfg))) 79 val perfDebugInfo = new PerfDebugInfo() 80} 81 82class FuncUnitOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 83 val ctrl = new FuncUnitCtrlOutput(cfg) 84 val res = new FuncUnitDataOutput(cfg) 85 val perfDebugInfo = new PerfDebugInfo() 86} 87 88class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 89 val flush = Flipped(ValidIO(new Redirect)) 90 val in = Flipped(DecoupledIO(new FuncUnitInput(cfg))) 91 val out = DecoupledIO(new FuncUnitOutput(cfg)) 92 val csrin = OptionWrapper(cfg.isCsr, new CSRInput) 93 val csrio = OptionWrapper(cfg.isCsr, new CSRFileIO) 94 val csrToDecode = OptionWrapper(cfg.isCsr, Output(new CSRToDecode)) 95 val fenceio = OptionWrapper(cfg.isFence, new FenceIO) 96 val frm = OptionWrapper(cfg.needSrcFrm, Input(UInt(3.W))) 97 val vxrm = OptionWrapper(cfg.needSrcVxrm, Input(UInt(2.W))) 98 val vtype = OptionWrapper(cfg.writeVlRf, (Valid(new VType))) 99 val vlIsZero = OptionWrapper(cfg.writeVlRf, Output(Bool())) 100 val vlIsVlmax = OptionWrapper(cfg.writeVlRf, Output(Bool())) 101 val instrAddrTransType = Option.when(cfg.isJmp || cfg.isBrh)(Input(new AddrTransType)) 102} 103 104abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends XSModule with HasCriticalErrors { 105 val io = IO(new FuncUnitIO(cfg)) 106 val criticalErrors = Seq(("none", false.B)) 107 108 // should only be used in non-piped fu 109 def connectNonPipedCtrlSingal: Unit = { 110 io.out.bits.ctrl.robIdx := RegEnable(io.in.bits.ctrl.robIdx, io.in.fire) 111 io.out.bits.ctrl.pdest := RegEnable(io.in.bits.ctrl.pdest, io.in.fire) 112 io.out.bits.ctrl.rfWen .foreach(_ := RegEnable(io.in.bits.ctrl.rfWen.get, io.in.fire)) 113 io.out.bits.ctrl.fpWen .foreach(_ := RegEnable(io.in.bits.ctrl.fpWen.get, io.in.fire)) 114 io.out.bits.ctrl.vecWen .foreach(_ := RegEnable(io.in.bits.ctrl.vecWen.get, io.in.fire)) 115 io.out.bits.ctrl.v0Wen .foreach(_ := RegEnable(io.in.bits.ctrl.v0Wen.get, io.in.fire)) 116 io.out.bits.ctrl.vlWen .foreach(_ := RegEnable(io.in.bits.ctrl.vlWen.get, io.in.fire)) 117 // io.out.bits.ctrl.flushPipe should be connected in fu 118 io.out.bits.ctrl.preDecode.foreach(_ := RegEnable(io.in.bits.ctrl.preDecode.get, io.in.fire)) 119 io.out.bits.ctrl.fpu .foreach(_ := RegEnable(io.in.bits.ctrl.fpu.get, io.in.fire)) 120 io.out.bits.ctrl.vpu .foreach(_ := RegEnable(io.in.bits.ctrl.vpu.get, io.in.fire)) 121 io.out.bits.perfDebugInfo := RegEnable(io.in.bits.perfDebugInfo, io.in.fire) 122 } 123 124 def connectNonPipedCtrlSingalForCSR: Unit = { 125 io.out.bits.ctrl.robIdx := DataHoldBypass(io.in.bits.ctrl.robIdx, io.in.fire) 126 io.out.bits.ctrl.pdest := DataHoldBypass(io.in.bits.ctrl.pdest, io.in.fire) 127 io.out.bits.ctrl.rfWen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.rfWen.get, io.in.fire)) 128 io.out.bits.ctrl.fpWen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.fpWen.get, io.in.fire)) 129 io.out.bits.ctrl.vecWen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.vecWen.get, io.in.fire)) 130 io.out.bits.ctrl.v0Wen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.v0Wen.get, io.in.fire)) 131 io.out.bits.ctrl.vlWen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.vlWen.get, io.in.fire)) 132 // io.out.bits.ctrl.flushPipe should be connected in fu 133 io.out.bits.ctrl.preDecode.foreach(_ := DataHoldBypass(io.in.bits.ctrl.preDecode.get, io.in.fire)) 134 io.out.bits.ctrl.fpu.foreach(_ := DataHoldBypass(io.in.bits.ctrl.fpu.get, io.in.fire)) 135 io.out.bits.ctrl.vpu.foreach(_ := DataHoldBypass(io.in.bits.ctrl.vpu.get, io.in.fire)) 136 io.out.bits.perfDebugInfo := DataHoldBypass(io.in.bits.perfDebugInfo, io.in.fire) 137 } 138 139 def connect0LatencyCtrlSingal: Unit = { 140 io.out.bits.ctrl.robIdx := io.in.bits.ctrl.robIdx 141 io.out.bits.ctrl.pdest := io.in.bits.ctrl.pdest 142 io.out.bits.ctrl.rfWen.foreach(_ := io.in.bits.ctrl.rfWen.get) 143 io.out.bits.ctrl.fpWen.foreach(_ := io.in.bits.ctrl.fpWen.get) 144 io.out.bits.ctrl.vecWen.foreach(_ := io.in.bits.ctrl.vecWen.get) 145 io.out.bits.ctrl.v0Wen.foreach(_ := io.in.bits.ctrl.v0Wen.get) 146 io.out.bits.ctrl.vlWen.foreach(_ := io.in.bits.ctrl.vlWen.get) 147 // io.out.bits.ctrl.flushPipe should be connected in fu 148 io.out.bits.ctrl.preDecode.foreach(_ := io.in.bits.ctrl.preDecode.get) 149 io.out.bits.ctrl.fpu.foreach(_ := io.in.bits.ctrl.fpu.get) 150 io.out.bits.ctrl.vpu.foreach(_ := io.in.bits.ctrl.vpu.get) 151 io.out.bits.perfDebugInfo := io.in.bits.perfDebugInfo 152 } 153} 154 155/** 156 * @author LinJiaWei, Yinan Xu 157 */ 158trait HasPipelineReg { this: FuncUnit => 159 def latency: Int 160 161 val latdiff :Int = cfg.latency.extraLatencyVal.getOrElse(0) 162 val preLat :Int = latency - latdiff 163 require(latency >= 0 && latdiff >=0) 164 165 def pipelineReg(init: FuncUnitInput , valid:Bool, ready: Bool,latency: Int, flush:ValidIO[Redirect]): (Seq[FuncUnitInput],Seq[Bool],Seq[Bool])={ 166 val rdyVec = Seq.fill(latency)(Wire(Bool())) :+ ready 167 val validVec = valid +: Seq.fill(latency)(RegInit(false.B)) 168 val ctrlVec = init.ctrl +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl))) 169 val dataVec = init.data +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.data))) 170 val perfVec = init.perfDebugInfo +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.perfDebugInfo))) 171 172 173 174 val robIdxVec = ctrlVec.map(_.robIdx) 175 176 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 177 val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(flush)) 178 179 for (i <- 0 until latency) { 180 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1).asTypeOf(Bool()) 181 } 182 for (i <- 1 to latency) { 183 validVec(i) := validVec(i - 1) 184 when(rdyVec(i - 1) && validVec(i - 1)) { 185 ctrlVec(i) := ctrlVec(i - 1) 186 dataVec(i) := dataVec(i - 1) 187 perfVec(i) := perfVec(i - 1) 188 } 189 } 190 191 (ctrlVec.zip(dataVec).zip(perfVec).map{ 192 case(( ctrl,data), perf) => { 193 val out = Wire(new FuncUnitInput(cfg)) 194 out.ctrl := ctrl 195 out.ctrlPipe.foreach(_ := 0.U.asTypeOf(out.ctrlPipe.get)) 196 out.validPipe.foreach(_ := 0.U.asTypeOf(out.validPipe.get)) 197 out.dataPipe.foreach(_ := 0.U.asTypeOf(out.dataPipe.get)) 198 out.data := data 199 out.perfDebugInfo := perf 200 out 201 } 202 },validVec, rdyVec) 203 } 204 val (pipeReg : Seq[FuncUnitInput], validVecThisFu ,rdyVec ) = pipelineReg(io.in.bits, io.in.valid,io.out.ready,preLat, io.flush) 205 val validVec = io.in.bits.validPipe.get.zip(validVecThisFu).map(x => x._1 && x._2) 206 val ctrlVec = io.in.bits.ctrlPipe.get 207 val dataVec = io.in.bits.dataPipe.get 208 val perfVec = pipeReg.map(_.perfDebugInfo) 209 210 211 val fixtiminginit = Wire(new FuncUnitInput(cfg)) 212 fixtiminginit.ctrl := ctrlVec.last 213 fixtiminginit.ctrlPipe.foreach(_ := 0.U.asTypeOf(fixtiminginit.ctrlPipe.get)) 214 fixtiminginit.validPipe.foreach(_ := 0.U.asTypeOf(fixtiminginit.validPipe.get)) 215 fixtiminginit.dataPipe.foreach(_ := 0.U.asTypeOf(fixtiminginit.dataPipe.get)) 216 fixtiminginit.data := dataVec.last 217 fixtiminginit.perfDebugInfo := perfVec.last 218 219 // fixtiming pipelinereg 220 val (fixpipeReg : Seq[FuncUnitInput], fixValidVec, fixRdyVec) = pipelineReg(fixtiminginit, validVec.last,rdyVec.head ,latdiff, io.flush) 221 val fixDataVec = fixpipeReg.map(_.data) 222 val fixPerfVec = fixpipeReg.map(_.perfDebugInfo) 223 val pcVec = fixDataVec.map(_.pc) 224 225 io.in.ready := fixRdyVec.head 226 io.out.valid := fixValidVec.last 227 228 io.out.bits.ctrl.robIdx := ctrlVec.last.robIdx 229 io.out.bits.ctrl.pdest := ctrlVec.last.pdest 230 io.out.bits.ctrl.rfWen.foreach(_ := ctrlVec.last.rfWen.get) 231 io.out.bits.ctrl.fpWen.foreach(_ := ctrlVec.last.fpWen.get) 232 io.out.bits.ctrl.vecWen.foreach(_ := ctrlVec.last.vecWen.get) 233 io.out.bits.ctrl.v0Wen.foreach(_ := ctrlVec.last.v0Wen.get) 234 io.out.bits.ctrl.vlWen.foreach(_ := ctrlVec.last.vlWen.get) 235 io.out.bits.ctrl.fpu.foreach(_ := ctrlVec.last.fpu.get) 236 io.out.bits.ctrl.vpu.foreach(_ := ctrlVec.last.vpu.get) 237 io.out.bits.perfDebugInfo := fixPerfVec.last 238 239 // vstart illegal 240 if (cfg.exceptionOut.nonEmpty) { 241 val outVstart = ctrlVec.last.vpu.get.vstart 242 val vstartIllegal = outVstart =/= 0.U 243 io.out.bits.ctrl.exceptionVec.get := 0.U.asTypeOf(io.out.bits.ctrl.exceptionVec.get) 244 io.out.bits.ctrl.exceptionVec.get(illegalInstr) := vstartIllegal 245 } 246 247 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) 248 249 def PipelineReg[TT <: Data](i: Int)(next: TT) = { 250 val lat = preLat min i 251 RegEnable( 252 next, 253 regEnable(lat) 254 ) 255 } 256 257 def SNReg[TT <: Data](in: TT, n: Int): TT ={ 258 val lat = preLat min n 259 var next = in 260 for (i <- 1 to lat) { 261 next = PipelineReg[TT](i)(next) 262 } 263 next 264 } 265 266 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 267 268 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 269 270 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 271 272 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 273 274 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 275 276} 277 278abstract class PipedFuncUnit(override val cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) 279 with HasPipelineReg { 280 override def latency: Int = cfg.latency.latencyVal.get 281} 282