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