1    /*
     2     * Copyright (c) 2012-2015 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     *  ======== MultiProc.xdc ========
    34     *
    35     */
    36    
    37    import xdc.rov.ViewInfo;
    38    
    39    import xdc.runtime.Assert;
    40    
    41    /*!
    42     *  ======== MultiProc ========
    43     *  Processor Id Module Manager
    44     *
    45     *  Many IPC modules require identifying processors in a
    46     *  multi-processor environment. The MultiProc module centralizes
    47     *  processor id management into one module.  Since this configuration
    48     *  is almost always universally required, most IPC applications
    49     *  require supplying configuration of this module.
    50     *
    51     *  Each processor in the MultiProc module may be uniquely identified by
    52     *  either a name string or an integer ranging from 0 to MAXPROCESSORS - 1.
    53     *  Configuration is supplied using the {@link #setConfig} meta function,
    54     *  the {@link #numProcessors} and {@link #baseIdOfCluster}.
    55     *
    56     *  The setConfig function tells the MultiProc module:
    57     *  @p(blist)
    58     *      - The specific processor for which the application is being built
    59     *      - The number of processors in the cluster
    60     *  @p
    61     *
    62     *  A cluster is a set of processors within a system which share some share
    63     *  shared memory and supports notifications. Typically most systems contain
    64     *  one cluster.  When there are multiple clusters in the system, the
    65     *  {@link #numProcessors} and {@link #baseIdOfCluster} configuration
    66     *  paramaters are required to be set before calling {@link #setConfig}
    67     *
    68     *  For examle in a system with 2 C6678 devices [each C6678 contains 8
    69     *  homogeneuous cores].  For first C6678 device:
    70     *  @p(code)
    71     *  var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
    72     *  MultiProc.baseIdOfCluster = 0;
    73     *  MultiProc.numProcessors = 16;
    74     *  MultiProc.setConfig(null, ["CORE0", "CORE1", "CORE2", "CORE3",
    75     *                             "CORE4", "CORE5", "CORE6", "CORE7"]);
    76     *  @p
    77     *
    78     *  For second C6678 device:
    79     *  @p(code)
    80     *  var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
    81     *  MultiProc.baseIdOfCluster = 8;
    82     *  MultiProc.numProcessors = 16;
    83     *  MultiProc.setConfig(null, ["CORE0", "CORE1", "CORE2", "CORE3",
    84     *                             "CORE4", "CORE5", "CORE6", "CORE7"]);
    85     *  @p
    86     *
    87     *  Using the information supplied using the {@link #setConfig} meta function
    88     *  and the {@link #baseIdOfCluster} module configuration, the processor IDs
    89     *  are internally set.  Please refer to the documentation for
    90     *  {@link #setConfig} and {@link #baseIdOfCluster} for more details.
    91     *
    92     *  At runtime, the {@link #getId} call returns the MultiProc id of those
    93     *  processors within its cluster. At config-time, the {@link #getIdMeta}
    94     *  call returns the the same value.
    95     *
    96     */
    97    
    98    module MultiProc
    99    {
   100        metaonly struct ModuleView {
   101            UInt16       id;                /* Own ID                           */
   102            UInt16       numProcessors;     /* # of processors                  */
   103            String       nameList[];        /* Proc names ordered by procId     */
   104        }
   105    
   106        @Facet
   107        metaonly config ViewInfo.Instance rovViewInfo =
   108            ViewInfo.create({
   109                viewMap: [
   110                [
   111                    'Module',
   112                    {
   113                        type: ViewInfo.MODULE,
   114                        viewInitFxn: 'viewInitModule',
   115                        structName: 'ModuleView'
   116                    }
   117                ],
   118                ]
   119            });
   120    
   121        /*!
   122         *  Assert raised when an invalid processor id is used
   123         */
   124        config Assert.Id A_invalidMultiProcId  = {
   125            msg: "A_invalidMultiProcId: Invalid MultiProc id"
   126        };
   127    
   128        /*!
   129         *  Assert raised when a NULL processor name is encountered
   130         */
   131        config Assert.Id A_invalidProcName  = {
   132            msg: "A_invalidProcName: NULL MultiProc name encountered"
   133        };
   134    
   135        /*!
   136         *  Invalid processor id constant
   137         *
   138         *  This constant denotes that the processor id is not valid.
   139         */
   140        const UInt16 INVALIDID = 0xFFFF;
   141    
   142        /*! @_nodoc
   143         *  ======== nameList ========
   144         *  Unique name for the each processor used in a multi-processor app
   145         *
   146         *  This array should never be set or read directly by the MultiProc user.
   147         *  The nameList is used to store names configuration supplied via the
   148         *  {@link #setConfig} static function.
   149         *
   150         *  At runtime, the {@link #getName} function may be used to retrieve
   151         *  the name of any processor given it's MultiProc id.
   152         */
   153        config String nameList[];
   154    
   155        /*! @_nodoc
   156         *  ======== id ========
   157         *  Unique software id number for the processor
   158         *
   159         *  This value should never be set or read directly by the MultiProc user.
   160         *  Instead, the {@link #getId}, {@link #getIdMeta}, and
   161         *  {@link #setLocalId} calls should be used to respectively retrieve any
   162         *  processors' MultiProc ids or set the local processor's MultiProc id.
   163         */
   164        metaonly config UInt16 id = 0;
   165    
   166        /*! @_nodoc
   167         *  ======== numProcsInCluster ========
   168         *  Number of processors in a cluster
   169         *
   170         *  This parameter should never be set: numProcsInCluster is
   171         *  internally set by the {@link #setConfig} meta function.
   172         *  setConfig statically sets the value of this configuration to the
   173         *  length of the supplied nameList array.
   174         */
   175        config UInt16 numProcsInCluster = 1;
   176    
   177        /*!
   178         *  ======== baseIdOfCluster ========
   179         *  The base processor ID of the cluster.
   180         *
   181         *  The ID of each processor in a cluster is computed by adding
   182         *  its position in the name list of {@link #setConfig} to the
   183         *  base ID of the cluster. When more than one cluster exists in
   184         *  the system, this parameter must be set before calling
   185         *  {@link #setConfig}.
   186         */
   187        metaonly config UInt16 baseIdOfCluster = 0;
   188    
   189        /*!
   190         *  ======== numProcessors ========
   191         *  Number of processors in the system
   192         *
   193         *  This configuration should only be set when there is more than one
   194         *  cluster in the system.  It must be set before calling
   195         *  {@link #setConfig}. If the system contains only one cluster,
   196         *  it is internally set by the {@link #setConfig} meta function to the
   197         *  length of the supplied nameList array.
   198         *  After {@link #setConfig} has been  called, it is possible to
   199         *  retrive the maximum # of processors by reading this module config
   200         *  either at run-time or at config time.
   201         */
   202        config UInt16 numProcessors = 1;
   203    
   204        /*!
   205         *  ======== ProcAddrMode ========
   206         *  Enumerate the Processor Addressing Modes
   207         *
   208         *  This enumeration defines the various processor addressing modes
   209         *  which might impact the behavior and resource allocations of modules
   210         *  that communicate with other processors in the system (i.e. IPC).
   211         *
   212         *  It is a way for the system integrator to control the internal
   213         *  behavior and resource allocations of various module to suit the
   214         *  needs of the program. However, it is at the discretion of each
   215         *  module on how to respond to these processor addressing modes.
   216         *
   217         *  For example, the NameServer module reflects on this mode when
   218         *  constructing its internal data structures. For the 'Global' mode,
   219         *  it will allocate a resource for every processor in the system.
   220         *  When using 'Cluster' mode, resources are only allocated for
   221         *  processors in the cluster. A side-effect is that when using
   222         *  Cluster mode, name queries cannot be addressed to processors
   223         *  outside of the cluster.
   224         *
   225         *  Specify the addressing mode by setting the
   226         *  {@link #procAddrMode MultiProc.procAddrMode} configuration
   227         *  parameter.
   228         *
   229         *  @field(ProcAddrMode_Global) Every processor in the system must
   230         *  be directly addressable. Usually, this requires a resource
   231         *  allocation for each processor. This might require a dedicated
   232         *  hardware resource and/or a memory allocation on behalf of every
   233         *  processor in the sytem. For large systems, this might result in
   234         *  significant memory requirements. Use with caution.
   235         *
   236         *  @field(ProcAddrMode_Cluster) Direct addressing is required
   237         *  only for the processors in your cluster. Processors outside of
   238         *  the cluster may share resources. This mode limits the per processor
   239         *  resource allocations to just the processors within your cluster.
   240         *  This address mode is typically used for large processor systems.
   241         *
   242         *  @see {@link #procAddrMode MultiProc.procAddrMode}
   243         */
   244        enum ProcAddrMode {
   245            ProcAddrMode_Global,
   246            ProcAddrMode_Cluster
   247        };
   248    
   249        /*!
   250         *  ======== procAddrMode ========
   251         *  Define which processor addressing mode is in operation
   252         *
   253         *  This configuration parameter is reflected upon by various system
   254         *  components whose implementation is impacted by the processor
   255         *  addressing mode currently in effect. It allows modules to optimize
   256         *  their behavior and resource allocations for any given processor
   257         *  address mode.
   258         *
   259         *  The MultiProc module has no specific behavior associated with
   260         *  this configuration parameter. It is simply a convenient location
   261         *  for such a configuration parameter as most processor aware
   262         *  modules already depend on MultiProc.
   263         *
   264         *  @see {@link #ProcAddrMode MultiProc.ProcAddrMode}
   265         */
   266        config ProcAddrMode procAddrMode = MultiProc.ProcAddrMode_Global;
   267    
   268        /*! @_nodoc
   269         *  ======== getClusterId ========
   270         */
   271        UInt16 getClusterId(UInt16 procId);
   272    
   273        /*!
   274         *  ======== getIdMeta ========
   275         *  Meta version of {@link #getId}
   276         *
   277         *  Statically returns the internally set ID based on configuration
   278         *  supplied via {@link #setConfig}.
   279         *
   280         *  @param(name)        MultiProc procName
   281         */
   282        metaonly UInt16 getIdMeta(String name);
   283    
   284        /*!
   285         *  ======== getDeviceProcNames ========
   286         *  Returns an array of all possible processor names on the build device
   287         *
   288         *  @(return)           Array of valid MultiProc processor names
   289         */
   290        metaonly Any getDeviceProcNames();
   291    
   292        /*!
   293         *  ======== setConfig ========
   294         *  Configure the MultiProc module
   295         *
   296         *  Configuration of the MultiProc module is primarily accomplished using
   297         *  the setConfig API at config time.  The setConfig API allows the
   298         *  MultiProc module to identify:
   299         *  @p(blist)
   300         *      - Which is the local processor
   301         *      - Which processors are being used
   302         *      - Which processors can synchronize
   303         *  @p
   304         *  The second of these two pieces of information is supplied via the
   305         *  nameList argument.  The nameList is a non-empty set of distinct
   306         *  processors valid for the particular device.  For a list of valid
   307         *  processor names for a given device, please refer to the :
   308         *  {@link ./../ipc/family/doc-files/procNames.html Table of
   309         *   Valid Names for Each Device}.
   310         *
   311         *  The local processor is identified by using a single name from
   312         *  nameList.  A MultiProc id is internally set to the index of
   313         *  'name' in the supplied 'nameList'.  I.e. in the example:
   314         *
   315         *  @p(code)
   316         *  MultiProc.setConfig("DSP", ["HOST", "DSP", "OTHERCORE"]);
   317         *  @p
   318         *
   319         *  The processors, "HOST", "DSP" and "OTHERCORE" get assigned MultiProc
   320         *  IDs 0, 1, and 2, respectively.  The local processor, "DSP" is assigned
   321         *  an ID of '1'.
   322         *
   323         *  If the local processor is not known at static time, it is possible to
   324         *  supply a null name. MultiProc will set the local id to
   325         *  {@link #INVALIDID} until it is set at runtime using
   326         *  MultiProc_setLocalId.
   327         *
   328         *  @param(name)        MultiProc name for the local processor
   329         *  @param(nameList)    Array of all processors used by the application
   330         */
   331        metaonly Void setConfig(String name, String nameList[]);
   332    
   333        /*! @_nodoc
   334         *  ======== getName$view ========
   335         *  ROV-time version of {@link #getName}
   336         */
   337        metaonly String getName$view(UInt id);
   338    
   339        /*! @_nodoc
   340         *  ======== self$view ========
   341         *  ROV-time version of {@link #self}
   342         */
   343        metaonly UInt self$view();
   344    
   345        /*! @_nodoc
   346         *  This is needed to prevent the MultiProc module from being optimized away
   347         *  during the whole_program[_debug] partial link.
   348         */
   349        Void dummy();
   350    
   351    internal:
   352    
   353        /*  Store these elements in the module state (instead of config) to
   354         *  support boot-time assignment (for single image reuse).
   355         */
   356        struct Module_State {
   357            UInt16 id;
   358            UInt16 baseIdOfCluster;
   359            UInt16 clusterProcList[];       /* list of procIds in cluster */
   360        };
   361    }