1package xiangshan.backend.fu 2 3import chipsalliance.rocketchip.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.fpu.Bundles.Fflags 14import xiangshan.backend.fu.vector.Bundles.Vxsat 15 16class FuncUnitCtrlInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 17 val fuOpType = FuOpType() 18 val robIdx = new RobPtr 19 val pdest = UInt(PhyRegIdxWidth.W) 20 val rfWen = OptionWrapper(cfg.writeIntRf, Bool()) 21 val fpWen = OptionWrapper(cfg.writeFpRf, Bool()) 22 val vecWen = OptionWrapper(cfg.writeVecRf, Bool()) 23 val flushPipe = OptionWrapper(cfg.flushPipe, Bool()) 24 val preDecode = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo) 25 val ftqIdx = OptionWrapper(cfg.needPc || cfg.replayInst, new FtqPtr) 26 val ftqOffset = OptionWrapper(cfg.needPc || cfg.replayInst, UInt(log2Up(PredictWidth).W)) 27 val predictInfo = OptionWrapper(cfg.hasRedirect, new Bundle { 28 val target = UInt(VAddrData().dataWidth.W) 29 val taken = Bool() 30 }) 31 val fpu = OptionWrapper(cfg.needFPUCtrl, new FPUCtrlSignals) 32 val vpu = OptionWrapper(cfg.needVecCtrl, new VPUCtrlSignals) 33} 34 35class FuncUnitCtrlOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 36 val robIdx = new RobPtr 37 val pdest = UInt(PhyRegIdxWidth.W) // Todo: use maximum of pregIdxWidth of different pregs 38 val rfWen = OptionWrapper(cfg.writeIntRf, Bool()) 39 val fpWen = OptionWrapper(cfg.writeFpRf, Bool()) 40 val vecWen = OptionWrapper(cfg.writeVecRf, Bool()) 41 val exceptionVec = OptionWrapper(cfg.exceptionOut.nonEmpty, ExceptionVec()) 42 val flushPipe = OptionWrapper(cfg.flushPipe, Bool()) 43 val replay = OptionWrapper(cfg.replayInst, Bool()) 44 val preDecode = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo) 45 val fpu = OptionWrapper(cfg.needFPUCtrl, new FPUCtrlSignals) // only used in FMA 46 val vpu = OptionWrapper(cfg.needVecCtrl, new VPUCtrlSignals) 47} 48 49class FuncUnitDataInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 50 val src = MixedVec(cfg.genSrcDataVec) 51 val imm = UInt(cfg.dataBits.W) 52 val pc = OptionWrapper(cfg.needPc, UInt(VAddrData().dataWidth.W)) 53} 54 55class FuncUnitDataOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 56 val data = UInt(cfg.dataBits.W) 57 val fflags = OptionWrapper(cfg.writeFflags, Fflags()) 58 val vxsat = OptionWrapper(cfg.writeVxsat, Vxsat()) 59 val pc = OptionWrapper(cfg.isFence, UInt(VAddrData().dataWidth.W)) 60 val redirect = OptionWrapper(cfg.hasRedirect, ValidIO(new Redirect)) 61} 62 63class FuncUnitInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 64 val ctrl = new FuncUnitCtrlInput(cfg) 65 val data = new FuncUnitDataInput(cfg) 66} 67 68class FuncUnitOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 69 val ctrl = new FuncUnitCtrlOutput(cfg) 70 val res = new FuncUnitDataOutput(cfg) 71} 72 73class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 74 val flush = Flipped(ValidIO(new Redirect)) 75 val in = Flipped(DecoupledIO(new FuncUnitInput(cfg))) 76 val out = DecoupledIO(new FuncUnitOutput(cfg)) 77 val csrio = if (cfg.isCsr) Some(new CSRFileIO) else None 78 val fenceio = if (cfg.isFence) Some(new FenceIO) else None 79 val frm = if (cfg.needSrcFrm) Some(Input(UInt(3.W))) else None 80} 81 82abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends XSModule { 83 val io = IO(new FuncUnitIO(cfg)) 84 85 // should only be used in non-piped fu 86 def connectNonPipedCtrlSingal: Unit = { 87 io.out.bits.ctrl.robIdx := DataHoldBypass(io.in.bits.ctrl.robIdx, io.in.fire) 88 io.out.bits.ctrl.pdest := DataHoldBypass(io.in.bits.ctrl.pdest, io.in.fire) 89 io.out.bits.ctrl.preDecode.foreach(_ := DataHoldBypass(io.in.bits.ctrl.preDecode.get, io.in.fire)) 90 io.out.bits.ctrl.fpu .foreach(_ := DataHoldBypass(io.in.bits.ctrl.fpu.get, io.in.fire)) 91 } 92} 93 94/** 95 * @author LinJiaWei, Yinan Xu 96 */ 97trait HasPipelineReg { this: FuncUnit => 98 def latency: Int 99 100 require(latency > 0) 101 102 val validVec = io.in.valid +: Seq.fill(latency)(RegInit(false.B)) 103 val rdyVec = Seq.fill(latency)(Wire(Bool())) :+ io.out.ready 104// val ctrlVec = io.in.bits.ctrl +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl))) 105// val dataVec = io.in.bits.data +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.data))) 106 107 val robIdxVec = io.in.bits.ctrl.robIdx +: Array.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl.robIdx))) 108 val pdestVec = io.in.bits.ctrl.pdest +: Array.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl.pdest))) 109 110 val pcVec = io.in.bits.data.pc.map(x => x) +: Array.fill(latency)( io.in.bits.data.pc.map(x => Reg(chiselTypeOf(x)))) // Reg(chiselTypeOf(io.in.bits.pc.get)) 111 val preDecodeVec = io.in.bits.ctrl.preDecode.map(x => x) +: Array.fill(latency)(io.in.bits.ctrl.preDecode.map(x => Reg(chiselTypeOf(x)))) 112 val fpuVec = io.in.bits.ctrl.fpu.map(x => x) +: Array.fill(latency)(io.in.bits.ctrl.fpu.map(x => Reg(chiselTypeOf(x)))) 113 114 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 115 val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(io.flush)) 116 117 for (i <- 0 until latency) { 118 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 119 } 120 121 for (i <- 1 until latency) { 122 when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){ 123 validVec(i) := validVec(i - 1) 124 robIdxVec(i) := robIdxVec(i - 1) 125 pdestVec(i) := pdestVec(i - 1) 126 pcVec(i).zip(pcVec(i - 1)).foreach{case (l,r) => l := r} 127 preDecodeVec(i).zip(preDecodeVec(i - 1)).foreach{case (l,r) => l := r} 128 fpuVec(i).zip(fpuVec(i - 1)).foreach{case (l,r) => l := r} 129 }.elsewhen(flushVec(i) || rdyVec(i)){ 130 validVec(i) := false.B 131 } 132 } 133 134 io.in.ready := rdyVec(0) 135 io.out.valid := validVec.last 136 io.out.bits.ctrl.robIdx := robIdxVec.last 137 io.out.bits.ctrl.pdest := pdestVec.last 138 io.out.bits.res.pc.zip(pcVec.last).foreach{case (l,r) => l := r} 139 io.out.bits.ctrl.preDecode.zip(preDecodeVec.last).foreach{case (l,r) => l := r} 140 io.out.bits.ctrl.fpu.zip(fpuVec.last).foreach{case (l,r) => l := r} 141 142 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 143 144 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 145 next, 146 regEnable(i) 147 ) 148 149 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 150 151 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 152 153 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 154 155 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 156 157 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 158 159} 160 161 162