1    /*
     2     * Copyright (c) 2014-2016 Texas Instruments Incorporated - http://www.ti.com
     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     *  ======== TimestampProvider.xdc ========
    35     */
    36    
    37    package ti.uia.family.dm.dra7xx;
    38    
    39    import ti.uia.loggers.LoggerStopMode;
    40    import xdc.rov.ViewInfo;
    41    import xdc.runtime.Assert;
    42    import xdc.runtime.Diags;
    43    import xdc.runtime.Log;
    44    import xdc.runtime.Types;
    45    
    46    /*!
    47     *  ======== TimestampProvider ========
    48     *  System-wide timestamp provider
    49     *
    50     *  This timestamp provider is used by UIA to provide a common time
    51     *  base for all processors. This allows System Analyzer to correlate
    52     *  the log events from all processors to a common time base. Event
    53     *  correlation is required for the multi-core execution graph. Use
    54     *  this module as the global timestamp proxy for the
    55     *  {@link ti.uia.runtime.LogSync} module.
    56     *
    57     *  This module requires the use of a timer to provide a common system
    58     *  tick. The timer needs to have access to the 32 KHz clock. Not all
    59     *  timers are suitable for use by this module. See the {@link #timerId}
    60     *  configuration parameter for a list of recommended timers. Exactly one
    61     *  processor must be the owner of the timer. See {@link #owner} for details.
    62     *
    63     *  Ledgers are used internally by this module to keep track of the
    64     *  other processors in the system. The ledgers are shared across
    65     *  processor boundaries. You must provide the base address of a ledger
    66     *  so that all processors know where to find it. See the {@link #ledgers}
    67     *  configuration parameter for details. There are two types of ledgers:
    68     *  a group ledger, and a private ledger. One group ledger is mandatory,
    69     *  private ledgers are typically used by the EVE processors. Ledgers are
    70     *  defined by the role used to access them. See the {@link #Role}
    71     *  enumeration for details.
    72     *
    73     *  @a(Configuration Example)
    74     *
    75     *  This is a four processor example: DSP1 DSP2 EVE1 EVE2. In this example,
    76     *  DSP1 is to be the owner of the timer. Three ledgers will be used, one
    77     *  group ledger and two private ledgers. The group ledger is used by DSP1
    78     *  and DSP2. One private ledger is used by DSP1 and EVE1. The other private
    79     *  ledger is used by DSP2 and EVE2.
    80     *
    81     *  Add the following to your DSP1 configuration script.
    82     *
    83     *  @p(code)
    84     *  // add Timer3 (id=2) to SYS/BIOS available mask //
    85     *  var TimerSupport = xdc.useModule('ti.sysbios.family.shared.vayu.TimerSupport');
    86     *  TimerSupport.availMask |= (0x1 << 2);
    87     *
    88     *  // configure timestamp proxy //
    89     *  var TimestampProvider = xdc.useModule('ti.uia.family.dm.dra7xx.TimestampProvider');
    90     *  TimestampProvider.timerId = 2;
    91     *  TimestampProvider.owner = true;
    92     *  TimestampProvider.eventId = 65;
    93     *  TimestampProvider.cpuIntrNum = 13;
    94     *  TimestampProvider.syncInterval = 33;
    95     *
    96     *  // group ledger
    97     *  TimestampProvider.ledgers.$add(
    98     *      new TimestampProvider.Ledger({
    99     *          role: TimestampProvider.Ledger_PEER,
   100     *          base: 0x40500000,
   101     *          size: 2, // DSP1 DSP2
   102     *          index: 0 // DSP1
   103     *      })
   104     *  );
   105     *
   106     *  // eve1 ledger
   107     *  TimestampProvider.ledgers.$add(
   108     *      new TimestampProvider.Ledger({
   109     *          role: TimestampProvider.Role_USER,
   110     *          base: 0x42020000
   111     *      })
   112     *  );
   113     *
   114     *  // enable event correlation
   115     *  var LogSync = xdc.useModule('ti.uia.runtime.LogSync');
   116     *  LogSync.GlobalTimestampProxy = TimestampProvider;
   117     *  LogSync.enableEventCorrelationForJTAG = true;
   118     *  @p
   119     *  Add the following to your DSP2 configuration script.
   120     *
   121     *  @p(code)
   122     *  // configure timestamp proxy for event correlation
   123     *  var TimestampProvider = xdc.useModule('ti.uia.family.dm.dra7xx.TimestampProvider');
   124     *
   125     *  TimestampProvider.timerId = 2;
   126     *  TimestampProvider.owner = false; // DSP1 is owner
   127     *  TimestampProvider.eventId = 65;
   128     *  TimestampProvider.cpuIntrNum = 13;
   129     *  TimestampProvider.syncInterval = 33;
   130     *
   131     *  // group ledger
   132     *  TimestampProvider.ledgers.$add(
   133     *      new TimestampProvider.Ledger({
   134     *          role: TimestampProvider.Role_PEER,
   135     *          base: 0x40500000,
   136     *          size: 2, // DSP1 DSP2
   137     *          index: 1 // DSP2
   138     *      })
   139     *  );
   140     *
   141     *  // eve2 ledger
   142     *  TimestampProvider.ledgers.$add(
   143     *      new TimestampProvider.Ledger({
   144     *          role: TimestampProvider.Role_USER,
   145     *          base: 0x42120000
   146     *      })
   147     *  );
   148     *
   149     *  // enable event correlation
   150     *  var LogSync = xdc.useModule('ti.uia.runtime.LogSync');
   151     *  LogSync.GlobalTimestampProxy = TimestampProvider;
   152     *  LogSync.enableEventCorrelationForJTAG = true;
   153     *  @p
   154     *  Add the following to your EVE1 configuration script.
   155     *
   156     *  @p(code)
   157     *  // configure timestamp proxy for event correlation
   158     *  var TimestampProvider = xdc.useModule('ti.uia.family.dm.dra7xx.TimestampProvider');
   159     *
   160     *  TimestampProvider.timerId = 2;
   161     *  TimestampProvider.owner = false; // DSP1 is owner
   162     *  TimestampProvider.eventId = 35;
   163     *  TimestampProvider.cpuIntrNum = 9;
   164     *  TimestampProvider.syncInterval = 33;
   165     *
   166     *  // use private ledger, role = owner
   167     *  TimestampProvider.ledgers.$add(
   168     *      new TimestampProvider.Ledger({
   169     *          role: TimestampProvider.Role_OWNER,
   170     *          base: 0x40020000
   171     *      })
   172     *  );
   173     *
   174     *  // enable event correlation
   175     *  var LogSync = xdc.useModule('ti.uia.runtime.LogSync');
   176     *  LogSync.GlobalTimestampProxy = TimestampProvider;
   177     *  LogSync.enableEventCorrelationForJTAG = true;
   178     *  @p
   179     *  Add the following to your EVE2 configuration script.
   180     *
   181     *  @p(code)
   182     *  // configure timestamp proxy for event correlation
   183     *  var TimestampProvider = xdc.useModule('ti.uia.family.dm.dra7xx.TimestampProvider');
   184     *
   185     *  TimestampProvider.timerId = 2;
   186     *  TimestampProvider.owner = false; // DSP1 is owner
   187     *  TimestampProvider.eventId = 35;
   188     *  TimestampProvider.cpuIntrNum = 9;
   189     *  TimestampProvider.syncInterval = 33;
   190     *
   191     *  // use private ledger, role = owner
   192     *  TimestampProvider.ledgers.$add(
   193     *      new TimestampProvider.Ledger({
   194     *          role: TimestampProvider.Role_OWNER,
   195     *          base: 0x40020000
   196     *      })
   197     *  );
   198     *
   199     *  // enable event correlation
   200     *  var LogSync = xdc.useModule('ti.uia.runtime.LogSync');
   201     *  LogSync.GlobalTimestampProxy = TimestampProvider;
   202     *  LogSync.enableEventCorrelationForJTAG = true;
   203     *  @p
   204     *
   205     *  @a(CPU Frequency Configuration)
   206     *
   207     *  In order for event correlation to be accurate, the cpu frequency must
   208     *  be set as accurately as possible. This module can be used to determine
   209     *  you actual cpu frequency.
   210     *
   211     *  Enable the timestamp sample buffer with the {@link #estCpuFreq}
   212     *  configuration parameter. Run your program continuously for 30 seconds.
   213     *  Use ROV to view the cpu frequency in the TimestampProvider module view.
   214     *
   215     *  Once you have determined your cpu frequency, use that value to configure
   216     *  the SYS/BIOS cpu frequency.
   217     *
   218     *  @p(code)
   219     *  var BIOS = xdc.useModule('ti.sysbios.BIOS');
   220     *  BIOS.cpuFreq = { hi: 0, lo: 609024002 };
   221     *  @p
   222     *
   223     *  Hint: disable the {@link #estCpuFreq} when done to reduce your data
   224     *  footprint.
   225     */
   226    
   227    @ModuleStartup
   228    @Template("./TimestampProvider.xdt")
   229    
   230    module TimestampProvider inherits ti.uia.runtime.IUIATimestampProvider
   231    {
   232        /*!
   233         *  ======== timerId ========
   234         *  Identify which timer to use as the timestamp clock source
   235         *
   236         *  The timers are named Timer1-Timer16; their corresponding ids
   237         *  are 0-15 (e.g. for Timer3, use id=2). Not all timers are
   238         *  appropriate clock sources for this module. Use one of the
   239         *  following timers:
   240         *
   241         *  @p(html)
   242         *  <table>
   243         *    <style scoped>th,td {padding:4px}</style>
   244         *    <tr style="text-align:left; background-color:LightGray">
   245         *      <th>Timer Name</th>
   246         *      <th>Description</th>
   247         *    </tr>
   248         *    <tr>
   249         *      <td>Timer[3,4,9,11,13,14,15,16]</td>
   250         *      <td>PD_L4PER power domain</td>
   251         *    </tr>
   252         *    <tr>
   253         *      <td>Timer[5,6,7,8]</td>
   254         *      <td>PD_IPU power domain</td>
   255         *    </tr>
   256         *  </table>
   257         *  @p
   258         *
   259         *  All executables must use the same timer in order to support
   260         *  event correlation in System Analyzer.
   261         */
   262        config UInt timerId;
   263    
   264        /*!
   265         *  ======== owner ========
   266         *  Determine ownership of the timer
   267         *
   268         *  When set to true, the timer will be enabled and configured
   269         *  during the boot phase. The owner should run before any other
   270         *  processor using this same timer. Only one processor should
   271         *  be configured as the owner of the timer. This processor will
   272         *  also listen for the timer interrupt and acknowledge it.
   273         *
   274         *  When set to false, it is expected that another processor will
   275         *  enable and configure the timer. This processor will simply
   276         *  listen for the timer interrupt and acknowledge it.
   277         *
   278         *  Note: The ARP32 does not support timer ownership. This config
   279         *  param must always be false when running on the ARP32.
   280         */
   281        config Bool owner;
   282    
   283        /*!
   284         *  ======== eventId ========
   285         *  Specify interrupt controller event to receive timer interrupt
   286         *
   287         *  The eventId specifies which interrupt controller event should
   288         *  receive the timer interrupt. This value is used to route the
   289         *  timer interrupt through the Interrupt Crossbar to the interrupt
   290         *  controller event. It is also used to route the interrupt event
   291         *  to the cpu interrupt specified in {@link #cpuIntrNum}.
   292         *
   293         *  The following table indicates possible event ids, but this is
   294         *  device specific. Please consult your manual.
   295         *
   296         *  @p(html)
   297         *  <table>
   298         *    <style scoped>th,td {padding:4px}</style>
   299         *    <tr style="text-align:left; background-color:LightGray">
   300         *      <th>Processor</th>
   301         *      <th>Event ID</th>
   302         *    </tr>
   303         *    <tr>
   304         *      <td>DSP</td>
   305         *      <td>63-78, 81</td>
   306         *    </tr>
   307         *    <tr>
   308         *      <td>EVE</td>
   309         *      <td>32-39</td>
   310         *    </tr>
   311         *  </table>
   312         *  @p
   313         */
   314        config Int eventId;
   315    
   316        /*!
   317         *  ======== cpuIntrNum ========
   318         *  Specify cpu interrupt to receive timer interrupt
   319         *
   320         *  For accurate event correlation in System Analyzer, it is
   321         *  recommended not to share this interrupt.
   322         *
   323         *  The following table indicates possible interrupt numbers, but
   324         *  this is device specific. Please consult your manual.
   325         *
   326         *  @p(html)
   327         *  <table>
   328         *    <style scoped>th,td {padding:4px}</style>
   329         *    <tr style="text-align:left; background-color:LightGray">
   330         *      <th>Processor</th>
   331         *      <th>Timer ID</th>
   332         *    </tr>
   333         *    <tr>
   334         *      <td>DSP</td>
   335         *      <td>4-15</td>
   336         *    </tr>
   337         *    <tr>
   338         *      <td>EVE</td>
   339         *      <td>8-11</td>
   340         *    </tr>
   341         *  </table>
   342         *  @p
   343         */
   344        config Int cpuIntrNum;
   345    
   346        /*!
   347         *  ======== syncInterval ========
   348         *  Specify the interval for logging sync events
   349         *
   350         *  UIA Sync events are used by System Analyzer to correlate the
   351         *  events from each processor onto a global time base. Only the
   352         *  last sync event is actually used.
   353         *
   354         *  This configuration parameter specifies how frequently the sync
   355         *  events should be raised. In order to maintain accurate event
   356         *  correlation, you should raise one sync event within each log
   357         *  data window. For example, if your log buffer contains 100 ms
   358         *  of data, then you should raise a sync event each 0.1 seconds
   359         *  (100 ms = 0.1 sec).
   360         *
   361         *  Each syncInterval is 0.001953125 seconds. Divide the data window
   362         *  by this value to get the syncInterval (round down).
   363         *
   364         *  @p(code)
   365         *      0.1 sec / 0.001953125 sec = 51.2
   366         *
   367         *      TimestampProvider.syncInterval = 51;
   368         *  @p
   369         *
   370         *  When using multiple logger instances, the data window for each
   371         *  instance is probably different. Use System Analyzer to measure
   372         *  the data overlap of your region of interest. Use the length of
   373         *  this region to calculate the syncInterval.
   374         *
   375         *  The syncInterval should be as large as possible to reduce logging
   376         *  overhead, yet small enough to yield accurate event correlation.
   377         */
   378        config UInt syncInterval = 50;
   379    
   380        /*!
   381         *  ======== estCpuFreq ========
   382         *  Estimate the cpu frequency using timestamp sample buffer
   383         *
   384         *  When enabled, this module will save timestamps in the sample
   385         *  buffer which are then used to calculate an estimate of the
   386         *  cpu frequency. Run the processor continuously for 30 seconds
   387         *  to ensure the sample buffer is full. Open ROV and select the
   388         *  Module tab. The calculated cpu frequency is displayed in the
   389         *  estCpuFreq column. The timestamp samples are displayed in the
   390         *  Sample Buffer tab.
   391         *
   392         *  Set this config param to false to reduce the data footprint in
   393         *  your released product.
   394         */
   395        config Bool estCpuFreq = false;
   396    
   397        /*!
   398         *  ======== Role ========
   399         *  Define roles for each ledger instance
   400         *
   401         *  There may be multiple ledger instances in a system. There are
   402         *  two types of ledgers: 1. a group ledger, and 2. a private ledger.
   403         *  A group ledger may have two or more users. A private ledger has
   404         *  exactly two users. When a processor creates a private ledger,
   405         *  that processor may not create any additional ledgers of any type.
   406         *  A private ledger is typicaly used by the ARP32 processor.
   407         *
   408         *  The ledger type is identified by the role used to access it.
   409         *
   410         *  @p(html)
   411         *  <div class="xdocText"><dl>
   412         *  <dt>Role_PEER</dt>
   413         *      <dd>
   414         *      This role is used to access a group ledger instance. This
   415         *      ledger instance is used by multiple processors. The ledger
   416         *      is an array of GroupLedgerElem elements. Each processor
   417         *      uses one entry in the ledger. The size of the ledger must
   418         *      equal the number of users.<br><br>
   419         *
   420         *      All users of this ledger are peers. The ledger is not created
   421         *      by any processor, it must be defined in the memory map.<br><br>
   422         *      </dd>
   423         *
   424         *  <dt>Role_OWNER</dt>
   425         *      <dd>
   426         *      This role is used to access a private ledger. This ledger
   427         *      is used by only two processors: the local processor (the
   428         *      owner) and a remote processor (the user). The ledger is
   429         *      allocated in the local processor's memory map. This same
   430         *      ledger must be defined by a Role_USER role on one other
   431         *      processor.<br><br>
   432         *      </dd>
   433         *
   434         *  <dt>Role_USER</dt>
   435         *      <dd>
   436         *      This role is used to access a private ledger.  This role is the
   437         *      complement of the Role_OWNER role. When using a private ledger,
   438         *      the actual ledger is created by the other processor.<br><br>
   439         *
   440         *      A processor using the Role_USER role, will access the ledger with
   441         *      the given address, but it does not allocate the ledger.<br><br>
   442         *
   443         *      It is possible to access multiple private ledgers from the
   444         *      same processor. Each Role_USER corresponds to a private ledger
   445         *      created by another processor.<br><br>
   446         *      </dd>
   447         *  </dl>
   448         *  @p
   449         */
   450        enum Role {
   451            Role_PEER = 0x01,               /*! shared by multiple processors */
   452            Role_OWNER = 0x02,              /*! shared with one remote processor */
   453            Role_USER = 0x03                /*! shared with one remote processor */
   454        };
   455    
   456        /*!
   457         *  ======== Ledger ========
   458         *  Define a ledger used in the system
   459         *
   460         *  A ledger is used to keep track of which processors are running.
   461         *  Depending on the ledger role, there can be two or more users of
   462         *  the same ledger instance. You can define multiple ledgers. See
   463         *  {@link #ledgers} for examples of creating ledgers.
   464         *
   465         *  @field(role)
   466         *  Defines how this processor will be using the ledger. The role
   467         *  also implicitly defines which type of ledger is created. See
   468         *  the {@link #Role} enumeration for details.
   469         *
   470         *  @field(base)
   471         *  The base address of the ledger as seen by the local processor.
   472         *
   473         *  @field(size)
   474         *  The number of users of the current ledger. When adding a new
   475         *  user to a ledger, be sure to update this value for all processors
   476         *  using the same ledger.
   477         *
   478         *  @field(index)
   479         *  The entry index in the ledger to be used by this processor. Each
   480         *  processor must have its own unique entry. The index is zero based
   481         *  (as in array indexing). Index values range from 0 - (size-1).
   482         */
   483        struct Ledger {
   484            Role role;                      /*! role used to access the ledger */
   485            Ptr base;                       /*! base address of the ledger */
   486            Int size;                       /*! number of users */
   487            Int index;                      /*! entry assigned to this processor */
   488        };
   489    
   490        /*!
   491         *  ======== ledgers ========
   492         *  Define the ledgers to be managed by this processor
   493         *
   494         *  Ledgers are used to keep track of the other processors. This
   495         *  is needed to support the auto-logging feature and to issue
   496         *  LogSync events. Each processor must define at least one ledger.
   497         *
   498         *  There are two types of ledgers: a group ledger, and a private
   499         *  ledger. See the {@link #Role} enumeration for details.
   500         *
   501         *  Use as few ledgers as possible. However, some system constraints
   502         *  will require additional ledgers. For example, the EVE processors
   503         *  have very slow data access to on-chip or external memory. Therefore,
   504         *  we recommend that each EVE processor use a private ledger. Place
   505         *  the private ledger in DMEM to ensure fast memory access.
   506         *
   507         *  Add the following to your EVE1 configuration script.
   508         *
   509         *  @p(code)
   510         *  var TimestampProvider = xdc.useModule('ti.uia.family.dm.dra7xx.TimestampProvider');
   511         *
   512         *  // use private ledger, role = owner
   513         *  TimestampProvider.ledgers.$add(
   514         *      new TimestampProvider.Ledger({
   515         *          role: TimestampProvider.Role_OWNER,
   516         *          base: 0x40020000
   517         *      })
   518         *  );
   519         *  @p
   520         *
   521         *  Each private ledger has exactly two users: an owner (Role_OWNER)
   522         *  and a user (Role_USER). In the example above, the EVE would always
   523         *  be the owner. Typically, the DSP would be the corresponding user.
   524         *
   525         *  Add the following to your DSP1 configuration script.
   526         *
   527         *  @p(code)
   528         *  var TimestampProvider = xdc.useModule('ti.uia.family.dm.dra7xx.TimestampProvider');
   529         *
   530         *  // eve1 ledger, role = user
   531         *  TimestampProvider.ledgers.$add(
   532         *      new TimestampProvider.Ledger({
   533         *          role: TimestampProvider.Role_USER,
   534         *          base: 0x42020000
   535         *      })
   536         *  );
   537         * @p
   538         *
   539         *  Note in the example above, the EVE defines the ledger address
   540         *  using its local address (e.g. 0x40020000). However, the DSP must
   541         *  use the interconnect address (e.g. 0x42020000).
   542         *
   543         *  For the remaining processors in the system, you could use one
   544         *  group ledger. All processors using the same group must agree on
   545         *  the ledger address, and the number of entries. Each processor must
   546         *  be assigned its own entry in the ledger.
   547         *
   548         *  The following example defines a single group ledger used by two
   549         *  processors: DSP1 and DSP2. Add the following to your DSP1
   550         *  configuration script.
   551         *
   552         *  @p(code)
   553         *  var TimerSupport = xdc.useModule('ti.sysbios.family.shared.vayu.TimerSupport');
   554         *
   555         *  // group ledger, role = peer
   556         *  TimestampProvider.ledgers.$add(
   557         *      new TimestampProvider.Ledger({
   558         *          role: TimestampProvider.Ledger_PEER,
   559         *          base: 0x40500000,
   560         *          size: 2, // DSP1 DSP2
   561         *          index: 0 // DSP1
   562         *      })
   563         *  );
   564         *  @p
   565         *  Add the following to your DSP2 configuration script.
   566         *
   567         *  @p(code)
   568         *  var TimerSupport = xdc.useModule('ti.sysbios.family.shared.vayu.TimerSupport');
   569         *
   570         *  // group ledger, role = peer
   571         *  TimestampProvider.ledgers.$add(
   572         *      new TimestampProvider.Ledger({
   573         *          role: TimestampProvider.Role_PEER,
   574         *          base: 0x40500000,
   575         *          size: 2, // DSP1 DSP2
   576         *          index: 1 // DSP2
   577         *      })
   578         *  );
   579         *  @p
   580         *
   581         *  It is also possible to partition the remaining processors into
   582         *  groups and assign a group ledger to each processor group. This
   583         *  might be done to support independent application domains. However,
   584         *  one requirement is that the processor which owns the timer must
   585         *  participate in all group ledgers. For example, if DSP1 has
   586         *
   587         *  @p(code)
   588         *  TimestampProvider.owner = true;
   589         *  @p
   590         *
   591         *  then DSP1 must participate in all group ledgers (i.e. Role_PEER).
   592         */
   593        config Ledger ledgers[length];
   594    
   595        /*!
   596         *  ======== L_latch ========
   597         *  Log event raised at the end of the timer isr
   598         *
   599         *  The timer isr maintains a global tick value used by System
   600         *  Analyzer to correlate the log events across processor boundaries.
   601         *  This event is raised at the end of the timer isr. The latch count
   602         *  should be the same on all processors. The isr timestamp is also
   603         *  reported. This value can be used to measure the accuracy of the
   604         *  event correlation. The isr timestamp is captured at the very
   605         *  beginning of the timer isr.
   606         */
   607        config Log.Event L_latch = {
   608            mask: Diags.INFO,
   609            msg: "L_latch: latch=0x%x:0x%x, isr ts=0x%x:0x%x"
   610        };
   611    
   612    
   613        /*!
   614         *  ======== L_suspend ========
   615         *  Log event raised when loggers are to be suspended
   616         *
   617         *  The module has determined that the system state is not nominal. To
   618         *  preserve the events in the log buffers leading up to this point,
   619         *  the loggers will be suspended. This event is raised shortly before
   620         *  the loggers are actually suspended.
   621         */
   622        config Log.Event L_suspend = {
   623            mask: Diags.INFO,
   624            msg: "L_suspend: loggers suspended"
   625        };
   626    
   627        /*! @_nodoc */
   628        override metaonly config Bool canCpuCyclesPerTickBeChanged = false;
   629    
   630        /*! @_nodoc */
   631        override metaonly config Bool canFrequencyBeChanged = false;
   632    
   633        /*! @_nodoc */
   634        override metaonly config UInt32 cpuCyclesPerTick = 0;
   635    
   636    internal:
   637        /* global timestamp frequency (Hz) */
   638        const UInt GBL_FREQ = 200000000;
   639    
   640        /* timer period for each sync interval */
   641        const UInt TPRD = 64;
   642    
   643        /* number of timestamp samples used for calibration */
   644        const UInt TSSZ = (1 << 6); /* must be a power of 2 */
   645    
   646        /* number of global ticks for each cpu freq sample */
   647        const UInt GBLTC = 100;
   648    
   649        /* size of ledger array */
   650        const UInt LEGSZ = 16;
   651    
   652        /* size of logger instance array */
   653        const UInt LOGSZ = 6;
   654    
   655        /* latch timeout value in nano-seconds */
   656        const UInt TIMEOUT = 1200;
   657    
   658        /* isr spin count */
   659        config UInt SPINCNT;
   660    
   661        /* group ledger element */
   662        struct GroupLedgerElem {
   663            UInt32  masterLC_hi;            /* master latch count (hi 32-bits) */
   664            UInt32  masterLC_lo;            /* master latch count (lo 32-bits) */
   665            UInt32  latch;                  /* local processor latch count */
   666            Bool    nominal;                /* local group state */
   667        }
   668    
   669        /* private ledger */
   670        struct PrivateLedger {
   671            UInt32  userLC;                 /* global latch count */
   672            Bool    nominal;                /* system state */
   673            UInt32  ownerLC;                /* local latch count */
   674        }
   675    
   676        /*
   677         *  ======== A_badRole ========
   678         *  Unknown ledger role
   679         *
   680         *  The current ledger role is not recognized as a valid member of
   681         *  the enum Role.
   682         */
   683        config Assert.Id A_badRole = {
   684            msg: "A_badRole: unknown ledger role"
   685        };
   686    
   687        /*
   688         *  ======== A_noGroupLedger ========
   689         *  A group ledger was not found
   690         *
   691         *  There should always be at least one group ledger in the ledgers
   692         *  array. This is validated at config time, so it should always be
   693         *  true at runtime.
   694         */
   695        config Assert.Id A_noGroupLedger = {
   696            msg: "A_noGroupLedger: unable to find a group ledger"
   697        };
   698    
   699        /*
   700         *  ======== A_badLoggerState ========
   701         *  Conflicting logger states
   702         *
   703         *  The system analysis should not result in the logger state to be
   704         *  both 'pause' and 'resume' at the same time.
   705         */
   706        config Assert.Id A_badLoggerState = {
   707            msg: "A_badLoggerState: logger state should not be both pause and resume at the same time."
   708        };
   709    
   710        /*
   711         *  ======== enableTimer ========
   712         *  Function that enables the timer
   713         */
   714        Void enableTimer();
   715    
   716        /*
   717         *  ======== startTimer ========
   718         *  Function that starts timer before main
   719         */
   720        Void startTimer();
   721    
   722        /*
   723         *  ======== isr ========
   724         */
   725        @DirectCall
   726        Void isr();
   727    
   728        /*
   729         *  ======== grpRolloverIsr ========
   730         *  Timer rollover interrupt handler for group ledger
   731         */
   732        @DirectCall
   733        Void grpRolloverIsr(UArg baseAddr);
   734    
   735        /*
   736         *  ======== pvtRolloverIsr ========
   737         *  Timer rollover interrupt handler for private ledger
   738         */
   739        @DirectCall
   740        Void pvtRolloverIsr(UArg baseAddr);
   741    
   742        /*
   743         *  ======== pauseLoggers ========
   744         *  Pause all logger instances to preserve log events.
   745         */
   746        Void pauseLoggers();
   747    
   748        /*
   749         *  ======== resumeLoggers ========
   750         *  Resume logging.
   751         */
   752        Void resumeLoggers();
   753    
   754        /*!  @_nodoc */
   755        metaonly struct ModuleView {
   756            String latchCount;
   757            String estCpuFreq;
   758        }
   759    
   760        /*!  @_nodoc */
   761        metaonly struct SampleBufferView {
   762            UInt    serial;
   763            String  tsHi;
   764            String  tsLo;
   765        }
   766    
   767        /*! @_nodoc */
   768        @Facet
   769        metaonly config ViewInfo.Instance rovViewInfo =
   770            ViewInfo.create({
   771                viewMap: [
   772                    ['Module',
   773                        {
   774                            type: ViewInfo.MODULE,
   775                            viewInitFxn: 'viewInitModule',
   776                            structName: 'ModuleView'
   777                        }
   778                    ],
   779                    ['Sample Buffer',
   780                        {
   781                            type: ViewInfo.MODULE_DATA,
   782                            viewInitFxn: 'viewInitSampleBuffer',
   783                            structName: 'SampleBufferView'
   784                        }
   785                    ]
   786                ]
   787            });
   788    
   789        /* module state structure */
   790        struct Module_State {
   791            Ptr                     timer;          /* timer (owner=true) */
   792            Types.Timestamp64       latch;          /* global latch counter */
   793            Bool                    logging;        /* logging enabled flag */
   794            PrivateLedger *         ledgerPvt;      /* private ledger */
   795            Int                     count;          /* number of logger instances */
   796            LoggerStopMode.Handle   loggers[LOGSZ]; /* logger instance handles */
   797            UInt                    tshead;         /* tsbuf head pointer */
   798            Types.Timestamp64       tsbuf[];        /* timestamp buffer */
   799        }
   800    }