* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
* \file SoftMemory.h
* \brief
*/
#pragma once
#include <iostream>
#include <map>
#include <vector>
#include <cstdint>
#include <stdexcept>
#include <algorithm>
#include <memory>
namespace CostModel {
class SoftMemory {
public:
struct MemoryBlock {
uintptr_t startAddr;
size_t size;
bool isFree;
std::string regionType;
MemoryBlock(uintptr_t addr, size_t sz, bool free, const std::string& type)
: startAddr(addr), size(sz), isFree(free), regionType(type)
{}
};
static SoftMemory& Instance()
{
static SoftMemory softMemory;
return softMemory;
}
SoftMemory()
{
memoryMap[0x08048000] = std::vector<uint8_t>(0x1000, 0);
memoryMap[0x08049000] = std::vector<uint8_t>(0x1000, 0);
memoryMap[0x0804a000] = std::vector<uint8_t>(0x1000, 0);
memoryBlocks.emplace_back(0x08048000, 0x1000, false, "text");
memoryBlocks.emplace_back(0x08049000, 0x1000, false, "data");
memoryBlocks.emplace_back(0x0804a000, 0x1000, false, "bss");
heapStart = 0x0804b000;
heapEnd = heapStart;
stackStart = 0xc0000000;
stackEnd = stackStart;
}
uintptr_t AllocateHeap(size_t size)
{
if (!enable) {
return 0;
}
uintptr_t addr = heapEnd;
heapEnd += size;
if (heapEnd >= stackEnd) {
throw std::runtime_error("Out of memory: heap exhausted");
}
memoryMap[addr] = std::vector<uint8_t>(size, 0);
memoryBlocks.emplace_back(addr, size, false, "heap");
return addr;
}
uintptr_t AllocateStack(size_t size)
{
if (!enable) {
return 0;
}
stackEnd -= size;
if (stackEnd <= heapEnd) {
throw std::runtime_error("Out of memory: stack exhausted");
}
uintptr_t addr = stackEnd;
memoryMap[addr] = std::vector<uint8_t>(size, 0);
memoryBlocks.emplace_back(addr, size, false, "stack");
return addr;
}
uintptr_t AllocateData(size_t size, const std::vector<uint8_t>& data)
{
if (!enable) {
return 0;
}
std::sort(memoryBlocks.begin(), memoryBlocks.end(), [](const MemoryBlock& a, const MemoryBlock& b) {
return a.startAddr < b.startAddr;
});
for (size_t i = 0; i < memoryBlocks.size() - 1; ++i) {
uintptr_t gapStart = memoryBlocks[i].startAddr + memoryBlocks[i].size;
uintptr_t gapEnd = memoryBlocks[i + 1].startAddr;
size_t gapSize = gapEnd - gapStart;
if (gapSize >= size) {
uintptr_t addr = gapStart;
memoryMap[addr] = data;
memoryMap[addr] = std::vector<uint8_t>(size, 0);
memoryBlocks.emplace_back(addr, size, false, "data");
return addr;
}
}
uintptr_t addr = heapEnd;
heapEnd += size;
if (heapEnd >= stackEnd) {
throw std::runtime_error("Out of memory: data allocation failed");
}
memoryMap[addr] = data;
memoryBlocks.emplace_back(addr, size, false, "data");
return addr;
}
void Deallocate(uintptr_t addr)
{
auto it = memoryMap.find(addr);
if (it != memoryMap.end()) {
for (auto& block : memoryBlocks) {
if (block.startAddr == addr) {
block.isFree = true;
break;
}
}
memoryMap.erase(it);
}
}
void PrintMemoryLayout() const
{
std::cout << "Memory Layout:\n";
std::cout << "--------------------------------------------------\n";
std::vector<MemoryBlock> sorted_blocks = memoryBlocks;
std::sort(sorted_blocks.begin(), sorted_blocks.end(), [](const MemoryBlock& a, const MemoryBlock& b) {
return a.startAddr < b.startAddr;
});
for (const auto& block : sorted_blocks) {
std::cout << "0x" << std::hex << block.startAddr << " - 0x" << (block.startAddr + block.size) << " ("
<< std::dec << block.size << " bytes) " << block.regionType
<< (block.isFree ? " [FREE]" : " [USED]") << "\n";
}
std::cout << "--------------------------------------------------\n";
std::cout << "Heap top: 0x" << std::hex << heapEnd << "\n";
std::cout << "Stack bottom: 0x" << std::hex << stackEnd << "\n";
std::cout << "--------------------------------------------------\n";
}
void Enable() { enable = true; }
private:
std::map<uintptr_t, std::vector<uint8_t>> memoryMap;
std::vector<MemoryBlock> memoryBlocks;
uintptr_t heapStart;
uintptr_t heapEnd;
uintptr_t stackStart;
uintptr_t stackEnd;
bool enable = false;
};
}