Skip to content

Commit

Permalink
#0: Remove grayskull support from BRISC and NCRISC firmware
Browse files Browse the repository at this point in the history
Grayskull needed a mode where the NCRISC firmware is loaded into IRAM, which
complicates everything.
  • Loading branch information
jbaumanTT committed Mar 6, 2025
1 parent 5b95f51 commit 28b52f5
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 225 deletions.
20 changes: 1 addition & 19 deletions tt_metal/hw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ foreach(ARCH IN LISTS ARCHS)
substitutes
tdma_xmov
noc
ncrisc-halt
ncrisc-halt-wormhole
)

Expand All @@ -180,7 +179,6 @@ foreach(ARCH IN LISTS ARCHS)
set(substitutes_SOURCE "${PROJECT_SOURCE_DIR}/tt_metal/hw/toolchain/substitutes.cpp")
set(tdma_xmov_SOURCE "${PROJECT_SOURCE_DIR}/tt_metal/hw/firmware/src/tdma_xmov.c")
set(noc_SOURCE "${PROJECT_SOURCE_DIR}/tt_metal/hw/firmware/src/${ARCH}/noc.c")
set(ncrisc-halt_SOURCE "${PROJECT_SOURCE_DIR}/tt_metal/hw/toolchain/ncrisc-halt.S")
set(ncrisc-halt-wormhole_SOURCE "${PROJECT_SOURCE_DIR}/tt_metal/hw/toolchain/ncrisc-halt-wormhole.S")

# Set GPP_FLAGS based on ARCH
Expand Down Expand Up @@ -217,23 +215,7 @@ foreach(ARCH IN LISTS ARCHS)
list(APPEND GPP_INCLUDES -I${PROJECT_SOURCE_DIR}/tt_metal/third_party/tt_llk/tt_llk_${ARCH_B0}/llk_lib)

foreach(HWLIB IN LISTS HWLIBS)
if(
"${ARCH}"
STREQUAL
"blackhole"
AND (
(
"${HWLIB}"
STREQUAL
"ncrisc-halt"
)
OR (
"${HWLIB}"
STREQUAL
"tmu-crt0k-ncrisc"
)
)
)
if("${ARCH}" STREQUAL "blackhole" AND ("${HWLIB}" STREQUAL "tmu-crt0k-ncrisc"))
continue() # Skip the iteration, blackhole doesn't have IRAM
endif()
if((NOT "${ARCH}" STREQUAL "wormhole") AND "${HWLIB}" STREQUAL "ncrisc-halt-wormhole")
Expand Down
99 changes: 7 additions & 92 deletions tt_metal/hw/firmware/src/brisc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ constexpr uint32_t RISCV_IC_TRISC1_MASK = 0x4;
constexpr uint32_t RISCV_IC_TRISC2_MASK = 0x8;
constexpr uint32_t RISCV_IC_TRISC_ALL_MASK = RISCV_IC_TRISC0_MASK | RISCV_IC_TRISC1_MASK | RISCV_IC_TRISC2_MASK;

#define NCRISC_FIRMWARE_IN_IRAM (defined(ARCH_GRAYSKULL))

#if NCRISC_FIRMWARE_IN_IRAM
constexpr uint32_t num_cbs_to_early_init = 4; // safe small number to overlap w/ ncrisc copy
#else
constexpr uint32_t num_cbs_to_early_init = 0;
#endif

tt_l1_ptr mailboxes_t* const mailboxes = (tt_l1_ptr mailboxes_t*)(MEM_MAILBOX_BASE);
uint32_t ncrisc_kernel_start_offset16;

Expand Down Expand Up @@ -183,26 +175,6 @@ void set_deassert_addresses() {
#endif
}

void l1_to_ncrisc_iram_copy(uint32_t src_addr, uint16_t size, uint32_t address_offset = 0) {
#if NCRISC_FIRMWARE_IN_IRAM
// Always copy ncrisc even if its size is 0 (save branch)...
// Copy NCRISC firmware from L1 to local IRAM using tensix DMA
tdma_xmov(
TDMA_MOVER0,
src_addr,
MEM_MOVER_VIEW_IRAM_BASE_ADDR + address_offset,
size,
XMOV_L1_TO_L0);
#endif
}

