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