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