/*========================== begin_copyright_notice ============================
Copyright (C) 2021 Intel Corporation

SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/

#ifndef _MEM_MODEL_H
#define _MEM_MODEL_H

#include <cstring>
#include <mutex>


#define FOUR_MB (4 * 1024 * 1024)
#define FOUR_KB (4 * 1024)

/*
 * Surface - represents a memory buffer
 */
class Surface {
public:
    // Constructor
    Surface();

    // Destructor
    ~Surface();
    
    // Writing into the surface
    // 
    // addr - an offset into the surface
    // data - data to be written
    void Write(uint32_t addr, uint32_t data);

    // Printing the surface image
    void Print(bool asFloat);


private:

    // Computes the pointer to the surface corresponding to the given address
    uint8_t * GetPtr(uint32_t addr);

    // PageTable - represents a 4KB page table where each entry points to a 4KB page
    typedef struct PageTableS {
        // Initially each page table is empty
        PageTableS() { memset(pte, 0, 1024 * sizeof(uint32_t*)); }
        uint32_t* pte[1024];
    } PageTable;

    PageTable*   _pageDir[1024]; // Page directory is an array of 1024 pointers to page tables

    uint32_t _numOfWrites;  // number of writes
    uint32_t _maxAddr;      // maximal address
};
    
/*
 * MemoryModel - a simple memory model
 */ 
class MemoryModel {
public:

    // Constructor
    MemoryModel();
    
    // Destructor
    ~MemoryModel();

    // Writing into a surface
    // 
    // bti  - surface ID (BTI index)
    // addr - an offset into the surface
    // data - data to be written
    void Write(uint32_t bti, uint32_t addr, uint32_t data);

    // Printing the memory image
    void Print(bool asFloat);

private:

    Surface*   _mem[256];   // an array of potential 256 surfaces

    std::mutex _mutex;      // mutex
};

#endif