Skip to content

Functional memory model

Pavel I. Kryukov edited this page Jul 28, 2018 · 5 revisions

This page is maintained by Alexander Titov


Functional Memory

The functional memory is an abstraction that present how the memory is defined in the ISA. In the other word, it is how a programmer sees the memory. Note that functional memory does not reflect the organization of the memory in the real machine.

In short, the functional memory is a sequence of bytes. Each of them has unique address and can be read and written using it.

The FuncMemory class implements a functional memory model. It provides interfaces to parse an ELF formatted executable file, download and store content of ELF sections, read and write data. The class is defined in trunk/func_sim/func_memory/func_memory.h.

Hierarchy of Functional Memory

The typical address size for the MIPS architecture is equal to 32 bits, i.e. the memory size is 2^32 = 4 GB. It is clear that such amount of memory cannot be assigned in the simulator. Moreover, an usual program uses significantly less memory.

In order to not allocate the whole required bytes at once, but still be able to read or write by any address, the functional memory is organized as a hierarchy.

Note: that is done only because of the limitation of our program model and does not reflect the real memory organization.

There are three levels in our implementation of the functional memory:

  • The lowest level is a page. It is a block of bytes that keeps the real data.
  • The middle level is a set of pages. It is an array of pointers to all pages that includes in the set.
  • The highest level is an array of sets.

The hierarchy is shown on the following picture:

NULL means that this set or page has not been written yet and the memory for it is not allocated in the simulator.

The values of set number, page number and offset can be extracted directly from the memory address. The following picture shows the address separating:

Simplified Hierarchy of Functional Memory

If the three level hierarchy is too complex for you, it is possible to implement a simpler hierarchy described in this section. Note that in this case you will receive lower mark, but it is better than nothing.

In the simplified version the functional memory is just an static array of bytes (i.e. no dynamic memory allocation). In this case the size of your memory will be small and can be able to process only a limited range of memory address. For our work, it will be enough to process only addresses from the following range: [0x3FFFF0; 41FFF0]. Therefore, the array will contain 0x20000 bytes. As it is not a very larger number, it can be allocated at once statically.

Note: if you decide to choose this option you should not care about address separation into set, page and offset.

Download contents of ELF sections

An object of FuncMemory class is initialized taking the information from the binary ELF file. To create an object of FuncMemory class and download context of ELF sections, you have to invoke its constructor:

FuncMemory ( uint64 addr_size = 32,
             uint64 page_num_size = 10,
             uint64 offset_size = 12);

void load_elf_file( const std::string& elf_file_name);

with the following parameters:

  • elf_file_name - name of a MIPS executable file (e.g. mips_bin_exmpl.out). You can find examples of such files in trunk/tests/samples/ or even create your own files (for more information see README.txt in that folder).
  • addr_size - the size of the memory address (number of bits).
  • page_num_size - the number of bits in the memory address that represent the page number inside the set.
  • offset_size - the number of bits in the memory address that represent the byte number inside the page.

You can see how it works in unit tests: infra/memory/t/unit_test.cpp. Tests download sections from an executable file given as the only parameter, perform read and write operations, and print the contents of the functional memory.


Read and write data

read method

Class FuncMemory contains only one method to read the data of the stored section:

template<typename T>
T read( uint64 addr, T mask = all_ones<T>()) const;

It returns a value stored in the byte sequence, which length is equal to sizeof(T) and the address of the first byte of which is equal to addr.

For example, if the functional memory has the following content (the order of bits into the bytes are from left to right):

0x400090    0x400091    0x400092     <-- addresses of bytes
    |           |           |
... | 0001 0011 | 0011 1000 | 1111 0010 | 1101 0000 | ...

Then read( 0x400091, 2) return the value of subsequence | 0011 1000 | 1111 0010 |, which is equal to 0x4f1c.

startPC method

This method just return the start address of .text and has the following declaration:

uint64 startPC() const;

It is used to know where the first instruction of the program is located.

write method

It is similar to the read despite the fact that the data is not read, but written by the specified address. The method has the following interface:

template<typename T>
void write( T value, uint64 addr, T mask = all_ones<T>());
dump method

This method is used to display the contents of the functional memory.


Clone this wiki locally