263 lines
13 KiB
C
263 lines
13 KiB
C
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
|
/* Copyright (C) 2026 David (Corey) Herrera */
|
|
/**
|
|
* @file ft_tt_memmap.h
|
|
* @brief Foundry's L1 map for one Blackhole Tensix tile, plus the few hardware addresses and
|
|
* sizes the host and Foundry's firmware both depend on. Shared by the host library (tt/),
|
|
* Foundry's firmware (tt/fw/), the kernels (tt/kernels/) and the generated linker scripts.
|
|
*
|
|
* TWO KINDS OF VALUE live here, and each one says which it is:
|
|
* [HW] fixed by the silicon; cited to tt-isa-documentation BlackholeA0 (the page named).
|
|
* [FOUNDRY] Foundry's own choice. Both ends of every [FOUNDRY] region are Foundry code, so the
|
|
* value is ours to define. Each one equals the value the shipped images were linked
|
|
* against, which is what keeps every existing image and the host byte-identical.
|
|
*
|
|
* THE L1 MAP is one list of regions in address order, each with an explicit size. A region
|
|
* Foundry does not use is one named reserved span, so every used address keeps its value.
|
|
* Where both neighbours are Foundry's, the next base is computed (base + size); otherwise the
|
|
* address is stated.
|
|
*
|
|
* EVERY OBJECT-LIKE MACRO IS A PLAIN INTEGER EXPRESSION. tools/emit_tensix_linker_script.py
|
|
* reads them through `cc -E -dM` and evaluates them itself: no casts, no sizeof, no offsetof,
|
|
* no division, no conditional operator. The function-like helpers are exempt.
|
|
*
|
|
* @status Clean-room rewrite (plan 4.3), from the public docs, Foundry's own consumers and the
|
|
* measured layout of the previous build. Every value consumers use is unchanged.
|
|
* @issues None
|
|
* @todo None
|
|
*/
|
|
|
|
#ifndef FT_TT_MEMMAP_H
|
|
#define FT_TT_MEMMAP_H
|
|
|
|
#include <stdint.h>
|
|
|
|
/* ================================================================
|
|
* Compile-time assertion, usable at file scope from C99 host code and from the firmware
|
|
* ================================================================ */
|
|
|
|
/** Fails the build when `condition` is false. `tag` must be unique within a translation unit. */
|
|
#define FT_TT_STATIC_ASSERT(condition, tag) \
|
|
typedef char ft_tt_static_assert_##tag[(condition) ? 1 : -1]
|
|
|
|
/* ================================================================
|
|
* Memories outside L1
|
|
* ================================================================ */
|
|
|
|
/** [HW] 1536 KiB of L1 per Tensix tile (TensixTile/README.md; BabyRISCV/README.md memory map,
|
|
* MEM_L1_BASE 0x0000_0000..0x0017_FFFF). */
|
|
#define FT_TT_MEM_L1_SIZE (1536u * 1024u)
|
|
|
|
/** [FOUNDRY] Bytes of one DRAM bank Foundry addresses: 16 MiB short of the 4 GiB each bank
|
|
* exposes (NoC/Coordinates.md). Checked against the arch table's dram_bytes_per_bank. */
|
|
#define FT_TT_MEM_DRAM_SIZE 0xFF000000u
|
|
|
|
/** [FOUNDRY] DRAM banks Foundry interleaves over. */
|
|
#define FT_TT_NUM_DRAM_BANKS 8u
|
|
|
|
/** [HW] Each RISC-V's private data RAM (BabyRISCV/README.md "Local Data RAM", MEM_LOCAL_BASE):
|
|
* 8 KiB on B and NC, 4 KiB on T0, T1, T2. */
|
|
#define FT_TT_MEM_LOCAL_BASE 0xFFB00000u
|
|
#define FT_TT_MEM_BRISC_LOCAL_SIZE (8u * 1024u)
|
|
#define FT_TT_MEM_NCRISC_LOCAL_SIZE (8u * 1024u)
|
|
#define FT_TT_MEM_TRISC_LOCAL_SIZE (4u * 1024u)
|
|
|
|
/* ================================================================
|
|
* The L1 map, in address order
|
|
* ================================================================ */
|
|
|
|
/* 0x0000: BRISC's reset PC is the fixed value 0 (SoftReset.md). Foundry does not use the word
|
|
* there. */
|
|
|
|
/** [FOUNDRY] Return-value word for NoC atomics. BRISC firmware presets every NoC's atomic
|
|
* initiator to return here (fw/ft_brisc_fw.c). */
|
|
#define FT_TT_MEM_NOC_ATOMIC_RET_VAL_ADDR 0x4u
|
|
#define FT_TT_MEM_NOC_ATOMIC_RET_VAL_SIZE 4u
|
|
|
|
/** [FOUNDRY] Reserved: Foundry places nothing between the atomic word and the mailbox. */
|
|
#define FT_TT_MEM_LOW_RESERVED_BASE \
|
|
(FT_TT_MEM_NOC_ATOMIC_RET_VAL_ADDR + FT_TT_MEM_NOC_ATOMIC_RET_VAL_SIZE)
|
|
#define FT_TT_MEM_LOW_RESERVED_SIZE 0x58u
|
|
|
|
/** [FOUNDRY] The host <-> firmware mailbox (ft_tt_mailbox.h). The region is larger than the
|
|
* mailbox struct; the host clears the whole of [BASE, END) before booting a core. */
|
|
#define FT_TT_MEM_MAILBOX_BASE (FT_TT_MEM_LOW_RESERVED_BASE + FT_TT_MEM_LOW_RESERVED_SIZE)
|
|
#define FT_TT_MEM_MAILBOX_SIZE 0x33F0u
|
|
#define FT_TT_MEM_MAILBOX_END (FT_TT_MEM_MAILBOX_BASE + FT_TT_MEM_MAILBOX_SIZE)
|
|
|
|
/** [FOUNDRY] Reserved gap after the mailbox. */
|
|
#define FT_TT_MEM_MAILBOX_GAP_SIZE 0x10u
|
|
|
|
/** [FOUNDRY] A block BRISC firmware zeroes at every boot (fw/ft_brisc_fw.c). */
|
|
#define FT_TT_MEM_ZEROS_BASE (FT_TT_MEM_MAILBOX_END + FT_TT_MEM_MAILBOX_GAP_SIZE)
|
|
#define FT_TT_MEM_ZEROS_SIZE 0x200u
|
|
|
|
/** [FOUNDRY] Reserved: not used by Foundry. */
|
|
#define FT_TT_MEM_PRE_FIRMWARE_RESERVED_BASE (FT_TT_MEM_ZEROS_BASE + FT_TT_MEM_ZEROS_SIZE)
|
|
#define FT_TT_MEM_PRE_FIRMWARE_RESERVED_SIZE 0x400u
|
|
|
|
/**
|
|
* [FOUNDRY] The five firmware slots, back to back. The host loads each processor's firmware
|
|
* here and BRISC programs the subordinates' reset PCs to these bases (SoftReset.md: the TRISC0/1/2
|
|
* and NCRISC reset PC registers and their overrides); the emitted linker scripts place the
|
|
* images.
|
|
*/
|
|
#define FT_TT_MEM_BRISC_FIRMWARE_SIZE 0x2200u
|
|
#define FT_TT_MEM_NCRISC_FIRMWARE_SIZE 0xA00u
|
|
#define FT_TT_MEM_TRISC0_FIRMWARE_SIZE 0xA00u
|
|
#define FT_TT_MEM_TRISC1_FIRMWARE_SIZE 0xA00u
|
|
#define FT_TT_MEM_TRISC2_FIRMWARE_SIZE 0xA00u
|
|
|
|
#define FT_TT_MEM_BRISC_FIRMWARE_BASE \
|
|
(FT_TT_MEM_PRE_FIRMWARE_RESERVED_BASE + FT_TT_MEM_PRE_FIRMWARE_RESERVED_SIZE)
|
|
#define FT_TT_MEM_NCRISC_FIRMWARE_BASE \
|
|
(FT_TT_MEM_BRISC_FIRMWARE_BASE + FT_TT_MEM_BRISC_FIRMWARE_SIZE)
|
|
#define FT_TT_MEM_TRISC0_FIRMWARE_BASE \
|
|
(FT_TT_MEM_NCRISC_FIRMWARE_BASE + FT_TT_MEM_NCRISC_FIRMWARE_SIZE)
|
|
#define FT_TT_MEM_TRISC1_FIRMWARE_BASE \
|
|
(FT_TT_MEM_TRISC0_FIRMWARE_BASE + FT_TT_MEM_TRISC0_FIRMWARE_SIZE)
|
|
#define FT_TT_MEM_TRISC2_FIRMWARE_BASE \
|
|
(FT_TT_MEM_TRISC1_FIRMWARE_BASE + FT_TT_MEM_TRISC1_FIRMWARE_SIZE)
|
|
#define FT_TT_MEM_FIRMWARE_END \
|
|
(FT_TT_MEM_TRISC2_FIRMWARE_BASE + FT_TT_MEM_TRISC2_FIRMWARE_SIZE)
|
|
|
|
/** [FOUNDRY] Reserved: not used by Foundry. */
|
|
#define FT_TT_MEM_POST_FIRMWARE_RESERVED_SIZE 0x100u
|
|
|
|
/**
|
|
* [FOUNDRY] First byte of the reserved tail of the read-only region (up to
|
|
* FT_TT_MEM_MAP_READ_ONLY_END). Foundry never stores anything there.
|
|
*/
|
|
#define FT_TT_MEM_TENSIX_ROUTING_TABLE_BASE \
|
|
(FT_TT_MEM_FIRMWARE_END + FT_TT_MEM_POST_FIRMWARE_RESERVED_SIZE)
|
|
|
|
/** [FOUNDRY] End of the region no kernel may write. */
|
|
#define FT_TT_MEM_MAP_READ_ONLY_END 0x9100u
|
|
|
|
/** [FOUNDRY] End of the map. [READ_ONLY_END, MAP_END) is reserved. */
|
|
#define FT_TT_MEM_MAP_END 0x9F80u
|
|
|
|
/** [FOUNDRY] Everything from the end of the map to the end of L1 is the usable arena. */
|
|
#define FT_TT_L1_USABLE_BASE FT_TT_MEM_MAP_END
|
|
#define FT_TT_L1_USABLE_SIZE (FT_TT_MEM_L1_SIZE - FT_TT_L1_USABLE_BASE)
|
|
|
|
/**
|
|
* [FOUNDRY] Kernel-staging scratch, one slot per processor, at the start of the usable arena.
|
|
* Each firmware copies its initialised data from its slot into its local data RAM at boot
|
|
* (fw/ft_*_fw.c initialise_local_memory()), so a slot is as large as that processor's local
|
|
* data RAM, and the slots are live only while a core boots.
|
|
*/
|
|
#define FT_TT_MEM_BRISC_INIT_LOCAL_L1_BASE_SCRATCH FT_TT_L1_USABLE_BASE
|
|
#define FT_TT_MEM_NCRISC_INIT_LOCAL_L1_BASE_SCRATCH \
|
|
(FT_TT_MEM_BRISC_INIT_LOCAL_L1_BASE_SCRATCH + FT_TT_MEM_BRISC_LOCAL_SIZE)
|
|
#define FT_TT_MEM_TRISC0_INIT_LOCAL_L1_BASE_SCRATCH \
|
|
(FT_TT_MEM_NCRISC_INIT_LOCAL_L1_BASE_SCRATCH + FT_TT_MEM_NCRISC_LOCAL_SIZE)
|
|
#define FT_TT_MEM_TRISC1_INIT_LOCAL_L1_BASE_SCRATCH \
|
|
(FT_TT_MEM_TRISC0_INIT_LOCAL_L1_BASE_SCRATCH + FT_TT_MEM_TRISC_LOCAL_SIZE)
|
|
#define FT_TT_MEM_TRISC2_INIT_LOCAL_L1_BASE_SCRATCH \
|
|
(FT_TT_MEM_TRISC1_INIT_LOCAL_L1_BASE_SCRATCH + FT_TT_MEM_TRISC_LOCAL_SIZE)
|
|
#define FT_TT_MEM_INIT_LOCAL_SCRATCH_END \
|
|
(FT_TT_MEM_TRISC2_INIT_LOCAL_L1_BASE_SCRATCH + FT_TT_MEM_TRISC_LOCAL_SIZE)
|
|
|
|
/** [FOUNDRY] Reserved span after the staging slots. */
|
|
#define FT_TT_MEM_POST_SCRATCH_RESERVED_SIZE 0x2800u
|
|
|
|
/** [FOUNDRY] A small staging span the L1 layout tests keep clear of. */
|
|
#define FT_TT_MEM_LOGICAL_TO_VIRTUAL_SCRATCH \
|
|
(FT_TT_MEM_INIT_LOCAL_SCRATCH_END + FT_TT_MEM_POST_SCRATCH_RESERVED_SIZE)
|
|
#define FT_TT_MEM_LOGICAL_TO_VIRTUAL_SIZE 0x20u
|
|
|
|
/* ================================================================
|
|
* Linker limits per processor
|
|
* ================================================================ */
|
|
|
|
/** [FOUNDRY] Upper bound the linker scripts put on one kernel image. NOT an allocation bound:
|
|
* it is larger than the usable arena; ft_tt_buffer.h bounds by FT_TT_MEM_L1_SIZE instead. */
|
|
#define FT_TT_MEM_MAX_KERNEL_SIZE 0x176400u
|
|
#define FT_TT_MEM_BRISC_KERNEL_SIZE FT_TT_MEM_MAX_KERNEL_SIZE
|
|
#define FT_TT_MEM_NCRISC_KERNEL_SIZE FT_TT_MEM_MAX_KERNEL_SIZE
|
|
#define FT_TT_MEM_TRISC0_KERNEL_SIZE FT_TT_MEM_MAX_KERNEL_SIZE
|
|
#define FT_TT_MEM_TRISC1_KERNEL_SIZE FT_TT_MEM_MAX_KERNEL_SIZE
|
|
#define FT_TT_MEM_TRISC2_KERNEL_SIZE FT_TT_MEM_MAX_KERNEL_SIZE
|
|
|
|
/** [FOUNDRY] Smallest stack the linker scripts leave below the top of local data RAM. */
|
|
#define FT_TT_MEM_BRISC_STACK_MIN_SIZE 256u
|
|
#define FT_TT_MEM_NCRISC_STACK_MIN_SIZE 256u
|
|
#define FT_TT_MEM_TRISC0_STACK_MIN_SIZE 192u
|
|
#define FT_TT_MEM_TRISC1_STACK_MIN_SIZE 192u
|
|
#define FT_TT_MEM_TRISC2_STACK_MIN_SIZE 256u
|
|
|
|
/* ================================================================
|
|
* Grid, alignment, board
|
|
* ================================================================ */
|
|
|
|
/** [HW] The physical NoC grid is 17 x 12 tiles (NoC/Coordinates.md, the NoC #0 / #1 grid
|
|
* diagrams). ft_tt_arch_check_headers() holds these to the arch table. */
|
|
#define FT_TT_NOC_SIZE_X 17u
|
|
#define FT_TT_NOC_SIZE_Y 12u
|
|
|
|
/** [FOUNDRY] Tensix harvesting removes whole columns: ft_tt_harvest_axis's COLUMN (2) in
|
|
* ft_tt_arch.h; ft_tt_arch_check_headers() holds the two together. */
|
|
#define FT_TT_TENSIX_HARVEST_AXIS 2u
|
|
|
|
/** [FOUNDRY] Alignment of every NoC transfer's L1 and DRAM addresses. */
|
|
#define FT_TT_L1_ALIGNMENT 16u
|
|
#define FT_TT_DRAM_ALIGNMENT 64u
|
|
|
|
/** [FOUNDRY] The board the kernel images are built for (tensix_kernel_build_arch.sh carries
|
|
* the same pair; ft_tt_coord_check_kernel_build_assumptions() compares them with the card). */
|
|
#define FT_TT_KERNEL_BUILD_L1_BANK_COUNT 140u
|
|
#define FT_TT_KERNEL_BUILD_DRAM_BANK_COUNT 8u
|
|
|
|
/* ================================================================
|
|
* Processors, in the order every per-processor array uses
|
|
* ================================================================ */
|
|
|
|
/** [FOUNDRY] Two data-movement RISC-Vs (B, NC) and three compute RISC-Vs (T0, T1, T2); five
|
|
* in all (TensixTile/README.md "5x Baby RISCV cores"). */
|
|
#define FT_TT_PROC_DM0 0u
|
|
#define FT_TT_PROC_DM1 1u
|
|
#define FT_TT_PROC_MATH0 2u
|
|
#define FT_TT_PROC_MATH1 3u
|
|
#define FT_TT_PROC_MATH2 4u
|
|
#define FT_TT_PROC_COUNT 5u
|
|
|
|
/* ================================================================
|
|
* Overlay stream registers (circular-buffer page counters)
|
|
* ================================================================ */
|
|
|
|
/** [HW] NOC_OVERLAY_START_ADDR (BabyRISCV/README.md memory map). */
|
|
#define FT_TT_NOC_OVERLAY_BASE 0xFFB40000u
|
|
|
|
/** [FOUNDRY] Address stride between consecutive streams' register blocks. */
|
|
#define FT_TT_NOC_STREAM_REG_SPACE_SIZE 0x1000u
|
|
|
|
/** Address of 32-bit register `index` of overlay stream `stream`. */
|
|
#define FT_TT_STREAM_REG_ADDR(stream, index) \
|
|
(FT_TT_NOC_OVERLAY_BASE + (uint32_t)(stream) * FT_TT_NOC_STREAM_REG_SPACE_SIZE + \
|
|
((uint32_t)(index) << 2))
|
|
|
|
/** [FOUNDRY] Circular buffer `cb` keeps its page counters in stream `cb`: pages received in
|
|
* register 10, pages acknowledged in register 8. */
|
|
#define FT_TT_CB_TILES_RECEIVED_ADDR(cb) FT_TT_STREAM_REG_ADDR((cb), 10u)
|
|
#define FT_TT_CB_TILES_ACKED_ADDR(cb) FT_TT_STREAM_REG_ADDR((cb), 8u)
|
|
|
|
/* ================================================================
|
|
* The map holds together
|
|
* ================================================================ */
|
|
|
|
FT_TT_STATIC_ASSERT(FT_TT_PROC_COUNT == 5u, memmap_five_processors);
|
|
FT_TT_STATIC_ASSERT(FT_TT_MEM_MAILBOX_BASE == 0x60u, memmap_mailbox_base);
|
|
FT_TT_STATIC_ASSERT(FT_TT_MEM_ZEROS_BASE == 0x3460u, memmap_zeros_base);
|
|
FT_TT_STATIC_ASSERT(FT_TT_MEM_BRISC_FIRMWARE_BASE == 0x3A60u, memmap_brisc_firmware_base);
|
|
FT_TT_STATIC_ASSERT(FT_TT_MEM_FIRMWARE_END == 0x8460u, memmap_firmware_end);
|
|
FT_TT_STATIC_ASSERT(FT_TT_MEM_TENSIX_ROUTING_TABLE_BASE < FT_TT_MEM_MAP_READ_ONLY_END,
|
|
memmap_protected_target_is_read_only);
|
|
FT_TT_STATIC_ASSERT(FT_TT_MEM_MAP_READ_ONLY_END <= FT_TT_MEM_MAP_END, memmap_read_only_in_map);
|
|
FT_TT_STATIC_ASSERT(FT_TT_MEM_INIT_LOCAL_SCRATCH_END <= FT_TT_MEM_LOGICAL_TO_VIRTUAL_SCRATCH,
|
|
memmap_staging_slots_in_order);
|
|
FT_TT_STATIC_ASSERT(FT_TT_MEM_LOGICAL_TO_VIRTUAL_SCRATCH == 0x13780u, memmap_staging_span);
|
|
FT_TT_STATIC_ASSERT(FT_TT_L1_USABLE_BASE % FT_TT_L1_ALIGNMENT == 0u, memmap_arena_aligned);
|
|
|
|
#endif /* FT_TT_MEMMAP_H */
|