1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.backend.MDUOpType 7import xiangshan.backend.fu.fpu.FPUOpType.{FU_D2S, FU_DIVSQRT, FU_F2I, FU_FCMP, FU_FMV, FU_S2D} 8import xiangshan.backend.fu.fpu.divsqrt.DivSqrt 9import xiangshan.backend.fu.fpu._ 10import xiangshan.backend.fu.fpu.fma.FMA 11 12/* 13 XiangShan Function Unit 14 A Exu can have one or more function units 15 */ 16 17trait HasFuLatency { 18 val latencyVal: Option[Int] 19} 20 21case class CertainLatency(value: Int) extends HasFuLatency { 22 override val latencyVal: Option[Int] = Some(value) 23} 24 25case class UncertainLatency() extends HasFuLatency { 26 override val latencyVal: Option[Int] = None 27} 28 29 30case class FuConfig 31( 32 fuGen: () => FunctionUnit, 33 fuSel: FunctionUnit => Bool, 34 fuType: UInt, 35 numIntSrc: Int, 36 numFpSrc: Int, 37 writeIntRf: Boolean, 38 writeFpRf: Boolean, 39 hasRedirect: Boolean, 40 latency: HasFuLatency = CertainLatency(0) 41) { 42 def srcCnt: Int = math.max(numIntSrc, numFpSrc) 43} 44 45 46class FuOutput extends XSBundle { 47 val data = UInt(XLEN.W) 48 val uop = new MicroOp 49} 50 51 52class FunctionUnitIO(len: Int) extends XSBundle { 53 val in = Flipped(DecoupledIO(new Bundle() { 54 val src = Vec(3, UInt(len.W)) 55 val uop = new MicroOp 56 })) 57 58 val out = DecoupledIO(new FuOutput) 59 60 val redirectIn = Flipped(ValidIO(new Redirect)) 61 62 override def cloneType: FunctionUnitIO.this.type = 63 new FunctionUnitIO(len).asInstanceOf[this.type] 64} 65 66abstract class FunctionUnit(len: Int = 64) extends XSModule { 67 68 val io = IO(new FunctionUnitIO(len)) 69 70} 71 72trait HasPipelineReg { 73 this: FunctionUnit => 74 75 def latency: Int 76 77 require(latency > 0) 78 79 val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B)) 80 val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready 81 val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp)) 82 83 84 val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn)) 85 86 for (i <- 0 until latency) { 87 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 88 } 89 90 for (i <- 1 to latency) { 91 when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) { 92 validVec(i) := false.B 93 }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) { 94 validVec(i) := validVec(i - 1) 95 uopVec(i) := uopVec(i - 1) 96 } 97 } 98 99 io.in.ready := rdyVec(0) 100 io.out.valid := validVec.last && !flushVec.last 101 io.out.bits.uop := uopVec.last 102 103 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 104 next, 105 enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 106 ) 107 108 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 109 110 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 111 112 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 113 114 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 115 116 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 117} 118 119object FunctionUnit extends HasXSParameter { 120 121 def divider = new SRT4Divider(XLEN) 122 123 def multiplier = new ArrayMultiplier(XLEN + 1, Seq(0, 2)) 124 125 def alu = new Alu 126 127 def jmp = new Jump 128 129 def fence = new Fence 130 131 def csr = new CSR 132 133 def i2f = new IntToFloatSingleCycle 134 135 def fmac = new FMA 136 137 def fcmp = new FCMP 138 139 def fmv = new FMV(XLEN) 140 141 def f2i = new FloatToInt 142 143 def f32toF64 = new F32toF64 144 145 def f64toF32 = new F64toF32 146 147 def fdivSqrt = new DivSqrt 148 149 def fmiscSel(fu: String)(x: FunctionUnit): Bool = { 150 x.io.in.bits.uop.ctrl.fuOpType.head(4) === s"b$fu".U 151 } 152 153 val aluCfg = FuConfig( 154 fuGen = alu _, 155 fuSel = _ => true.B, 156 fuType = FuType.alu, 157 numIntSrc = 2, 158 numFpSrc = 0, 159 writeIntRf = true, 160 writeFpRf = false, 161 hasRedirect = true 162 ) 163 164 val jmpCfg = FuConfig( 165 fuGen = jmp _, 166 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.jmp, 167 fuType = FuType.jmp, 168 numIntSrc = 1, 169 numFpSrc = 0, 170 writeIntRf = true, 171 writeFpRf = false, 172 hasRedirect = true 173 ) 174 175 val fenceCfg = FuConfig( 176 fuGen = fence _, 177 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence, 178 FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false 179 ) 180 181 val csrCfg = FuConfig( 182 fuGen = csr _, 183 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr, 184 fuType = FuType.csr, 185 numIntSrc = 1, 186 numFpSrc = 0, 187 writeIntRf = true, 188 writeFpRf = false, 189 hasRedirect = false 190 ) 191 192 val i2fCfg = FuConfig( 193 fuGen = i2f _, 194 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.i2f, 195 FuType.i2f, 196 numIntSrc = 1, 197 numFpSrc = 0, 198 writeIntRf = false, 199 writeFpRf = true, 200 hasRedirect = false, 201 CertainLatency(0) 202 ) 203 204 val divCfg = FuConfig( 205 fuGen = divider _, 206 fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType), 207 FuType.div, 208 2, 209 0, 210 writeIntRf = true, 211 writeFpRf = false, 212 hasRedirect = false, 213 UncertainLatency() 214 ) 215 216 val mulCfg = FuConfig( 217 fuGen = multiplier _, 218 fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType), 219 FuType.mul, 220 2, 221 0, 222 writeIntRf = true, 223 writeFpRf = false, 224 hasRedirect = false, 225 CertainLatency(3) 226 ) 227 228 val fmacCfg = FuConfig( 229 fuGen = fmac _, 230 fuSel = _ => true.B, 231 FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(5) 232 ) 233 234 val fcmpCfg = FuConfig( 235 fuGen = fcmp _, 236 fuSel = fmiscSel(FU_FCMP), 237 FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2) 238 ) 239 240 val fmvCfg = FuConfig( 241 fuGen = fmv _, 242 fuSel = fmiscSel(FU_FMV), 243 FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = true, hasRedirect = false, CertainLatency(1) 244 ) 245 246 val f2iCfg = FuConfig( 247 fuGen = f2i _, 248 fuSel = fmiscSel(FU_F2I), 249 FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2) 250 ) 251 252 val s2dCfg = FuConfig( 253 fuGen = f32toF64 _, 254 fuSel = fmiscSel(FU_S2D), 255 FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2) 256 ) 257 258 val d2sCfg = FuConfig( 259 fuGen = f64toF32 _, 260 fuSel = fmiscSel(FU_D2S), 261 FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2) 262 ) 263 264 val fdivSqrtCfg = FuConfig( 265 fuGen = fdivSqrt _, 266 fuSel = fmiscSel(FU_DIVSQRT), 267 FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency() 268 ) 269 270 val lduCfg = FuConfig( 271 null, // DontCare 272 null, 273 FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false, 274 UncertainLatency() 275 ) 276 277 val stuCfg = FuConfig( 278 null, 279 null, 280 FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false, 281 UncertainLatency() 282 ) 283 284 val mouCfg = FuConfig( 285 null, 286 null, 287 FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false, 288 UncertainLatency() 289 ) 290} 291