1 2 3 4 5 6 7 8 9 10 11 12
13 14 15
16
17 package xdc.runtime;
18
19 /*!
20 * ======== Startup ========
21 * The `xdc.runtime` startup bootstrap
22 *
23 * This module manages the very early startup initialization that occurs
24 * before C's `main()` function is invoked. This initialization typically
25 * consists of setting hardware specific registers that control watchdog
26 * timers, access to memory, cache settings, clock speeds, etc.
27 *
28 * In addition to configuration parameters that allow the user to add custom
29 * startup functions, this module also provides services that allow modules
30 * to automatically add initialization functions to the startup sequence.
31 *
32 * @a(Startup Sequence)
33 * The following list defines the startup sequence and, in particular, when
34 * user provided startup functions are invoked:
35 * @p(nlist)
36 * - CPU is initialized and initial C stack setup is performed.
37 * - The function specified by `Startup.resetFxn` is called.
38 * `Startup.resetFxn` is called only on platforms where reset is performed
39 * before running a program. For example, boot code for all TI targets
40 * invokes `Startup.resetFxn`, but this function is not invoked on
41 * Microsoft targets.
42 * - C runtime initialization is performed.
43 * - Functions from the array `Startup.firstFxns` are called.
44 * - All `Mod_Module_startup` functions (see Module Initialization below)
45 * are called in a loop until all such functions return
46 * `{@link #Startup_DONE}` or the `{@link #maxPasses}` threshold is
47 * reached.
48 * - Functions from the array `Startup.lastFxns` are called.
49 * - The function `main` is called.
50 * @p
51 * The steps 4 - 6 occur during C++ static object initialization. Since
52 * the ANSI C++ Language Standard does not provide a means to control
53 * the order of C++ constructors, if a C++ constructor uses an XDC module,
54 * there is no guarantee that the module's startup function already ran.
55 * Therefore, any C++ constructor that needs XDC modules' services should
56 * call `Startup_exec` first to force all startup related functions from
57 * steps 4 - 6 to run, before the constructor uses any XDC module.
58 * @p
59 * Also, if a target does not support C++, the steps 4 - 6 will not run
60 * automatically. It is then up to a user's code to invoke `Startup_exec`,
61 * possibly as the first step in `main`.
62 * @p
63 *
64 * @a(Module Initialization)
65 * Every module can optionally define a startup function which is called
66 * before `main()`. Modules declare that they want to participate in this
67 * startup sequence via the `@ModuleStartup` attribute in the module's spec
68 * file. Modules that use this attribute must also implement the following
69 * startup function:
70 * @p(code)
71 * Int Mod_Module_startup(Int state);
72 * @p
73 * where "Mod" is the name of the module requesting startup support.
74 *
75 * The parameter to the startup function serves as "state variable" whose
76 * initial value will be `Startup_NOTDONE`. If `startup()` returns a value
77 * other than `Startup_DONE`, it will be called in a subsequent pass with this
78 * return value passed in as `state`. To ensure this process terminates,
79 * no startup function is ever called more than `{@link #maxPasses}`
80 * times.
81 *
82 * For situations in which the startup of one module depends upon another
83 * having completed its startup processing, the following function is
84 * automatically defined for all modules and proxies:
85 * @p(code)
86 * Bool Mod_Module_startupDone();
87 * @p
88 * where "Mod" is the name of some module or proxy. These predicates can
89 * be used as guards inside of a startup function to probe whether a
90 * particular module has completed its own startup processing. As a
91 * convenience, the function `Startup_rtsDone()` probes the necessary set of
92 * `xdc.runtime` modules required to support instance `create()` functions, and
93 * should be called before any startup-time instance creation and/or
94 * memory allocation is performed.
95 * @p(code)
96 * Int Mod_Module_startup(Int state)
97 * {
98 * if (!Startup_rtsDone()) {
99 * return (Startup_NOTDONE);
100 * }
101 * .
102 * .
103 * .
104 * return (Startup_DONE);
105 * }
106 * @p
107 *
108 * @a(Examples)
109 * The following code shows how to add custom startup functions to this module.
110 * @p(code)
111 * var Startup = xdc.useModule('xdc.runtime.Startup');
112 * Startup.resetFxn = "&myResetFxn";
113 * Startup.firstFxns[Startup.firstFxns.length++] = "&myFirst";
114 * Startup.lastFxns[Startup.lastFxns.length++] = "&myLast";
115 * @p
116 *
117 */
118 @Template("./Startup.xdt")
119 @DirectCall
120
121 module Startup {
122
123 /*!
124 * ======== DONE ========
125 * Returned from module startup functions no further calls are required
126 */
127 const Int DONE = -1;
128
129 /*!
130 * ======== NOTDONE ========
131 * Initial value of state argument passed to module startup functions
132 */
133 const Int NOTDONE = 0;
134
135 /*!
136 * ======== ModuleView ========
137 * @_nodoc
138 */
139 metaonly struct ModuleView {
140 Bool rtsStartupDone;
141 Bool startupBegun;
142 String resetFxn;
143 String firstFxns[];
144 String lastFxns[];
145 }
146
147 /*!
148 * ======== StartupStateView ========
149 * @_nodoc
150 */
151 metaonly struct StartupStateView {
152 Int order;
153 String moduleName;
154 String done;
155 }
156
157 /*!
158 * ======== rovViewInfo ========
159 * @_nodoc
160 */
161 @Facet
162 metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
163 xdc.rov.ViewInfo.create({
164 viewMap: [
165 ['Module',
166 {
167 type: xdc.rov.ViewInfo.MODULE,
168 viewInitFxn: 'viewInitModule',
169 structName: 'ModuleView'
170 }
171 ],
172 ['Startup State',
173 {
174 type: xdc.rov.ViewInfo.MODULE_DATA,
175 viewInitFxn: 'viewInitStartupState',
176 structName: 'StartupStateView'
177 }
178 ]
179 ]
180 });
181
182 /*!
183 * ======== maxPasses ========
184 * Max number of iterations over the set of startup functions
185 */
186
187 config Int maxPasses = 32;
188
189 /*!
190 * ======== InitFxn ========
191 * Type of function assignable to `firstFxns`, `lastFxns`, or `resetFxn`
192 */
193 typedef Void (*InitFxn)();
194
195 /*!
196 * ======== firstFxns ========
197 * List of functions called before module startup
198 *
199 * @see
200 * #xdoc-sect-2 Startup Sequence
201 */
202
203 config InitFxn firstFxns[length] = [];
204
205 /*!
206 * ======== lastFxns ========
207 * List of functions called after module startup
208 *
209 * @see
210 * #xdoc-sect-2 Startup Sequence
211 */
212
213 config InitFxn lastFxns[length] = [];
214
215 /*!
216 * ======== resetFxn ========
217 * Function to be called by during initialization
218 *
219 * This function is called only on platforms where reset is performed
220 * before running the program. The purpose of this function is to set up
221 * the hardware registers (cache, external memory interface, etc.) before
222 * any other code executes.
223 *
224 * This function is called as early as possible in the
225 * {@link #xdoc-sect-2 program initialization} process.
226 *
227 * @see
228 * #xdoc-sect-2 Startup Sequence
229 */
230
231 metaonly config InitFxn resetFxn = null;
232
233 /*!
234 * ======== exec ========
235 * Execute the startup functions of all resident modules
236 *
237 * Note that this function is idempotent, and can be called at any point
238 * in the platform/target startup sequence in which "ordinary" C functions
239 * can execute. By default, this function is called as part of the
240 * standard C++ static initialization sequence.
241 *
242 * If your target compiler does not support C++, this function must be
243 * called at least once prior to using any `xdc.runtime` modules.
244 * Simply call this function at the very beginning of `main()`.
245 */
246
247 Void exec();
248
249 /*!
250 * ======== rtsDone ========
251 * Query the state of the `xdc.runtime` package
252 *
253 * This function is used by module startup functions to determine when it
254 * is possible to use the `xdc.runtime` modules; e.g. to allocate memory,
255 * create instances managed by some module (even those outside the
256 * `xdc.runtime` package), call a `Log` function, etc.
257 *
258 * @a(returns)
259 * Returns `TRUE` when all `xdc.runtime` modules have completed
260 * initialization.
261 */
262
263 Bool rtsDone();
264
265 internal:
266
267 /*!
268 * ======== reset ========
269 * Application-specific reset function
270 *
271 * This function is defined in `Startup.xdt`
272 * (`xdc_runtime_Startup_reset__I`) and is called as early as possible in
273 * the {@link #xdoc-sect-2 program initialization} process; for many
274 * platforms, it is called prior the the initialization of the C
275 * runtime environment.
276 *
277 * @see
278 * #xdoc-sect-2 Startup Sequence
279 */
280 Void reset();
281
282 Void startMods(Int state[], Int len);
283 readonly config Void (*startModsFxn)(Int[], Int) = startMods;
284
285 extern Void execImplFxn() = xdc_runtime_Startup_exec__I;
286
287 readonly config Void (*execImpl)() = execImplFxn;
288
289 typedef Int (*SFxn)(Int);
290
291 config SFxn sfxnTab[];
292
293 /*!
294 * ======== sfxnRts ========
295 * Array of runtime modules' startup functions
296 *
297 * This array also contains startup functions of the modules that inherit
298 * from interfaces in `xdc.runtime`. Functions added to this array are
299 * called only once before the startup procedure for all modules begins.
300 *
301 * @see
302 * #xdoc-sect-2 Startup Sequence
303 */
304 config Bool sfxnRts[];
305
306 /*!
307 * ======== getState ========
308 * Function that returns the value of the startup state.
309 *
310 * Modules for which the config C code is generated separately, and
311 * possibly before the configuration step is run, must call a function
312 * to get their startup state. They cannot reach into the state array
313 * directly because they don't know their indices in that array.
314 */
315 Int getState(Types.ModuleId id);
316
317 /*!
318 * ======== IdMap ========
319 * keeps track of modules in stateTab and their module IDs for purposes
320 * of the function getState.
321 */
322 struct IdMap {
323 UInt ind;
324 Types.ModuleId modId;
325 }
326
327 struct Module_State {
328 Int *stateTab;
329 Bool execFlag;
330 Bool rtsDoneFlag;
331 };
332
333 }
334 335 336
337