1    /* --COPYRIGHT--,BSD
     2     * Copyright (c) $(CPYYEAR), 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     * --/COPYRIGHT--*/
    32    /*
    33     *  ======== NotifyDriverCirc.xdc ================
    34     */
    35    
    36    import ti.sdo.utils.MultiProc;
    37    import ti.sdo.ipc.interfaces.INotifyDriver;
    38    import ti.sdo.ipc.notifyDrivers.IInterrupt;
    39    import ti.sdo.ipc.Notify;
    40    
    41    import xdc.rov.ViewInfo;
    42    
    43    import xdc.runtime.Assert;
    44    
    45    /*!
    46     *  ======== NotifyDriverCirc ========
    47     *  A shared memory driver using circular buffer for the Notify Module.
    48     *
    49     *  This is a {@link ti.sdo.ipc.Notify} driver that utilizes shared memory
    50     *  and inter-processor hardware interrupts for notification between cores.
    51     *  This driver supports caching.
    52     *
    53     *  This driver is designed to work with a variety of devices, each with
    54     *  distinct interrupt mechanisms.  Therefore, this module needs to be plugged
    55     *  with an appropriate module that implements the {@link IInterrupt} interface
    56     *  for a given device.
    57     *
    58     *  The Notify_[enable/disable]Event APIs are not supported by this driver.
    59     *
    60     *  The driver utilizes shared memory in the manner indicated by the following
    61     *  diagram.
    62     *
    63     *  @p(code)
    64     *  
    65     *  NOTE: Processors '0' and '1' correspond to the processors with lower and
    66     *        higher MultiProc ids, respectively
    67     *
    68     * sharedAddr -> --------------------------- bytes
    69     *               |  eventEntry0  (0)       | 8  
    70     *               |  eventEntry1  (0)       | 8
    71     *               |  ...                    | 
    72     *               |  eventEntry15 (0)       | 8
    73     *               |  [align to cache size]  |
    74     *               |-------------------------|
    75     *               |  eventEntry16 (0)       | 8
    76     *               |  eventEntry17 (0)       | 8
    77     *               |  ...                    | 
    78     *               |  eventEntry31 (0)       | 8
    79     *               |  [align to cache size]  |
    80     *               |-------------------------|
    81     *               |  putWriteIndex (0)      | 4
    82     *               |  [align to cache size]  |
    83     *               |-------------------------|
    84     *               |  putReadIndex (0)       | 4
    85     *               |  [align to cache size]  |
    86     *               |-------------------------|
    87     *               |  eventEntry0  (1)       | 8  
    88     *               |  eventEntry1  (1)       | 8
    89     *               |  ...                    | 
    90     *               |  eventEntry15 (1)       | 8
    91     *               |  [align to cache size]  |
    92     *               |-------------------------|
    93     *               |  eventEntry16 (1)       | 8
    94     *               |  eventEntry17 (1)       | 8
    95     *               |  ...                    | 
    96     *               |  eventEntry31 (1)       | 8
    97     *               |  [align to cache size]  |
    98     *               |-------------------------|
    99     *               |  getWriteIndex (1)      | 4
   100     *               |  [align to cache size]  |
   101     *               |-------------------------|
   102     *               |  getReadIndex (1)       | 4
   103     *               |  [align to cache size]  |
   104     *               |-------------------------|
   105     *
   106     *
   107     *  Legend:
   108     *  (0), (1) : Memory that belongs to the proc with lower and higher 
   109     *             MultiProc.id, respectively
   110     *   |----|  : Cache line boundary
   111     *
   112     *  @p
   113     */
   114    
   115    @InstanceFinalize
   116    
   117    module NotifyDriverCirc inherits ti.sdo.ipc.interfaces.INotifyDriver
   118    {
   119        /*! @_nodoc */
   120        metaonly struct BasicView {
   121            String      remoteProcName;
   122            Bool        cacheEnabled;
   123            UInt        bufSize;
   124            UInt        spinCount;
   125            UInt        maxSpinWait;
   126        }
   127        
   128        /*! @_nodoc */
   129        metaonly struct EventDataView {
   130            UInt        index;
   131            String      buffer;
   132            Ptr         addr;
   133            UInt        eventId;
   134            Ptr         payload;
   135        }
   136        
   137        /*!
   138         *  ======== rovViewInfo ========
   139         */
   140        @Facet
   141        metaonly config ViewInfo.Instance rovViewInfo =
   142            ViewInfo.create({
   143                viewMap: [
   144                    ['Basic',
   145                        {
   146                            type: ViewInfo.INSTANCE,
   147                            viewInitFxn: 'viewInitBasic',
   148                            structName: 'BasicView'
   149                        }
   150                    ],
   151                    ['Events',
   152                        {
   153                            type: ViewInfo.INSTANCE_DATA,
   154                            viewInitFxn: 'viewInitData',
   155                            structName: 'EventDataView'
   156                        }
   157                    ],
   158                ]
   159            });
   160        
   161        /*!
   162         *  Assert raised when trying to use Notify_[enable/disable]Event with
   163         *  NotifyDriverCirc
   164         */
   165        config Assert.Id A_notSupported =
   166            {msg: "A_notSupported: [enable/disable]Event not supported by NotifyDriverCirc"};
   167    
   168        
   169        /*! @_nodoc
   170         *  IInterrupt proxy that handles interrupts between multiple CPU cores
   171         */
   172        proxy InterruptProxy inherits IInterrupt;
   173        
   174        /*!
   175         *  ======== enableStats ========
   176         *  Enable statistics for sending an event
   177         *
   178         *  If this parameter is to 'TRUE' and 'waitClear' is also set to
   179         *  TRUE when calling (@link #sendEvent(), then the module keeps
   180         *  track of the number of times the processor spins waiting for
   181         *  an empty slot and the max amount of time it waits.
   182         */
   183        config Bool enableStats = false;
   184        
   185        /*!
   186         *  ======== numMsgs ========
   187         *  The number of messages or slots in the circular buffer
   188         *
   189         *  This is use to determine the size of the put and get buffers.
   190         *  Each eventEntry is two 32bits wide, therefore the total size
   191         *  of each circular buffer is [numMsgs * sizeof(eventEntry)].
   192         *  The total size of each buffer must be a multiple of the 
   193         *  the cache line size. For example, if the cacheLineSize = 128
   194         *  then numMsgs could be 16, 32, etc...
   195         */
   196        config UInt numMsgs = 32;
   197        
   198        /*!
   199         *  ======== sharedMemReq ========
   200         *  Amount of shared memory required for creation of each instance
   201         *
   202         *  @param(params)      Pointer to parameters that will be used in the
   203         *                      create
   204         *
   205         *  @a(returns)         Number of MAUs in shared memory needed to create 
   206         *                      the instance.
   207         */
   208        SizeT sharedMemReq(const Params *params);
   209        
   210    instance:
   211    
   212        /*!
   213         *  ======== sharedAddr ========
   214         *  Address in shared memory where this instance will be placed
   215         *
   216         *  Use {@link #sharedMemReq} to determine the amount of shared memory
   217         *  required.
   218         */
   219        config Ptr sharedAddr = null;
   220    
   221        /*!
   222         *  ======== cacheEnabled ========
   223         *  Whether cache operations will be performed
   224         *
   225         *  If it is known that no cache operations are needed for this instance
   226         *  set this flag to FALSE.  If {@link #sharedAddr} lies within a shared
   227         *  region and the cache enabled setting for the region is FALSE,
   228         *  then the value specified here will be overriden to FALSE.
   229         */
   230        config Bool cacheEnabled = true;
   231        
   232        /*!
   233         *  ======== cacheLineSize ========
   234         *  The cache line size of the shared memory
   235         *
   236         *  This value should be configured 
   237         */
   238        config SizeT cacheLineSize = 128;
   239        
   240        /*!
   241         *  ======== remoteProcId ========
   242         *  The MultiProc ID corresponding to the remote processor
   243         *
   244         *  This parameter must be set for every device.  The
   245         *  MultiProc_getId call can be used to obtain
   246         *  a MultiProc id given the remote processor's name.
   247         */
   248        config UInt16 remoteProcId = MultiProc.INVALIDID;
   249    
   250        /*!
   251         *  ======== intVectorId ========
   252         *  Interrupt vector ID to be used by the driver.
   253         *
   254         *  This parameter is only used by C64x+ targets
   255         */
   256        config UInt intVectorId = ~1u;
   257    
   258        /*!
   259         *  ======== localIntId ========
   260         *  Local interrupt ID for interrupt line
   261         *
   262         *  For devices that support multiple inter-processor interrupt lines, this
   263         *  configuration parameter allows selecting a specific line to use for
   264         *  receiving an interrupt.  The value specified here corresponds to the
   265         *  incoming interrupt line on the local processor.
   266         *
   267         *  If this configuration is not set, a default interrupt id is 
   268         *  typically chosen.
   269         */
   270        config UInt localIntId = -1u;
   271    
   272        /*!
   273         *  ======== remoteIntId ========
   274         *  Remote interrupt ID for interrupt line
   275         *
   276         *  For devices that support multiple inter-processor interrupt lines, this
   277         *  configuration parameter allows selecting a specific line to use for
   278         *  receiving an interrupt.  The value specified here corresponds to the
   279         *  incoming interrupt line on the remote processor.
   280         *
   281         *  If this configuration is not set, a default interrupt id is 
   282         *  typically chosen.
   283         */
   284        config UInt remoteIntId = -1u;
   285    
   286    internal:
   287    
   288        /*! The max index set to (numMsgs - 1) */
   289        config UInt maxIndex;
   290        
   291        /*!
   292         *  The modulo index value. Set to (numMsgs / 4).
   293         *  Used in the isr for doing cache_wb of readIndex.
   294         */
   295        config UInt modIndex;
   296        
   297        /*! 
   298         *  Plugs the interrupt and executes the callback functions according
   299         *  to event priority
   300         */
   301        Void isr(UArg arg);
   302    
   303        /*! 
   304         *  Structure for each event. This struct is placed in shared memory.
   305         */
   306        struct EventEntry {
   307            volatile Bits32 eventid;
   308            volatile Bits32 payload;
   309        }
   310    
   311        /*! Instance state structure */
   312        struct Instance_State {
   313            EventEntry       *putBuffer;     /* buffer used to put events        */
   314            Bits32           *putReadIndex;  /* ptr to readIndex for put buffer  */
   315            Bits32           *putWriteIndex; /* ptr to writeIndex for put buffer */
   316            EventEntry       *getBuffer;     /* buffer used to get events        */
   317            Bits32           *getReadIndex;  /* ptr to readIndex for get buffer  */
   318            Bits32           *getWriteIndex; /* ptr to writeIndex for put buffer */
   319            Bits32           evtRegMask;     /* local event register mask        */
   320            SizeT            opCacheSize;    /* optimized cache size for wb/inv  */
   321            UInt32           spinCount;      /* number of times sender waits     */
   322            UInt32           spinWaitTime;   /* largest wait time for sender     */
   323            Notify.Handle    notifyHandle;   /* Handle to front-end object       */
   324            IInterrupt.IntInfo intInfo;      /* Intr info passed to Interr mod   */
   325            UInt16           remoteProcId;   /* Remote MultiProc id              */
   326            Bool             cacheEnabled;   /* set by param or SharedRegion     */
   327        }
   328    }