1package xiangshan.backend.fu 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utility.DataHoldBypass 7import xiangshan._ 8import xiangshan.backend.rob.RobPtr 9import xiangshan.frontend.{FtqPtr, PreDecodeInfo} 10import xiangshan.backend.datapath.DataConfig._ 11 12class FuncUnitInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 13 val fuOpType = FuOpType() 14 val src = MixedVec(cfg.genSrcDataVec) 15 val imm = UInt(cfg.dataBits.W) 16 val robIdx = new RobPtr 17 val pdest = UInt(PhyRegIdxWidth.W) 18 val rfWen = if (cfg.writeIntRf) Some(Bool()) else None 19 val fpWen = if (cfg.writeFpRf) Some(Bool()) else None 20 val vecWen = if (cfg.writeVecRf) Some(Bool()) else None 21 val fpu = if (cfg.needFPUCtrl) Some(new FPUCtrlSignals) else None 22 23 val flushPipe = if (cfg.flushPipe) Some(Bool()) else None 24 val pc = if (cfg.needPc) Some(UInt(VAddrData().dataWidth.W)) else None 25 val preDecode = if (cfg.hasPredecode) Some(new PreDecodeInfo) else None 26 val ftqIdx = if (cfg.needPc || cfg.replayInst) 27 Some(new FtqPtr) else None 28 val ftqOffset = if (cfg.needPc || cfg.replayInst) 29 Some(UInt(log2Up(PredictWidth).W)) else None 30 val predictInfo = if (cfg.hasRedirect)Some(new Bundle { 31 val target = UInt(VAddrData().dataWidth.W) 32 val taken = Bool() 33 }) else None 34} 35 36class FuncUnitOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle { 37 val data = UInt(cfg.dataBits.W) 38 val pdest = UInt(PhyRegIdxWidth.W) // Todo: use maximum of pregIdxWidth of different pregs 39 val robIdx = new RobPtr 40 val redirect = if (cfg.hasRedirect) Some(ValidIO(new Redirect)) else None 41 val fflags = if (cfg.writeFflags) Some(UInt(5.W)) else None 42 val exceptionVec = if (cfg.exceptionOut.nonEmpty) Some(ExceptionVec()) else None 43 val flushPipe = if (cfg.flushPipe) Some(Bool()) else None 44 val replay = if (cfg.replayInst) Some(Bool()) else None 45 val pc = if (cfg.isFence) Some(UInt(VAddrData().dataWidth.W))else None 46 val fpu = if (cfg.needFPUCtrl) Some(new FPUCtrlSignals) else None // only used in FMA 47 val preDecode = if (cfg.hasPredecode)Some(new PreDecodeInfo) else None 48} 49 50class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends Bundle { 51 val flush = Flipped(ValidIO(new Redirect)) 52 val in = Flipped(DecoupledIO(new FuncUnitInput(cfg))) 53 val out = DecoupledIO(new FuncUnitOutput(cfg)) 54 val csrio = if (cfg.isCsr) Some(new CSRFileIO) else None 55 val fenceio = if (cfg.isFence) Some(new FenceIO) else None 56 val frm = if (cfg.needSrcFrm) Some(Input(UInt(3.W))) else None 57} 58 59abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends Module { 60 val io = IO(new FuncUnitIO(cfg)) 61 62 // should only be used in non-piped fu 63 def connectNonPipedCtrlSingal: Unit = { 64 io.out.bits.robIdx := DataHoldBypass(io.in.bits.robIdx, io.in.fire) 65 io.out.bits.pdest := DataHoldBypass(io.in.bits.pdest, io.in.fire) 66 io.out.bits.pc.foreach(_ := io.in.bits.pc.get) 67 io.out.bits.preDecode.foreach(_ := io.in.bits.preDecode.get) 68 io.out.bits.fpu.foreach(_ := DataHoldBypass(io.in.bits.fpu.get, io.in.fire)) 69 } 70} 71 72/** 73 * @author LinJiaWei, Yinan Xu 74 */ 75trait HasPipelineReg { this: FuncUnit => 76 def latency: Int 77 78 require(latency > 0) 79 80 val validVec = io.in.valid +: Seq.fill(latency)(RegInit(false.B)) 81 val rdyVec = Seq.fill(latency)(Wire(Bool())) :+ io.out.ready 82 val robIdxVec = io.in.bits.robIdx +: Array.fill(latency)(Reg(chiselTypeOf(io.in.bits.robIdx))) 83 84 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 85 val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(io.flush)) 86 87 for (i <- 0 until latency) { 88 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 89 } 90 91 for (i <- 1 to latency) { 92 when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){ 93 validVec(i) := validVec(i - 1) 94 robIdxVec(i) := robIdxVec(i - 1) 95 }.elsewhen(flushVec(i) || rdyVec(i)){ 96 validVec(i) := false.B 97 } 98 } 99 100 io.in.ready := rdyVec(0) 101 io.out.valid := validVec.last 102 io.out.bits.robIdx := robIdxVec.last 103 104 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 105 106 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 107 next, 108 regEnable(i) 109 ) 110 111 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 112 113 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 114 115 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 116 117 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 118 119 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 120 121} 122 123 124