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
34 35 36
37 import xdc.runtime.ILogger;
38 import ti.uia.runtime.ILoggerSnapshot;
39 import xdc.rov.ViewInfo;
40 import xdc.runtime.Log;
41 import xdc.runtime.Diags;
42 import xdc.runtime.Types;
43 import xdc.runtime.Log;
44 import xdc.runtime.Error;
45
46 /*!
47 * ======== LoggerStreamer ========
48 * This general purpose logger is useful in situations where the application
49 * wants to manage the buffers used to store and transmit events. This includes
50 * managing the sending of the buffers to an instrumentation host (e.g.
51 * System Analyzer in CCS). The logger is named "LoggerStreamer" because it is
52 * designed to enable the application to send a stream of packets containing
53 * UIA event data to the instrumentation host.
54 *
55 * The application is responsible for providing the buffers that LoggerStreamer
56 * uses. There are two ways to accomplish this.
57 * @p(blist)
58 * - Provide a prime callback function via the `{@link #primeFxn}`
59 * configuration parameter.
60 * - Call the `{@link #prime}` API once.
61 * @p
62 *
63 * The logger stores the events in a UIAPacket event packet structure that
64 * allows them to be sent directly to System Analyzer (e.g. via UDP), enabling
65 * efficient streaming of the data from the target to the host. The first
66 * four 32-bit words contain a `{@link UIAPacket#Hdr}` structure. This struct
67 * is used by the host (e.g. System Analyzer in CCS) to help decode the
68 * data (e.g. endianess, length of data, etc.). The `{@link UIAPacket#Hdr}`
69 * structure is initialized via the `{@link #initBuffer}` API. All buffers
70 * given to LoggerStreamer (via priming or exchange) must be initialized via
71 * `{@link #initBuffer}`.
72 *
73 * The size of buffer -*- includes UIAPacket_Hdr?
74 * LoggerStreamer treats the buffer as a UInt32 array. So the application
75 * must guarantee the buffers are aligned on word addresses. Alignment on
76 * cache line boundaries is recommended for best performance.
77 *
78 * When the buffer is filled, LoggerStreamer will hand it off to the
79 * application using an application-provided exchange function (`{@link #exchangeFxn}`).
80 * The exchange function must be of type `{@link #ExchangeFxnType}`.
81 * The exchange function is called in the context of a log
82 * so generally the exchange function should be quick to execute.
83 *
84 * The exchange function is called within the context of a Log call, so the exchange
85 * function should be design to fast. Since the exchange function is called
86 * within the context of the Log call, LoggerStreamer guarantees no Log
87 * records are dropped (i.e. LoggerStreamer is lossless).
88 *
89 * LoggerStreamer was designed to have as minimal impact as possible on an
90 * application when calling a Log function. There are several configuration
91 * parameters that allow an application to get the optimal performance in
92 * exchange for certain restrictions.
93 *
94 * Interrupts are disabled during the duration of the log call including
95 * when the exchange function is called. LoggerStreamer will ignore any
96 * log events generated during the exchangeFxn (e.g. posting a semaphore).
97 *
98 * @a(Examples)
99 * The following XDC configuration statements
100 * create a logger module, and assign it as the default logger for all
101 * modules.
102 *
103 * @p(code)
104 * var Defaults = xdc.useModule('xdc.runtime.Defaults');
105 * var Diags = xdc.useModule('xdc.runtime.Diags');
106 * var LoggerStreamer = xdc.useModule('ti.uia.sysbios.LoggerStreamer');
107 *
108 * LoggerStreamer.bufSize = 1024;
109 * LoggerStreamer.isTimestampEnabled = true;
110 * LoggerStreamer.primeFxn = '&prime';
111 * LoggerStreamer.exchangeFxn = '&exchange';
112 * Defaults.common$.logger = LoggerStreamer.create();
113 * @p
114 *
115 * @a(Examples)
116 * The following C code demonstrates a basic prime and exchange example.
117 * A real implementation would send the buffer to an instrumentation
118 * host (e.g. System Analyzer in CCS) via a transport such as UDP.
119 *
120 * @p(code)
121 * UInt32 buffer[2][BUFSIZE];
122
123 * Ptr prime()
124 * {
125 * LoggerStreamer_initBuffer(buffer[0], 0);
126 * LoggerStreamer_initBuffer(buffer[1], 0);
127 * return ((Ptr)(buffer[0]));
128 * }
129 *
130 * Ptr exchange(Ptr *full)
131 * {
132 * count++;
133 * // Ping-pong between the two buffers
134 * return ((Ptr*)buffer[count & 1]);
135 * }
136 * @p
137 */
138
139 @ModuleStartup
140 @Template("./LoggerStreamer.xdt")
141 @CustomHeader
142 module LoggerStreamer inherits ILoggerSnapshot {
143
144 /*!
145 * ======== TransportType ========
146 * Used to specify the type of transport to use
147 *
148 * This enum is used by the instrumentation host to determine what
149 * the transport is. It is not used by the target code.
150 */
151 enum TransportType {
152 TransportType_UART = 0,
153 TransportType_USB = 1,
154 TransportType_ETHERNET = 2,
155 TransportType_CUSTOM = 3
156 };
157
158 /*!
159 * @_nodoc
160 * ======== ModuleView ========
161 */
162 metaonly struct ModuleView {
163 Bool isEnabled;
164 Bool isTimestampEnabled;
165 Int bufferSize;
166 String primeFunc;
167 String exchangeFunc;
168 String transportType;
169 String customTransport;
170 }
171
172 metaonly struct RecordView {
173 Int sequence;
174 Long timestampRaw;
175 String modName;
176 String text;
177 Int eventId;
178 String eventName;
179 IArg arg0;
180 IArg arg1;
181 IArg arg2;
182 IArg arg3;
183 IArg arg4;
184 IArg arg5;
185 IArg arg6;
186 IArg arg7;
187 }
188
189 /*!
190 * @_nodoc
191 * ======== rovViewInfo ========
192 */
193 @Facet
194 metaonly config ViewInfo.Instance rovViewInfo =
195 ViewInfo.create({
196 viewMap: [
197 ['Module',
198 {
199 type: ViewInfo.MODULE,
200 viewInitFxn: 'viewInitModule',
201 structName: 'ModuleView'
202 }
203 ],
204 ['Records',
205 {
206 type: xdc.rov.ViewInfo.MODULE_DATA,
207 viewInitFxn: 'viewInitRecords',
208 structName: 'RecordView'
209 }
210 ]
211 ]
212 });
213
214 /*!
215 * ======== initBuffer ========
216 * Initializes the UIA packet header.
217 *
218 * This API is used to initialize a buffer before it is given to
219 * LoggerStreamer (via priming or exchange). The function initializes
220 * the UIAPacket portion of the buffer.
221 *
222 * @param(buffer) Pointer to the buffer that LoggerStreamer will
223 * fill with Log events. The first four 32-bit words
224 * will contain the UIAPacket_Hdr structure.
225 *
226 * @param(src) Used to initialize the UIA source address. For
227 * a single core device, this will generally be 0.
228 * For multi-core devices, it generally corresponds
229 * to the DNUM (on C6xxxx deviecs) or the Ipc
230 * MultiProc id. It must be unique for all cores and
231 * match the configuration in the System Analyzer
232 * endpoint configuration.
233 */
234 @Macro Void initBuffer(Ptr buffer, UInt16 src);
235
236 /*!
237 * ======== flush ========
238 * Force LoggerStreamer to call the exchange function
239 *
240 * This API makes LoggerStreamer call the application provided
241 * `{@link #exchangeFxn}` function if there are Log events present
242 * in the buffer.
243 *
244 * The call to the `{@link #exchangeFxn}` function is called in the
245 * context of the flush call.
246 */
247 Void flush();
248
249 /*!
250 * ======== prime =========
251 * If PrimeFxn is not set the user must call prime with the first buffer.
252 */
253 Bool prime(Ptr buffer);
254
255 /*!
256 * ======== ExchangeFxnType ========
257 * Typedef for the exchange function pointer.
258 */
259 typedef Ptr (*ExchangeFxnType)(Ptr);
260
261 /*!
262 * ======== PrimeFxnType ========
263 * Typedef for the exchange function pointer.
264 */
265 typedef Ptr (*PrimeFxnType)(Void);
266
267 /*!
268 * ======== bufSize ========
269 * LoggerStreamer buffer size in MAUs (Minimum Addressable Units e.g. Bytes)
270 *
271 * NOTE: the buffer size must contain an integer number of 32b words
272 * (e.g. if a MAU = 1 byte, then the buffer size must be a multiple of 4).
273 * The buffer size must also be at least maxEventSize + 64.
274 */
275 config SizeT bufSize = 1400;
276
277 /*!
278 * ======== transportType ========
279 * Transport used to send the records to an instrumentation host
280 *
281 * This parameter is used to specify the transport that the
282 * `{@link #exchangeFxn}` function will use to send the buffer to
283 * an instrumentation host (e.g. System Analyzer in CCS).
284 *
285 * This parameter is placed into the generated UIA XML file. The
286 * instrumentation host can use the XML file to help it auto-detect as
287 * much as possible and act accordingly.
288 *
289 * If the desired transport is not in the `{@link #TransportType}` enum,
290 * select `{@link #TransportType_CUSTOM}` and set the
291 * `{@link #customTransportType}` string with the desired string.
292 */
293 metaonly config TransportType transportType = TransportType_ETHERNET;
294
295 /*!
296 * ======== customTransportType ========
297 * Custom transport used to send the records to an instrumentation host
298 *
299 * If the desired transport is not in the `{@link #TransportType}` enum,
300 * and `{@link #transportType}` is set to `{@link #TransportType_CUSTOM}`,
301 * this parameter must be filled in with the correct transport name.
302 *
303 * If `{@link #transportType}` is NOT set to
304 * `{@link #TransportType_CUSTOM}`, this parameter is ignored.
305 */
306 config String customTransportType = null;
307
308 /*!
309 * ======== isTimestampEnabled ========
310 * Enable or disable logging the 64b local CPU timestamp
311 * at the start of each event
312 *
313 * Having a timestamp allows an instrumentation host (e.g.
314 * System Analyzer) to display events with the correct system time.
315 */
316 config Bool isTimestampEnabled = false;
317
318 /*!
319 * @_nodoc
320 * ======== isBadPacketDetectionEnabled ========
321 * Enable or disable checking that the event contents in the packet are
322 * properly formatted with no data errors
323 *
324 * If enabled, a breakpoint can be placed in the code to detect when
325 * a bad packet is found.
326 */
327 config Bool isBadPacketDetectionEnabled = false;
328 /*!
329 * ======== supportLoggerDisable ========
330 * Allow LoggerStreamer to be enabled/disabled during runtime.
331 */
332 config Bool supportLoggerDisable = false;
333
334 /*!
335 * ======== testForNullWrPtr ========
336 * Protect against log calls during the exchange function.
337 */
338 config Bool testForNullWrPtr = true;
339
340 /*!
341 * ======== primeFxn ========
342 * Function pointer to the prime function.
343 */
344 config PrimeFxnType primeFxn = null;
345
346 /*!
347 * ======== exchangeFxn ========
348 * Function pointer to the exchange function.
349 *
350 * exchange function must return a pointer to a buffer that is word aligned, initialized with
351 * a UIA header and the correct size. This is called in the context of a log
352 * so generally the exchange function should be quick to execute.
353 */
354 config ExchangeFxnType exchangeFxn = null;
355
356
357 /*!
358 * ======== statusLogger ========
359 * This configuration option is not supported by this logger and should be left null.
360 */
361 config xdc.runtime.IFilterLogger.Handle statusLogger = null;
362
363 /*!
364 * ======== level1Mask ========
365 * Mask of diags categories whose initial filtering level is Diags.LEVEL1
366 *
367 * See '{@link #level4Mask}' for details.
368 */
369 config Diags.Mask level1Mask = 0;
370
371 /*!
372 * ======== level2Mask ========
373 * Mask of diags categories whose initial filtering level is Diags.LEVEL2
374 *
375 * See '{@link #level4Mask}' for details.
376 */
377 config Diags.Mask level2Mask = 0;
378
379 /*!
380 * ======== level3Mask ========
381 * Mask of diags categories whose initial filtering level is Diags.LEVEL3
382 *
383 * See '{@link #level4Mask}' for details.
384 */
385 config Diags.Mask level3Mask = 0;
386
387 /*!
388 * ======== level4Mask ========
389 * Mask of diags categories whose initial filtering level is Diags.LEVEL4
390 *
391 * If 'filterByLevel' is true, then all LoggerBuf instances will filter
392 * incoming events based on their event level.
393 *
394 * The LoggerCircBuf module allows for specifying a different filter level for
395 * every Diags bit. These filtering levels are module wide; LoggerBuf does
396 * not support specifying the levels on a per-instance basis.
397 *
398 * The setFilterLevel API can be used to change the filtering levels at
399 * runtime.
400 *
401 * The default filtering levels are assigned using the 'level1Mask' -
402 * 'level4Mask' config parameters. These are used to specify, for each of
403 * the four event levels, the set of bits which should filter at that
404 * level by default.
405 *
406 * The default filtering configuration sets the filter level to
407 * Diags.LEVEL4 for all logging-related diags bits so that all events are
408 * logged by default.
409 */
410 config Diags.Mask level4Mask = Diags.ALL_LOGGING;
411
412 /*!
413 * ======== moduleToRouteToStatusLogger ========
414 * This configuration option is not supported by this logger and should be left unconfigured.
415 */
416 metaonly config String moduleToRouteToStatusLogger;
417
418 /*!
419 * ======== setModuleIdToRouteToStatusLogger ========
420 * This function is provided for compatibility with the ILoggerSnapshot interface only
421 * and simply returns when called.
422 */
423 @DirectCall
424 Void setModuleIdToRouteToStatusLogger(Types.ModuleId mid);
425
426 /*!
427 * @_nodoc
428 * ======== L_test ========
429 * Event used to benchmark write0.
430 */
431 config xdc.runtime.Log.Event L_test = {
432 mask: xdc.runtime.Diags.USER1,
433 msg: "Test"
434 };
435
436 /*!
437 * @_nodoc
438 * ======== E_badLevel ========
439 * Error raised if get or setFilterLevel receive a bad level value
440 */
441 config Error.Id E_badLevel = {
442 msg: "E_badLevel: Bad filter level value: %d"
443 };
444
445 /*!
446 * ======== maxEventSize ========
447 * The maximum event size (in Maus) that can be written with a single event.
448 * Must be less than or equal to bufSize - 64.
449 *
450 * The writeMemoryRange API checks to see if the event size required to write
451 * the block of memory is larger than maxEventSize. If so, it will split the
452 * memory range up into a number of smaller blocks and log the blocks using
453 * separate events with a common snapshot ID in order to allow the events to be
454 * collated and the original memory block to be reconstructed on the host.
455 */
456 config SizeT maxEventSize = 512;
457
458 /*!
459 * @_nodoc
460 * ======== validatePacket ========
461 * if isBadPacketDetectionEnabled is configured as true, this function is called prior
462 * to the exchange function being called.
463 *
464 * Returns null if the packet is ok, else returns the address of a string
465 * that describes the error.
466 */
467 @DirectCall
468 Char* validatePacket(UInt32 *writePtr, UInt32 numBytesInPacket);
469
470 instance:
471
472 /*!
473 * ======== create ========
474 * Create a `LoggerStreamer` logger
475 */
476 create();
477
478 /*!
479 * ======== write0 ========
480 * Process a log event with 0 arguments and the calling address.
481 *
482 * Same as `write4` except with 0 arguments rather than 4.
483 * @see #write4()
484 */
485 @DirectCall
486 override Void write0(xdc.runtime.Log.Event evt,
487 xdc.runtime.Types.ModuleId mid);
488
489 /*!
490 * ======== write1 ========
491 * Process a log event with 1 arguments and the calling address.
492 *
493 * Same as `write4` except with 1 arguments rather than 4.
494 * @see #write4()
495 */
496 @DirectCall
497 override Void write1(xdc.runtime.Log.Event evt,
498 xdc.runtime.Types.ModuleId mid,
499 IArg a1);
500
501 /*!
502 * ======== write2 ========
503 * Process a log event with 2 arguments and the calling address.
504 *
505 * Same as `write4` except with 2 arguments rather than 4.
506 * @see #write4()
507 */
508 @DirectCall
509 override Void write2(xdc.runtime.Log.Event evt,
510 xdc.runtime.Types.ModuleId mid,
511 IArg a1, IArg a2);
512
513 /*!
514 * ======== write4 ========
515 * Process a log event with 4 arguments and the calling address.
516 *
517 * @see ILogger#write4()
518 */@DirectCall
519 override Void write4(xdc.runtime.Log.Event evt,
520 xdc.runtime.Types.ModuleId mid,
521 IArg a1, IArg a2, IArg a3, IArg a4);
522
523 /*!
524 * ======== write8 ========
525 * Process a log event with 8 arguments and the calling address.
526 *
527 * Same as `write4` except with 8 arguments rather than 4.
528 *
529 * @see #write4()
530 */
531 @DirectCall
532 override Void write8(xdc.runtime.Log.Event evt,
533 xdc.runtime.Types.ModuleId mid,
534 IArg a1, IArg a2, IArg a3, IArg a4,
535 IArg a5, IArg a6, IArg a7, IArg a8);
536
537 /*!
538 * ======== setFilterLevel ========
539 * Sets the level of detail that instances will log.
540 *
541 * Events with the specified level or higher will be logged, events
542 * below the specified level will be dropped.
543 *
544 * Events are filtered first by diags category, then by level. If an
545 * event's diags category is disabled in the module's diags mask, then it
546 * will be filtered out regardless of level. The event will not even be
547 * passed to the logger.
548 *
549 * This API allows for setting the filtering level for more than one
550 * diags category at a time. The mask parameter can be a single category
551 * or multiple categories combined, and the level will be set for all of
552 * those categories.
553 *
554 * @param(mask) The diags categories to set the level for
555 * @param(filterLevel) The new filtering level for the specified
556 * categories
557 */
558 @DirectCall
559 override Void setFilterLevel(Diags.Mask mask, Diags.EventLevel filterLevel);
560
561 /*!
562 * ======== getFilterLevel ========
563 * Returns the mask of diags categories currently set to the specified
564 * level.
565 *
566 * See '{@link #setFilterLevel}' for an explanation of level filtering.
567 */
568 @DirectCall
569 override Diags.Mask getFilterLevel(Diags.EventLevel level);
570
571
572
573 internal:
574
575
576 const Int WRITE0_SIZE_IN_BYTES = 8;
577 const Int WRITE1_SIZE_IN_BYTES = 12;
578 const Int WRITE2_SIZE_IN_BYTES = 16;
579 const Int WRITE4_SIZE_IN_BYTES = 24;
580 const Int WRITE8_SIZE_IN_BYTES = 40;
581
582 const Int TIMESTAMP = 8;
583 const Int NO_TIMESTAMP = 0;
584
585 /*!
586 * ======== filterOutEvent ========
587 */
588 @DirectCall
589 Bool filterOutEvent(Diags.Mask mask);
590
591 592 593 594
595 struct Module_State {
596 Bool enabled;
597 UInt32 *buffer;
598 UInt32 *write;
599 UInt32 *end;
600 Diags.Mask level1;
601 Diags.Mask level2;
602 Diags.Mask level3;
603 Types.ModuleId moduleIdToRouteToStatusLogger;
604 SizeT maxEventSizeInBits32;
605 Int droppedEvents;
606 };
607
608 struct Instance_State {
609 };
610 }