Foundry/tt/kernels/ft_tensix_compute_cb.h

102 lines
4.4 KiB
C

/* SPDX-License-Identifier: AGPL-3.0-or-later */
/* Copyright (C) 2026 David (Corey) Herrera */
/**
* @file ft_tensix_compute_cb.h
* @brief Circular-buffer flow control for compute kernels: wait/pop on the UNPACK thread,
* reserve/push on the PACK thread, with the counter publication done by the coprocessor
* (SETDMAREG + STALLWAIT + STOREREG) so it lands after the unpacker/packer has finished.
*
* The CB bookkeeping struct and the two overlay stream registers per CB are owned by
* ft_tensix_circular_buffer.h. Thread ownership is the kernel's gating, not checked here.
*
* @status Clean-room rewrite, plan Phase 4 step 4.5a.
* @issues None
* @todo None
*/
#ifndef FT_TENSIX_COMPUTE_CB_H
#define FT_TENSIX_COMPUTE_CB_H
#include <stdint.h>
#include "ft_tensix_circular_buffer.h"
#include "ft_tensix_compute.h"
/* STOREREG takes a register as an 18-bit word address (STOREREG.md): RISC byte address >> 2. */
#define FT_TENSIX_CB_TENSIX_REG_ADDRESS(byte_address) ((((uint32_t)(byte_address)) >> 2) & 0x3ffffu)
/* GPR the unpack side stages the acked count in (Foundry convention). */
#define FT_TENSIX_CB_GPR_UNPACK_ACKED 4u
/** Block until `tile_count` tiles are available in CB `cb_index`. [UNPACK] */
static FT_BH_INLINE void ft_tensix_compute_cb_wait_front(uint32_t cb_index, uint32_t tile_count)
{
volatile FT_BH_REG_PTR uint32_t *p = ft_tensix_cb_pages_received_pointer((int32_t)cb_index);
uint16_t wanted = (uint16_t)tile_count;
uint16_t received;
uint16_t available;
do {
received = (uint16_t)p[0];
available = (uint16_t)(received - ft_tensix_cb(cb_index)->tiles.counters.tiles_acked);
} while (available < wanted);
}
/** Release `tile_count` tiles: publish the acked count, then advance the read pointer.
* [UNPACK] */
static FT_BH_INLINE void ft_tensix_compute_cb_pop_front(uint32_t cb_index, uint32_t tile_count)
{
ft_tensix_cb_interface *cb = ft_tensix_cb(cb_index);
uint32_t reg = FT_TENSIX_CB_TENSIX_REG_ADDRESS(
ft_tensix_cb_pages_acked_pointer((int32_t)cb_index));
uint32_t byte_count = tile_count * cb->fifo_page_size;
cb->tiles.counters.tiles_acked = (uint16_t)(cb->tiles.counters.tiles_acked + tile_count);
FT_BH_PUSH_SETDMAREG(0, cb->tiles.counters.tiles_acked, 0,
FT_TENSIX_LO_16(FT_TENSIX_CB_GPR_UNPACK_ACKED));
FT_BH_TTINSN_STALLWAIT(FT_BH_STALLWAIT_BLOCK_THCON, FT_BH_STALLWAIT_COND_UNPACK);
FT_BH_PUSH_STOREREG(FT_TENSIX_CB_GPR_UNPACK_ACKED, reg);
cb->fifo_read_pointer += byte_count;
if (cb->fifo_read_pointer >= cb->fifo_limit) {
cb->fifo_read_pointer -= cb->fifo_size;
}
}
/** Block until `tile_count` tiles of space are free. Polls the acked register against this
* thread's own received count. [PACK] */
static FT_BH_INLINE void ft_tensix_compute_cb_reserve_back(uint32_t cb_index, uint32_t tile_count)
{
volatile FT_BH_REG_PTR uint32_t *p = ft_tensix_cb_pages_acked_pointer((int32_t)cb_index);
uint16_t received = ft_tensix_cb(cb_index)->tiles.counters.tiles_received;
int32_t free_tiles;
do {
uint16_t acked = (uint16_t)p[0];
uint16_t free_wrapped = (uint16_t)(ft_tensix_cb(cb_index)->fifo_num_pages
- (uint16_t)(received - acked));
free_tiles = (int32_t)free_wrapped;
} while (free_tiles < (int32_t)tile_count);
}
/** Commit `tile_count` tiles: advance the write pointer, then publish the received count.
* [PACK] */
static FT_BH_INLINE void ft_tensix_compute_cb_push_back(uint32_t cb_index, uint32_t tile_count)
{
ft_tensix_cb_interface *cb = ft_tensix_cb(cb_index);
uint32_t byte_count = tile_count * cb->fifo_page_size;
uint32_t reg = FT_TENSIX_CB_TENSIX_REG_ADDRESS(
ft_tensix_cb_pages_received_pointer((int32_t)cb_index));
cb->fifo_write_pointer += byte_count;
cb->fifo_write_tile_pointer = 0;
if (cb->fifo_write_pointer >= cb->fifo_limit) {
cb->fifo_write_pointer -= cb->fifo_size;
}
cb->tiles.counters.tiles_received =
(uint16_t)(cb->tiles.counters.tiles_received + tile_count);
FT_BH_PUSH_SETDMAREG(0, cb->tiles.counters.tiles_received, 0,
FT_TENSIX_LO_16(FT_TENSIX_GPR_PACK_NUM_MSGS_RECEIVED));
FT_BH_TTINSN_STALLWAIT(FT_BH_STALLWAIT_BLOCK_THCON, FT_BH_STALLWAIT_COND_PACK);
FT_BH_PUSH_STOREREG(FT_TENSIX_GPR_PACK_NUM_MSGS_RECEIVED, reg);
}
#endif /* FT_TENSIX_COMPUTE_CB_H */