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 XSBundle { 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 XSModule { 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 val pdestVec = io.in.bits.pdest +: Array.fill(latency)(Reg(chiselTypeOf(io.in.bits.pdest))) 84 85 val pcVec = io.in.bits.pc.map(x => x) +: Array.fill(latency)( io.in.bits.pc.map(x => Reg(chiselTypeOf(x)))) // Reg(chiselTypeOf(io.in.bits.pc.get)) 86 val preDecodeVec = io.in.bits.preDecode.map(x => x) +: Array.fill(latency)(io.in.bits.preDecode.map(x => Reg(chiselTypeOf(x)))) 87 val fpuVec = io.in.bits.fpu.map(x => x) +: Array.fill(latency)(io.in.bits.fpu.map(x => Reg(chiselTypeOf(x)))) 88 89 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 90 val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(io.flush)) 91 92 for (i <- 0 until latency) { 93 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 94 } 95 96 for (i <- 1 to latency) { 97 when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){ 98 validVec(i) := validVec(i - 1) 99 robIdxVec(i) := robIdxVec(i - 1) 100 pdestVec(i) := pdestVec(i - 1) 101 pcVec(i).zip(pcVec(i - 1)).foreach{case (l,r) => l := r} 102 preDecodeVec(i).zip(preDecodeVec(i - 1)).foreach{case (l,r) => l := r} 103 fpuVec(i).zip(fpuVec(i - 1)).foreach{case (l,r) => l := r} 104 }.elsewhen(flushVec(i) || rdyVec(i)){ 105 validVec(i) := false.B 106 } 107 } 108 109 io.in.ready := rdyVec(0) 110 io.out.valid := validVec.last 111 io.out.bits.robIdx := robIdxVec.last 112 io.out.bits.pdest := pdestVec.last 113 io.out.bits.pc.zip(pcVec.last).foreach{case (l,r) => l := r} 114 io.out.bits.preDecode.zip(preDecodeVec.last).foreach{case (l,r) => l := r} 115 io.out.bits.fpu.zip(fpuVec.last).foreach{case (l,r) => l := r} 116 117 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 118 119 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 120 next, 121 regEnable(i) 122 ) 123 124 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 125 126 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 127 128 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 129 130 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 131 132 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 133 134} 135 136 137