Snitch Runtime
Loading...
Searching...
No Matches
start.c
1// Copyright 2023 ETH Zurich and University of Bologna.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#ifdef __cplusplus
6#define EXTERN_C extern "C"
7#else
8#define EXTERN_C
9#endif
10
11#ifdef SNRT_INIT_CLS
12extern uint32_t snrt_cls_base_addr();
13#endif
14
15#ifdef SNRT_INIT_TLS
16static inline void snrt_init_tls() {
17 extern volatile uint32_t __tdata_start, __tdata_end;
18 extern volatile uint32_t __tbss_start, __tbss_end;
19
20 size_t size;
21 volatile uint32_t tls_ptr;
22
23 // To avoid contentions in main memory, and take advantage of the
24 // bandwidth of the DMA, the DM core initializes the TLS section
25 // for every core in a cluster.
26 if (snrt_is_dm_core()) {
27 size = (size_t)(&__tdata_end) - (size_t)(&__tdata_start);
28
29 // First initialize the DM core's .tdata section from main memory
30 asm volatile("mv %0, tp" : "=r"(tls_ptr) : :);
31 snrt_dma_start_1d(tls_ptr, (uint64_t)&__tdata_start, size);
33
34 // Then initialize all other cores' .tdata sections from the DM
35 // core's. The offset between the TLS section of successive cores
36 // is defined in start.S
37 size_t tls_offset = (1 << SNRT_LOG2_STACK_SIZE) + 8;
38 for (int i = 1; i < snrt_cluster_core_num(); i++) {
39 snrt_dma_start_1d(tls_ptr + i * tls_offset, tls_ptr, size);
40 }
41
42 // Initialize all cores' .tbss sections
43 tls_ptr += size;
44 size = (size_t)(&__tbss_end) - (size_t)(&__tbss_start);
45 for (int i = 0; i < snrt_cluster_core_num(); i++) {
46 snrt_dma_memset((void*)(tls_ptr + i * tls_offset), 0, size);
47 }
49 }
50
51 snrt_cluster_hw_barrier();
52}
53#endif
54
55#ifdef SNRT_INIT_BSS
56static inline void snrt_init_bss() {
57 extern volatile uint32_t __bss_start, __bss_end;
58
59 // Only one core needs to perform the initialization
60 if (snrt_cluster_idx() == 0) {
61 if (snrt_is_dm_core()) {
62 size_t size = (size_t)(&__bss_end) - (size_t)(&__bss_start);
63 snrt_dma_memset((void*)&__bss_start, 0, size);
65 }
66 snrt_cluster_hw_barrier();
67 }
68}
69#endif
70
71#ifdef SNRT_WAKE_UP
72static inline void snrt_wake_up() {
73 // Core 0 of cluster 0 wakes up all other cores
74 if (snrt_cluster_idx() == 0 && snrt_cluster_core_idx() == 0) {
75 // Do not use `snrt_wake_all` routine which requires
76 // TLS to already be initialized.
77 for (int i = 0; i < snrt_cluster_num(); i++) {
78 if (snrt_cluster_idx() != i) {
79 snrt_cluster(i)->peripheral_reg.cl_clint_set.f.cl_clint_set =
80 (1 << snrt_cluster_core_num()) - 1;
81 }
82 }
83 snrt_fence();
84 }
85
86 // Synchronize all cores
87 snrt_cluster_hw_barrier();
88
89 // Clear the reset flag
90 snrt_int_clr_mcip();
91}
92#endif
93
94#ifdef SNRT_INIT_CLS
95static inline void snrt_init_cls() {
96 extern volatile uint32_t __cdata_start, __cdata_end;
97 extern volatile uint32_t __cbss_start, __cbss_end;
98
99 // Only one core per cluster has to do this
100 if (snrt_is_dm_core()) {
101 uint64_t ptr = (uint64_t)snrt_cls_base_addr();
102 size_t size;
103
104 // Copy cdata section to base of the TCDM
105 size = (size_t)(&__cdata_end) - (size_t)(&__cdata_start);
106 snrt_dma_start_1d(ptr, (uint64_t)(&__cdata_start), size);
107
108 // Clear cbss section
109 ptr += size;
110 size = (size_t)(&__cbss_end) - (size_t)(&__cbss_start);
111 snrt_dma_memset((void*)ptr, 0, size);
113 }
114 // Init the cls pointer
115 _cls_ptr = (cls_t*)snrt_cls_base_addr();
116 snrt_cluster_hw_barrier();
117}
118#endif
119
120#ifdef SNRT_INIT_LIBS
121static inline void snrt_init_libs() {
122 snrt_alloc_init();
123 snrt_l1_init();
124 snrt_l3_init();
125 snrt_comm_init();
126}
127#endif
128
129#ifdef SNRT_CRT0_EXIT
130extern void snrt_exit_default(int exit_code);
131#ifndef SNRT_CRT0_ALTERNATE_EXIT
132extern void snrt_exit(int exit_code);
133#endif
134#endif
135
136// Referenced in an assembly file (start.S), must use C linkage
137EXTERN_C void snrt_main() {
138 int exit_code = 0;
139 if (snrt_cluster_idx() == 0) {
140 snrt_int_clr_mcip();
141 }
142
143#ifdef SNRT_CRT0_CALLBACK0
144 snrt_crt0_callback0();
145#endif
146
147#ifdef SNRT_INIT_BSS
148 snrt_init_bss();
149#endif
150
151#ifdef SNRT_WAKE_UP
152 snrt_wake_up();
153#endif
154
155#ifdef SNRT_CRT0_CALLBACK1
156 snrt_crt0_callback1();
157#endif
158
159#ifdef SNRT_INIT_TLS
160 snrt_init_tls();
161#endif
162
163#ifdef SNRT_CRT0_CALLBACK2
164 snrt_crt0_callback2();
165#endif
166
167#ifdef SNRT_INIT_CLS
168 snrt_init_cls();
169#endif
170
171#ifdef SNRT_CRT0_CALLBACK3
172 snrt_crt0_callback3();
173#endif
174
175#ifdef SNRT_INIT_LIBS
176 snrt_init_libs();
177#endif
178
179#ifdef SNRT_CRT0_CALLBACK4
180 snrt_crt0_callback4();
181#endif
182
183#ifdef SNRT_CRT0_PRE_BARRIER
184 snrt_cluster_hw_barrier();
185#endif
186
187#ifdef SNRT_CRT0_CALLBACK5
188 snrt_crt0_callback5();
189#endif
190
191#ifdef SNRT_INVOKE_MAIN
192 extern int main();
193 exit_code = main();
194#endif
195
196#ifdef SNRT_CRT0_CALLBACK6
197 snrt_crt0_callback6();
198#endif
199
200#ifdef SNRT_CRT0_POST_BARRIER
201 snrt_cluster_hw_barrier();
202#endif
203
204#ifdef SNRT_CRT0_CALLBACK7
205 snrt_crt0_callback7();
206#endif
207
208#ifdef SNRT_CRT0_EXIT
209 snrt_exit(exit_code);
210#endif
211
212#ifdef SNRT_CRT0_CALLBACK8
213 snrt_crt0_callback8();
214#endif
215}
static uint32_t snrt_dma_start_1d(uint64_t dst, uint64_t src, size_t size, const uint32_t channel=0)
Start an asynchronous 1D DMA transfer with 64-bit wide pointers on a specific DMA channel.
Definition dma.h:31
static void snrt_dma_wait_all(const uint32_t channel=0)
Block until a specific DMA channel is idle.
Definition dma.h:239
Definition cls_decls.h:11