Framework Components DSKT2 User's Guide

From Texas Instruments Wiki
Jump to: navigation, search

Note: This article was sourced from, and supersedes SPRUEV5A.

Acronyms and Definitions

  • DSKT2 is a Framework Components API providing services to instantiate, activate, and control XDAIS algorithms, typically within the context of a larger framework (e.g. Codec Engine).
  • IALG Interface is a set of standard interface functions exported by an XDAIS algorithm (algAlloc(), algActivate(), algControl(), algDeactivate(), algFree(), algInit(), algMoved(), algNumAlloc()). It is defined by, and distributed with, the XDAIS product.
  • Scratch Memory is an XDAIS-defined scheme for sharing memory between XDAIS algorithms. Typically the framework does the following:
    1. Calls the algorithm's algActivate() function to allow it to initialize scratch memory buffers from persistent memory.
    2. Calls the algorithm's processing function(s).
    3. Calls the algorithm's algDeactivate() function to allow it to save the appropriate scratch memory contents back to persistent memory.
Once this cycle is complete, the framework can repeat the cycle for another algorithm, which may use the same physical scratch memory during its processing.


This XDAIS helper library provides services to support the creation, initialization, control, and deletion of XDAIS algorithm instance objects.

The primary purpose of the DSKT2 library is to automate the standard algorithm operations that use an algorithm’s IALG methods. A significant part of the work required to instantiate and use an algorithm is algorithm-independent. This work includes using an algorithm’s IALG methods to instantiate the algorithm, get its memory requests, allocate memory for the algorithm, and activate/deactivate scratch memory. DSKT2 provides API interfaces (described in the DSKT2 API Reference Guide) to perform these and other tasks.

DSKT2 also introduces two primary features that result in fine-grained memory configuration and optimized memory management and use:

  • You can define multiple memory heap segments and configure a mapping from an algorithm's memory requests to a preferred heap segment designated for the request's memory-space attribute.
  • You can transparently share scratch memory assignments of algorithm instances that belong to the same scratch-group ID.

By adopting DSKT2, you can realize the following benefits:

  • You can reduce the DSP application footprint by not duplicating functionality that is provided by DSKT2.
  • Having all algorithm memory allocation performed inside DSKT2 provides the ability to retain a certain level of control of DSP-side memory allocations. Without this centralized allocation of algorithm memory, each algorithm developer could implement different allocation policies, for example grabbing all on-chip memory for their own algorithms, without consideration for other algorithms concurrently running on the DSP.

DSKT2 Calling Sequence

The following code example uses the typical calling sequence for DSKT2 APIs:

