1    /*
     2     * Copyright (c) 2012, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     * */
    32    
    33    /*
    34     *  ======== LogSnapshot.xdc ========
    35     */
    36    package ti.uia.runtime;
    37    import xdc.runtime.Types;
    38    import ti.uia.runtime.LoggerTypes;
    39    import xdc.runtime.ILogger;
    40    import ti.uia.runtime.CtxFilter;
    41    import xdc.runtime.ILogger;
    42    import xdc.runtime.Diags;
    43    import xdc.runtime.Text;
    44    import ti.uia.events.UIASnapshot;
    45    import ti.uia.runtime.IUIATraceSyncClient;
    46    
    47    /*!
    48     *  ======== LogSnapshot ========
    49     *  Snapshot Event logging manager for logging blocks of memory, strings in memory
    50     *     and names of dynamically created objects
    51     *
    52     *  {@link ti.uia.events.UIASnapshot Snapshot events} are used to log dynamic
    53     *  target state information in order to
    54     *  capture the execution context of the application at a particular moment in
    55     *  time.  Types of information that can be logged include:
    56     *  @p(blist)
    57     *      - Blocks of memory (using the {@link #writeMemoryBlock LogSnapshot_writeMemoryBlock} API)
    58     *      - Strings that reside in memory (using the {@link #writeString LogSnapshot_writeString} API)
    59     *      - Names of dynamically created objects (using the {@link #writeNameOfReference LogSnapshot_writeNameOfReference} API)
    60     *  @p
    61     *  The host-side tooling can be instructed to treat a series of LogSnapshot
    62     *  events as representing the state of the target at the same moment in time by
    63     *  using the same non-zero value in the {@link #getSnapshotId snapshot ID} parameter
    64     *  of each of the LogSnapshot events in the series.
    65     *
    66     *  Snapshot events are logged by a logger that implements the
    67     *  {@link ti.uia.runtime.ILoggerSnapshot ILoggerSnapshot}
    68     *  interface (e.g. {@link ti.uia.runtime.LoggerCircBuf LoggerCircBuf},
    69     *  {@link ti.uia.runtime.LoggerStopMode LoggerStopMode},
    70     *  {@link ti.uia.runtime.LoggerProbePoint LoggerProbePoint}).
    71     *  Rather than invoking the logger's APIs directly, the APIs are
    72     *  called indirectly via the LogSnapshot module's APIs so that different types
    73     *  of loggers can be used without having to recompile the source code that is
    74     *  logging the snapshot events.
    75     * @a(Examples)
    76     *  @p(html)
    77     *  <B>Example 1: A simple 2-line configuration script</B>
    78     *  @p
    79     *  The following configuration script shows the simplest way
    80     * to configure an application to use log snapshot events:
    81     * @p(code)
    82     * var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');
    83     * var LogSnapshot   = xdc.useModule('ti.uia.runtime.LogSnapshot');
    84     * @p
    85     * The first line causes the {@link ti.uia.sysbios.LoggingSetup LoggingSetup}
    86     * module's .xs script to automatically create a 32K Byte logger and assign it to
    87     * xdc.runtime.Main.common$.logger.  It also sets any unconfigured Diags masks
    88     * for the Main module to Diags.RUNTIME_ON, enabling the events to be logged.
    89     * @p
    90     * The second line causes the LogSnapshot .xs script to run during the configuration
    91     * process when building the application. The script detects that a logger has
    92     * not been assigned to the LogSnapshot module, so it checks if
    93     * a logger has been configured for either the Main module or the Defaults module.
    94     * Since there is a logger for the Main module, the script configures the LogSnapshot
    95     * module to log events to the same logger instance.
    96     *
    97     *  @p(html)
    98     *  <hr />
    99     *  <B>Example 2: Using a dedicated low priority logger for snapshot events</B>
   100     *  @p
   101     * In some situations, the amount of data logged by the LogSnapshot
   102     * APIs may exceed the ability of the target to move the event data out of the
   103     * Main module's logger's circular buffer and up to the host.  One way of
   104     * ensuring that the other events that are logged are not dropped due to this
   105     * type of situation is to configure the LogSnapshot module to write events
   106     * to a separate lower priority logger.
   107     * @p
   108     * The following is an example of a
   109     * configuration script that configures a logger for use by the LogSnapshot
   110     * module.  This example uses a LoggerCircBuf logger, which is appropriate for
   111     * uploading events in real-time as the target executes using either
   112     * JTAG RunMode(C6X targets) or using a non-JTAG transport such as Ethernet.
   113     * Assigning this logger a {@link ti.uia.runtime.IUIATransferlow#Priority_LOW
   114     * low priority} causes the contents of this logger to be uploaded after
   115     * higher priority events (e.g. sync point events, context change events,
   116     * and error, warning, info events) have been uploaded.
   117     * @p
   118     * @p(code)
   119     * var Logger = xdc.useModule('ti.uia.runtime.LoggerCircBuf');
   120     * var LogSnapshot   = xdc.useModule('ti.uia.runtime.LogSnapshot');
   121     *
   122     * // Create a low priority logger and use it for snapshot events
   123     * var IUIATransfer = xdc.useModule('ti.uia.runtime.IUIATransfer');
   124     * var loggerParams = new Logger.Params();
   125     * loggerParams.priority = IUIATransfer.Priority_LOW;
   126     * // set the logger buffer size in bytes
   127     * loggerParams.transferBufSize = 32768;
   128     * var snapshotLogger = Logger.create(loggerParams);
   129     * snapshotLogger.instance.name = "SnapshotLog";
   130     * LogSnapshot.common$.logger = snapshotLogger;
   131     * @p
   132     * Using different types of loggers:
   133     * @p(blist)
   134     *      - To upload events by JTAG when the target halts (JTAG StopMode),
   135     * replace the first line in the example with
   136     * @p(code)
   137     * Logger = xdc.useModule('ti.uia.runtime.LoggerStopMode');
   138     * @p(blist)
   139     *      - To upload events by JTAG whenever an event is logged using probe point
   140     * breakpoints (i.e. momentarily halting the target while the event is uploaded
   141     * and then resuming execution), replace the first line in the example with
   142     * @p(code)
   143     * Logger = xdc.useModule('ti.uia.runtime.LoggerProbePoint');
   144     * @p
   145     *
   146     *
   147     *  @p(html)
   148     *  <hr />
   149     *  <B>Example 3: Using Diags masks to control snapshot events</B>
   150     *  @p
   151     *  The generation of a 'Snapshot' event is controlled by a module's diagnostics
   152     *  mask, which is described in details in the CDoc for xdc.runtime.Diags. Each
   153     *  {@link ti.uia.events.UIASnapshot snapshot event} is controlled using the
   154     *  Diags.ANALYSIS mask, and will only be logged when the diagnostics mask for
   155     *  the module that is logging the code has the Diags.ANALYSIS bit
   156     *  configured as either ALWAYS_ON or RUNTIME_ON.
   157     *  @p
   158     *  The `LogSnapshot` function call sites are implemented in such a way that an
   159     *  optimizer can completely eliminate `LogSnapshot` code from the program if
   160     *  the module's `ANALYSIS` events have been disabled at configuration time. If
   161     *  the 'ANALYSIS' events are permanently turned on at configuration time,
   162     *  then the optimizer can eliminate all runtime conditional checking and
   163     *  simply invoke the 'LogSnapshot' functions directly. Runtime checking is
   164     *  performed only when the ANALYSIS events are configured to be runtime
   165     *  modifiable.
   166     *  @p
   167     * The following is an example of the configuration script used
   168     * to configure the default mask for modules to have Analysis events such as
   169     * the UIASnapshot events always on.
   170     * @p(code)
   171     *  // Configure all modules to always log Analysis events
   172     *  var Diags = xdc.useModule('xdc.runtime.Diags');
   173     *  var Defaults = xdc.useModule('xdc.runtime.Defaults');
   174     *  Defaults.common$.diags_ANALYSIS = Diags.ALWAYS_ON;
   175     * @p
   176     *
   177     */
   178    
   179    @CustomHeader
   180    module LogSnapshot inherits IUIATraceSyncClient {
   181    
   182        /*!
   183         *  ======== EventRec ========
   184         *  The target representation of a recorded event
   185         *
   186         *  This structure defines how events are recorded on the target.
   187         */
   188        struct EventRec {
   189            Types.Timestamp64 tstamp; /*! time event was written */
   190            Bits32 serial; /*! serial number of event */
   191            Types.Event evt; /*! target encoding of an Event */
   192            Int snapshotId;
   193            IArg fmt;
   194            Ptr pData;
   195            UInt16 lengthInMAUs; /*! arguments passed via Log_write/print */
   196        }
   197        /*!
   198         *  ======== maxLengthInMAUs ========
   199         *  Maximum number of MAUs (miniumum addressable units, e.g. bytes)
   200         *     supported by `LogSnapshot` events.
   201         *
   202         *  Attempting to write more than the maximum length results in the
   203         *  multiple events being logged.  The maxLengthInMAUs must be
   204         *  lower than the size of the buffer that the events are being logged to.
   205         *  Must be less than 1400 in order to support streaming of event
   206         *  data over UDP.
   207         */
   208        config Int maxLengthInMAUs = 512;
   209    
   210        /*!
   211         *  ======== isTimestampEnabled ========
   212         *  used to enable or disable logging the 64b local CPU timestamp
   213         *  at the start of each event
   214         */
   215        config Bool isTimestampEnabled = true;
   216    
   217        /*! @_nodoc
   218         *  ======== loggerDefined ========
   219         *  set to true in the configuration script when a logger that implements
   220         *  ILoggerSnapshot is attached
   221         */
   222        config Bool loggerDefined = false;
   223        /*!
   224         *  ======== loggerObj ========
   225         *  handle of the logger that is to be used to log snapshot events
   226         */
   227        config Ptr loggerObj = null;
   228    
   229        /*! @_nodoc */
   230        config ti.uia.runtime.LoggerTypes.LogMemoryRangeFxn loggerMemoryRangeFxn = null;
   231        /*===========================================================================================*/
   232    
   233        /*!
   234         *  ======== putMemoryRange ========
   235         *  Unconditionally put the specified `Types` event.
   236         *  Supports both writeMemoryRange and writeString.
   237         *
   238         *  This method unconditionally puts the specified memoryRange`{@link Types#Event}`
   239         *  `evt` into the log.  This type of event is created either implicitly
   240         *  (and passed to an `{@link ISnapshotLogger}` implementation) or explicitly
   241         *  via `{@link Types#makeEvent()}`.
   242         *
   243         *  @param(evt)         the `Types` event to put into the log
   244         *  @param(mid)         the module ID of the caller
   245         *  @param(snapshotId)  unique ID that binds together a series of events used to
   246         *                        log a large memory range
   247         *  @param(fileName)    the name of the file that the event was logged from
   248         *  @param(lineNum)     the line number that the event was logged from
   249         *  @param(fmt)         a user-specified print format string
   250         *  @param(startAdrs)   the start address of the memory range to log
   251         *  @param(lengthInMAUs)   the number of minimum addressable units (e.g. bytes) to log
   252         *  @a(return)          value to use as snapshotId parameter for subsequent events
   253         */
   254        @Macro Void putMemoryRange(Types.Event evt, Types.ModuleId mid,
   255          IArg fileName, IArg lineNum, UInt32 snapshotID, IArg fmt, IArg startAdrs, IArg lengthInMAUs);
   256    
   257        /*!
   258         *  ======== memoryBlock ========
   259         *  Generate a `LogSnapshot` event for a block of memory
   260         *
   261         * @a(Examples)
   262         * Example: The following C code shows how to log a snapshot event to
   263         *   capture a block of memory.
   264         *
   265         *  @p(code)
   266         *  #include <ti/uia/runtime/LogSnapshot.h>
   267         *  ...
   268         *  UInt32* pIntArray = (UInt32 *)malloc(sizeof(UInt32) * 200);
   269         *  ...
   270         *  LogSnapshot_writeMemoryBlock(0,"pIntArray ptr=0x%x, numBytes=%d",(UInt32)pIntArray,200);
   271         *  ...
   272         *  @p
   273         *  The following text will be displayed for the event, if it was logged
   274         *  from file demo.c at line 1234 and all 200 bytes were logged in the
   275         *  same event.
   276         *  @p(code)
   277         *  Memory Snapshot at [demo.c:1234] [snapshotID=0,adrs=0x80002000,
   278         *    numMAUsDataInEvent=200,numMAUsDataInRecord=200] ptr=0x80002000, numBytes=200
   279         *  @p
   280         *  If the 200 bytes were spread across multiple events,
   281         *  the numMAUsDataInRecord would indicate how many bytes were in the
   282         *  memory block, and numMAUsDataInEvent would indicate how many bytes
   283         *  were stored in that particular event.
   284         *  @p
   285         *  @param(snapshotID) ID used to identify snapshot events taken at the same
   286         *                     time. Set to 0 for first in series, set rest to return
   287         *                     value of LogSnapshot API.  {@link #getSnapshotId see getSnapshotId()}
   288         *  @param(fmt)        a constant string that provides a user-readable description
   289         *                     of what information the event is capturing
   290         *  @param(pMemoryRange)  the start address of the range of memory
   291         *  @param(lengthInMAUs) the number of MAUs of data payload for the
   292         *                     multi-event data record
   293         */
   294        @Macro Void writeMemoryBlock(UInt32 snapshotID, IArg fmt, Ptr pMemoryRange,
   295          UInt16 lengthInMAUs);
   296    
   297        /*!
   298         *  ======== string ========
   299         *  Generate a `LogSnapshot` event for a string in memory
   300         *
   301         *  @a(Example)
   302         *   The following C code shows how to log a snapshot event to log the
   303         *   contents of a string in memory.
   304         *
   305         *  @p(code)
   306         *  #include <ti/uia/runtime/LogSnapshot.h>
   307         *  ...
   308         *  Void myFunc(String name){
   309         *     ...
   310         *     LogSnapshot_writeString(0,"User-defined name=%s.",name, strlen(name));
   311         *  }
   312         *  @p
   313         *  The following text will be displayed for the event, if it was logged
   314         *  from file demo.c at line 1234 and all bytes in the 40 character string
   315         *  was logged in the same event.
   316         *  @p(code)
   317         *  String Snapshot at [../demo.c:1234] [snapshotID=0,adrs=0x80001234,40,40] User-defined name=ValueOfParm.
   318         *  @p
   319         *  @param(snapshotID) ID used to identify snapshot events taken at the same
   320         *                     time. Set to 0 for first in series, set rest to return
   321         *                     value of LogSnapshot API. {@link #getSnapshotId see getSnapshotId()}
   322         *  @param(fmt)        a constant string that provides a user-readable description
   323         *                     of what information the event is capturing
   324         *  @param(pString)    the start address of the string in memory
   325         *  @param(lengthInMAUs) the number of MAUs to log (e.g. strlen(pString))
   326         */
   327        @Macro Void writeString(UInt32 snapshotID, IArg fmt, Ptr pString,
   328        UInt16 lengthInMAUs);
   329    
   330        /*!
   331         *  ======== nameOfReference ========
   332         *  Used to log the contents of a dynamic string on the heap so that host-side
   333         *  tooling can display this string as the name of handle / reference ID
   334         *
   335         *  @a(Example)
   336         *   The following C code shows how to log a task name for use by task
   337         *   execution graphs etc.
   338         *
   339         *  @p(code)
   340         *  #include <ti/uia/runtime/LogSnapshot.h>
   341         *  #include <ti/sysbios/BIOS.h>
   342         *  #include <ti/sysbios/knl/Task.h>
   343         *  ...
   344         *  // Task create hook function that logs the task name.
   345         *  // Notes: Task name is not trequired when creating a BIOS task. Please \
   346         *  // make sure a name is provided in order for the host side analysis tool
   347         *  // to work properly.
   348         *  Void  tskCreateHook(Task_Handle hTask, Error_Block *eb) {
   349         *          String name;
   350         *          name = Task_Handle_name(hTask);
   351         *          LogSnapshot_writeNameOfReference(hTask,"Task_create: name=%s",
   352         *            name,strlen(name)+1);
   353         *  }
   354         *  @p
   355         *  This event prints the Log call site (%$F) and a format string (%$S)
   356         *  which describes what information the event is logging.
   357         *  The following text will be displayed for the event:
   358         *  @p(code)
   359         *  nameOfReference at  [demo.c:line 1234] [refID=0x80002000,adrs=0x80001234,40,40] Task_create: name=10msThread.
   360         *  @param(refID)        reference ID (e.g. task handle) that the name is
   361         *                       associated with
   362         *  @param(pString)      the start address of the string on the heap
   363         *  @param(lengthInMAUs) the number of MAUs to log (e.g. strlen(pString))
   364         *  @param(fmt)          a constant string that provides format specifiers
   365         *                       describing the string
   366         */
   367        @Macro Void writeNameOfReference(UInt32 refID, IArg fmt, Ptr pString,
   368        UInt16 lengthInMAUs);
   369    
   370        /*!
   371         * ======== getSnapshotId ========
   372         * returns a unique ID to use to group a set of snapshot event logs together
   373         *
   374         * Allows tooling to treat a set of consecutive event logs as a unit and
   375         * display all of the relevent data together as a set
   376         *  @a(Example)
   377         *   The following C code shows how to log two snapshot events that capture
   378         *   the target state of two different data structures, using a common unique
   379         *   non-zero snapshot ID provided by the getSnapshotId to inform the host-side
   380         *   tooling that the events represent the target state at the same point in time
   381         *  @p(code)
   382         *  #include <ti/uia/runtime/LogSnapshot.h>
   383         *  ...
   384         *  MyStruct1 myStruct1;
   385         *  MyStruct2 myStruct2;
   386         *  UInt32 snapshotId;
   387         *  ...
   388         *  snapshotId = LogSnapshot_getSnapshotId();
   389         *  LogSnapshot_writeMemoryBlock(snapshotId,"myStruct1 ptr=0x%x, numBytes=%d",(UInt32)&myStruct1,sizeof(MyStruct1));
   390         *  LogSnapshot_writeMemoryBlock(snapshotId,"myStruct2 ptr=0x%x, numBytes=%d",(UInt32)&myStruct2,sizeof(MyStruct2));
   391         *  ...
   392         *  @p
   393         * @a(return) a unique non-zero snapshot ID to pass in as a parameter to the
   394         *    LogSnapshot APIs
   395         */
   396        @DirectCall
   397        UInt32 getSnapshotId();
   398    
   399        /*!
   400         *  ======== doPrint ========
   401         *  Render an event as text via `{@link System#printf System_printf}`
   402         *
   403         *  This method is not currently implemented.
   404         *
   405         *  @param(evRec)   a non`NULL` pointer to an initialized `
   406         *     LogSnapshot_EventRec`structure to be formated via
   407         *     {@link System#printf System_printf}`.
   408         */
   409    
   410        Void LogSnapshot_doPrint(EventRec *er);
   411    
   412        /* @_nodoc
   413         *  ======== idToInfo ========
   414         *  Map event ID strings into a string of the form <eventName>::<eventMsg>
   415         */
   416        metaonly config String idToInfo[string] = [];
   417    
   418    }