Skip to content

Commit

Permalink
#0: linker script cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
nathan-TT committed Sep 30, 2024
1 parent 8d6ee5d commit 756b522
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 41 deletions.
5 changes: 2 additions & 3 deletions tt_metal/hw/toolchain/main.ld
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ REGION_ALIAS("REGION_CODE", TARGET_CODE(LD_TARGET, FIRMWARE))
REGION_ALIAS("REGION_DATA", TARGET_LOCAL_DATA_MEM(LD_TARGET))
REGION_ALIAS("REGION_STACK", TARGET_STACK_MEM(LD_TARGET))

__firmware_stack_size = TARGET_STACK_SIZE(LD_TARGET);
#define FIRMWARE_STACK_SIZE TARGET_STACK_SIZE(LD_TARGET)
#define KERNEL_ENTRY_SYMBOL _Z11kernel_initv

#include "sections.ld"

_Z11kernel_initv = _etext;
71 changes: 33 additions & 38 deletions tt_metal/hw/toolchain/sections.ld
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@
any modifications should be made to tensix-sections-pre-proc.ld, tensix-sections.ld is a generated file
*/

/*
Firmware text/ldm start at the start of the section
Kernel text/ldm start where firmware left off
*/
__firmware_start = DEFINED(__fw_export_end_text) ? __fw_export_end_text : ORIGIN(REGION_CODE);
__ldm_start = DEFINED(__fw_export_ldm_end) ? __fw_export_ldm_end : ORIGIN(REGION_DATA);

/*
Need a 32B separation between FW end and Kernel start on eriscs to
ensure kernel does not get cached into i$ because we cannot flush the i$.
FW must align to 32 byte boundary so Kernel begins aligned to meet noc
alignment constraints
*/
#if defined(TYPE_FIRMWARE)
/* Start of the appropriate region. */
#define TEXT_START ORIGIN(REGION_CODE)
#define DATA_START ORIGIN(REGION_DATA)
#elif defined(TYPE_KERNEL)
/* Where firmware ended. */
#define TEXT_START __fw_export_end_text
#define DATA_START __fw_export_ldm_end
#else
#error "Neither TYPE_FIRMARE nor TYPE_KERNEL defined, what am I to be?"
#endif

#if defined (TYPE_FIRMWARE)
#if defined (TARGET_IERISC)
#if defined(TYPE_FIRMWARE)
/* Need separation beteen end of firmware and start of kernel, so that
they don't share unflushable i$ cache lines. */
#if defined(TARGET_IERISC)
#define MEM_PAD MEM_IERISC_KERNEL_PAD
#else
#define MEM_PAD MEM_TENSIX_KERNEL_PAD
Expand All @@ -32,7 +32,7 @@ __ldm_start = DEFINED(__fw_export_ldm_end) ? __fw_export_ldm_end : ORIGIN(REGION
#define MEM_PAD 0
#endif

#define MEM_ALIGN MEM_PAD + 4
#define MEM_ALIGN (MEM_PAD + 4)

OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv",
"elf32-littleriscv")
Expand All @@ -42,9 +42,12 @@ SEARCH_DIR("/opt/riscv32i/riscv32-unknown-elf/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = __firmware_start);
.init __firmware_start :
.init TEXT_START :
{
/* Because TEXT_START might not be the start of a region, we
need to force this section to be emitted so that following sections
do not restart the region, if this one is empty. */
. = .;
KEEP (*(SORT_NONE(.init)))
} > REGION_CODE
.text :
Expand All @@ -71,23 +74,21 @@ SECTIONS
*(l1_data_noinit)
} > REGION_CODE

. += MEM_PAD;
. = ALIGN(MEM_ALIGN);
. = ALIGN(. + MEM_PAD, MEM_ALIGN);

PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
__fw_export_end_text = DEFINED(__fw_export_end_text) ? __fw_export_end_text : .;
#if defined(TYPE_FIRMWARE)
__fw_export_end_text = .;
PROVIDE (KERNEL_ENTRY_SYMBOL = __fw_export_end_text);
#endif

#if defined(TYPE_KERNEL)
__kernel_init_local_l1_base = .;
#endif

PROVIDE(__global_pointer$ = ORIGIN(REGION_DATA) + 0x7f0);
.ldm_data __ldm_start :
.ldm_data DATA_START :
{
/* ldm is copied in 4 byte chunks */
. = ALIGN(4);
. = .; /* Force section emission. */
__ldm_data_start = .;
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
Expand Down Expand Up @@ -130,36 +131,30 @@ SECTIONS
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
. = ALIGN(4);
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__ldm_bss_end = .;
} > REGION_DATA

/* Use __ldm_bss_end to pick up where the last REGION_DATA ended
This is needed because of the way kernel REGION_DATA picks up where firmware
ended. If the section above is empty (highly unlikely) we don't want to
re-start at the origion of REGION_DATA
*/
local_data_noinit __ldm_bss_end (NOLOAD) :
local_data_noinit (NOLOAD) :
{
*(local_data_noinit)
} > REGION_DATA

#ifdef TYPE_FIRMWARE
/* FW must align to 16 byte boundary so Kernel begins aligned to meet noc
alignment constraints */
. = ALIGN(16);
_edata = .; PROVIDE (edata = .);
_end = .; PROVIDE (end = .);
__fw_export_ldm_end = DEFINED(__fw_export_ldm_end) ? __fw_export_ldm_end : _end;
__fw_export_ldm_end = .;
#endif

/* Move to end of local memory for stack */
.stack :
{
__stack_bottom = .;
. += __firmware_stack_size;
. += FIRMWARE_STACK_SIZE;
__stack_top = .;
} > REGION_STACK

Expand Down

0 comments on commit 756b522

Please sign in to comment.