#include <xdc/std.h>                /* data types */
#include <ti/sdo/fc/dskt2/dskt2.h>
#include <mymod_vend.h>             /* alg-specific interface */
Void smain(Int argc, Char * argv[])
    IMYMOD_Handle       alg;
    IMYMOD_Params       params = IMYMOD_PARAMS;
    IALG_Fxns          *fxns;
    Int                 scratchId = 0;
    Int                 status;
    /* IALG_Fxns for my algorithm */
    fxns = (IALG_Fxns *)&MYMOD_VEND_IMYMOD;
    /* Create my alg */
    alg = (IMYMOD_Handle)DSKT2_createAlg(scratchId,
            fxns, NULL, (IALG_Params *)&params);
    if (alg == NULL) {
        /* ... handle memory allocation failure... */
    /* Activate alg before calling its process function */
    DSKT2_activateAlg(scratchId, (IALG_Handle)alg);
    /* Call alg's processing function */
    status = alg->fxns->process((IALG_Handle)alg);
    /* Deactivate the alg */
    DSKT2_deactivateAlg(scratchId, (IALG_Handle)alg1);
    /* Free alg */
    DSKT2_freeAlg(scratchId, (IALG_Handle)alg);

Configuring DSKT2 to Map Algorithm Data Memory Segments

For DSKT2 to fully honor algorithm memory requests it must know the following:

  • What BIOS memory segments are available to allocate from?
  • What are the attributes of the available memory segments?

This section describes the configuration of this information for the DSKT2 module.

There are two ways to configure DSKT2 parameters.

  • You can use a low-level C language and linker command file based approach to directly modify global DSKT2 parameters.
  • You can use XDC tooling to configure the DSKT2 module. The XDC tooling approach results in the generation of the same low-level C-based global variables, so the type of configuration technology used does not matter to the underlying DSKT2 library implementation.

You will still need to configure some BIOS heaps that will be used by the DSKT2 module. See the BIOS documentation for memory config details (note, there are differences between DSP/BIOS 5 and SYS/BIOS 6).

For example, if you want to define a DSP/BIOS 5 heap that will be used by DSKT2, you may have something like the following in your TCF file:

// Create a heap in external memory and give it a label
var EXTMEM = prog.module("MEM").create("EXTMEM")
EXTMEM.createHeap = true;
EXTMEM.enableHeapLabel = true;
EXTMEM.heapLabel = prog.extern("EXTMEM_HEAP");

Note that the heap must be given a label so that it can be referenced by DSKT2.

XDC Configuration of DSKT2

Follow these steps to use XDC to configure DSKT2:

  1. The first statement related to DSKT2 in your XDC configuration (cfg) file should bring in (i.e. 'use') the DSKT2 module as follows:
    var DSKT2 = xdc.useModule('ti.sdo.fc.dskt2.DSKT2');
  2. To allow DSKT2 to use external scratch memory, add the following statement:

    Setting the ALLOW_EXTERNAL_SCRATCH property to "true" means that if a scratch request in internal memory cannot be granted AND there is insufficient memory in persistent internal memory to allocate for the request, then DSKT2 allocates using external memory.

    If you set this property to "false", then DSKT2_createAlg() fails if there is insufficient scratch memory and insufficient internal persistent memory to satisfy the request.

  3. Next, your CFG file should specify the heap that DSKT2 will use by default to allocate internal objects. This is the name of a heap label that has been defined in a TCF file. For example, if you defined the heap label "EXTMEM_HEAP" as in Configuring DSKT2 to Map Algorithm Data Memory Segments, then in your CFG file, you could specify that DSKT2 use heap for allocating its internal objects as follows.

    Notice that you add a leading underscore ("_") to the name of the heap label, since prog.extern() generates a "C" name, and DSKT2_HEAP is the assembly name of the heap.

  4. Then, you map IALG memory space types to specific heaps. In the following statements, _L1D_HEAP and _EXTMEM_HEAP are heap labels that have been assigned to DSP/BIOS MEM segments
    DSKT2.DARAM0 = "_L1D_HEAP";
    DSKT2.DARAM1 = "_L1D_HEAP";
    DSKT2.DARAM2 = "_L1D_HEAP";
    DSKT2.SARAM0 = "_L1D_HEAP";
    DSKT2.SARAM1 = "_L1D_HEAP";
    DSKT2.SARAM2 = "_L1D_HEAP";
  5. Then, you assign sizes to the scratch groups. There can be up to 20 scratch groups for each of the memory types, DARAM and SARAM. In the following statements, the scratch group 0 is assigned a size of 512 MAUs.

    If you assign the same heap label to both DSKT2.DARAM0 and DSKT2.SARAM0, the values in DSKT2.SARAM_SCRATCH_SIZES are ignored; algorithms that request scratch memory from SARAM are granted scratch memory in DARAM if memory is available.

  6. Finally, you name a function to implement cache writeback and invalidation. This function must have the following signature in your C code:
    (*DSKT2_CacheWBInvFxn)(Ptr blockPtr, size_t byteCnt, Bool wait);

    For C6000 platforms, DSKT2 calls this function to ensure that the algorithm instance memory is not resident in a cache when it is instantiated. This is necessary for compliance with the XDAIS C6000 DMA Rules and Guidelines.

    On DSP/BIOS 5 systems, the default value of this parameter is "BCACHE_wbInv", so you don't need to set this on C6000 platforms. If you are configuring this for a C55, then you would set it to null as follows:

    DSKT2.cacheWritebackInvalidateFxn = null;

XDC Configuration Example

For example, the combined DSP/BIOS 5-based example.tcf file for the DSKT2 configuration might look like the following:

/* ======== example.tcf ======== */
// DaVinci platform
var platform = "ti.platforms.evmDM6446";
var params = null;
/* load the platform */
utils.loadPlatform(platform, params);
/* Enable BIOS features needed */
var DDR = prog.module("MEM").instance("DDR2");
 *  Create external memory segment for this (simulated) board
 *  Enable heaps in it and define the label for heap usage.
DDR.base             = 0x83F00000;
DDR.len              = 0x0FFE00;   // may be much bigger            = "code/data"; // so we can put code here
DDR.createHeap       = true;
DDR.enableHeapLabel  = true;
DDR["heapLabel"]     = prog.extern("EXTMEM_HEAP");
DDR.heapSize         = 0xc0000;
DDR.comment          = "DDR";
 *  Enable heaps in L1DSRAM (internal L1 cache ram, fixed
 *  size) and define the label for heap usage.
bios.L1DSRAM.createHeap       = true;
bios.L1DSRAM.enableHeapLabel  = true;
bios.L1DSRAM["heapLabel"]     = prog.extern("L1D_HEAP");
bios.L1DSRAM.heapSize         = 0x4000;

And, the combined example.cfg file for the DSKT2 XDC configuration might look like the following:

 *  ======== example.cfg ========
 *  Example configuration of DSKT2 module
// Get the DSKT2 module.
var DSKT2 = xdc.useModule('ti.sdo.fc.dskt2.DSKT2');
// If a scratch request in internal memory cannot be granted
// AND there is insufficient persistent internal memory to
// allocate for the request, THEN DSKT2 uses external memory.
// Set the heap that the DSKT2 will use to allocate internal
// objects. This is a heap label defined in a .tcf file.
// Map IALG memory space types to specific heaps assigned to
// DSP/BIOS MEM segments.
// Assign sizes to scratch groups.

Non-XDC Configuration of DSKT2

It is also possible to configure DSKT2 without using XDC tooling. In this case, you still need to configure DSP/BIOS heaps in a TCF file, as described in XDC Configuration of DSKT2. You will also need a C source file and linker command file to build your application.

To match the XDC configuration of DSKT2 shown in the previous section, your C file should contain the following:

 *  ======== dskt2_config.c ========
 *  DSKT2 scratch config file to initialize pre-allocated
 *  scratch heap size for each node priority level.
#include <std.h>
#include <ti/sdo/fc/dskt2/dskt2.h>
#include <ti/sdo/fc/dskt2/_dskt2.h>
#include <bcache.h>
#ifdef _6x_
far DSKT2_CacheWBInvFxn DSKT2_cacheWBInvFxn = BCACHE_wbInv;
DSKT2_CacheWBInvFxn DSKT2_cacheWBInvFxn = NULL;
    0x200       /* 0 */
    0,          /* 1 */
    0,          /* 2 */
    0,          /* 3 */
    0,          /* 4 */
    0,          /* 5 */
    0,          /* 6 */
    0,          /* 7 */
    0,          /* 8 */
    0,          /* 9 */
    0,          /* 10 */
    0,          /* 11 */
    0,          /* 12 */
    0,          /* 13 */
    0,          /* 14 */
    0,          /* 15*/
    0,          /* 16 */
    0,          /* 17 */
    0,          /* 18 */
    0,          /* 19 */
    0x200,      /* 0 */
    0,          /* 1 */
    0,          /* 2 */
    0,          /* 3 */
    0,          /* 4 */
    0,          /* 5 */
    0,          /* 6 */
    0,          /* 7 */
    0,          /* 8 */
    0,          /* 9 */
    0,          /* 10 */
    0,          /* 11 */
    0,          /* 12 */
    0,          /* 13 */
    0,          /* 14 */
    0,          /* 15*/
    0,          /* 16 */
    0,          /* 17 */
    0,          /* 18 */
    0,          /* 19 */

For DSP/BIOS 5, the linker command file needs to link in the DSP/BIOS generated linker command file and the DSKT2 library, and define the mapping of IALG memory spaces to DSP/BIOS heaps. The following linker command file code illustrates this.

 * example.cmd
 * Linker command file for non RTSC DSKT2 configuration.
/* Link in DSP/BIOS 5 generated linker command file */
-l examplecfg.cmd
/* Link in DSKT2 library */
-l dskt2.a64P
 * Mapping of IALG mem spaces to BIOS heaps
 * (Note: there is no DSKT2 mapping of IALG_EXTERNAL)
__DSKT_DARAM0 = _L1D_HEAP;      /* IALG_DARAM0 */
__DSKT_DARAM1 = _L1D_HEAP;      /* IALG_DARAM1 */
__DSKT_DARAM2 = _L1D_HEAP;      /* IALG_DARAM2 */
/* DSKT2 heap for allocating internal objects */

DSKT2 Support for Shared Algorithm Scratch Memory

The XDAIS standard includes provisions to allow algorithms to share memory buffers and reduce the overall application memory footprint.

XDAIS Scratch Memory Support Overview

TMS320 DSP Algorithm Standard (XDAIS) compliant algorithms request memory blocks from their housing application frameworks. Each requested memory block is designated as either "persistent" or "scratch".

Scratch memory is defined as a type of memory that is freely used by an algorithm without regard to its prior contents, that is, no assumptions about the content can be made by the algorithm and the algorithm is free to leave it in any state. The algorithm instance initializes its scratch buffers when the application activates the instance by granting it exclusive access to the scratch region and calling its IALG activation function, algActivate().

During initialization of its scratch buffers in algActivate() the algorithm can only access its static memory and what’s saved in its persistent instance memory. The application calls algDeactivate() when it wants to use/free up the scratch area granted to the instance. The algorithm saves to its persistent memory any information in its scratch buffers that it will need later during re-activation to re-initialize its scratch buffers.

After the standard algorithm initialization call to algInit(), all compliant algorithm instances with scratch buffers are in either one of these two states: activated or deactivated. It is in activated state if no algDeactivate() calls have been issued since the last algActivate() call. Algorithm is in deactivated state if it has received no algActivate() calls since algInit() or since the last algDeactivate().

The basic rule of operation is that an algorithm instance must be in the activated state when any of its processing functions are called.

The basic rule of sharing a system overlay scratch area is that at any given time at most one algorithm instance sharing the overlay area can be activated—all other instances must be de-activated.

A XDAIS application framework is always in charge as to where to allocate scratch memory and decides which groups of algorithm instances (if any) will share a common “scratch” overlay region and when a particular algorithm instance gets activated or deactivated.

Scratch Groups for Arranged Sharing of Scratch Memory

Scratch groups form the basis for arranging multiple algorithm instances to share "scratch memory". Each scratch group is associated with an ID. It is the responsibility of the application framework to ensure mutually exclusive operation of algorithm instances having the same scratch group ID. No algorithm instance is allowed to preempt another algorithm instance’s processing stage belonging to the same scratch group.

One way to assign scratch IDs if algorithms are run from DSP/BIOS tasks is to use the task priority as the scratch ID for this algorithm. This technique can be used so long as the application doesn’t change task priorities at run-time.

Using a “task priority level” based protection approach, algorithms that share the same scratch buffers run at the same priority level, and preemption is avoided. Therefore, multiple algorithms running at the same task priority level can share the same physical addresses for their scratch buffers and are ensured exclusive access to the shared buffer when their processing functions get called.

Here’s an overview of how this works for DSKT2: OEMs configure the size of scratch memory to be supported for each group ID. For example, this size could be set to the largest amount of scratch needed by any of the algorithms to be instantiated with the specified scratch ID.

For example, the following statements configure two scratch buffers— one of 2048 MAU and another of 1024 MAU. These are designated as the default sizes of the shared scratch memory area allocated in the IALG_DARAM memory spaces.

// Get the DSKT2 module
var DSKT2 = xdc.useModule('ti.sdo.fc.dskt2.DSKT2');
// Assign sizes 2048 and 1024 to scratch groups 5 and 6,
// respectively, for IALG_DARAM memory spaces.
DSKT2.DARAM_SCRATCH_SIZES = [0,0,0,0,0, 2048, 1024,

These scratch buffers are shared among algorithm instances configured with scratch group IDs 5 and 6, respectively. The following actions occur:

  1. When the first XDAIS algorithm created with the specified scratch ID requests scratch memory, DSKT2 dynamically allocates "shared" scratch buffers of the maximum size configured by the OEM for the specified scratch ID and the amount requested by the algorithm.
  2. DSKT2 uses the OEM-configured mappings of IALG memory spaces to designated DSP/BIOS heap segments when determining which system heaps to use for creating the shared scratch buffers.
  3. DSKT2 pieces out individual scratch buffers from shared buffers, to satisfy each individual scratch buffer requested by the algorithm. The memory allocator processes each request for scratch in the memTab[] by assigning a slice of the shared scratch buffer with adjustments for alignment. If the algorithm requests more scratch than is allocated in the shared scratch buffer, DSKT2 allocates as much of the scratch memory as it can from any other shared scratch buffer available to the same scratch group. All other requests are fulfilled as non-shared private memory based on the following policy:
    1. If the algorithm requests scratch memory in IALG_DARAM0, the DSKT2 allocator first tries to satisfy the request using the shared IALG_DARAM scratch buffer. If it cannot, it tries to satisfy the request using the IALG_SARAM shared scratch of the same scratch group. If both attempts fail, it attempts to dynamically allocate the buffer in one of the OEM configured “internal” system heaps. If those attempts also fail:
      1. DSKT2 indicates failure if “Allow External Memory for IALG_SCRATCH requests” configuration is not enabled. That is, if DSKT2.ALLOW_EXTERNAL_SCRATCH is configured to be false.
      2. Otherwise, DSKT2 attempts to allocate memory in external heap.
    2. If the algorithm requests scratch memory in IALG_DARAM1 or in IALG_DARAM2, and the actual mapped DSP/BIOS heap is different than the heap for IALG_DARAM0, the allocator first tries to satisfy the request by attempting dynamic allocation in the requested memory space as configured by OEM. If that fails, any existing shared scratch buffers at the same priority level in IALG_DARAM0 or IALG_SARAM0 are tried respectively. If still not satisfied, DSKT2, attempts to dynamically allocate the buffer in one of the OEM configured “internal” system heaps. If those attempts also fail:
      1. DSKT2 indicates failure if “Allow External Memory for IALG_SCRATCH requests” configuration is not enabled.
      2. Otherwise, DSKT2 attempts to allocate memory in “external” heap.
    3. Scratch memory requests in IALG_SARAM0, IALG_SARAM1, or IALG_SARAM2 are handled similarly to their DARAM counterparts as outlined in steps (a) and (b)
  4. As each new algorithm requesting scratch memory at a given scratch group is instantiated, the scratch is pieced out from the previously allocated shared buffer, and the reference count for the buffer is incremented.
  5. When freeing algorithm instance memory (via DSKT2_freeAlg), any shared scratch buffer is not immediately freed, but those allocated outside the shared buffers are dynamically freed. Each time an algorithm using scratch is deleted, the reference count for the shared scratch buffer at the given priority level is decremented.
  6. When the last algorithm using scratch at a given scratch group is deleted, the shared scratch buffer at that scratch group is freed by DSKT2, as it is no longer needed.

Hardware Dependencies

DSKT2 does not reference hardware-specific configuration directly. Instead, the DSP/BIOS configuration tools are used in conjunction with the DSP/BIOS MEM module for creating and configuring multiple system heaps and dynamic memory allocation and freeing. DSP/BIOS TSK APIs are called for implementing critical sections. If you have linked with the debug library, LOG_printf() calls are used for limited real-time trace messages.

DSKT2 is designed to be modular and independent—all current DSP/BIOS dependencies can be implemented independently by custom application frameworks.

Runtime Optimization of Algorithm Activation and Deactivation

A benefit of using the DSKT2-mandated calling sequences outlined in DSKT2 Calling Sequence is that the implementation of the DSKT2_activateAlg() and DSKT2_deactivateAlg() APIs can transparently maintain runtime state information to minimize real activation/de-activation of the algorithm instances.

Since DSKT2 can track state at runtime to determine when there is no actual “sharing” of scratch buffers it can transparently avoid unnecessary calls to IALG algActivate and algDeactivate functions. Actual de-activation of the “current” algorithm is deferred by implementing DSKT2_deactivateAlg “optimistically”. When DSKT2_activateAlg needs to activate an algorithm it checks if the instance is already active within the same scratch group, if it is already active nothing needs to be done. If another algorithm (identified by unique IALG_handles) is currently active, DSKT2_activateAlg de-activates the other (current active) instance and activates the given algorithm instance. It is sufficient for DSKT2 to keep track of only the “currently active” algorithm for each scratch group and a single test.

You can use DSKT2_deactivateAll() to perform the deactivation without deferral.

Context Switching During XDAIS Callback Functions

In order to adopt a task-priority based scratch buffer sharing, we impose certain restrictions on callback functions that can be called by XDAIS algorithms. To maintain coherence of algorithm scratch buffers, callback functions are not allowed to issue any operations that may result in a context switch that may lead to the preemption of current task by another task at the same priority level. These callback functions could be defined by the XDAIS spec (for example the ACPY2 or ACPY3 DMA APIs) or they may be proprietary XDAIS-compliant algorithm framework APIs.

The restriction is required since there is no mechanism available for the callback function to be able to do algorithm deactivation and then re-activation (algActivate and algDeactivate functions cannot be called during any of its algorithm processing calls, that is, during an intermediate stage of execution). A framework or callback function cannot call algDeactivate or algDeactivate calls, which would be one way to ensure the integrity of instance scratch buffers. XDAIS algorithms are developed under the assumption that they are operationally not preemptable. If they do get preempted, their persistent and scratch memory must be saved and restored by the framework, making the preemption transparent to the algorithm. Additionally, algorithms implement algActivate/algDeactivate knowing that they can only be called at well-specified steady states, not at arbitrary execution points within any one of its processing or control functions.

Finally, if a callback function has to share an algorithm's scratch buffer during the execution of the callback function, it can save and then restore the shared scratch before resuming back to the algorithm. This approach is a fair one, as the burden is on the callback side.

DSKT2 IALG Extension: Providing Information to Algorithms

In anticipation of formalization of a future XDAIS spec enhancement involving the IALG interface, the DSKT2 framework provides the actual physical memory space information for each memory buffer it grants to the algorithm during the algInit() call. Algorithms that are designed to exploit this feature will be able to utilize the provided IALG_MemSpace information to optimize or fine tune its operation or optionally return "failure" status to indicate inability to ensure proper operation with the provided memory.

XDAIS-compliant algorithms use algAlloc() to provide information about what type of memory space they want each buffer to be allocated on. However, they are expected to function correctly even if they don’t get the exact memory space they requested. Applications, for example, due to scarcity of internal memory may decide to allocate some of the buffers in external memory even thought the algorithm’s request was for internal memory.

The only risk involved is that algorithms designed to exploit this enhancement may not operate correctly when: (1) they are deployed in non-DSKT2 frameworks, and (2) they expect and rely on the memory space designation information to be passed by the framework, and (3) when the framework allocates memory in a memory space other than what the algorithm requested. This risk can be minimized by disclosing the information and impact properly to the algorithm developers.

See Also

This presentation demonstrates the main features of DSKT2.

For details about the DSKT2 APIs, see the DSKT2 API Reference Guide.

The following sources provide additional related information:

  • Memory management in XDAIS with DSKT2
  • Techniques for Implementing Shared Relocatable Buffers Using the TMS320 DSP Algorithm Standard (SPRA790)
  • TMS320 DSP Algorithm Standard Rules and Guidelines (SPRU352G)
  • TMS320 DSP Algorithm Standard API Reference (SPRU360E)
  • Reference Framework RF5 Channel Infrastructure Design Document, Version 0.9
  • Reference Frameworks for eXpressDSP Software: API Reference (SPRA147C)