void l1_to_ncrisc_iram_copy_wait() {
#if NCRISC_FIRMWARE_IN_IRAM
// Wait for DMA to finish
wait_tdma_movers_done(RISCV_TDMA_STATUS_FLAG_MOVER0_BUSY_MASK);
#endif
}

void device_setup() {
instrn_buf[0] = core.instrn_buf_base(0);
instrn_buf[1] = core.instrn_buf_base(1);
Expand Down Expand Up @@ -270,51 +242,14 @@ void device_setup() {
// core.ex_sem_init(semaphore::CFG_STATE_BUSY, MAX_CONFIG_STATES, 0, instrn_buf[0]);
}

inline void init_ncrisc_iram() {
#if NCRISC_FIRMWARE_IN_IRAM
uint16_t fw_size16 = mailboxes->launch[mailboxes->launch_msg_rd_ptr].kernel_config.ncrisc_kernel_size16;
ncrisc_kernel_start_offset16 = fw_size16;

// Copies from L1 to IRAM on chips where NCRISC has IRAM
l1_to_ncrisc_iram_copy(MEM_NCRISC_INIT_IRAM_L1_BASE >> 4, fw_size16);
l1_to_ncrisc_iram_copy_wait();
#endif
}

inline void deassert_ncrisc_trisc() {
// Below sets ncrisc to go so we can wait until it is cleared on first iteration
mailboxes->slave_sync.all = RUN_SYNC_MSG_ALL_SLAVES_DONE;

init_ncrisc_iram();

// Bring ncrisc/triscs out of reset
deassert_all_reset();
}

inline __attribute__((always_inline)) void wait_for_ncrisc_to_halt() {
#if NCRISC_FIRMWARE_IN_IRAM
WAYPOINT("INW");
while (mailboxes->slave_sync.dm1 != RUN_SYNC_MSG_DONE);
WAYPOINT("IND");
#endif
}

inline __attribute__((always_inline)) void reset_ncrisc_with_iram() {
#if NCRISC_FIRMWARE_IN_IRAM
assert_just_ncrisc_reset();
#endif
}

inline void set_ncrisc_kernel_resume_deassert_address() {
#if NCRISC_FIRMWARE_IN_IRAM
volatile tt_reg_ptr uint32_t* cfg_regs = core.cfg_regs_base(0);
WAYPOINT("INRW");
while (mailboxes->ncrisc_halt.resume_addr == 0);
WAYPOINT("INRD");
cfg_regs[NCRISC_RESET_PC_PC_ADDR32] = mailboxes->ncrisc_halt.resume_addr;
#endif
}

inline void run_triscs(dispatch_core_processor_masks enables) {
// Wait for init_sync_registers to complete. Should always be done by the time we get here.
while (mailboxes->slave_sync.trisc0 != RUN_SYNC_MSG_DONE) {
Expand All @@ -328,17 +263,13 @@ inline void run_triscs(dispatch_core_processor_masks enables) {
}
}

inline void finish_ncrisc_copy_and_run(dispatch_core_processor_masks enables) {
// On Wormhole, start_ncrisc_kernel_run will reset NCRISC to start the kernel running.
inline void start_ncrisc_kernel_run_early(dispatch_core_processor_masks enables) {
// On Wormhole, start_ncrisc_kernel_run will reset NCRISC to start the
// kernel running. We delay it until later to give the NCRISC time to load
// CBs before we wait on it.
#if !defined(NCRISC_FIRMWARE_KERNEL_SPLIT)
if (enables & DISPATCH_CLASS_MASK_TENSIX_ENABLE_DM1) {
l1_to_ncrisc_iram_copy_wait();
mailboxes->slave_sync.dm1 = RUN_SYNC_MSG_GO;

#if NCRISC_FIRMWARE_IN_IRAM
// Note: only ncrisc is in reset, so just deasserts ncrisc
deassert_all_reset();
#endif
}
#endif
}
Expand Down Expand Up @@ -386,12 +317,6 @@ int main() {
mailboxes->ncrisc_halt.resume_addr = 0;
mailboxes->slave_sync.dm1 = RUN_SYNC_MSG_GO;
deassert_ncrisc_trisc();
// When NCRISC has IRAM, it needs to be halted before data can be copied from L1 to IRAM
// This routine allows us to resume NCRISC after the copy is done
set_ncrisc_kernel_resume_deassert_address();

// Wait for ncrisc to halt
wait_for_ncrisc_to_halt();

mailboxes->go_message.signal = RUN_MSG_DONE;

Expand All @@ -414,7 +339,6 @@ int main() {
#endif

while (1) {
reset_ncrisc_with_iram();

WAYPOINT("GW");
uint8_t go_message_signal = RUN_MSG_DONE;
Expand Down Expand Up @@ -466,20 +390,12 @@ int main() {
DeviceZoneSetCounter(launch_msg_address->kernel_config.host_assigned_id);
enum dispatch_core_processor_masks enables =
(enum dispatch_core_processor_masks)launch_msg_address->kernel_config.enables;
#if !NCRISC_FIRMWARE_IN_IRAM
// On Wormhole and Blackhole, trigger the NCRISC to start loading CBs and IRAM as soon as possible.
// Trigger the NCRISC to start loading CBs and IRAM as soon as possible.
if (enables & DISPATCH_CLASS_MASK_TENSIX_ENABLE_DM1) {
mailboxes->slave_sync.dm1 = RUN_SYNC_MSG_LOAD;
}
#endif
// Copies from L1 to IRAM on chips where NCRISC has IRAM
uint32_t kernel_config_base = firmware_config_init(mailboxes, ProgrammableCoreType::TENSIX, DISPATCH_CLASS_TENSIX_DM0);
int ncrisc_index = static_cast<std::underlying_type<TensixProcessorTypes>::type>(TensixProcessorTypes::DM1);
uint32_t ncrisc_kernel_src_address =
kernel_config_base + launch_msg_address->kernel_config.kernel_text_offset[ncrisc_index];
l1_to_ncrisc_iram_copy(ncrisc_kernel_src_address >> 4,
launch_msg_address->kernel_config.ncrisc_kernel_size16,
ncrisc_kernel_start_offset16);
// Invalidate the i$ now the kernels have loaded and before running
volatile tt_reg_ptr uint32_t* cfg_regs = core.cfg_regs_base(0);
cfg_regs[RISCV_IC_INVALIDATE_InvalidateAll_ADDR32] = RISCV_IC_BRISC_MASK | RISCV_IC_TRISC_ALL_MASK | RISCV_IC_NCRISC_MASK;
Expand Down Expand Up @@ -507,15 +423,14 @@ int main() {

uint32_t tt_l1_ptr* cb_l1_base =
(uint32_t tt_l1_ptr*)(kernel_config_base + launch_msg_address->kernel_config.local_cb_offset);
setup_local_cb_read_write_interfaces(cb_l1_base, 0, num_cbs_to_early_init, true, true, false);
finish_ncrisc_copy_and_run(enables);
start_ncrisc_kernel_run_early(enables);

// Run the BRISC kernel
WAYPOINT("R");
if (enables & DISPATCH_CLASS_MASK_TENSIX_ENABLE_DM0) {
uint32_t end_cb_index = launch_msg_address->kernel_config.max_local_cb_end_index;
setup_local_cb_read_write_interfaces(
cb_l1_base, num_cbs_to_early_init, end_cb_index, true, true, false);
cb_l1_base, 0, end_cb_index, true, true, false);
cb_l1_base =
(uint32_t tt_l1_ptr*)(kernel_config_base + launch_msg_address->kernel_config.remote_cb_offset);
end_cb_index = launch_msg_address->kernel_config.min_remote_cb_start_index;
Expand Down
26 changes: 2 additions & 24 deletions tt_metal/hw/firmware/src/ncrisc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
#include "debug/stack_usage.h"
// clang-format on

#define NCRISC_FIRMWARE_IN_IRAM (defined(ARCH_GRAYSKULL))

uint32_t halt_stack_ptr_save;

tt_l1_ptr mailboxes_t *const mailboxes = (tt_l1_ptr mailboxes_t *)(MEM_MAILBOX_BASE);
Expand Down Expand Up @@ -60,34 +58,20 @@ namespace kernel_profiler {
}
#endif

extern "C" void ncrisc_resume(void);
extern "C" void notify_brisc_and_halt(uint32_t status);
extern "C" void notify_brisc_and_halt_to_iram(uint32_t status, uint32_t first_argument);

inline __attribute__((always_inline)) void set_ncrisc_resume_addr() {
#if NCRISC_FIRMWARE_IN_IRAM
mailboxes->ncrisc_halt.resume_addr = (uint32_t)ncrisc_resume;
#endif
}

inline __attribute__((always_inline)) void notify_brisc_and_wait() {
#if NCRISC_FIRMWARE_IN_IRAM
notify_brisc_and_halt(RUN_SYNC_MSG_DONE);
#else
while (true) {
uint8_t run_value = *ncrisc_run;
if (run_value == RUN_SYNC_MSG_GO || run_value == RUN_SYNC_MSG_LOAD) {
break;
}
invalidate_l1_cache();
}
#endif
}

inline __attribute__((always_inline)) void signal_ncrisc_completion() {
#if !NCRISC_FIRMWARE_IN_IRAM
*ncrisc_run = RUN_SYNC_MSG_DONE;
#endif
}

#if defined(ARCH_WORMHOLE)
Expand Down Expand Up @@ -115,10 +99,6 @@ int main(int argc, char *argv[]) {

risc_init();

// If NCRISC has IRAM it needs to halt before BRISC copies data from L1 to IRAM
// Need to save address to jump to after BRISC resumes NCRISC
set_ncrisc_resume_addr();

// Cleanup profiler buffer incase we never get the go message
while (1) {
WAYPOINT("W");
Expand Down Expand Up @@ -152,17 +132,15 @@ int main(int argc, char *argv[]) {

void (*kernel_address)(uint32_t) = (void (*)(uint32_t))
(kernel_config_base + launch_msg->kernel_config.kernel_text_offset[index]);
#ifdef ARCH_BLACKHOLE
#if !defined(ARCH_WORMHOLE)
while (*ncrisc_run != RUN_SYNC_MSG_GO) {
invalidate_l1_cache();
}
(*kernel_address)((uint32_t)kernel_address);
#elif defined(ARCH_WORMHOLE)
#else
// Jumping to IRAM causes bizarre behavior, so signal the brisc to reset the ncrisc to the IRAM address.
mailboxes->ncrisc_halt.resume_addr = (uint32_t)kernel_init;
notify_brisc_and_halt_to_iram(RUN_SYNC_MSG_WAITING_FOR_RESET, (uint32_t)kernel_address);
#else
kernel_init((uint32_t)kernel_address);
#endif
RECORD_STACK_USAGE();
WAYPOINT("D");
Expand Down
84 changes: 0 additions & 84 deletions tt_metal/hw/toolchain/ncrisc-halt.S

This file was deleted.

6 changes: 0 additions & 6 deletions tt_metal/jit_build/build.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,9 @@ void JitBuildState::finish_init() {
std::string build_dir =
llrt::RunTimeOptions::get_instance().get_root_dir() + "runtime/hw/lib/" + get_alias(env_.arch_) + "/";
if (this->is_fw_) {
if (this->target_name_ == "brisc" and this->env_.arch_ == tt::ARCH::GRAYSKULL) {
this->link_objs_ += build_dir + "tdma_xmov.o ";
}
if (this->target_name_ != "erisc") {
this->link_objs_ += build_dir + "tmu-crt0.o ";
}
if (this->target_name_ == "ncrisc" and this->env_.arch_ == tt::ARCH::GRAYSKULL) {
this->link_objs_ += build_dir + "ncrisc-halt.o ";
}
if (this->target_name_ == "ncrisc" and this->env_.arch_ == tt::ARCH::WORMHOLE_B0) {
this->link_objs_ += build_dir + "ncrisc-halt-wormhole.o ";
this->link_objs_ += build_dir + "tdma_xmov.o ";
Expand Down

0 comments on commit 28b52f5

Please sign in to comment.