// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : mem_section.c
// Author        : xianfeng.du
// Created On    : 2022-06-25
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

#include "mem_sections.h"
#include "ucp_printf.h"

MEM_SECTION_INFO RFM_IM_SECTION EcsSram = {
    .baseAddr = (ECS_SRAM_BASE_ADDR + 0x0),
    .currAddr = (ECS_SRAM_BASE_ADDR + 0x0),
    .maxSize = ECS_SRAM_SIZE,
    .memSectionName = "ECS_SRAM"
};

MEM_SECTION_INFO RFM_IM_SECTION PetSram = {
    .baseAddr = (PET_SRAM_BASE_ADDR + 0x0),
    .currAddr = (PET_SRAM_BASE_ADDR + 0x0),
    .maxSize = PET_SRAM_SIZE,
    .memSectionName = "PET_SRAM"
};

MEM_SECTION_INFO RFM_IM_SECTION MsgDdrMem = {
    .baseAddr = (UCP_MSG_MEM_BASE_ADDR + 0x0),
    .currAddr = (UCP_MSG_MEM_BASE_ADDR + 0x0),
    .maxSize = UCP_MSG_MEM_SIZE,
    .memSectionName = "MSG_DDR_MEM"
};


void memSectionInit(MEM_SECTION_INFO* memSecInfo, uint64_t baseAddr, uint32_t maxSize, char* memSectionName)
{
	UCP_PRINT_LOG("[memSectionInit]: 0x%lx, 0x%lx, %u, %s", (uint64_t)memSecInfo, baseAddr, maxSize, memSectionName);

    memSecInfo->baseAddr = baseAddr;
    memSecInfo->maxSize = maxSize;
    memSecInfo->memSectionName = memSectionName;

    memSecInfo->currAddr = baseAddr;
}

void memSectionReset(MEM_SECTION_INFO* memSecInfo)
{
    memSecInfo->currAddr = memSecInfo->baseAddr;
}

void memSectionAllocPrint(MEM_SECTION_INFO* memSecInfo, uint32_t allocSize, char* varString)
{
#if (UCP_PRINT_LEVEL & PRINT_DEBUG)
    char* pMemSectionName = (char*)&memSecInfo->memSectionName[0];
#endif

    UCP_PRINT_DEBUG("Memory Section - [%s]: Base Address: [0x%lx]; Maximum Size: [%8u]\n",
        pMemSectionName,
        memSecInfo->baseAddr,
        memSecInfo->maxSize);
    UCP_PRINT_DEBUG("Memory Section - [%s]: Variable Name: [%s]; Allocated Address: [0x%lx]; Allocated Size: [%6u]\n",
        pMemSectionName,
        varString,
        memSecInfo->currAddr,
        allocSize);
}

void* memSectionAlloc(MEM_SECTION_INFO* memSecInfo, uint32_t allocSize, uint32_t allocAlign, char* varString)
{
    void* ret;

    uint64_t baseAddr = memSecInfo->baseAddr;
    uint64_t currAddr = ((memSecInfo->currAddr + (allocAlign - 1)) / allocAlign) * allocAlign;
    uint32_t maxSize = memSecInfo->maxSize;

    uint8_t* p = (uint8_t *)baseAddr;
    uint32_t offset = currAddr - baseAddr;

    if ((offset + allocSize) <= maxSize) {
        ret = (void*)&p[offset];

        memSecInfo->currAddr = currAddr;

        /* disable as default since it cost much time. Could be enabled when needed. */
        memSectionAllocPrint(memSecInfo, allocSize, varString);

        memSecInfo->currAddr = currAddr + allocSize;
    } else {
    	UCP_PRINT_ERROR("Memory Section - [%s]: Base Address: [0x%lx]; Maximum Size: [%8u]",
            memSecInfo->memSectionName,
            baseAddr,
            maxSize);

    	UCP_PRINT_ERROR("Memory Section - [%s]: Variable Name: [%s]; Allocated Address: [0x%lx]; Allocated Size: [%6u]",
            memSecInfo->memSectionName,
            varString,
            currAddr,
            allocSize);

    	UCP_PRINT_ERROR("Can't allocate %u bytes in Memory Section - [%s] for Variable - [%s]!", allocSize, memSecInfo->memSectionName, varString);
        ret = NULL;
    }

    return ret;
}

/*MEM_SECTION_INFO* GetEcsSramSection()
{
    return (MEM_SECTION_INFO*)&EcsSram;
}*/

MEM_SECTION_INFO* GetPetSramSection()
{
    return (MEM_SECTION_INFO*)&PetSram;
}

MEM_SECTION_INFO* GetMsgDdrSection()
{
    return (MEM_SECTION_INFO*)&MsgDdrMem;
}


