diff options
Diffstat (limited to 'qtmips_machine/memory.cpp')
-rw-r--r-- | qtmips_machine/memory.cpp | 123 |
1 files changed, 106 insertions, 17 deletions
diff --git a/qtmips_machine/memory.cpp b/qtmips_machine/memory.cpp index 21ca03f..a9cc055 100644 --- a/qtmips_machine/memory.cpp +++ b/qtmips_machine/memory.cpp @@ -56,28 +56,47 @@ std::uint32_t MemoryAccess::read_word(std::uint32_t offset) { } MemorySection::MemorySection(std::uint32_t length) { - this->length = length; + this->len = length; this->dt = new std::uint8_t[length]; + memset(this->dt, 0, sizeof *this->dt * length); +} + +MemorySection::MemorySection(const MemorySection &ms) : MemorySection(ms.length()) { + memcpy(this->dt, ms.data(), sizeof *this->dt * this->len); } MemorySection::~MemorySection() { delete this->dt; } -using namespace std; - void MemorySection::write_byte(std::uint32_t offset, std::uint8_t value) { - if (offset >= this->length) + if (offset >= this->len) throw QTMIPS_EXCEPTION(OutOfMemoryAccess, "Trying to write outside of the memory section", QString("Accessing using offset: ") + QString(offset)); this->dt[offset] = value; } -std::uint8_t MemorySection::read_byte(std::uint32_t offset) { - if (offset >= this->length) +std::uint8_t MemorySection::read_byte(std::uint32_t offset) const { + if (offset >= this->len) throw QTMIPS_EXCEPTION(OutOfMemoryAccess, "Trying to read outside of the memory section", QString("Accessing using offset: ") + QString(offset)); return this->dt[offset]; } +std::uint32_t MemorySection::length() const { + return len; +} + +const std::uint8_t* MemorySection::data() const { + return this->dt; +} + +bool MemorySection::operator==(const MemorySection &ms) const { + return ! memcmp(this->dt, ms.data(), sizeof *this->dt * this->len); +} + +bool MemorySection::operator!=(const MemorySection &ms) const { + return ! this->operator ==(ms); +} + // Number of bites per row on lookup tree #define MEMORY_TREE_ROW ((32 - MEMORY_SECTION_BITS) / MEMORY_TREE_H) // Size of row in memory lookup tree @@ -102,17 +121,12 @@ Memory::Memory() { this->mt_root = allocate_section_tree(); } -Memory::~Memory() { - // Free up memory tree - // TODO +Memory::Memory(const Memory &m) { + this->mt_root = copy_section_tree(m.get_memorytree_root(), 0); } -union MemoryTree *Memory::allocate_section_tree() { - union MemoryTree *mt = new union MemoryTree[MEMORY_TREE_LEN]; - for (size_t i = 0; i < MEMORY_TREE_LEN; i++) - // Note that this also nulls sec pointer as those are both pointers and so they have same size - mt[i].mt = nullptr; - return mt; +Memory::~Memory() { + free_section_tree(this->mt_root, 0); } // Create address mask with section length @@ -123,7 +137,7 @@ union MemoryTree *Memory::allocate_section_tree() { #define ADDRESS_TREE_INDEX(DEPTH, ADDR) ((ADDR >> (DEPTH * MEMORY_TREE_ROW)) & ADDRESS_MASK(MEMORY_TREE_ROW)) -MemorySection *Memory::get_section(std::uint32_t address, bool create) { +MemorySection *Memory::get_section(std::uint32_t address, bool create) const { std::uint32_t addr = address >> MEMORY_SECTION_BITS; // drop all bits for addressing inside of the section union MemoryTree *w = this->mt_root; size_t ii; @@ -155,10 +169,85 @@ void Memory::write_byte(std::uint32_t address, std::uint8_t value) { section->write_byte(SECTION_ADDRESS(address), value); } -std::uint8_t Memory::read_byte(std::uint32_t address) { +std::uint8_t Memory::read_byte(std::uint32_t address) const { MemorySection *section = this->get_section(address, true); if (section == nullptr) return 0; else return section->read_byte(SECTION_ADDRESS(address)); } + +bool Memory::operator==(const Memory&m) const { + return compare_section_tree(this->mt_root, m.get_memorytree_root(), 0); +} + +bool Memory::operator!=(const Memory&m) const { + return ! this->operator ==(m); +} + +const union MemoryTree *Memory::get_memorytree_root() const { + return this->mt_root; +} + +union MemoryTree *Memory::allocate_section_tree() { + union MemoryTree *mt = new union MemoryTree[MEMORY_TREE_LEN]; + for (size_t i = 0; i < MEMORY_TREE_LEN; i++) + // Note that this also nulls sec pointer as those are both pointers and so they have same size + mt[i].mt = nullptr; + return mt; +} + +void Memory::free_section_tree(union MemoryTree *mt, size_t depth) { + if (depth < (MEMORY_TREE_H - 1)) { // Following level is memory tree + for (int i = 0; i < MEMORY_TREE_LEN; i++) { + if (mt[i].mt != nullptr) + free_section_tree(mt[i].mt, depth + 1); + } + } else { // Following level is memory section + for (int i = 0; i < MEMORY_TREE_LEN; i++) { + if (mt[i].sec != nullptr) + delete mt[i].sec; + } + } +} + +bool Memory::compare_section_tree(const union MemoryTree *mt1, const union MemoryTree *mt2, size_t depth) { + if (depth < (MEMORY_TREE_H - 1)) { // Following level is memory tree + for (int i = 0; i < MEMORY_TREE_LEN; i++) { + if ( + ((mt1[i].mt == nullptr || mt2[i].mt == nullptr) && mt1[i].mt != mt2[i].mt) + || + (mt1[i].mt != nullptr && mt2[i].mt != nullptr && !compare_section_tree(mt1[i].mt, mt2[i].mt, depth + 1)) + ) { + return false; + } + } + } else { // Following level is memory section + for (int i = 0; i < MEMORY_TREE_LEN; i++) { + if ( + ((mt1[i].sec == nullptr || mt2[i].sec == nullptr) && mt1[i].sec != mt2[i].sec) + || + (mt1[i].sec != nullptr && mt2[i].sec != nullptr && *mt1[i].sec != *mt2[i].sec) + ) { + return false; + } + } + } + return true; +} + +union MemoryTree *Memory::copy_section_tree(const union MemoryTree *mt, size_t depth) { + union MemoryTree *nmt = allocate_section_tree(); + if (depth < (MEMORY_TREE_H - 1)) { // Following level is memory tree + for (int i = 0; i < MEMORY_TREE_LEN; i++) { + if (mt[i].mt != nullptr) + nmt[i].mt = copy_section_tree(mt[i].mt, depth + 1); + } + } else { // Following level is memory section + for (int i = 0; i < MEMORY_TREE_LEN; i++) { + if (mt[i].sec != nullptr) + nmt[i].sec = new MemorySection(*mt[i].sec); + } + } + return nmt; +} |