1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.backend.fu.fpu.divsqrt.DivSqrt 7import xiangshan.backend.fu.fpu._ 8import xiangshan.backend.fu.fpu.fma.FMA 9 10/* 11 XiangShan Function Unit 12 A Exu can have one or more function units 13 */ 14 15trait HasFuLatency { 16 val latencyVal: Option[Int] 17} 18 19case class CertainLatency(value: Int) extends HasFuLatency{ 20 override val latencyVal: Option[Int] = Some(value) 21} 22 23case class UncertainLatency() extends HasFuLatency { 24 override val latencyVal: Option[Int] = None 25} 26 27 28 29case class FuConfig 30( 31 fuType: UInt, 32 numIntSrc: Int, 33 numFpSrc: Int, 34 writeIntRf: Boolean, 35 writeFpRf: Boolean, 36 hasRedirect: Boolean, 37 latency: HasFuLatency = CertainLatency(0) 38) { 39 def srcCnt: Int = math.max(numIntSrc, numFpSrc) 40} 41 42 43 44class FuOutput extends XSBundle { 45 val data = UInt(XLEN.W) 46 val uop = new MicroOp 47} 48 49 50class FunctionUnitIO[TI <: Data, TO <: Data] 51( 52 cfg: FuConfig, 53 len: Int 54) extends XSBundle 55{ 56 val in = Flipped(DecoupledIO(new Bundle() { 57 val src = Vec(cfg.srcCnt, UInt(len.W)) 58 val uop = new MicroOp 59 60 def connectToExuInput(exuIn: ExuInput): Unit = { 61 val exuSrcIn = Seq(exuIn.src1, exuIn.src2, exuIn.src3) 62 src.zip(exuSrcIn).foreach{case (x, y) => x := y} 63 uop := exuIn.uop 64 } 65 })) 66 67 val out = DecoupledIO(new FuOutput) 68 69 val redirectIn = Flipped(ValidIO(new Redirect)) 70 71 override def cloneType: FunctionUnitIO.this.type = 72 new FunctionUnitIO(cfg, len).asInstanceOf[this.type] 73} 74 75abstract class FunctionUnit 76( 77 val cfg: FuConfig, 78 val len: Int = 64 79) extends XSModule { 80 81 val io = IO(new FunctionUnitIO(cfg, len)) 82 83} 84 85trait HasPipelineReg { this: FunctionUnit => 86 87 require(cfg.latency.latencyVal.nonEmpty && cfg.latency.latencyVal.get > 0) 88 val latency = cfg.latency.latencyVal.get 89 90 val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B)) 91 val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready 92 val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp)) 93 94 95 val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn)) 96 97 for (i <- 0 until latency) { 98 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 99 } 100 101 for (i <- 1 to latency) { 102 when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) { 103 validVec(i) := false.B 104 }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) { 105 validVec(i) := validVec(i - 1) 106 uopVec(i) := uopVec(i - 1) 107 } 108 } 109 110 io.in.ready := rdyVec(0) 111 io.out.valid := validVec.last && !flushVec.last 112 io.out.bits.uop := uopVec.last 113 114 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 115 next, 116 enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 117 ) 118 119 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 120 121 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 122 123 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 124 125 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 126 127 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 128} 129 130object FunctionUnit extends HasXSParameter { 131 132 def divider = new SRT4Divider(XLEN) 133 def multiplier = new ArrayMultiplier(XLEN+1, Seq(0, 2)) 134 135 def alu = new Alu 136 137 def jmp = new Jump 138 def fence = new Fence 139 def csr = new CSR 140 def i2f = new IntToFloatSingleCycle 141 142 def fmac = new FMA 143 def fcmp = new FCMP 144 def fmv = new FMV(XLEN) 145 def f2i = new FloatToInt 146 def f32toF64 = new F32toF64 147 def f64toF32 = new F64toF32 148 def fdivSqrt = new DivSqrt 149 150 def fmiscSel(fu: String)(x: FPUSubModule): Bool = { 151 x.io.in.bits.uop.ctrl.fuOpType.head(4) === s"b$fu".U 152 } 153 154 val lduCfg = 155 FuConfig(FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false, 156 UncertainLatency() 157 ) 158 159 val stuCfg = 160 FuConfig(FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false, 161 UncertainLatency() 162 ) 163 164 val mouCfg = 165 FuConfig(FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false, 166 UncertainLatency() 167 ) 168} 169