-
Notifications
You must be signed in to change notification settings - Fork 138
Functional memory model
This page is maintained by Alexander Titov
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
.
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:
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 . |
---|
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 intrunk/tests/samples/
or even create your own files (for more information seeREADME.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.
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
.
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.
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>());
This method is used to display the contents of the functional memory.
MIPT-V / MIPT-MIPS — Cycle-accurate pre-silicon simulation.