diff options
author | Karel Kočí <cynerd@email.cz> | 2017-11-21 19:48:51 +0100 |
---|---|---|
committer | Karel Kočí <cynerd@email.cz> | 2017-11-21 19:48:51 +0100 |
commit | 499a88621d12ff0cdcba1f8c796b7031d6adc649 (patch) | |
tree | c050b5224c896b3e14d74866473aef9c2a5e9b69 /qtmips_machine/memory.cpp | |
parent | 68f2af6801756980ec53347c0acb7fcc292f7939 (diff) | |
download | qtmips-499a88621d12ff0cdcba1f8c796b7031d6adc649.tar.gz qtmips-499a88621d12ff0cdcba1f8c796b7031d6adc649.tar.bz2 qtmips-499a88621d12ff0cdcba1f8c796b7031d6adc649.zip |
Add possibility to compare memory and registers state
For core testing we want to compare whole memory and registers.
Registers are pretty simple but in case of memory it is some what more
complicated and required its own tests to be sure that it works.
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; +} |