1package xiangshan.backend.fu 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import xiangshan.ExceptionNO._ 6import xiangshan.SelImm 7import xiangshan.backend.Std 8import xiangshan.backend.fu.fpu.{FDivSqrt, FMA, FPToFP, FPToInt, IntToFP} 9import xiangshan.backend.fu.wrapper.{Alu, BranchUnit, DivUnit, JumpUnit, MulUnit, VSetRiWi, VSetRiWvf, VSetRvfWvf} 10import xiangshan.backend.Bundles.ExuInput 11import xiangshan.backend.datapath.DataConfig._ 12 13/** 14 * 15 * @param name [[String]] name of fuConfig 16 * @param fuType [[Int]] type of func, select from [[xiangshan.backend.fu.FuType]] 17 * @param fuGen how to create $fu 18 * @param srcData type of src data used by this $fu 19 * @param maybeBlock the $fu need ready signal to block internal pipeline 20 * @param writeIntRf the $fu write int regfiles 21 * @param writeFpRf the $fu write float regfiles 22 * @param writeVecRf the $fu write vector regfiles 23 * @param writeFflags the $fu write fflags csr 24 * @param writeVxsat the $fu write vxsat csr 25 * @param dataBits the width of data in the $fu 26 * @param piped if the $fu is pipelined 27 * @param latency the latency of instuction executed in the $fu 28 * @param hasInputBuffer if the $fu has input buffer 29 * @param exceptionOut the $fu can produce these exception 30 * @param hasLoadError if the $fu has load error out 31 * @param flushPipe if the instuction executed in the $fu need flush out 32 * @param replayInst if the instuction executed in the $fu can replay in some condition 33 * @param trigger if the $fu need trigger out 34 * @param needSrcFrm if the $fu need float rounding mode signal 35 * @param immType the immediate type of this $fu 36 * @param vconfigWakeUp 37 * @param maskWakeUp 38 * 39 * @define fu function unit 40 */ 41case class FuConfig ( 42 name : String, 43 fuType : Int, 44 fuGen : (Parameters, FuConfig) => FuncUnit, 45 srcData : Seq[Seq[DataConfig]], 46 maybeBlock : Boolean = false, 47 writeIntRf : Boolean = false, 48 writeFpRf : Boolean = false, 49 writeVecRf : Boolean = false, 50 writeFflags : Boolean = false, 51 writeVxsat : Boolean = false, 52 dataBits : Int = 64, 53 piped : Boolean = false, 54 latency : HasFuLatency = CertainLatency(0), 55 hasInputBuffer: (Boolean, Int, Boolean) = (false, 0, false), 56 exceptionOut : Seq[Int] = Seq(), 57 hasLoadError : Boolean = false, 58 flushPipe : Boolean = false, 59 replayInst : Boolean = false, 60 trigger : Boolean = false, 61 needSrcFrm : Boolean = false, 62 immType : Set[UInt] = Set(), 63 // vector 64 vconfigWakeUp : Boolean = false, 65 maskWakeUp : Boolean = false, 66) { 67 var vconfigIdx = -1 68 var maskSrcIdx = -1 69 if (vconfigWakeUp) { 70 vconfigIdx = getSpecialSrcIdx(VConfigData(), "when vconfigWakeUp is true, srcData must always contains VConfigData()") 71 } 72 if (maskWakeUp) { 73 maskSrcIdx = getSpecialSrcIdx(MaskSrcData(), "when maskWakeUp is true, srcData must always contains MaskSrcData()") 74 } 75 76 require(!piped || piped && latency.latencyVal.isDefined, "The latency value must be set when piped is enable") 77 require(!vconfigWakeUp || vconfigWakeUp && vconfigIdx >= 0, "The index of vl src must be set when vlWakeUp is enable") 78 require(!maskWakeUp || maskWakeUp && maskSrcIdx >= 0, "The index of mask src must be set when vlWakeUp is enable") 79 80 def numIntSrc : Int = srcData.map(_.count(x => IntRegSrcDataSet.contains(x))).max 81 def numFpSrc : Int = srcData.map(_.count(x => FpRegSrcDataSet.contains(x))).max 82 def numVecSrc : Int = srcData.map(_.count(x => VecRegSrcDataSet.contains(x))).max 83 def numVfSrc : Int = srcData.map(_.count(x => VfRegSrcDataSet.contains(x))).max 84 def numRegSrc : Int = srcData.map(_.count(x => RegSrcDataSet.contains(x))).max 85 def numSrc : Int = srcData.map(_.length).max 86 87 def readFp: Boolean = numFpSrc > 0 88 89 def fuSel(uop: ExuInput): Bool = { 90 // Don't add more shit here!!! 91 // Todo: add new FuType to distinguish f2i, f2f 92 if (this.fuType == FuType.fmisc) { 93 this.name match { 94 case FuConfig.F2iCfg.name => uop.rfWen.get 95 case FuConfig.F2fCfg.name => uop.fpu.get.fpWen && !uop.fpu.get.div && !uop.fpu.get.sqrt 96 } 97 } else { 98 uop.fuType === this.fuType.U 99 } 100 } 101 102 /** 103 * params(i): data type set of the ith src port 104 * @return 105 */ 106 def getRfReadDataCfgSet: Seq[Set[DataConfig]] = { 107 val numSrcMax = srcData.map(_.length).max 108 // make srcData is uniform sized to avoid exception when transpose 109 val alignedSrcData: Seq[Seq[DataConfig]] = srcData.map(x => x ++ Seq.fill(numSrcMax - x.length)(null)) 110 alignedSrcData.transpose.map(_.toSet.intersect(RegSrcDataSet)) 111 } 112 113 def getSrcDataType(srcIdx: Int): Set[DataConfig] = { 114 srcData 115 .map((x: Seq[DataConfig]) => if(x.isDefinedAt(srcIdx)) Some(x(srcIdx)) else None) 116 .filter(_.nonEmpty) 117 .map(_.get) 118 .toSet 119 } 120 121 def hasNoDataWB: Boolean = { 122 !(writeIntRf || writeFpRf || writeVecRf) 123 } 124 125 def getSrcMaxWidthVec = { 126 getRfReadDataCfgSet.map(_.map(_.dataWidth).max) 127 } 128 129 def genSrcDataVec: Seq[UInt] = { 130 getSrcMaxWidthVec.map(w => UInt(w.W)) 131 } 132 133 // csr's redirect is in its exception bundle 134 def hasRedirect: Boolean = Seq(FuType.jmp, FuType.brh).contains(fuType) 135 136 def hasPredecode: Boolean = Seq(FuType.jmp, FuType.brh, FuType.csr).contains(fuType) 137 138 def needPc: Boolean = Seq(FuType.jmp, FuType.brh, FuType.csr, FuType.fence).contains(fuType) 139 140 def needFPUCtrl: Boolean = { 141 import FuType._ 142 Set(fmac, fDivSqrt, fmisc, i2f).contains(fuType) 143 } 144 145 def needVecCtrl: Boolean = { 146 import FuType._ 147 Set(vipu, vialuF, vfpu, vppu).contains(fuType) 148 } 149 150 def isMul: Boolean = fuType == FuType.mul 151 152 def isDiv: Boolean = fuType == FuType.div 153 154 def isCsr: Boolean = fuType == FuType.csr 155 156 def isFence: Boolean = fuType == FuType.fence 157 158 /** 159 * Get index of special src data, like [[VConfigData]], [[MaskSrcData]] 160 * @param data [[DataConfig]] 161 * @param tips tips if get failed 162 * @return the index of special src data 163 */ 164 protected def getSpecialSrcIdx(data: DataConfig, tips: String): Int = { 165 val srcIdxVec = srcData.map(x => x.indexOf(data)) 166 val idx0 = srcIdxVec.head 167 for (idx <- srcIdxVec) { 168 require(idx >= 0 && idx == idx0, tips + ", and at the same index.") 169 } 170 idx0 171 } 172} 173 174object FuConfig { 175 val JmpCfg: FuConfig = FuConfig ( 176 name = "jmp", 177 fuType = FuType.jmp, 178 fuGen = (p: Parameters, cfg: FuConfig) => Module(new JumpUnit(cfg)(p)).suggestName("jmp"), 179 srcData = Seq( 180 Seq(IntData()), // jal 181 ), 182 writeIntRf = true, 183 writeFpRf = false, 184 immType = Set(SelImm.IMM_I, SelImm.IMM_UJ, SelImm.IMM_U), 185 ) 186 187 val BrhCfg: FuConfig = FuConfig ( 188 name = "brh", 189 fuType = FuType.brh, 190 fuGen = (p: Parameters, cfg: FuConfig) => Module(new BranchUnit(cfg)(p).suggestName("brh")), 191 srcData = Seq( 192 Seq(IntData(), IntData()), 193 ), 194 writeIntRf = false, 195 writeFpRf = false, 196 immType = Set(SelImm.IMM_SB), 197 ) 198 199 val I2fCfg: FuConfig = FuConfig ( 200 name = "i2f", 201 FuType.i2f, 202 fuGen = (p: Parameters, cfg: FuConfig) => Module(new IntToFP(cfg)(p).suggestName("i2f")), 203 srcData = Seq( 204 Seq(IntData()), 205 ), 206 writeIntRf = false, 207 writeFpRf = true, 208 writeFflags = true, 209 latency = CertainLatency(2), 210 needSrcFrm = true, 211 ) 212 213 val CsrCfg: FuConfig = FuConfig ( 214 name = "csr", 215 fuType = FuType.csr, 216 fuGen = (p: Parameters, cfg: FuConfig) => Module(new CSR(cfg)(p).suggestName("csr")), 217 srcData = Seq( 218 Seq(IntData()), 219 ), 220 writeIntRf = true, 221 writeFpRf = false, 222 exceptionOut = Seq(illegalInstr, breakPoint, ecallU, ecallS, ecallM), 223 flushPipe = true 224 ) 225 226 val AluCfg: FuConfig = FuConfig ( 227 name = "alu", 228 fuType = FuType.alu, 229 fuGen = (p: Parameters, cfg: FuConfig) => Module(new Alu(cfg)(p).suggestName("Alu")), 230 srcData = Seq( 231 Seq(IntData(), IntData()), 232 ), 233 writeIntRf = true, 234 writeFpRf = false, 235 immType = Set(SelImm.IMM_I, SelImm.IMM_U), 236 ) 237 238 val MulCfg: FuConfig = FuConfig ( 239 name = "mul", 240 fuType = FuType.mul, 241 fuGen = (p: Parameters, cfg: FuConfig) => Module(new MulUnit(cfg)(p).suggestName("Mul")), 242 srcData = Seq( 243 Seq(IntData(), IntData()), 244 ), 245 writeIntRf = true, 246 writeFpRf = false, 247 latency = CertainLatency(2), 248 ) 249 250 val DivCfg: FuConfig = FuConfig ( 251 name = "div", 252 fuType = FuType.div, 253 fuGen = (p: Parameters, cfg: FuConfig) => Module(new DivUnit(cfg)(p).suggestName("Div")), 254 srcData = Seq( 255 Seq(IntData(), IntData()), 256 ), 257 writeIntRf = true, 258 writeFpRf = false, 259 latency = UncertainLatency(), 260 hasInputBuffer = (true, 4, true) 261 ) 262 263 val FenceCfg: FuConfig = FuConfig ( 264 name = "fence", 265 FuType.fence, 266 fuGen = (p: Parameters, cfg: FuConfig) => Module(new Fence(cfg)(p).suggestName("Fence")), 267 srcData = Seq( 268 Seq(IntData(), IntData()), 269 ), 270 writeIntRf = false, 271 writeFpRf = false, 272 latency = UncertainLatency(), 273 exceptionOut = Seq(illegalInstr), 274 flushPipe = true 275 ) 276 277 // Todo: split it to simple bitmap exu and complex bku 278 val BkuCfg: FuConfig = FuConfig ( 279 name = "bku", 280 fuType = FuType.bku, 281 fuGen = (p: Parameters, cfg: FuConfig) => Module(new Bku(cfg)(p).suggestName("Bku")), 282 srcData = Seq( 283 Seq(IntData(), IntData()), 284 ), 285 writeIntRf = true, 286 writeFpRf = false, 287 latency = CertainLatency(1), 288 ) 289 290 val VSetRvfWvfCfg: FuConfig = FuConfig( 291 name = "vsetrvfwvf", 292 fuType = FuType.vsetiwf, 293 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRvfWvf(cfg)(p).suggestName("VSetRvfWvf")), 294 srcData = Seq( 295 Seq(FpData(), FpData()), 296 ), 297 writeIntRf = false, 298 writeFpRf = false, 299 writeVecRf = true, 300 latency = CertainLatency(0), 301 immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI), 302 ) 303 304 val VSetRiWvfCfg: FuConfig = FuConfig( 305 name = "vsetriwvf", 306 fuType = FuType.vsetiwf, 307 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWvf(cfg)(p).suggestName("VSetRiWvf")), 308 srcData = Seq( 309 Seq(IntData(), IntData()), 310 ), 311 writeIntRf = false, 312 writeFpRf = false, 313 writeVecRf = true, 314 latency = CertainLatency(0), 315 immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI), 316 ) 317 318 val VSetRiWiCfg: FuConfig = FuConfig( 319 name = "vsetriwi", 320 fuType = FuType.vsetiwi, 321 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWi(cfg)(p).suggestName("VSetRiWi")), 322 srcData = Seq( 323 Seq(IntData(), IntData()), 324 ), 325 writeIntRf = true, 326 writeFpRf = false, 327 latency = CertainLatency(0), 328 immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI), 329 ) 330 331 val FmacCfg: FuConfig = FuConfig ( 332 name = "fmac", 333 fuType = FuType.fmac, 334 fuGen = (p: Parameters, cfg: FuConfig) => Module(new FMA(cfg)(p).suggestName("FMac")), 335 srcData = Seq( 336 Seq(FpData(), FpData()), 337 Seq(FpData(), FpData(), FpData()), 338 ), 339 writeIntRf = false, 340 writeFpRf = true, 341 writeFflags = true, 342 latency = UncertainLatency(), 343 needSrcFrm = true, 344 ) 345 346 val F2iCfg: FuConfig = FuConfig ( 347 name = "f2i", 348 fuType = FuType.fmisc, 349 fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToInt(cfg)(p).suggestName("F2i")), 350 srcData = Seq( 351 Seq(FpData(), FpData()), 352 Seq(FpData()), 353 ), 354 writeIntRf = true, 355 writeFpRf = false, 356 writeFflags = true, 357 latency = CertainLatency(2), 358 needSrcFrm = true, 359 ) 360 361 val F2fCfg: FuConfig = FuConfig ( 362 name = "f2f", 363 fuType = FuType.fmisc, 364 fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToFP(cfg)(p).suggestName("F2f")), 365 srcData = Seq( 366 Seq(FpData(), FpData()), 367 Seq(FpData()), 368 ), 369 writeIntRf = false, 370 writeFpRf = true, 371 writeFflags = true, 372 latency = CertainLatency(2), 373 needSrcFrm = true, 374 ) 375 376 val FDivSqrtCfg: FuConfig = FuConfig ( 377 name = "fDivSqrt", 378 fuType = FuType.fDivSqrt, 379 fuGen = (p: Parameters, cfg: FuConfig) => Module(new FDivSqrt(cfg)(p).suggestName("FDivSqrt")), 380 srcData = Seq( 381 Seq(FpData(), FpData()), 382 ), 383 writeIntRf = false, 384 writeFpRf = true, 385 writeFflags = true, 386 latency = UncertainLatency(), 387 hasInputBuffer = (true, 8, true), 388 needSrcFrm = true, 389 ) 390 391 val LduCfg: FuConfig = FuConfig ( 392 name = "ldu", 393 fuType = FuType.ldu, 394 fuGen = null, // Todo 395 srcData = Seq( 396 Seq(IntData()), 397 ), 398 writeIntRf = true, 399 writeFpRf = true, 400 latency = UncertainLatency(), 401 exceptionOut = Seq(loadAddrMisaligned, loadAccessFault, loadPageFault), 402 flushPipe = true, 403 replayInst = true, 404 hasLoadError = true, 405 immType = Set(SelImm.IMM_I), 406 ) 407 408 val StaCfg: FuConfig = FuConfig ( 409 name = "sta", 410 fuType = FuType.stu, 411 fuGen = null, // Todo 412 srcData = Seq( 413 Seq(IntData()), 414 ), 415 writeIntRf = false, 416 writeFpRf = false, 417 latency = UncertainLatency(), 418 exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault), 419 immType = Set(SelImm.IMM_S), 420 ) 421 422 val StdCfg: FuConfig = FuConfig ( 423 name = "std", 424 fuType = FuType.stu, 425 fuGen = (p: Parameters, cfg: FuConfig) => Module(new Std(cfg)(p).suggestName("Std")), 426 srcData = Seq( 427 Seq(IntData()), 428 Seq(FpData()), 429 ), 430 writeIntRf = false, 431 writeFpRf = false, 432 latency = CertainLatency(1), 433 exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault) 434 ) 435 436 val MouCfg: FuConfig = FuConfig ( 437 name = "mou", 438 fuType = FuType.mou, 439 fuGen = null, // Todo 440 srcData = Seq( 441 Seq(IntData()), 442 ), 443 writeIntRf = true, 444 writeFpRf = false, 445 latency = UncertainLatency(), 446 exceptionOut = (LduCfg.exceptionOut ++ StaCfg.exceptionOut ++ StdCfg.exceptionOut).distinct 447 ) 448 449 val MoudCfg: FuConfig = FuConfig ( 450 name = "moud", 451 fuType = FuType.mou, 452 fuGen = null, // Todo 453 srcData = Seq( 454 Seq(IntData()), 455 ), 456 writeIntRf = false, 457 writeFpRf = false, 458 latency = UncertainLatency() 459 ) 460 461 val VialuCfg = FuConfig ( 462 name = "vialu", 463 fuType = FuType.vialuF, 464 fuGen = null, 465 srcData = Seq( 466 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0, vtype&vl 467 ), 468 writeVecRf = true, 469 latency = CertainLatency(1), 470 ) 471 472 val VipuCfg: FuConfig = FuConfig ( 473 name = "vipu", 474 fuType = FuType.vipu, 475 fuGen = null, // Todo 476 srcData = Seq( 477 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0 478 ), 479 writeIntRf = false, 480 writeFpRf = false, 481 writeVecRf = true, 482 latency = UncertainLatency(), 483 ) 484 485 val VfpuCfg: FuConfig = FuConfig ( 486 name = "vfpu", 487 fuType = FuType.vfpu, 488 fuGen = null, // Todo 489 srcData = Seq( 490 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0 491 Seq(FpData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // f[rs1], vs2, vd_old, v0 492 ), 493 writeIntRf = false, 494 writeFpRf = false, 495 writeVecRf = true, 496 latency = UncertainLatency(), 497 ) 498 // Todo 499 // def VlduCfg = FuConfig () 500 // def VstuCfg = FuConfig () 501 502} 503 504