From e8f5bab17e6d61c05b48bc5f0ac2bce6b3bf64af Mon Sep 17 00:00:00 2001 From: Zhongdi LUO Date: Mon, 13 Jul 2026 07:20:42 +0000 Subject: [PATCH] feat: add 4-lane NVIDIA-style configurations --- radiance.mk | 8 +++---- src/main/resources/vsrc/vortex | 2 +- .../radiance/core/TensorCoreDecoupled.scala | 22 +++++++++++++++---- .../scala/radiance/tile/RadianceTile.scala | 17 +++++++------- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/radiance.mk b/radiance.mk index bd84102..11bbf42 100644 --- a/radiance.mk +++ b/radiance.mk @@ -17,14 +17,14 @@ RADIANCE_VSRC_DIR = $(base_dir)/generators/radiance/src/main/resources/vsrc ifeq ($(shell echo $(CONFIG) | grep -E "SynConfig$$"),$(CONFIG)) EXTRA_SIM_PREPROC_DEFINES += +define+SYNTHESIS +define+NDEBUG +define+DPI_DISABLE endif -ifeq ($(shell echo $(CONFIG) | grep -E "FP16Config$$"),$(CONFIG)) - EXTRA_SIM_PREPROC_DEFINES += +define+NUM_CORES=8 +ifeq ($(shell echo $(CONFIG) | grep -E "(FP16|Volta|Ampere)Config$$"),$(CONFIG)) + EXTRA_SIM_PREPROC_DEFINES += +define+NUM_CORES=1 endif ifeq ($(shell echo $(CONFIG) | grep -E "HopperConfig$$"),$(CONFIG)) - EXTRA_SIM_PREPROC_DEFINES += +define+NUM_CORES=4 +define+EXT_T_HOPPER + EXTRA_SIM_PREPROC_DEFINES += +define+NUM_CORES=1 +define+EXT_T_HOPPER endif ifeq ($(shell echo $(CONFIG) | grep -E "BlackwellConfig$$"),$(CONFIG)) - EXTRA_SIM_PREPROC_DEFINES += +define+NUM_CORES=4 +define+EXT_T_BLACKWELL + EXTRA_SIM_PREPROC_DEFINES += +define+NUM_CORES=1 +define+EXT_T_BLACKWELL endif ifeq ($(shell echo $(CONFIG) | grep -E "FlashConfig$$"),$(CONFIG)) EXTRA_SIM_PREPROC_DEFINES += +define+NUM_CORES=4 diff --git a/src/main/resources/vsrc/vortex b/src/main/resources/vsrc/vortex index 9560f9c..fb56e62 160000 --- a/src/main/resources/vsrc/vortex +++ b/src/main/resources/vsrc/vortex @@ -1 +1 @@ -Subproject commit 9560f9cab6294c55a4127404645715dec40d3ff5 +Subproject commit fb56e625bb8dcf5397727d6789b10cc28644677b diff --git a/src/main/scala/radiance/core/TensorCoreDecoupled.scala b/src/main/scala/radiance/core/TensorCoreDecoupled.scala index dcaa9f9..0610706 100644 --- a/src/main/scala/radiance/core/TensorCoreDecoupled.scala +++ b/src/main/scala/radiance/core/TensorCoreDecoupled.scala @@ -47,8 +47,16 @@ class TensorCoreDecoupled( val numSourceIds: Int = 16, val numFPRegs: Int = 32 ) extends Module { + require(numLanes == 4 || numLanes == 8, + s"Hopper tensor core supports 4 or 8 lanes, got ${numLanes}") val tilingParams = - if (half) TensorTilingParams.fp16 else TensorTilingParams.fp32 + if (half && numLanes == 4) { + TensorTilingParams(m = 16, n = 16, k = 32, mc = 4, nc = 2, kc = 8) + } else if (half) { + TensorTilingParams.fp16 + } else { + TensorTilingParams.fp32 + } val numWarpBits = log2Ceil(numWarps) val wordSize = if (half) 2 else 4 val wordSizeInBits = wordSize * 8/*bits*/ @@ -127,7 +135,8 @@ class TensorCoreDecoupled( // or [0,n/2), where 2 is the stride can be read in a single request size. require(tilingParams.m == tilingParams.n, "currently only supports square SMEM tile") - val numIndices = tilingParams.m / 2/*FIXME:hardcoded?*/ + val fragmentBytes = memWidth / 8 + val numIndices = (tilingParams.m * tilingParams.kc * wordSize) / fragmentBytes val indexBits = log2Ceil(numIndices) val lastIndex = (1 << indexBits) - 1 @@ -345,8 +354,10 @@ class TensorCoreDecoupled( // serialize every two B responses into one full 4x4 B tile // FIXME: do the same for A + val numBFragmentsPerTile = + (tilingParams.nc * tilingParams.kc * wordSize) / fragmentBytes val fullB = Module(new FillBuffer( - chiselTypeOf(respQueueB.bits.data), 2/*substeps*/ + chiselTypeOf(respQueueB.bits.data), numBFragmentsPerTile )) fullB.io.enq.valid := respQueueB.valid fullB.io.enq.bits := respQueueB.bits.data @@ -524,10 +535,13 @@ class TensorCoreDecoupled( // select the correct 4x4 tile from A operand buffer val numTilesM = tilingParams.m / tilingParams.mc val numTilesMBits = log2Ceil(numTilesM) + val numAFragmentsPerTile = + (tilingParams.mc * tilingParams.kc * wordSize) / fragmentBytes def selectOperandA(buf: Vec[UInt]): UInt = { require(buf.length == numIndices) val stepM = stepCompute & ((1 << numTilesMBits) - 1).U - Cat(buf((stepM << 1) + 1.U), buf(stepM << 1)) + val base = stepM * numAFragmentsPerTile.U + Cat((0 until numAFragmentsPerTile).reverse.map(i => buf(base + i.U))) } val operandA = selectOperandA(fullABuf.io.deq.bits.data) val operandATag = fullABuf.io.deq.bits.tag diff --git a/src/main/scala/radiance/tile/RadianceTile.scala b/src/main/scala/radiance/tile/RadianceTile.scala index 2c02ce2..2c22419 100644 --- a/src/main/scala/radiance/tile/RadianceTile.scala +++ b/src/main/scala/radiance/tile/RadianceTile.scala @@ -764,13 +764,14 @@ class RadianceTileModuleImp(outer: RadianceTile) } def connectTensor = { + core.io.tc_tmem_C_rdata := DontCare if (outer.radianceParams.core.tensorCoreDecoupled) { val tcb0 = new { val addr = core.io.tc_a_bits_address(31, 0) val tag = core.io.tc_a_bits_tag(outer.tensorTagWidth - 1, 0) val write = core.io.tc_a_bits_write(0) - val mask = core.io.tc_a_bits_mask(31, 0) - val data = core.io.tc_a_bits_data(255, 0) + val mask = core.io.tc_a_bits_mask(outer.tcSmemSize - 1, 0) + val data = core.io.tc_a_bits_data(outer.tcSmemSize * 8 - 1, 0) val aValid = core.io.tc_a_valid(0) val dReady = core.io.tc_d_ready(0) } @@ -778,8 +779,8 @@ class RadianceTileModuleImp(outer: RadianceTile) val addr = core.io.tc_a_bits_address(63, 32) val tag = core.io.tc_a_bits_tag(4 + outer.tensorTagWidth - 1, 4) val write = core.io.tc_a_bits_write(1) - val mask = core.io.tc_a_bits_mask(63, 32) - val data = core.io.tc_a_bits_data(511, 256) + val mask = core.io.tc_a_bits_mask(2 * outer.tcSmemSize - 1, outer.tcSmemSize) + val data = core.io.tc_a_bits_data(2 * outer.tcSmemSize * 8 - 1, outer.tcSmemSize * 8) val aValid = core.io.tc_a_valid(1) val dReady = core.io.tc_d_ready(1) } @@ -789,8 +790,8 @@ class RadianceTileModuleImp(outer: RadianceTile) val adapter = Module( new VortexTLAdapter( outer.smemSourceWidth, - new VortexBundleA(tagWidth = outer.tensorTagWidth, dataWidth = 32 * 8), - new VortexBundleD(tagWidth = outer.tensorTagWidth, dataWidth = 32 * 8), + new VortexBundleA(tagWidth = outer.tensorTagWidth, dataWidth = outer.tcSmemSize * 8), + new VortexBundleD(tagWidth = outer.tensorTagWidth, dataWidth = outer.tcSmemSize * 8), client ) ) @@ -800,7 +801,7 @@ class RadianceTileModuleImp(outer: RadianceTile) adapter.io.inReq.valid := bundle.aValid adapter.io.inReq.bits.address := bundle.addr adapter.io.inReq.bits.source := bundle.tag - adapter.io.inReq.bits.size := 5.U // 256 bits + adapter.io.inReq.bits.size := log2Ceil(outer.tcSmemSize).U adapter.io.inReq.bits.opcode := Mux(bundle.write.asBool, TLMessages.PutFullData, TLMessages.Get) adapter.io.inReq.bits.mask := bundle.mask adapter.io.inReq.bits.data := bundle.data @@ -812,7 +813,7 @@ class RadianceTileModuleImp(outer: RadianceTile) } core.io.tc_a_ready := Cat(0.U(1.W), adapters.last.io.inReq.ready, adapters.head.io.inReq.ready) core.io.tc_d_valid := Cat(0.U(1.W), adapters.last.io.inResp.valid, adapters.head.io.inResp.valid) - core.io.tc_d_bits_data := Cat(0.U((32 * 8).W), adapters.last.io.inResp.bits.data, adapters.head.io.inResp.bits.data) + core.io.tc_d_bits_data := Cat(0.U((outer.tcSmemSize * 8).W), adapters.last.io.inResp.bits.data, adapters.head.io.inResp.bits.data) core.io.tc_d_bits_tag := Cat(0.U(outer.tensorTagWidth.W), adapters.last.io.inResp.bits.source, adapters.head.io.inResp.bits.source) require(core.io.tc_d_bits_data.widthOption.get == adapters.head.io.inResp.bits.data.widthOption.get * 3) require(core.io.tc_d_bits_tag.widthOption.get == adapters.head.io.inResp.bits.source.widthOption.get * 3)