Download code/tt_bevformer/tt/kernels/kin_rows.cpp from changh95/bevformer-p150: direct link, hf CLI and curl.
- Browser
- Download file 5.29 kB
-
https://huggingface.co/changh95/bevformer-p150/resolve/main/code/tt_bevformer/tt/kernels/kin_rows.cpp
- Command line
-
hf download hf://changh95/bevformer-p150/code/tt_bevformer/tt/kernels/kin_rows.cpp
-
curl -L -o kin_rows.cpp https://huggingface.co/changh95/bevformer-p150/resolve/main/code/tt_bevformer/tt/kernels/kin_rows.cpp
5.29 kB
| // SPDX-License-Identifier: Apache-2.0 | |
| // K-IN rows (bevformer-p150 OPT_PLAN R2-2): one camera of the uploaded bf16 image rows -> the height-sharded L1 | |
| // input of the 7x7 / stride-2 stem conv (ttnn's L1 conv path), replacing the device reshape of the image rows to | |
| // 6-byte pixel pages and the stem's 10 DRAM PaddedSlices. | |
| // | |
| // in : [1, 1, CAMS * H, W * C_IN] bf16 ROW_MAJOR, DRAM interleaved (one page per image row, ROW_BYTES = W * C_IN * 2) | |
| // out: [1, 1, H * W, C_IN] bf16 ROW_MAJOR, L1 HEIGHT_SHARDED, shard [S, C_PAD] (C_PAD = 8: 16-byte rows), camera | |
| // CAM's image rows ROW0 = CAM * H .. ROW0 + H - 1 | |
| // | |
| // Core k (row-major over a GX-wide grid at the origin; ROW_MAJOR shard orientation) owns pixels | |
| // [k * S, min((k + 1) * S, N)), split between SLOTS data-movement RISC-Vs (BRISC / NCRISC, each its own scratch CB). | |
| // Each reads the image rows that hold its pixels into its scratch CB (whole pages), then copies each pixel's C_IN | |
| // bf16 values and zeros in channels C_IN .. C_PAD - 1 straight into its own shard (local L1 stores; no NoC write). | |
| // The copy is exact (bits moved, no conversion). Data-movement only, no CB push / pop, no semaphores, no multicast; | |
| // every read waited on by noc_async_read_barrier before use. Runtime args: COMMON only [in_addr, out_addr] (P3). | |
| constexpr uint32_t N = get_compile_time_arg_val(0); // pixels of one camera (H * W) | |
| constexpr uint32_t S = get_compile_time_arg_val(1); // shard rows (pixels per core) | |
| constexpr uint32_t W = get_compile_time_arg_val(2); // pixels per image row | |
| constexpr uint32_t C_IN = get_compile_time_arg_val(3); // channels (3) | |
| constexpr uint32_t C_PAD = get_compile_time_arg_val(4); // shard width in elements (8: 16 B rows) | |
| constexpr uint32_t NUM_CORES = get_compile_time_arg_val(5); // cores holding shards | |
| constexpr uint32_t GX = get_compile_time_arg_val(6); // grid width (cores) | |
| constexpr uint32_t CB_SCRATCH = get_compile_time_arg_val(7); // scratch CB: MAX_ROWS image rows | |
| constexpr uint32_t MAX_ROWS = get_compile_time_arg_val(8); // rows a slot's pixels can touch | |
| constexpr uint32_t SLOTS = get_compile_time_arg_val(9); // RISC-Vs sharing a core's shard (1 or 2) | |
| constexpr uint32_t SLOT = get_compile_time_arg_val(10); // this kernel's slot: pixels [SLOT * S / SLOTS, ...) | |
| constexpr uint32_t ROW0 = get_compile_time_arg_val(11); // first image row of the camera in the input | |
| constexpr auto in_args = TensorAccessorArgs<12>(); | |
| constexpr uint32_t ROW_BYTES = W * C_IN * 2; | |
| static_assert(C_IN == 3 && C_PAD == 8, "the copy loop handles 3 channels into 16-byte rows"); | |
| static_assert(ROW_BYTES % 64 == 0, "image rows must be 64-byte multiples (DRAM read alignment)"); | |
| void kernel_main() { | |
| const uint32_t in_addr = get_common_arg_val<uint32_t>(0); | |
| const uint32_t out_addr = get_common_arg_val<uint32_t>(1); | |
| const uint32_t core = get_absolute_logical_y() * GX + get_absolute_logical_x(); | |
| if (core >= NUM_CORES) { | |
| return; | |
| } | |
| constexpr uint32_t PART = (S + SLOTS - 1) / SLOTS; | |
| const uint32_t shard0 = core * S; | |
| const uint32_t p0 = shard0 + SLOT * PART; | |
| const uint32_t end = shard0 + ((SLOT + 1) * PART < S ? (SLOT + 1) * PART : S); | |
| const uint32_t p1 = end < N ? end : N; | |
| if (p0 >= p1) { | |
| return; | |
| } | |
| const uint32_t row0 = p0 / W; | |
| const uint32_t row1 = (p1 - 1) / W + 1; // exclusive | |
| const auto ia = TensorAccessor(in_args, in_addr, ROW_BYTES); | |
| const uint32_t scratch = (get_write_ptr(CB_SCRATCH) + 63u) & ~63u; | |
| for (uint32_t r = row0; r < row1; ++r) { | |
| noc_async_read(ia.get_noc_addr(ROW0 + r), scratch + (r - row0) * ROW_BYTES, ROW_BYTES); | |
| } | |
| noc_async_read_barrier(); | |
| asm volatile("" ::: "memory"); // no load of the rows may move above the barrier | |
| // pixel p's 3 bf16 = 6 bytes at scratch + 6 (p - row0 W); an even pixel starts on a 4-byte boundary | |
| const uint32_t src0 = scratch + (p0 - row0 * W) * C_IN * 2; | |
| uint32_t* dst = reinterpret_cast<uint32_t*>(out_addr + (p0 - shard0) * C_PAD * 2); | |
| uint32_t n = p1 - p0; | |
| const uint16_t* sh = reinterpret_cast<const uint16_t*>(src0); | |
| if (n && (reinterpret_cast<uint32_t>(sh) & 3u)) { // odd start pixel: one single | |
| dst[0] = static_cast<uint32_t>(sh[0]) | (static_cast<uint32_t>(sh[1]) << 16); | |
| dst[1] = sh[2]; | |
| dst[2] = 0; | |
| dst[3] = 0; | |
| sh += 3; | |
| dst += 4; | |
| --n; | |
| } | |
| const uint32_t* sw = reinterpret_cast<const uint32_t*>(sh); | |
| for (; n >= 2; n -= 2) { // 2 pixels = 3 words: a0 b0 | c0 a1 | b1 c1 | |
| const uint32_t w0 = sw[0], w1 = sw[1], w2 = sw[2]; | |
| dst[0] = w0; | |
| dst[1] = w1 & 0xFFFFu; | |
| dst[2] = 0; | |
| dst[3] = 0; | |
| dst[4] = (w1 >> 16) | (w2 << 16); | |
| dst[5] = w2 >> 16; | |
| dst[6] = 0; | |
| dst[7] = 0; | |
| sw += 3; | |
| dst += 8; | |
| } | |
| if (n) { | |
| sh = reinterpret_cast<const uint16_t*>(sw); | |
| dst[0] = static_cast<uint32_t>(sh[0]) | (static_cast<uint32_t>(sh[1]) << 16); | |
| dst[1] = sh[2]; | |
| dst[2] = 0; | |
| dst[3] = 0; | |
| } | |
| asm volatile("" ::: "memory"); | |
| } | |