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