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, VFAlu, VFMA, VFDivSqrt, VIAluFix, VIMacU, VPPU, VIPU, 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 piped if the $fu is pipelined 20 * @param maybeBlock the $fu need ready signal to block internal pipeline 21 * @param writeIntRf the $fu write int regfiles 22 * @param writeFpRf the $fu write float regfiles 23 * @param writeVecRf the $fu write vector regfiles 24 * @param writeFflags the $fu write fflags csr 25 * @param writeVxsat the $fu write vxsat csr 26 * @param dataBits the width of data in the $fu 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 piped : Boolean, 47 maybeBlock : Boolean = false, 48 writeIntRf : Boolean = false, 49 writeFpRf : Boolean = false, 50 writeVecRf : Boolean = false, 51 writeFflags : Boolean = false, 52 writeVxsat : Boolean = false, 53 dataBits : Int = 64, 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, vimac, vfpu, vppu, vfalu, vfma, vfdiv).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 override def toString: String = { 174 var str = s"${this.name}: " 175 if (vconfigWakeUp) str += s"vconfigIdx($vconfigIdx), " 176 if (maskWakeUp) str += s"maskSrcIdx($maskSrcIdx), " 177 str += s"latency($latency)" 178 str 179 } 180} 181 182object FuConfig { 183 val JmpCfg: FuConfig = FuConfig ( 184 name = "jmp", 185 fuType = FuType.jmp, 186 fuGen = (p: Parameters, cfg: FuConfig) => Module(new JumpUnit(cfg)(p)).suggestName("jmp"), 187 srcData = Seq( 188 Seq(IntData()), // jal 189 ), 190 piped = true, 191 writeIntRf = true, 192 immType = Set(SelImm.IMM_I, SelImm.IMM_UJ, SelImm.IMM_U), 193 ) 194 195 val BrhCfg: FuConfig = FuConfig ( 196 name = "brh", 197 fuType = FuType.brh, 198 fuGen = (p: Parameters, cfg: FuConfig) => Module(new BranchUnit(cfg)(p).suggestName("brh")), 199 srcData = Seq( 200 Seq(IntData(), IntData()), 201 ), 202 piped = true, 203 immType = Set(SelImm.IMM_SB), 204 ) 205 206 val I2fCfg: FuConfig = FuConfig ( 207 name = "i2f", 208 FuType.i2f, 209 fuGen = (p: Parameters, cfg: FuConfig) => Module(new IntToFP(cfg)(p).suggestName("i2f")), 210 srcData = Seq( 211 Seq(IntData()), 212 ), 213 piped = true, 214 writeFpRf = true, 215 writeFflags = true, 216 latency = CertainLatency(2), 217 needSrcFrm = true, 218 ) 219 220 val CsrCfg: FuConfig = FuConfig ( 221 name = "csr", 222 fuType = FuType.csr, 223 fuGen = (p: Parameters, cfg: FuConfig) => Module(new CSR(cfg)(p).suggestName("csr")), 224 srcData = Seq( 225 Seq(IntData()), 226 ), 227 piped = true, 228 writeIntRf = true, 229 exceptionOut = Seq(illegalInstr, breakPoint, ecallU, ecallS, ecallM), 230 flushPipe = true, 231 ) 232 233 val AluCfg: FuConfig = FuConfig ( 234 name = "alu", 235 fuType = FuType.alu, 236 fuGen = (p: Parameters, cfg: FuConfig) => Module(new Alu(cfg)(p).suggestName("Alu")), 237 srcData = Seq( 238 Seq(IntData(), IntData()), 239 ), 240 piped = true, 241 writeIntRf = true, 242 immType = Set(SelImm.IMM_I, SelImm.IMM_U), 243 ) 244 245 val MulCfg: FuConfig = FuConfig ( 246 name = "mul", 247 fuType = FuType.mul, 248 fuGen = (p: Parameters, cfg: FuConfig) => Module(new MulUnit(cfg)(p).suggestName("Mul")), 249 srcData = Seq( 250 Seq(IntData(), IntData()), 251 ), 252 piped = true, 253 writeIntRf = true, 254 latency = CertainLatency(2), 255 ) 256 257 val DivCfg: FuConfig = FuConfig ( 258 name = "div", 259 fuType = FuType.div, 260 fuGen = (p: Parameters, cfg: FuConfig) => Module(new DivUnit(cfg)(p).suggestName("Div")), 261 srcData = Seq( 262 Seq(IntData(), IntData()), 263 ), 264 piped = false, 265 writeIntRf = true, 266 latency = UncertainLatency(), 267 hasInputBuffer = (true, 4, true) 268 ) 269 270 val FenceCfg: FuConfig = FuConfig ( 271 name = "fence", 272 FuType.fence, 273 fuGen = (p: Parameters, cfg: FuConfig) => Module(new Fence(cfg)(p).suggestName("Fence")), 274 srcData = Seq( 275 Seq(IntData(), IntData()), 276 ), 277 piped = true, 278 latency = CertainLatency(0), 279 exceptionOut = Seq(illegalInstr), 280 flushPipe = true 281 ) 282 283 // Todo: split it to simple bitmap exu and complex bku 284 val BkuCfg: FuConfig = FuConfig ( 285 name = "bku", 286 fuType = FuType.bku, 287 fuGen = (p: Parameters, cfg: FuConfig) => Module(new Bku(cfg)(p).suggestName("Bku")), 288 srcData = Seq( 289 Seq(IntData(), IntData()), 290 ), 291 piped = true, 292 writeIntRf = true, 293 latency = CertainLatency(2), 294 ) 295 296 val VSetRvfWvfCfg: FuConfig = FuConfig( 297 name = "vsetrvfwvf", 298 fuType = FuType.vsetiwf, 299 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRvfWvf(cfg)(p).suggestName("VSetRvfWvf")), 300 srcData = Seq( 301 Seq(FpData(), FpData()), 302 ), 303 piped = true, 304 writeVecRf = true, 305 latency = CertainLatency(0), 306 immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI), 307 ) 308 309 val VSetRiWvfCfg: FuConfig = FuConfig( 310 name = "vsetriwvf", 311 fuType = FuType.vsetiwf, 312 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWvf(cfg)(p).suggestName("VSetRiWvf")), 313 srcData = Seq( 314 Seq(IntData(), IntData()), 315 ), 316 piped = true, 317 writeVecRf = true, 318 latency = CertainLatency(0), 319 immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI), 320 ) 321 322 val VSetRiWiCfg: FuConfig = FuConfig( 323 name = "vsetriwi", 324 fuType = FuType.vsetiwi, 325 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWi(cfg)(p).suggestName("VSetRiWi")), 326 srcData = Seq( 327 Seq(IntData(), IntData()), 328 ), 329 piped = true, 330 writeIntRf = true, 331 latency = CertainLatency(0), 332 immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI), 333 ) 334 335 val FmacCfg: FuConfig = FuConfig ( 336 name = "fmac", 337 fuType = FuType.fmac, 338 fuGen = (p: Parameters, cfg: FuConfig) => Module(new FMA(cfg)(p).suggestName("FMac")), 339 srcData = Seq( 340 Seq(FpData(), FpData()), 341 Seq(FpData(), FpData(), FpData()), 342 ), 343 piped = false, 344 writeFpRf = true, 345 writeFflags = true, 346 latency = UncertainLatency(), 347 needSrcFrm = true, 348 ) 349 350 val F2iCfg: FuConfig = FuConfig ( 351 name = "f2i", 352 fuType = FuType.fmisc, 353 fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToInt(cfg)(p).suggestName("F2i")), 354 srcData = Seq( 355 Seq(FpData(), FpData()), 356 Seq(FpData()), 357 ), 358 piped = true, 359 writeIntRf = true, 360 writeFflags = true, 361 latency = CertainLatency(2), 362 needSrcFrm = true, 363 ) 364 365 val F2fCfg: FuConfig = FuConfig ( 366 name = "f2f", 367 fuType = FuType.fmisc, 368 fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToFP(cfg)(p).suggestName("F2f")), 369 srcData = Seq( 370 Seq(FpData(), FpData()), 371 Seq(FpData()), 372 ), 373 piped = true, 374 writeFpRf = true, 375 writeFflags = true, 376 latency = CertainLatency(2), 377 needSrcFrm = true, 378 ) 379 380 val FDivSqrtCfg: FuConfig = FuConfig ( 381 name = "fDivSqrt", 382 fuType = FuType.fDivSqrt, 383 fuGen = (p: Parameters, cfg: FuConfig) => Module(new FDivSqrt(cfg)(p).suggestName("FDivSqrt")), 384 srcData = Seq( 385 Seq(FpData(), FpData()), 386 ), 387 piped = false, 388 writeFpRf = true, 389 writeFflags = true, 390 latency = UncertainLatency(), 391 hasInputBuffer = (true, 8, true), 392 needSrcFrm = true, 393 ) 394 395 val LduCfg: FuConfig = FuConfig ( 396 name = "ldu", 397 fuType = FuType.ldu, 398 fuGen = null, // Todo 399 srcData = Seq( 400 Seq(IntData()), 401 ), 402 piped = false, // Todo: check it 403 writeIntRf = true, 404 writeFpRf = true, 405 latency = UncertainLatency(), 406 exceptionOut = Seq(loadAddrMisaligned, loadAccessFault, loadPageFault), 407 flushPipe = true, 408 replayInst = true, 409 hasLoadError = true, 410 immType = Set(SelImm.IMM_I), 411 ) 412 413 val StaCfg: FuConfig = FuConfig ( 414 name = "sta", 415 fuType = FuType.stu, 416 fuGen = null, // Todo 417 srcData = Seq( 418 Seq(IntData()), 419 ), 420 piped = false, 421 latency = UncertainLatency(), 422 exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault), 423 immType = Set(SelImm.IMM_S), 424 ) 425 426 val StdCfg: FuConfig = FuConfig ( 427 name = "std", 428 fuType = FuType.stu, 429 fuGen = (p: Parameters, cfg: FuConfig) => Module(new Std(cfg)(p).suggestName("Std")), 430 srcData = Seq( 431 Seq(IntData()), 432 Seq(FpData()), 433 ), 434 piped = true, 435 latency = CertainLatency(0), 436 exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault) 437 ) 438 439 val MouCfg: FuConfig = FuConfig ( 440 name = "mou", 441 fuType = FuType.mou, 442 fuGen = null, // Todo 443 srcData = Seq( 444 Seq(IntData()), 445 ), 446 piped = false, // Todo: check it 447 writeIntRf = true, 448 latency = UncertainLatency(), 449 exceptionOut = (LduCfg.exceptionOut ++ StaCfg.exceptionOut ++ StdCfg.exceptionOut).distinct 450 ) 451 452 val MoudCfg: FuConfig = FuConfig ( 453 name = "moud", 454 fuType = FuType.mou, 455 fuGen = null, // Todo 456 srcData = Seq( 457 Seq(IntData()), 458 ), 459 piped = true, 460 latency = CertainLatency(0), 461 ) 462 463 val VialuCfg = FuConfig ( 464 name = "vialuFix", 465 fuType = FuType.vialuF, 466 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VIAluFix(cfg)(p).suggestName("VialuFix")), 467 srcData = Seq( 468 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0, vtype&vl 469 ), 470 piped = true, 471 writeVecRf = true, 472 writeVxsat = true, 473 latency = CertainLatency(1), 474 vconfigWakeUp = true, 475 maskWakeUp = true, 476 dataBits = 128, 477 immType = Set(SelImm.IMM_OPIVIU, SelImm.IMM_OPIVIS), 478 ) 479 480 val VimacCfg = FuConfig ( 481 name = "vimac", 482 fuType = FuType.vimac, 483 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VIMacU(cfg)(p).suggestName("Vimac")), 484 srcData = Seq( 485 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0, vtype&vl 486 ), 487 piped = true, 488 writeVecRf = true, 489 writeVxsat = true, 490 latency = CertainLatency(2), 491 vconfigWakeUp = true, 492 maskWakeUp = true, 493 dataBits = 128, 494 ) 495 496 val VppuCfg = FuConfig ( 497 name = "vppu", 498 fuType = FuType.vppu, 499 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VPPU(cfg)(p).suggestName("Vppu")), 500 srcData = Seq( 501 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0, vtype&vl 502 ), 503 piped = true, 504 writeVecRf = true, 505 writeVxsat = true, 506 latency = CertainLatency(1), 507 vconfigWakeUp = true, 508 maskWakeUp = true, 509 dataBits = 128, 510 immType = Set(SelImm.IMM_OPIVIU, SelImm.IMM_OPIVIS), 511 ) 512 513 val VipuCfg: FuConfig = FuConfig ( 514 name = "vipu", 515 fuType = FuType.vipu, 516 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VIPU(cfg)(p).suggestName("Vipu")), 517 srcData = Seq( 518 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0 519 ), 520 piped = true, 521 writeVecRf = true, 522 latency = CertainLatency(1), 523 vconfigWakeUp = true, 524 maskWakeUp = true, 525 dataBits = 128, 526 ) 527 528 val VfaluCfg = FuConfig ( 529 name = "vfalu", 530 fuType = FuType.vfalu, 531 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VFAlu(cfg)(p).suggestName("Vfalu")), 532 srcData = Seq( 533 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0, vtype&vl 534 ), 535 piped = true, 536 writeVecRf = true, 537 writeFflags = true, 538 latency = CertainLatency(1), 539 vconfigWakeUp = true, 540 maskWakeUp = true, 541 dataBits = 128, 542 ) 543 544 val VfmaCfg = FuConfig ( 545 name = "vfma", 546 fuType = FuType.vfma, 547 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VFMA(cfg)(p).suggestName("Vfma")), 548 srcData = Seq( 549 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0, vtype&vl 550 ), 551 piped = true, 552 writeVecRf = true, 553 writeFflags = true, 554 latency = CertainLatency(3), 555 vconfigWakeUp = true, 556 maskWakeUp = true, 557 dataBits = 128, 558 ) 559 560 val VfdivCfg = FuConfig( 561 name = "vfdiv", 562 fuType = FuType.vfdiv, 563 fuGen = (p: Parameters, cfg: FuConfig) => Module(new VFDivSqrt(cfg)(p).suggestName("Vfdiv")), 564 srcData = Seq( 565 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0, vtype&vl 566 ), 567 piped = false, 568 writeVecRf = true, 569 writeFflags = true, 570 latency = UncertainLatency(), 571 vconfigWakeUp = true, 572 maskWakeUp = true, 573 dataBits = 128, 574 ) 575 576 val VlduCfg: FuConfig = FuConfig ( 577 name = "vldu", 578 fuType = FuType.vldu, 579 fuGen = null, 580 srcData = Seq( 581 Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), //vs1, vs2, vd_old, v0, vconfig 582 ), 583 piped = false, // Todo: check it 584 writeVecRf = true, 585 latency = UncertainLatency(), 586 exceptionOut = Seq(loadAddrMisaligned, loadAccessFault, loadPageFault), 587 flushPipe = true, 588 replayInst = true, 589 hasLoadError = true, 590 vconfigWakeUp = true, 591 maskWakeUp = true, 592 dataBits = 128, 593 ) 594 //TODO 595 // def VstuCfg = FuConfig () 596 597 def allConfigs = Seq( 598 JmpCfg, BrhCfg, I2fCfg, CsrCfg, AluCfg, MulCfg, DivCfg, FenceCfg, BkuCfg, VSetRvfWvfCfg, VSetRiWvfCfg, VSetRiWiCfg, 599 FmacCfg, F2iCfg, F2fCfg, FDivSqrtCfg, LduCfg, StaCfg, StdCfg, MouCfg, MoudCfg, VialuCfg, VipuCfg, VlduCfg, 600 VfaluCfg, VfmaCfg 601 ) 602 603 def VecArithFuConfigs = Seq( 604 VialuCfg, VimacCfg, VppuCfg, VipuCfg, VfaluCfg, VfmaCfg 605 ) 606} 607 608