1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32
33 import xdc.rov.ViewInfo;
34 import xdc.runtime.IHeap;
35 import xdc.runtime.ILogger;
36 import xdc.runtime.ITimestampClient;
37 import xdc.runtime.Diags;
38 import xdc.runtime.Log;
39 import xdc.runtime.Assert;
40 import xdc.runtime.Error;
41 import xdc.runtime.Types;
42
43 44 45
46
47 /*!
48 * ======== LoggerBuf ========
49 * A logger which stores `Log` events in a buffer.
50 *
51 * This module provides a logger which captures `{@link xdc.runtime.Log}` events to a
52 * buffer in realtime. The `Log` events stored in the buffer are
53 * unformatted; `Log` event formatting is deferred until some client reads
54 * the raw event data from the buffer. You can use
55 * `{@link #flush LoggerBuf_flush()}` to process the `Log` events stored
56 * in the buffer and stream the formatted output to stdout
57 * (via `{@link xdc.runtime.System#printf}`). Alternatively, you can read a raw event
58 * (via `{@link #getNextEntry}`) and send it to another client that
59 * has the resources to format the event for display.
60 *
61 * The implementation of this logger is fast with minimal stack usage
62 * making it appropriate for a realtime application.
63 * This logger writes all `Log` events to a circular buffer. As a
64 * result, the execution time of all `Log` methods bound to this type
65 * of logger are deterministic (and quite short) because there are no
66 * additional memory allocation calls after the circular buffer was
67 * allocated.
68 *
69 * If this logger is used in a preemptive environment, then an appropriate
70 * gate must be assigned to the module. For example, if events are generated
71 * from an interrupt context, then a gate that disables interrupts
72 * must be used.
73 *
74 * @p(code)
75 * var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
76 * LoggerBuf.common$.gate = ...some gate instance...
77 * @p
78 *
79 * If the buffer type is circular, the log buffer of size
80 * `{@link #numEntries}` contains the last `numEntries` of `Log` events. If
81 * the buffer type is fixed, the log buffer contains the first
82 * `numEntries` events.
83 *
84 * LoggerBuf supports routing of 'STATUS' events (errors and warnings) to a
85 * separate ILogger instance. This is helpful in preserving these critical
86 * events, which may otherwise be overwritten by lower priority events. This
87 * feature is disabled by default. See {@link #statusLogger}.
88 *
89 * LoggerBuf implements the {@link xdc.runtime.IFilterLogger} interface and
90 * optionally supports filtering of events based on their detail level. This
91 * feature is disabled by default. See {@link xdc.runtime.IFilterLogger}.
92 *
93 * @a(Examples)
94 * Configuration example: The following XDC configuration statements
95 * create a logger instance, assign it as the default logger for all
96 * modules, and enable `USER1` logging in all modules of the package
97 * `my.pkg`. See the `{@link xdc.runtime.Diags#setMaskMeta Diags.setMaskMeta()}` function
98 * for details on specifying the module names.
99 *
100 * @p(code)
101 * var Defaults = xdc.useModule('xdc.runtime.Defaults');
102 * var Diags = xdc.useModule('xdc.runtime.Diags');
103 * var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
104 *
105 * LoggerBuf.enableFlush = true;
106 * var LoggerBufParams = new LoggerBuf.Params();
107 * LoggerBufParams.exitFlush = true;
108 * Defaults.common$.logger = LoggerBuf.create(LoggerBufParams);
109 * Diags.setMaskMeta("my.pkg.%", Diags.USER1, Diags.RUNTIME_ON);
110 * @p
111 */
112
113 @ModuleStartup
114 @InstanceFinalize
115 @InstanceInitError
116 @Gated
117
118 module LoggerBuf inherits xdc.runtime.IFilterLogger {
119
120 /*!
121 * ======== BufType ========
122 * Type of log buffer
123 */
124 enum BufType {
125 BufType_CIRCULAR, /*! The log buffer wraps, overwriting old entries */
126 BufType_FIXED /*! The log buffer halts collection when full */
127 };
128
129 metaonly struct BasicView {
130 String label;
131 Int lastSerial;
132 Int numEntries;
133 String type;
134 Bool enabledFlag;
135 };
136
137 metaonly struct RecordView {
138 Int serial;
139 Long timestampRaw;
140 UInt core;
141 String modName;
142 String text;
143 Int eventId;
144 String eventName;
145 IArg arg0;
146 IArg arg1;
147 IArg arg2;
148 IArg arg3;
149 IArg arg4;
150 IArg arg5;
151 IArg arg6;
152 IArg arg7;
153 }
154
155 /*!
156 * ======== rovViewInfo ========
157 * @_nodoc
158 */
159 @Facet
160 metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
161 xdc.rov.ViewInfo.create({
162 viewMap: [
163 ['Basic',
164 {
165 type: xdc.rov.ViewInfo.INSTANCE,
166 viewInitFxn: 'viewInitBasic',
167 structName: 'BasicView'
168 }
169 ],
170 ['Records',
171 {
172 type: xdc.rov.ViewInfo.INSTANCE_DATA,
173 viewInitFxn: 'viewInitRecords',
174 structName: 'RecordView'
175 }
176 ]
177 ]
178 });
179
180 /*!
181 * ======== StopModeData ========
182 * Data added to the RTA MetaData file to support stop mode RTA
183 */
184 @XmlDtd metaonly struct StopModeData {
185 String bufferSymbol;
186 Int bufferSize;
187 }
188
189 /*!
190 * ======== E_badLevel ========
191 * Error raised if get or setFilterLevel receives a bad level value
192 */
193 config Error.Id E_badLevel =
194 {msg: "E_badLevel: Bad filter level value: %d"};
195
196 /*!
197 * ======== TimestampProxy ========
198 * User supplied time-stamp proxy
199 *
200 * This proxy allows `LoggerBuf` to use a timestamp server different
201 * from the server used by `{@link xdc.runtime.Timestamp}`. However, if
202 * not supplied by a user, this proxy defaults to whichever timestamp
203 * server is used by `Timestamp`.
204 */
205 proxy TimestampProxy inherits ITimestampClient;
206
207 /*!
208 * ======== enableFlush ========
209 * Flush all logs at system exit
210 */
211 config Bool enableFlush = false;
212
213 /*!
214 * ======== statusLogger ========
215 * Route all 'STATUS' (error and warning) events to this logger.
216 *
217 * If a statusLogger is specified, all LoggerBuf instances will check to
218 * determine if any of the events they receive are errors or warnings (if
219 * their diags mask includes the STATUS category), and will log these
220 * events to the statusLogger.
221 *
222 * Error events are infrequent, but it's generally critical that they be
223 * seen. In a typical system, non-error events easily outnumber any error
224 * events, and the logger is likely to wrap, overwriting any error events.
225 * To protect these events from being overwritten and lost, they can be
226 * sent to their own separate logger to preserve them.
227 *
228 * The default value is null, indicating that the STATUS events will just
229 * be logged by the logger they were sent to.
230 */
231 config ILogger.Handle statusLogger = null;
232
233 /*!
234 * ======== level1Mask ========
235 * Mask of diags categories whose initial filtering level is Diags.LEVEL1
236 *
237 * See '{@link #level4Mask}' for details.
238 */
239 config Diags.Mask level1Mask = 0;
240
241 /*!
242 * ======== level2Mask ========
243 * Mask of diags categories whose initial filtering level is Diags.LEVEL2
244 *
245 * See '{@link #level4Mask}' for details.
246 */
247 config Diags.Mask level2Mask = 0;
248
249 /*!
250 * ======== level3Mask ========
251 * Mask of diags categories whose initial filtering level is Diags.LEVEL3
252 *
253 * See '{@link #level4Mask}' for details.
254 */
255 config Diags.Mask level3Mask = 0;
256
257 /*!
258 * ======== level4Mask ========
259 * Mask of diags categories whose initial filtering level is Diags.LEVEL4
260 *
261 * If `{@link xdc.runtime.IFilterLogger.filterByLevel}` is `true`, then all
262 * `LoggerBuf` instances will filter incoming events based on their
263 * event level.
264 *
265 * The `LoggerBuf` module allows for specifying a different filter level
266 * for every `Diags` bit. These filtering levels are module wide;
267 * `LoggerBuf` does not support specifying the levels on a per-instance
268 * basis.
269 *
270 * The `{@link xdc.runtime.IFilterLogger.setFilterLevel}` function can be used to
271 * change the filtering levels at runtime.
272 *
273 * The default filtering levels are assigned using the `level1Mask` -
274 * `level4Mask` config parameters. These are used to specify, for each of
275 * the four event levels, the set of bits which should filter at that
276 * level by default.
277 *
278 * The default filtering configuration sets the filter level to
279 * `Diags.LEVEL4` for all logging-related diags bits so that all events
280 * are logged by default.
281 */
282 config Diags.Mask level4Mask = Diags.ALL_LOGGING;
283
284 /*!
285 * ======== flushAll ========
286 * Flush logs of all instances that set `exitFlush` to true
287 *
288 * The user is responsible for making sure that no `LoggerBuf` instances
289 * are created or deleted during the execution of this function.
290 */
291 Void flushAll();
292
293 /*!
294 * ======== flushAllInternal ========
295 * @_nodoc
296 */
297 Void flushAllInternal(Int stat);
298
299 /*!
300 * ======== initDecoder ========
301 * @_nodoc
302 * Initialize the LoggerBufDecoder for use in the LoggerBuf 'Records' ROV
303 * view.
304 */
305 function initDecoder();
306
307 instance:
308 /*!
309 * ======== create ========
310 * Create a `LoggerBuf` logger
311 *
312 * @see LoggerBuf#Params
313 */
314 create();
315
316 /*!
317 * ======== numEntries ========
318 * Number of entries in buffer
319 *
320 * Each entry is large enough to store one `Log` event containing up to
321 * 4 optional arguments. Events containing more than 4 arguments (such
322 * as those from `{@link xdc.runtime.Log#write5}`) use 2 entries.
323 *
324 * `numEntries` must be a power of 2.
325 */
326 config Int numEntries = 64;
327
328 /*!
329 * ======== bufType ========
330 * Log buffer type
331 */
332 config BufType bufType = BufType_CIRCULAR;
333
334 /*!
335 * ======== exitFlush ========
336 * Flush log at system exit
337 *
338 * Only used when module parameter `{@link #enableFlush}` is `true`.
339 */
340 config Bool exitFlush = false;
341
342 /*!
343 * ======== bufSection ========
344 * Section name for the buffer managed by the static instance.
345 *
346 * The default section is the 'dataSection' in the platform.
347 */
348 metaonly config String bufSection = null;
349
350 /*!
351 * ======== bufHeap ========
352 * The heap that contains the `Log` buffer for dynamic instances.
353 *
354 * The default value `null` means the buffer will be allocated from
355 * the `{@link xdc.runtime.Memory#defaultHeapInstance}` heap.
356 */
357 config IHeap.Handle bufHeap = null;
358
359 /*!
360 * ======== reset ========
361 * Reset a log to empty state and enable it
362 *
363 * @a(WARNING) This method is not synchronized with other instance
364 * methods and, as a result, it must never be called when there is a
365 * chance that another instance method is currently in operation or
366 * when another method on this instance may preempt this call.
367 */
368 Void reset();
369
370 /*!
371 * ======== flush ========
372 * Read, clear, and output the contents of the log
373 *
374 * This method reads, clears, and "prints" each `Log` event (via
375 * `{@link xdc.runtime.System#printf}`) in the log.
376 */
377 Void flush();
378
379 /*!
380 * ======== getNextEntry ========
381 * Fills the passed `{@link xdc.runtime.Log#EventRec}` with the next entry in the log.
382 *
383 * This function is used to read and clear `Log` events from the
384 * buffer maintained by the `LoggerBuf` instance. The `Log` event can
385 * then be transmitted and displayed on a host.
386 *
387 * A read pointer is maintained in the `LoggerBuf` instance and
388 * points to the next record to read. Entries are not necessarily
389 * returned in chronological order, since buffers of type
390 * `{@link #BufType_CIRCULAR}` can wrap.
391 *
392 * @param(evtRec) pointer to a supplied `EventRec` object where the next
393 * entry in the log is copied to
394 *
395 * @a(returns)
396 * This function reports the number of entries actually read. The only
397 * values that can be returned are:
398 * @p(blist)
399 * - 0 no more entries to read
400 * - 1 or 2 read a complete entry written by `write4` or `write8`
401 * - -1 cleared an incomplete/overwritten entry, more entries to read
402 */
403 Int getNextEntry(Log.EventRec *evtRec);
404
405 internal:
406
407 Bool filterOutEvent(Diags.Mask mask);
408
409 410 411
412 Void instanceStartup(Object *obj);
413
414 const Int8 FULL = -1;
415 const Int8 WRAP = 0;
416
417 const Int8 NEXT = 1;
418
419 struct Entry {
420 Types.Timestamp64 tstamp;
421 Bits32 serial;
422 Types.Event evt;
423 IArg arg1;
424 IArg arg2;
425 IArg arg3;
426 IArg arg4;
427 };
428
429 struct Module_State {
430 Diags.Mask level1;
431 Diags.Mask level2;
432 Diags.Mask level3;
433 };
434
435 struct Instance_State {
436 IHeap.Handle bufHeap;
437 Entry entryArr[];
438 Entry *curEntry;
439 Entry *endEntry;
440 Entry *readEntry;
441 Bits32 serial;
442 Int16 numEntries;
443 Int8 advance;
444 Bool enabled;
445 Bool flush;
446 };
447
448 }