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