aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-12 00:39:09 +0100
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-12 00:39:09 +0100
commit8b553ef5863a07a0c9ae3a970bf6afe552ce6121 (patch)
treecb61054992ea0102ed7e400533fb7cc914fc7ab0
parent54d7ef4272673e55b6a4324373d11875280dad84 (diff)
downloadqtmips-8b553ef5863a07a0c9ae3a970bf6afe552ce6121.tar.gz
qtmips-8b553ef5863a07a0c9ae3a970bf6afe552ce6121.tar.bz2
qtmips-8b553ef5863a07a0c9ae3a970bf6afe552ce6121.zip
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 <pisa@cmp.felk.cvut.cz>
-rw-r--r--qtmips_gui/memorydock.cpp14
-rw-r--r--qtmips_gui/memorymodel.cpp18
-rw-r--r--qtmips_gui/memorymodel.h2
-rw-r--r--qtmips_machine/cache.cpp84
-rw-r--r--qtmips_machine/cache.h5
-rw-r--r--qtmips_machine/memory.cpp19
-rw-r--r--qtmips_machine/memory.h12
-rw-r--r--qtmips_machine/peripheral.cpp3
-rw-r--r--qtmips_machine/peripheral.h2
-rw-r--r--qtmips_machine/physaddrspace.cpp4
-rw-r--r--qtmips_machine/physaddrspace.h2
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);