From 8b553ef5863a07a0c9ae3a970bf6afe552ce6121 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Tue, 12 Feb 2019 00:39:09 +0100 Subject: Add debug access to rword and friends to allow read data through cache without disturbing statistic. This allows to switch view between CPU and raw memory content. Signed-off-by: Pavel Pisa --- qtmips_gui/memorydock.cpp | 14 +++++-- qtmips_gui/memorymodel.cpp | 18 +++++++-- qtmips_gui/memorymodel.h | 2 + qtmips_machine/cache.cpp | 84 +++++++++++++++++++++++++++------------- qtmips_machine/cache.h | 5 ++- qtmips_machine/memory.cpp | 19 ++++----- qtmips_machine/memory.h | 12 +++--- qtmips_machine/peripheral.cpp | 3 +- qtmips_machine/peripheral.h | 2 +- qtmips_machine/physaddrspace.cpp | 4 +- qtmips_machine/physaddrspace.h | 2 +- 11 files changed, 109 insertions(+), 56 deletions(-) diff --git a/qtmips_gui/memorydock.cpp b/qtmips_gui/memorydock.cpp index ccb3b6a..323f053 100644 --- a/qtmips_gui/memorydock.cpp +++ b/qtmips_gui/memorydock.cpp @@ -44,8 +44,6 @@ #include "memorytableview.h" #include "hexlineedit.h" - - MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) { setObjectName("Memory"); setWindowTitle("Memory"); @@ -58,6 +56,10 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) { cell_size->addItem("Word", MemoryModel::CELLSIZE_WORD); cell_size->setCurrentIndex(MemoryModel::CELLSIZE_WORD); + QComboBox *cached_access = new QComboBox(); + cached_access->addItem("Direct", 0); + cached_access->addItem("Cached", 1); + QTableView *memory_content = new MemoryTableView(0, settings); // memory_content->setSizePolicy(); MemoryModel *memory_model = new MemoryModel(0); @@ -67,8 +69,12 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) { QLineEdit *go_edit = new HexLineEdit(0, 8, 16, "0x"); + QHBoxLayout *layout_top = new QHBoxLayout; + layout_top->addWidget(cell_size); + layout_top->addWidget(cached_access); + QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(cell_size); + layout->addLayout(layout_top); layout->addWidget(memory_content); layout->addWidget(go_edit); @@ -79,6 +85,8 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) { connect(this, &MemoryDock::machine_setup, memory_model, &MemoryModel::setup); connect(cell_size, SIGNAL(currentIndexChanged(int)), memory_content, SLOT(set_cell_size(int))); + connect(cached_access, SIGNAL(currentIndexChanged(int)), + memory_model, SLOT(cached_access(int))); connect(go_edit, SIGNAL(value_edit_finished(std::uint32_t)), memory_content, SLOT(go_to_address(std::uint32_t))); connect(memory_content, SIGNAL(address_changed(std::uint32_t)), diff --git a/qtmips_gui/memorymodel.cpp b/qtmips_gui/memorymodel.cpp index 66da84c..12b3fcb 100644 --- a/qtmips_gui/memorymodel.cpp +++ b/qtmips_gui/memorymodel.cpp @@ -46,6 +46,7 @@ MemoryModel::MemoryModel(QObject *parent) machine = nullptr; memory_change_counter = 0; cache_data_change_counter = 0; + access_through_cache = 0; } int MemoryModel::rowCount(const QModelIndex & /*parent*/) const { @@ -80,6 +81,7 @@ QVariant MemoryModel::data(const QModelIndex &index, int role) const { QString s, t; std::uint32_t address; std::uint32_t data; + const machine::MemoryAccess *mem; if (!get_row_address(address, index.row())) return QString(""); if (index.column() == 0) { @@ -89,21 +91,24 @@ QVariant MemoryModel::data(const QModelIndex &index, int role) const { } if (machine == nullptr) return QString(""); - if (machine->memory() == nullptr) + mem = machine->memory(); + if (mem == nullptr) return QString(""); + if ((access_through_cache > 0) && (machine->cache_data() != nullptr)) + mem = machine->cache_data(); address += cellSizeBytes() * (index.column() - 1); if (address < index0_offset) return QString(""); switch (cell_size) { case CELLSIZE_BYTE: - data = machine->memory()->read_byte(address); + data = mem->read_byte(address, true); break; case CELLSIZE_HWORD: - data = machine->memory()->read_hword(address); + data = mem->read_hword(address, true); break; default: case CELLSIZE_WORD: - data = machine->memory()->read_word(address); + data = mem->read_word(address, true); break; } @@ -215,3 +220,8 @@ bool MemoryModel::adjustRowAndOffset(int &row, int optimal_row, std::uint32_t ad } return get_row_for_address(row, address); } + +void MemoryModel::cached_access(int cached) { + access_through_cache = cached; + update_all(); +} diff --git a/qtmips_gui/memorymodel.h b/qtmips_gui/memorymodel.h index f093dbb..83bc057 100644 --- a/qtmips_gui/memorymodel.h +++ b/qtmips_gui/memorymodel.h @@ -106,6 +106,7 @@ public slots: void setup(machine::QtMipsMachine *machine); void set_cell_size(int index); void check_for_updates(); + void cached_access(int cached); signals: void cell_size_changed(); @@ -118,6 +119,7 @@ private: machine::QtMipsMachine *machine; std::uint32_t memory_change_counter; std::uint32_t cache_data_change_counter; + int access_through_cache; }; diff --git a/qtmips_machine/cache.cpp b/qtmips_machine/cache.cpp index 742cdb5..30771b0 100644 --- a/qtmips_machine/cache.cpp +++ b/qtmips_machine/cache.cpp @@ -75,15 +75,17 @@ Cache::Cache(MemoryAccess *m, const MachineConfigCache *cc, unsigned memory_acc replc.lfu[row] = new unsigned[cnf.associativity()]; for (unsigned int i = 0; i < cnf.associativity(); i++) replc.lfu[row][i] = 0; - } + } break; case MachineConfigCache::RP_LRU: - replc.lru = new time_t*[cnf.sets()]; + replc.lru = new unsigned int*[cnf.sets()]; for (unsigned int row = 0; row < cnf.sets(); row++) { - replc.lru[row] = new time_t[cnf.associativity()]; + replc.lru[row] = new unsigned int[cnf.associativity()]; for (unsigned int i = 0; i < cnf.associativity(); i++) replc.lru[row][i] = 0; - } + } + break; + case MachineConfigCache::RP_RAND: default: break; } @@ -138,12 +140,17 @@ bool Cache::wword(std::uint32_t address, std::uint32_t value) { return changed; } -std::uint32_t Cache::rword(std::uint32_t address) const { +std::uint32_t Cache::rword(std::uint32_t address, bool debug_access) const { if (!cnf.enabled() || (address >= uncached_start && address <= uncached_last)) { - return mem->read_word(address); + return mem->read_word(address, debug_access); } + if (debug_access) { + if (!(location_status(address) & LOCSTAT_CACHED)) + return mem->read_word(address, debug_access); + return debug_rword(address); + } std::uint32_t data; access(address, &data, false); return data; @@ -236,16 +243,25 @@ enum LocationStatus Cache::location_status(std::uint32_t address) const { return mem->location_status(address); } +std::uint32_t Cache::debug_rword(std::uint32_t address) const { + std::uint32_t row, col, tag; + compute_row_col_tag(row, col, tag, address); + for (unsigned indx = 0; indx < cnf.associativity(); indx++) + if (dt[indx][row].valid && dt[indx][row].tag == tag) + return dt[indx][row].data[col]; + return 0; +} + bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::uint32_t value) const { bool changed = false; std::uint32_t row, col, tag; compute_row_col_tag(row, col, tag, address); unsigned indx = 0; - // Try to locate exact block or some unused one - while (indx < cnf.associativity() && dt[indx][row].valid && dt[indx][row].tag != tag) + // Try to locate exact block + while (indx < cnf.associativity() && (!dt[indx][row].valid || dt[indx][row].tag != tag)) indx++; - // Replace block + // Need to find new block if (indx >= cnf.associativity()) { // We have to kick something switch (cnf.replacement_policy()) { @@ -254,26 +270,37 @@ bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std:: break; case MachineConfigCache::RP_LFU: { - unsigned lowest = replc.lfu[row][0]; - indx = 0; - for (unsigned i = 1; i < cnf.associativity(); i++) - if (lowest > replc.lfu[row][i]) { - lowest = replc.lfu[row][i]; - indx = i; + unsigned lowest = replc.lfu[row][0]; + indx = 0; + for (unsigned i = 1; i < cnf.associativity(); i++) { + if (!dt[i][row].valid) { + indx = i; + break; + } + if (lowest > replc.lfu[row][i]) { + lowest = replc.lfu[row][i]; + indx = i; + } } + break; } - break; case MachineConfigCache::RP_LRU: { - time_t lowest = replc.lru[row][0]; - indx = 0; - for (unsigned i = 1; i < cnf.associativity(); i++) - if (lowest > replc.lru[row][i]) { - lowest = replc.lru[row][i]; - indx = i; + unsigned int least = 0xffff; + indx = 0; + for (unsigned i = 0; i < cnf.associativity(); i++) { + if (!dt[i][row].valid) { + // found free one, use it directly + indx = i; + break; + } + if (least < replc.lru[row][i]) { + least = replc.lru[row][i]; + indx = i; + } } + break; } - break; } } SANITY_ASSERT(indx < cnf.associativity(), "Probably unimplemented replacement policy"); @@ -307,13 +334,17 @@ bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std:: } } - // Update replc + // Update replcement data switch (cnf.replacement_policy()) { case MachineConfigCache::RP_LFU: - replc.lru[row][indx]++; + if (cd.valid && replc.lru[row][indx] == 0) + break; + for (unsigned i = 1; i < cnf.associativity(); i++) + replc.lru[row][i]++; + replc.lru[row][indx] = 0; break; case MachineConfigCache::RP_LRU: - replc.lfu[row][indx] = time(NULL); + replc.lfu[row][indx]++; break; default: break; @@ -345,7 +376,6 @@ void Cache::kick(unsigned associat_indx, unsigned row) const { switch (cnf.replacement_policy()) { case MachineConfigCache::RP_LFU: - replc.lru[row][associat_indx] = 0; break; default: break; diff --git a/qtmips_machine/cache.h b/qtmips_machine/cache.h index d08e66a..200f3ce 100644 --- a/qtmips_machine/cache.h +++ b/qtmips_machine/cache.h @@ -50,7 +50,7 @@ public: ~Cache(); bool wword(std::uint32_t address, std::uint32_t value); - std::uint32_t rword(std::uint32_t address) const; + std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; void flush(); // flush cache void sync(); // Same as flush @@ -91,12 +91,13 @@ private: mutable struct cache_data **dt; union { - time_t ** lru; // Access time + unsigned int ** lru; // Access time unsigned **lfu; // Access count } replc; // Data used for replacement policy mutable unsigned hit_read, miss_read, hit_write, miss_write; // Hit and miss counters + std::uint32_t debug_rword(std::uint32_t address) const; bool access(std::uint32_t address, std::uint32_t *data, bool write, std::uint32_t value = 0) const; void kick(unsigned associat_indx, unsigned row) const; std::uint32_t base_address(std::uint32_t tag, unsigned row) const; diff --git a/qtmips_machine/memory.cpp b/qtmips_machine/memory.cpp index af9420b..848669d 100644 --- a/qtmips_machine/memory.cpp +++ b/qtmips_machine/memory.cpp @@ -61,18 +61,18 @@ bool MemoryAccess::write_word(std::uint32_t offset, std::uint32_t value) { return wword(offset, value); } -std::uint8_t MemoryAccess::read_byte(std::uint32_t offset) const { +std::uint8_t MemoryAccess::read_byte(std::uint32_t offset, bool debug_access) const { int nth = SH_NTH_8(offset); - return (std::uint8_t)(rword(offset) >> nth); + return (std::uint8_t)(rword(offset, debug_access) >> nth); } -std::uint16_t MemoryAccess::read_hword(std::uint32_t offset) const { +std::uint16_t MemoryAccess::read_hword(std::uint32_t offset, bool debug_access) const { int nth = SH_NTH_16(offset); - return (std::uint16_t)(rword(offset) >> nth); + return (std::uint16_t)(rword(offset, debug_access) >> nth); } -std::uint32_t MemoryAccess::read_word(std::uint32_t offset) const { - return rword(offset); +std::uint32_t MemoryAccess::read_word(std::uint32_t offset, bool debug_access) const { + return rword(offset, debug_access); } void MemoryAccess::write_ctl(enum AccessControl ctl, std::uint32_t offset, std::uint32_t value) { @@ -151,7 +151,8 @@ bool MemorySection::wword(std::uint32_t offset, std::uint32_t value) { return changed; } -std::uint32_t MemorySection::rword(std::uint32_t offset) const { +std::uint32_t MemorySection::rword(std::uint32_t offset, bool debug_access) const { + (void)debug_access; offset = offset >> 2; if (offset >= this->len) throw QTMIPS_EXCEPTION(OutOfMemoryAccess, "Trying to read outside of the memory section", QString("Accessing using offset: ") + QString(offset)); @@ -263,12 +264,12 @@ bool Memory::wword(std::uint32_t address, std::uint32_t value) { return changed; } -std::uint32_t Memory::rword(std::uint32_t address) const { +std::uint32_t Memory::rword(std::uint32_t address, bool debug_access) const { MemorySection *section = this->get_section(address, false); if (section == nullptr) return 0; else - return section->read_word(SECTION_OFFSET_MASK(address)); + return section->read_word(SECTION_OFFSET_MASK(address), debug_access); } bool Memory::operator==(const Memory&m) const { diff --git a/qtmips_machine/memory.h b/qtmips_machine/memory.h index 33caf46..b354c4c 100644 --- a/qtmips_machine/memory.h +++ b/qtmips_machine/memory.h @@ -52,9 +52,9 @@ public: bool write_hword(std::uint32_t offset, std::uint16_t value); bool write_word(std::uint32_t offset, std::uint32_t value); - std::uint8_t read_byte(std::uint32_t offset) const; - std::uint16_t read_hword(std::uint32_t offset) const; - std::uint32_t read_word(std::uint32_t offset) const; + std::uint8_t read_byte(std::uint32_t offset, bool debug_access = false) const; + std::uint16_t read_hword(std::uint32_t offset, bool debug_access = false) const; + std::uint32_t read_word(std::uint32_t offset, bool debug_access = false) const; void write_ctl(enum AccessControl ctl, std::uint32_t offset, std::uint32_t value); std::uint32_t read_ctl(enum AccessControl ctl, std::uint32_t offset) const; @@ -64,7 +64,7 @@ public: protected: virtual bool wword(std::uint32_t offset, std::uint32_t value) = 0; - virtual std::uint32_t rword(std::uint32_t offset) const = 0; + virtual std::uint32_t rword(std::uint32_t offset, bool debug_access = false) const = 0; private: static int sh_nth(std::uint32_t offset); @@ -77,7 +77,7 @@ public: ~MemorySection(); bool wword(std::uint32_t offset, std::uint32_t value); - std::uint32_t rword(std::uint32_t offset) const; + std::uint32_t rword(std::uint32_t offsetbool, bool debug_access = false) const; void merge(MemorySection&); std::uint32_t length() const; @@ -107,7 +107,7 @@ public: MemorySection *get_section(std::uint32_t address, bool create) const; // returns section containing given address bool wword(std::uint32_t address, std::uint32_t value); - std::uint32_t rword(std::uint32_t address) const; + std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; bool operator==(const Memory&) const; bool operator!=(const Memory&) const; diff --git a/qtmips_machine/peripheral.cpp b/qtmips_machine/peripheral.cpp index ac74c2a..9e922b8 100644 --- a/qtmips_machine/peripheral.cpp +++ b/qtmips_machine/peripheral.cpp @@ -55,7 +55,8 @@ bool SimplePeripheral::wword(std::uint32_t address, std::uint32_t value) { return true; } -std::uint32_t SimplePeripheral::rword(std::uint32_t address) const { +std::uint32_t SimplePeripheral::rword(std::uint32_t address, bool debug_access) const { + (void)debug_access; std::uint32_t value = 0x12345678; #if 0 printf("SimplePeripheral::rword address 0x%08lx\n", diff --git a/qtmips_machine/peripheral.h b/qtmips_machine/peripheral.h index 92df1d7..0effd47 100644 --- a/qtmips_machine/peripheral.h +++ b/qtmips_machine/peripheral.h @@ -57,7 +57,7 @@ signals: public: bool wword(std::uint32_t address, std::uint32_t value); - std::uint32_t rword(std::uint32_t address) const; + std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; }; } diff --git a/qtmips_machine/physaddrspace.cpp b/qtmips_machine/physaddrspace.cpp index bb01b60..4d0045c 100644 --- a/qtmips_machine/physaddrspace.cpp +++ b/qtmips_machine/physaddrspace.cpp @@ -59,11 +59,11 @@ bool PhysAddrSpace::wword(std::uint32_t address, std::uint32_t value) { return p_range->mem_acces->write_word(address - p_range->start_addr, value); } -std::uint32_t PhysAddrSpace::rword(std::uint32_t address) const { +std::uint32_t PhysAddrSpace::rword(std::uint32_t address, bool debug_access) const { const RangeDesc *p_range = find_range(address); if (p_range == nullptr) return 0x00000000; - return p_range->mem_acces->read_word(address - p_range->start_addr); + return p_range->mem_acces->read_word(address - p_range->start_addr, debug_access); } enum LocationStatus PhysAddrSpace::location_status(std::uint32_t address) const { diff --git a/qtmips_machine/physaddrspace.h b/qtmips_machine/physaddrspace.h index c6f5e81..9c13e07 100644 --- a/qtmips_machine/physaddrspace.h +++ b/qtmips_machine/physaddrspace.h @@ -52,7 +52,7 @@ public: ~PhysAddrSpace(); bool wword(std::uint32_t address, std::uint32_t value); - std::uint32_t rword(std::uint32_t address) const; + std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; bool insert_range(MemoryAccess *mem_acces, std::uint32_t start_addr, std::uint32_t last_addr, bool move_ownership); bool remove_range(MemoryAccess *mem_acces); -- cgit v1.2.3