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 initialiazation 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 config Int maxPasses = 32;
187
188 /*!
189 * ======== InitFxn ========
190 * Type of function assignable to `firstFxns`, `lastFxns`, or `resetFxn`
191 */
192 typedef Void (*InitFxn)();
193
194 /*!
195 * ======== firstFxns ========
196 * List of functions called before module startup
197 *
198 * @see
199 * #xdoc-sect-2 Startup Sequence
200 */
201 config InitFxn firstFxns[length] = [];
202
203 /*!
204 * ======== lastFxns ========
205 * List of functions called after module startup
206 *
207 * @see
208 * #xdoc-sect-2 Startup Sequence
209 */
210 config InitFxn lastFxns[length] = [];
211
212 /*!
213 * ======== resetFxn ========
214 * Function to be called by during initialization
215 *
216 * This function is called only on platforms where reset is performed
217 * before running the program. The purpose of this function is to set up
218 * the hardware registers (cache, external memory interface, etc.) before
219 * any other code executes.
220 *
221 * This function is called as early as possible in the
222 * {@link #xdoc-sect-2 program initialization} process.
223 *
224 * @see
225 * #xdoc-sect-2 Startup Sequence
226 */
227 metaonly config InitFxn resetFxn = null;
228
229 /*!
230 * ======== exec ========
231 * Execute the startup functions of all resident modules
232 *
233 * Note that this function is idempotent, and can be called at any point
234 * in the platform/target startup sequence in which "ordinary" C functions
235 * can execute. By default, this function is called as part of the
236 * standard C++ static initialization sequence.
237 *
238 * If your target compiler does not support C++, this function must be
239 * called at least once prior to using any `xdc.runtime` modules.
240 * Simply call this function at the very beginning of `main()`.
241 */
242 Void exec();
243
244 /*!
245 * ======== rtsDone ========
246 * Query the state of the `xdc.runtime` package
247 *
248 * This function is used by module startup functions to determine
249 * when it is possible to use the `xdc.runtime` modules; e.g. to
250 * allocate memory, create instances managed by some module (even
251 * those outside the `xdc.runtime` package), call a `Log` function,
252 * etc.
253 *
254 * @a(returns)
255 * Returns `TRUE` when all `xdc.runtime` modules have completed
256 * initialization.
257 */
258 Bool rtsDone();
259
260 internal:
261
262 /*!
263 * ======== reset ========
264 * Application-specific reset function
265 *
266 * This function is defined in `Startup.xdt`
267 * (`xdc_runtime_Startup_reset__I`) and is called as early as
268 * possible in the {@link #xdoc-sect-2 program initialization}
269 * process; for many platforms, it is called prior the the
270 * initialization of the C runtime environment.
271 *
272 * @see
273 * #xdoc-sect-2 Startup Sequence
274 */
275 Void reset();
276
277 Void startMods(Int state[], Int len);
278 readonly config Void (*startModsFxn)(Int[], Int) = startMods;
279
280 extern Void execImplFxn() = xdc_runtime_Startup_exec__I;
281
282 readonly config Void (*execImpl)() = execImplFxn;
283
284 typedef Int (*SFxn)(Int);
285 config SFxn sfxnTab[];
286
287 /*!
288 * ======== sfxnRts ========
289 * Array of runtime modules' startup functions
290 *
291 * This array also contains startup functions of the modules that inherit
292 * from interfaces in `xdc.runtime`. Functions added to this array are
293 * called only once before the startup procedure for all modules begins.
294 *
295 * @see
296 * #xdoc-sect-2 Startup Sequence
297 */
298 config Bool sfxnRts[];
299
300 /*!
301 * ======== getState ========
302 * Function that returns the value of the startup state.
303 *
304 * Modules for which the config C code is generated separately, and
305 * possibly before the configuration step is run, must call a function
306 * to get their startup state. They cannot reach into the state array
307 * directly because they don't know their indices in that array.
308 */
309 Int getState(Types.ModuleId id);
310
311 /*!
312 * ======== IdMap ========
313 * keeps track of modules in stateTab and their module IDs for purposes
314 * of the function getState.
315 */
316 struct IdMap {
317 UInt ind;
318 Types.ModuleId modId;
319 }
320
321 struct Module_State {
322 Int *stateTab;
323 Bool execFlag;
324 Bool rtsDoneFlag;
325 };
326
327 }
328 329 330
331