blob: 435e08559ced0dbb4fe54419e0f18f53e5ccd2b6 [file] [log] [blame]
/* --COPYRIGHT--,ESD
* Copyright (c) 2008 Texas Instruments. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License
* v. 1.0 which accompanies this distribution. The Eclipse Public License is
* available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse
* Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Texas Instruments - initial implementation
* --/COPYRIGHT--*/
/*
* ======== LoggerBuf.xdc ========
*/
/*!
* ======== LoggerBuf ========
* A logger which stores `Log` events in a buffer.
*
* This module provides a logger which captures `{@link Log}` events to a
* buffer in realtime. The `Log` events stored in the buffer are
* unformatted; `Log` event formatting is deferred until some client reads
* the raw event data from the buffer. You can use
* `{@link #flush LoggerBuf_flush()}` to process the `Log` events stored
* in the buffer and stream the formatted output to stdout
* (via `{@link System#printf}`). Alternatively, you can read a raw event
* (via `{@link #getNextEntry}`) and send it to another client that
* has the resources to format the event for display.
*
* The implementation of this logger is fast with minimal stack usage
* making it appropriate for a realtime application.
* This logger writes all `Log` events to a circular buffer. As a
* result, the execution time of all `Log` methods bound to this type
* of logger are deterministic (and quite short) because there are no
* additional memory allocation calls after the circular buffer was
* allocated.
*
* If this logger is used in a preemptive environment, then an appropriate
* gate must be assigned to the module. For example, if events are generated
* from an interrupt context, then a gate that disables interrupts
* must be used.
*
* @p(code)
* var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
* LoggerBuf.common$.gate = ...some gate instance...
* @p
*
* If the buffer type is circular, the log buffer of size
* `{@link #numEntries}` contains the last `numEntries` of `Log` events. If
* the buffer type is fixed, the log buffer contains the first
* `numEntries` events.
*
* LoggerBuf supports routing of 'STATUS' events (errors and warnings) to a
* separate ILogger instance. This is helpful in preserving these critical
* events, which may otherwise be overwritten by lower priority events. This
* feature is disabled by default. See {@link #statusLogger}.
*
* LoggerBuf implements the {@link IFilterLogger} interface and
* optionally supports filtering of events based on their detail level. This
* feature is disabled by default. See {@link IFilterLogger}.
*
* @a(Examples)
* Configuration example: The following XDC configuration statements
* create a logger instance, assign it as the default logger for all
* modules, and enable `USER1` logging in all modules of the package
* `my.pkg`. See the `{@link Diags#setMaskMeta Diags.setMaskMeta()}` function
* for details on specifying the module names.
*
* @p(code)
* var Defaults = xdc.useModule('xdc.runtime.Defaults');
* var Diags = xdc.useModule('xdc.runtime.Diags');
* var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
*
* LoggerBuf.enableFlush = true;
* var LoggerBufParams = new LoggerBuf.Params();
* LoggerBufParams.exitFlush = true;
* Defaults.common$.logger = LoggerBuf.create(LoggerBufParams);
* Diags.setMaskMeta("my.pkg.%", Diags.USER1, Diags.RUNTIME_ON);
* @p
*/
@ModuleStartup /* Initialize static instances */
@InstanceFinalize /* this mod has cleanup fxn when instances are deleted */
@InstanceInitError /* instance create can fail */
@Gated
module LoggerBuf inherits IFilterLogger {
/*!
* ======== BufType ========
* Type of log buffer
*/
enum BufType {
BufType_CIRCULAR, /*! The log buffer wraps, overwriting old entries */
BufType_FIXED /*! The log buffer halts collection when full */
};
metaonly struct BasicView {
String label;
Int lastSerial;
Int numEntries;
String type;
Bool enabledFlag;
};
metaonly struct RecordView {
Int serial;
Long timestampRaw;
String modName;
String text;
Int eventId;
String eventName;
IArg arg0;
IArg arg1;
IArg arg2;
IArg arg3;
IArg arg4;
IArg arg5;
IArg arg6;
IArg arg7;
}
/*!
* ======== rovViewInfo ========
* @_nodoc
*/
@Facet
metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
xdc.rov.ViewInfo.create({
viewMap: [
['Basic',
{
type: xdc.rov.ViewInfo.INSTANCE,
viewInitFxn: 'viewInitBasic',
structName: 'BasicView'
}
],
['Records',
{
type: xdc.rov.ViewInfo.INSTANCE_DATA,
viewInitFxn: 'viewInitRecords',
structName: 'RecordView'
}
]
]
});
/*!
* ======== StopModeData ========
* Data added to the RTA MetaData file to support stop mode RTA
*/
@XmlDtd metaonly struct StopModeData {
String bufferSymbol;
Int bufferSize;
}
/*!
* ======== E_badLevel ========
* Error raised if get or setFilterLevel receives a bad level value
*/
config Error.Id E_badLevel =
{msg: "E_badLevel: Bad filter level value: %d"};
/*!
* ======== TimestampProxy ========
* User supplied time-stamp proxy
*
* This proxy allows `LoggerBuf` to use a timestamp server different
* from the server used by `{@link xdc.runtime.Timestamp}`. However, if
* not supplied by a user, this proxy defaults to whichever timestamp
* server is used by `Timestamp`.
*/
proxy TimestampProxy inherits ITimestampClient;
/*!
* ======== enableFlush ========
* Flush all logs at system exit
*/
config Bool enableFlush = false;
/*!
* ======== statusLogger ========
* Route all 'STATUS' (error and warning) events to this logger.
*
* If a statusLogger is specified, all LoggerBuf instances will check to
* determine if any of the events they receive are errors or warnings (if
* their diags mask includes the STATUS category), and will log these
* events to the statusLogger.
*
* Error events are infrequent, but it's generally critical that they be
* seen. In a typical system, non-error events easily outnumber any error
* events, and the logger is likely to wrap, overwriting any error events.
* To protect these events from being overwritten and lost, they can be
* sent to their own separate logger to preserve them.
*
* The default value is null, indicating that the STATUS events will just
* be logged by the logger they were sent to.
*/
config ILogger.Handle statusLogger = null;
/*!
* ======== level1Mask ========
* Mask of diags categories whose initial filtering level is Diags.LEVEL1
*
* See '{@link #level4Mask}' for details.
*/
config Diags.Mask level1Mask = 0;
/*!
* ======== level2Mask ========
* Mask of diags categories whose initial filtering level is Diags.LEVEL2
*
* See '{@link #level4Mask}' for details.
*/
config Diags.Mask level2Mask = 0;
/*!
* ======== level3Mask ========
* Mask of diags categories whose initial filtering level is Diags.LEVEL3
*
* See '{@link #level4Mask}' for details.
*/
config Diags.Mask level3Mask = 0;
/*!
* ======== level4Mask ========
* Mask of diags categories whose initial filtering level is Diags.LEVEL4
*
* If `{@link IFilterLogger.filterByLevel}` is `true`, then all
* `LoggerBuf` instances will filter incoming events based on their
* event level.
*
* The `LoggerBuf` module allows for specifying a different filter level
* for every `Diags` bit. These filtering levels are module wide;
* `LoggerBuf` does not support specifying the levels on a per-instance
* basis.
*
* The `{@link IFilterLogger.setFilterLevel}` function can be used to
* change the filtering levels at runtime.
*
* The default filtering levels are assigned using the `level1Mask` -
* `level4Mask` config parameters. These are used to specify, for each of
* the four event levels, the set of bits which should filter at that
* level by default.
*
* The default filtering configuration sets the filter level to
* `Diags.LEVEL4` for all logging-related diags bits so that all events
* are logged by default.
*/
config Diags.Mask level4Mask = Diags.ALL_LOGGING;
/*!
* ======== flushAll ========
* Flush logs of all instances that set `exitFlush` to true
*
* The user is responsible for making sure that no `LoggerBuf` instances
* are created or deleted during the execution of this function.
*/
Void flushAll();
/*!
* ======== flushAllInternal ========
* @_nodoc
*/
Void flushAllInternal(Int stat);
/*!
* ======== initDecoder ========
* @_nodoc
* Initialize the LoggerBufDecoder for use in the LoggerBuf 'Records' ROV
* view.
*/
function initDecoder();
instance:
/*!
* ======== create ========
* Create a `LoggerBuf` logger
*
* @see LoggerBuf#Params
*/
create();
/*!
* ======== numEntries ========
* Number of entries in buffer
*
* Each entry is large enough to store one `Log` event containing up to
* 4 optional arguments. Events containing more than 4 arguments (such
* as those from `{@link Log#write5}`) use 2 entries.
*
* `numEntries` must be a power of 2.
*/
config Int numEntries = 64;
/*!
* ======== bufType ========
* Log buffer type
*/
config BufType bufType = BufType_CIRCULAR;
/*!
* ======== exitFlush ========
* Flush log at system exit
*
* Only used when module parameter `{@link #enableFlush}` is `true`.
*/
config Bool exitFlush = false;
/*!
* ======== bufSection ========
* Section name for the buffer managed by the static instance.
*
* The default section is the 'dataSection' in the platform.
*/
metaonly config String bufSection = null;
/*!
* ======== bufHeap ========
* The heap that contains the `Log` buffer for dynamic instances.
*
* The default value `null` means the buffer will be allocated from
* the `{@link Memory#defaultHeapInstance}` heap.
*/
config IHeap.Handle bufHeap = null;
/*!
* ======== reset ========
* Reset a log to empty state and enable it
*
* @a(WARNING) This method is not synchronized with other instance
* methods and, as a result, it must never be called when there is a
* chance that another instance method is currently in operation or
* when another method on this instance may preempt this call.
*/
Void reset();
/*!
* ======== flush ========
* Read, clear, and output the contents of the log
*
* This method reads, clears, and "prints" each `Log` event (via
* `{@link System#printf}`) in the log.
*/
Void flush();
/*!
* ======== getNextEntry ========
* Fills the passed `{@link Log#EventRec}` with the next entry in the log.
*
* This function is used to read and clear `Log` events from the
* buffer maintained by the `LoggerBuf` instance. The `Log` event can
* then be transmitted and displayed on a host.
*
* A read pointer is maintained in the `LoggerBuf` instance and
* points to the next record to read. Entries are not necessarily
* returned in chronological order, since buffers of type
* `{@link #BufType_CIRCULAR}` can wrap.
*
* @param(evtRec) pointer to a supplied `EventRec` object where the next
* entry in the log is copied to
*
* @a(returns)
* This function reports the number of entries actually read. The only
* values that can be returned are:
* @p(blist)
* - 0 no more entries to read
* - 1 or 2 read a complete entry written by `write4` or `write8`
* - -1 cleared an incomplete/overwritten entry, more entries to read
*/
Int getNextEntry(Log.EventRec *evtRec);
internal:
Bool filterOutEvent(Diags.Mask mask);
const Int8 FULL = -1;
const Int8 WRAP = 0;
const Int8 NEXT = 1;
struct Entry {
Types.Timestamp64 tstamp;
Bits32 serial;
Types.Event evt;
IArg arg1;
IArg arg2;
IArg arg3;
IArg arg4;
};
struct Module_State {
Diags.Mask level1;
Diags.Mask level2;
Diags.Mask level3;
};
struct Instance_State {
IHeap.Handle bufHeap;
Entry entryArr[];
Entry *curEntry;
Entry *endEntry;
Entry *readEntry;
Bits32 serial;
Int16 numEntries;
Int8 advance;
Bool enabled;
Bool flush;
};
}