/*
 * Copyright (c) 2012-2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


/***************************/
/* SECTION MAPPING         */
/***************************/
var program = xdc.useModule('xdc.cfg.Program');

program.sectMap[".args"]        = new Program.SectionSpec();
program.sectMap[".bss"]         = new Program.SectionSpec();
program.sectMap[".cinit"]       = new Program.SectionSpec();
program.sectMap[".cio"]         = new Program.SectionSpec();
program.sectMap[".const"]       = new Program.SectionSpec();
program.sectMap[".data"]        = new Program.SectionSpec();
program.sectMap[".far"]         = new Program.SectionSpec();
program.sectMap[".fardata"]     = new Program.SectionSpec();
program.sectMap[".neardata"]    = new Program.SectionSpec();
program.sectMap[".rodata"]      = new Program.SectionSpec();
program.sectMap[".stack"]       = new Program.SectionSpec();
program.sectMap[".switch"]      = new Program.SectionSpec();
program.sectMap[".sysmem"]      = new Program.SectionSpec();
program.sectMap[".text"]        = new Program.SectionSpec();
    
// Must place these sections in core local memory 
program.sectMap[".args"].loadSegment        = "L2SRAM";
program.sectMap[".cio"].loadSegment         = "L2SRAM";

// Variables in the following data sections can potentially be 'shared' in
// OpenMP. These sections must be placed in shared memory.
program.sectMap[".bss"].loadSegment         = "DDR3";
program.sectMap[".cinit"].loadSegment       = "DDR3";
program.sectMap[".const"].loadSegment       = "DDR3";
program.sectMap[".data"].loadSegment        = "DDR3";
program.sectMap[".far"].loadSegment         = "DDR3";
program.sectMap[".fardata"].loadSegment     = "DDR3";
program.sectMap[".neardata"].loadSegment    = "DDR3";
program.sectMap[".rodata"].loadSegment      = "DDR3";
program.sectMap[".sysmem"].loadSegment      = "DDR3";

// Code sections shared by cores - place in shared memory to avoid duplication
program.sectMap[".switch"].loadSegment      = program.platform.codeMemory;
program.sectMap[".text"].loadSegment        = program.platform.codeMemory;

// Size the default stack and place it in L2SRAM 
var deviceName = String(Program.cpu.deviceName);
if  (deviceName.search("DRA7XX") == -1) { program.stack = 0x20000; } 
else                                    { program.stack = 0x8000;  }
program.sectMap[".stack"].loadSegment       = "L2SRAM";

// Since there are no arguments passed to main, set .args size to 0
program.argSize = 0;


/********************************/
/* OPENMP RUNTIME CONFIGURATION */
/********************************/

// Include OMP runtime in the build
var ompSettings = xdc.useModule("ti.runtime.openmp.Settings");

// Set to true if the application uses or has dependencies on BIOS components
ompSettings.usingRtsc = true;

if (ompSettings.usingRtsc)
{
    /* Configure OpenMP for BIOS
     * - OpenMP.configureCores(masterCoreId, numberofCoresInRuntime)
     *       Configures the id of the master core and the number of cores
     *       available to the runtime.
     */

    var OpenMP = xdc.useModule('ti.runtime.ompbios.OpenMP');

    // Configure the index of the master core and the number of cores available
    // to the runtime. The cores are contiguous.
    OpenMP.masterCoreIdx = 0;

    // Setup number of cores based on the device
    if      (deviceName.search("DRA7XX") != -1) { OpenMP.numCores = 2; }
    else if (deviceName.search("6670")   != -1) { OpenMP.numCores = 4; }
    else if (deviceName.search("6657")   != -1) { OpenMP.numCores = 2; }
    else if (deviceName.search("K2L")    != -1) { OpenMP.numCores = 4; }
    else                                        { OpenMP.numCores = 8; }

    // Pull in memory ranges described in Platform.xdc to configure the runtime
    var ddr3       = Program.cpu.memoryMap["DDR3"];
    var ddr3_nc    = Program.cpu.memoryMap["DDR3_NC"];
    var msmc       = Program.cpu.memoryMap["MSMCSRAM"];
    var msmcNcVirt = Program.cpu.memoryMap["OMP_MSMC_NC_VIRT"];
    var msmcNcPhy  = Program.cpu.memoryMap["OMP_MSMC_NC_PHY"];

    // Initialize the runtime with memory range information
    if (deviceName.search("DRA7XX") == -1) {
       OpenMP.msmcBase = msmc.base
       OpenMP.msmcSize = msmc.len;

       OpenMP.msmcNoCacheVirtualBase  = msmcNcVirt.base;
       OpenMP.msmcNoCacheVirtualSize  = msmcNcVirt.len;

       OpenMP.msmcNoCachePhysicalBase  = msmcNcPhy.base;
    }
    else
    {
       OpenMP.allocateStackFromHeap = true;
       OpenMP.allocateStackFromHeapSize = 0x010000;

       OpenMP.hasMsmc = false;
       OpenMP.ddrNoCacheBase = ddr3_nc.base;
       OpenMP.ddrNoCacheSize = ddr3_nc.len;
    }

    OpenMP.ddrBase          = ddr3.base;
    OpenMP.ddrSize          = ddr3.len;

    // Configure memory allocation using HeapOMP
    // HeapOMP handles 
    // - Memory allocation requests from BIOS components (core local memory)
    // - Shared memory allocation by utilizing the IPC module to enable 
    //   multiple cores to allocate memory out of the same heap - used by malloc
    if (deviceName.search("DRA7XX") == -1) {
       var HeapOMP = xdc.useModule('ti.runtime.ompbios.HeapOMP');

       // Shared Region 0 must be initialized for IPC 
       var sharedRegionId = 0;

       // Size of the core local heap
       var localHeapSize  = 0x8000;

       // Size of the heap shared by all the cores
       var sharedHeapSize = 0x08000000;

       // Initialize a Shared Region & create a heap in the DDR3 memory region
       var SharedRegion   = xdc.useModule('ti.sdo.ipc.SharedRegion');
       SharedRegion.setEntryMeta( sharedRegionId,
                                  {   base: ddr3.base,
                                      len:  sharedHeapSize,
                                      ownerProcId: OpenMP.masterCoreIdx,
                                      cacheEnable: true,
                                      createHeap: true,
                                      isValid: true,
                                      name: "DDR3_SR0",
                                  });

       // Configure and setup HeapOMP
       HeapOMP.configure(sharedRegionId, localHeapSize);
    }
    else
    {
       OpenMP.useIpcSharedHeap = false;
       OpenMP.allocateLocalHeapSize = 0x8000
       OpenMP.allocateSharedHeapSize = 0x00800000
    }

    
    var Startup = xdc.useModule('xdc.runtime.Startup');
    Startup.lastFxns.$add('&__TI_omp_initialize_rtsc_mode');
}
else
{
    /* Size the heap. It must be placed in shared memory */
    program.heap = sharedHeapSize;
}
