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 perfDebugInfo = new PerfDebugInfo() 79} 80 81class FuncUnitOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 82 val ctrl = new FuncUnitCtrlOutput(cfg) 83 val res = new FuncUnitDataOutput(cfg) 84 val perfDebugInfo = new PerfDebugInfo() 85} 86 87class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 88 val flush = Flipped(ValidIO(new Redirect)) 89 val in = Flipped(DecoupledIO(new FuncUnitInput(cfg))) 90 val out = DecoupledIO(new FuncUnitOutput(cfg)) 91 val csrin = OptionWrapper(cfg.isCsr, new CSRInput) 92 val csrio = OptionWrapper(cfg.isCsr, new CSRFileIO) 93 val csrToDecode = OptionWrapper(cfg.isCsr, Output(new CSRToDecode)) 94 val fenceio = OptionWrapper(cfg.isFence, new FenceIO) 95 val frm = OptionWrapper(cfg.needSrcFrm, Input(UInt(3.W))) 96 val vxrm = OptionWrapper(cfg.needSrcVxrm, Input(UInt(2.W))) 97 val vtype = OptionWrapper(cfg.writeVlRf, (Valid(new VType))) 98 val vlIsZero = OptionWrapper(cfg.writeVlRf, Output(Bool())) 99 val vlIsVlmax = OptionWrapper(cfg.writeVlRf, Output(Bool())) 100 val instrAddrTransType = Option.when(cfg.isJmp || cfg.isBrh)(Input(new AddrTransType)) 101} 102 103abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends XSModule with HasCriticalErrors { 104 val io = IO(new FuncUnitIO(cfg)) 105 val criticalErrors = Seq(("none", false.B)) 106 107 // should only be used in non-piped fu 108 def connectNonPipedCtrlSingal: Unit = { 109 io.out.bits.ctrl.robIdx := RegEnable(io.in.bits.ctrl.robIdx, io.in.fire) 110 io.out.bits.ctrl.pdest := RegEnable(io.in.bits.ctrl.pdest, io.in.fire) 111 io.out.bits.ctrl.rfWen .foreach(_ := RegEnable(io.in.bits.ctrl.rfWen.get, io.in.fire)) 112 io.out.bits.ctrl.fpWen .foreach(_ := RegEnable(io.in.bits.ctrl.fpWen.get, io.in.fire)) 113 io.out.bits.ctrl.vecWen .foreach(_ := RegEnable(io.in.bits.ctrl.vecWen.get, io.in.fire)) 114 io.out.bits.ctrl.v0Wen .foreach(_ := RegEnable(io.in.bits.ctrl.v0Wen.get, io.in.fire)) 115 io.out.bits.ctrl.vlWen .foreach(_ := RegEnable(io.in.bits.ctrl.vlWen.get, io.in.fire)) 116 // io.out.bits.ctrl.flushPipe should be connected in fu 117 io.out.bits.ctrl.preDecode.foreach(_ := RegEnable(io.in.bits.ctrl.preDecode.get, io.in.fire)) 118 io.out.bits.ctrl.fpu .foreach(_ := RegEnable(io.in.bits.ctrl.fpu.get, io.in.fire)) 119 io.out.bits.ctrl.vpu .foreach(_ := RegEnable(io.in.bits.ctrl.vpu.get, io.in.fire)) 120 io.out.bits.perfDebugInfo := RegEnable(io.in.bits.perfDebugInfo, io.in.fire) 121 } 122 123 def connectNonPipedCtrlSingalForCSR: Unit = { 124 io.out.bits.ctrl.robIdx := DataHoldBypass(io.in.bits.ctrl.robIdx, io.in.fire) 125 io.out.bits.ctrl.pdest := DataHoldBypass(io.in.bits.ctrl.pdest, io.in.fire) 126 io.out.bits.ctrl.rfWen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.rfWen.get, io.in.fire)) 127 io.out.bits.ctrl.fpWen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.fpWen.get, io.in.fire)) 128 io.out.bits.ctrl.vecWen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.vecWen.get, io.in.fire)) 129 io.out.bits.ctrl.v0Wen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.v0Wen.get, io.in.fire)) 130 io.out.bits.ctrl.vlWen.foreach(_ := DataHoldBypass(io.in.bits.ctrl.vlWen.get, io.in.fire)) 131 // io.out.bits.ctrl.flushPipe should be connected in fu 132 io.out.bits.ctrl.preDecode.foreach(_ := DataHoldBypass(io.in.bits.ctrl.preDecode.get, io.in.fire)) 133 io.out.bits.ctrl.fpu.foreach(_ := DataHoldBypass(io.in.bits.ctrl.fpu.get, io.in.fire)) 134 io.out.bits.ctrl.vpu.foreach(_ := DataHoldBypass(io.in.bits.ctrl.vpu.get, io.in.fire)) 135 io.out.bits.perfDebugInfo := DataHoldBypass(io.in.bits.perfDebugInfo, io.in.fire) 136 } 137 138 def connect0LatencyCtrlSingal: Unit = { 139 io.out.bits.ctrl.robIdx := io.in.bits.ctrl.robIdx 140 io.out.bits.ctrl.pdest := io.in.bits.ctrl.pdest 141 io.out.bits.ctrl.rfWen.foreach(_ := io.in.bits.ctrl.rfWen.get) 142 io.out.bits.ctrl.fpWen.foreach(_ := io.in.bits.ctrl.fpWen.get) 143 io.out.bits.ctrl.vecWen.foreach(_ := io.in.bits.ctrl.vecWen.get) 144 io.out.bits.ctrl.v0Wen.foreach(_ := io.in.bits.ctrl.v0Wen.get) 145 io.out.bits.ctrl.vlWen.foreach(_ := io.in.bits.ctrl.vlWen.get) 146 // io.out.bits.ctrl.flushPipe should be connected in fu 147 io.out.bits.ctrl.preDecode.foreach(_ := io.in.bits.ctrl.preDecode.get) 148 io.out.bits.ctrl.fpu.foreach(_ := io.in.bits.ctrl.fpu.get) 149 io.out.bits.ctrl.vpu.foreach(_ := io.in.bits.ctrl.vpu.get) 150 io.out.bits.perfDebugInfo := io.in.bits.perfDebugInfo 151 } 152} 153 154/** 155 * @author LinJiaWei, Yinan Xu 156 */ 157trait HasPipelineReg { this: FuncUnit => 158 def latency: Int 159 160 val latdiff :Int = cfg.latency.extraLatencyVal.getOrElse(0) 161 val preLat :Int = latency - latdiff 162 require(latency >= 0 && latdiff >=0) 163 164 def pipelineReg(init: FuncUnitInput , valid:Bool, ready: Bool,latency: Int, flush:ValidIO[Redirect]): (Seq[FuncUnitInput],Seq[Bool],Seq[Bool])={ 165 val rdyVec = Seq.fill(latency)(Wire(Bool())) :+ ready 166 val validVec = valid +: Seq.fill(latency)(RegInit(false.B)) 167 val ctrlVec = init.ctrl +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl))) 168 val dataVec = init.data +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.data))) 169 val perfVec = init.perfDebugInfo +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.perfDebugInfo))) 170 171 172 173 val robIdxVec = ctrlVec.map(_.robIdx) 174 175 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 176 val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(flush)) 177 178 for (i <- 0 until latency) { 179 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1).asTypeOf(Bool()) 180 } 181 for (i <- 1 to latency) { 182 validVec(i) := validVec(i - 1) 183 when(rdyVec(i - 1) && validVec(i - 1)) { 184 ctrlVec(i) := ctrlVec(i - 1) 185 dataVec(i) := dataVec(i - 1) 186 perfVec(i) := perfVec(i - 1) 187 } 188 } 189 190 (ctrlVec.zip(dataVec).zip(perfVec).map{ 191 case(( ctrl,data), perf) => { 192 val out = Wire(new FuncUnitInput(cfg)) 193 out.ctrl := ctrl 194 out.ctrlPipe.foreach(_ := 0.U.asTypeOf(out.ctrlPipe.get)) 195 out.validPipe.foreach(_ := 0.U.asTypeOf(out.validPipe.get)) 196 out.data := data 197 out.perfDebugInfo := perf 198 out 199 } 200 },validVec, rdyVec) 201 } 202 val (pipeReg : Seq[FuncUnitInput], validVecThisFu ,rdyVec ) = pipelineReg(io.in.bits, io.in.valid,io.out.ready,preLat, io.flush) 203 val validVec = io.in.bits.validPipe.get.zip(validVecThisFu).map(x => x._1 && x._2) 204 val ctrlVec = io.in.bits.ctrlPipe.get 205 val dataVec = pipeReg.map(_.data) 206 val perfVec = pipeReg.map(_.perfDebugInfo) 207 208 209 val fixtiminginit = Wire(new FuncUnitInput(cfg)) 210 fixtiminginit.ctrl := ctrlVec.last 211 fixtiminginit.ctrlPipe.foreach(_ := 0.U.asTypeOf(fixtiminginit.ctrlPipe.get)) 212 fixtiminginit.validPipe.foreach(_ := 0.U.asTypeOf(fixtiminginit.validPipe.get)) 213 fixtiminginit.data := dataVec.last 214 fixtiminginit.perfDebugInfo := perfVec.last 215 216 // fixtiming pipelinereg 217 val (fixpipeReg : Seq[FuncUnitInput], fixValidVec, fixRdyVec) = pipelineReg(fixtiminginit, validVec.last,rdyVec.head ,latdiff, io.flush) 218 val fixDataVec = fixpipeReg.map(_.data) 219 val fixPerfVec = fixpipeReg.map(_.perfDebugInfo) 220 val pcVec = fixDataVec.map(_.pc) 221 222 io.in.ready := fixRdyVec.head 223 io.out.valid := fixValidVec.last 224 225 io.out.bits.ctrl.robIdx := ctrlVec.last.robIdx 226 io.out.bits.ctrl.pdest := ctrlVec.last.pdest 227 io.out.bits.ctrl.rfWen.foreach(_ := ctrlVec.last.rfWen.get) 228 io.out.bits.ctrl.fpWen.foreach(_ := ctrlVec.last.fpWen.get) 229 io.out.bits.ctrl.vecWen.foreach(_ := ctrlVec.last.vecWen.get) 230 io.out.bits.ctrl.v0Wen.foreach(_ := ctrlVec.last.v0Wen.get) 231 io.out.bits.ctrl.vlWen.foreach(_ := ctrlVec.last.vlWen.get) 232 io.out.bits.ctrl.fpu.foreach(_ := ctrlVec.last.fpu.get) 233 io.out.bits.ctrl.vpu.foreach(_ := ctrlVec.last.vpu.get) 234 io.out.bits.perfDebugInfo := fixPerfVec.last 235 236 // vstart illegal 237 if (cfg.exceptionOut.nonEmpty) { 238 val outVstart = ctrlVec.last.vpu.get.vstart 239 val vstartIllegal = outVstart =/= 0.U 240 io.out.bits.ctrl.exceptionVec.get := 0.U.asTypeOf(io.out.bits.ctrl.exceptionVec.get) 241 io.out.bits.ctrl.exceptionVec.get(illegalInstr) := vstartIllegal 242 } 243 244 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) 245 246 def PipelineReg[TT <: Data](i: Int)(next: TT) = { 247 val lat = preLat min i 248 RegEnable( 249 next, 250 regEnable(lat) 251 ) 252 } 253 254 def SNReg[TT <: Data](in: TT, n: Int): TT ={ 255 val lat = preLat min n 256 var next = in 257 for (i <- 1 to lat) { 258 next = PipelineReg[TT](i)(next) 259 } 260 next 261 } 262 263 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 264 265 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 266 267 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 268 269 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 270 271 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 272 273} 274 275abstract class PipedFuncUnit(override val cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) 276 with HasPipelineReg { 277 override def latency: Int = cfg.latency.latencyVal.get 278} 279