aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_gui/NewDialog.ui17
-rw-r--r--qtmips_gui/newdialog.cpp26
-rw-r--r--qtmips_gui/newdialog.h3
-rw-r--r--qtmips_machine/cache.cpp30
-rw-r--r--qtmips_machine/cache.h7
-rw-r--r--qtmips_machine/machineconfig.cpp17
-rw-r--r--qtmips_machine/machineconfig.h4
-rw-r--r--qtmips_machine/qtmipsmachine.cpp6
8 files changed, 100 insertions, 10 deletions
diff --git a/qtmips_gui/NewDialog.ui b/qtmips_gui/NewDialog.ui
index 4171e73..411b075 100644
--- a/qtmips_gui/NewDialog.ui
+++ b/qtmips_gui/NewDialog.ui
@@ -251,6 +251,23 @@
</property>
</widget>
</item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Burst:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="mem_time_burst">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/qtmips_gui/newdialog.cpp b/qtmips_gui/newdialog.cpp
index 5e7f16d..3e37357 100644
--- a/qtmips_gui/newdialog.cpp
+++ b/qtmips_gui/newdialog.cpp
@@ -65,8 +65,12 @@ NewDialog::NewDialog(QWidget *parent, QSettings *settings) : QDialog(parent) {
connect(ui->hazard_unit, SIGNAL(clicked(bool)), this, SLOT(hazard_unit_change()));
connect(ui->hazard_stall, SIGNAL(clicked(bool)), this, SLOT(hazard_unit_change()));
connect(ui->hazard_stall_forward, SIGNAL(clicked(bool)), this, SLOT(hazard_unit_change()));
+
connect(ui->mem_protec_exec, SIGNAL(clicked(bool)), this, SLOT(mem_protec_exec_change(bool)));
connect(ui->mem_protec_write, SIGNAL(clicked(bool)), this, SLOT(mem_protec_write_change(bool)));
+ connect(ui->mem_time_read, SIGNAL(valueChanged(int)), this, SLOT(mem_time_read_change(int)));
+ connect(ui->mem_time_write, SIGNAL(valueChanged(int)), this, SLOT(mem_time_write_change(int)));
+ connect(ui->mem_time_burst, SIGNAL(valueChanged(int)), this, SLOT(mem_time_burst_change(int)));
cache_handler_d = new NewDialogCacheHandler(this, ui_cache_d);
cache_handler_p = new NewDialogCacheHandler(this, ui_cache_p);
@@ -171,6 +175,27 @@ void NewDialog::mem_protec_write_change(bool v) {
switch2custom();
}
+void NewDialog::mem_time_read_change(int v) {
+ if (config->memory_access_time_read() != (unsigned)v) {
+ config->set_memory_access_time_read(v);
+ switch2custom();
+ }
+}
+
+void NewDialog::mem_time_write_change(int v) {
+ if (config->memory_access_time_write() != (unsigned)v) {
+ config->set_memory_access_time_write(v);
+ switch2custom();
+ }
+}
+
+void NewDialog::mem_time_burst_change(int v) {
+ if (config->memory_access_time_burst() != (unsigned)v) {
+ config->set_memory_access_time_burst(v);
+ switch2custom();
+ }
+}
+
void NewDialog::config_gui() {
// Basic
ui->elf_file->setText(config->elf());
@@ -185,6 +210,7 @@ void NewDialog::config_gui() {
ui->mem_protec_write->setChecked(config->memory_write_protection());
ui->mem_time_read->setValue(config->memory_access_time_read());
ui->mem_time_write->setValue(config->memory_access_time_write());
+ ui->mem_time_burst->setValue(config->memory_access_time_burst());
// Cache
cache_handler_d->config_gui();
cache_handler_p->config_gui();
diff --git a/qtmips_gui/newdialog.h b/qtmips_gui/newdialog.h
index 5f85969..2b1b7c4 100644
--- a/qtmips_gui/newdialog.h
+++ b/qtmips_gui/newdialog.h
@@ -67,6 +67,9 @@ private slots:
void hazard_unit_change();
void mem_protec_exec_change(bool);
void mem_protec_write_change(bool);
+ void mem_time_read_change(int);
+ void mem_time_write_change(int);
+ void mem_time_burst_change(int);
private:
Ui::NewDialog *ui;
diff --git a/qtmips_machine/cache.cpp b/qtmips_machine/cache.cpp
index c1e4e7b..ad85c8a 100644
--- a/qtmips_machine/cache.cpp
+++ b/qtmips_machine/cache.cpp
@@ -37,10 +37,12 @@
using namespace machine;
-Cache::Cache(MemoryAccess *m, const MachineConfigCache *cc, unsigned memory_access_penalty_r, unsigned memory_access_penalty_w) : cnf(cc) {
+Cache::Cache(MemoryAccess *m, const MachineConfigCache *cc, unsigned memory_access_penalty_r,
+ unsigned memory_access_penalty_w, unsigned memory_access_penalty_b) : cnf(cc) {
mem = m;
access_pen_r = memory_access_penalty_r;
access_pen_w = memory_access_penalty_w;
+ access_pen_b = memory_access_penalty_b;
uncached_start = 0xf0000000;
uncached_last = 0xffffffff;
// Zero hit and miss rate
@@ -50,6 +52,8 @@ Cache::Cache(MemoryAccess *m, const MachineConfigCache *cc, unsigned memory_acc
miss_write = 0;
mem_reads = 0;
mem_writes = 0;
+ burst_reads = 0;
+ burst_writes = 0;
dt = nullptr;
replc.lfu = nullptr;
replc.lru = nullptr;
@@ -132,6 +136,7 @@ bool Cache::wword(std::uint32_t address, std::uint32_t value) {
(address >= uncached_start && address <= uncached_last)) {
mem_writes++;
emit memory_writes_update(mem_writes);
+ update_statistics();
return mem->write_word(address, value);
}
@@ -141,6 +146,7 @@ bool Cache::wword(std::uint32_t address, std::uint32_t value) {
if (cnf.write_policy() != MachineConfigCache::WP_BACK) {
mem_writes++;
emit memory_writes_update(mem_writes);
+ update_statistics();
return mem->write_word(address, value);
}
return changed;
@@ -151,6 +157,7 @@ std::uint32_t Cache::rword(std::uint32_t address, bool debug_access) const {
(address >= uncached_start && address <= uncached_last)) {
mem_reads++;
emit memory_reads_update(mem_reads);
+ update_statistics();
return mem->read_word(address, debug_access);
}
@@ -172,6 +179,7 @@ void Cache::flush() {
for (unsigned st = 0; st < cnf.sets(); st++)
if (dt[as][st].valid)
kick(as, st);
+ update_statistics();
}
void Cache::sync() {
@@ -195,19 +203,28 @@ unsigned Cache::memory_writes() const {
}
unsigned Cache::stalled_cycles() const {
- return miss_read * (access_pen_r - 1) + miss_write * (access_pen_w - 1);
+ unsigned st_cycles = mem_reads * (access_pen_r - 1) + mem_writes * (access_pen_w - 1);
+ if (access_pen_b != 0)
+ st_cycles -= burst_reads * (access_pen_r - access_pen_b) +
+ burst_writes * (access_pen_w - access_pen_b);
+ return st_cycles;
}
double Cache::speed_improvement() const {
unsigned lookup_time;
+ unsigned mem_access_time;
unsigned comp = hit_read + hit_write + miss_read + miss_write;
if (comp == 0)
return 100.0;
lookup_time = hit_read + miss_read;
if (cnf.write_policy() == MachineConfigCache::WP_BACK)
lookup_time += hit_write + miss_write;
+ mem_access_time = mem_reads * access_pen_r + mem_writes * access_pen_w;
+ if (access_pen_b != 0)
+ mem_access_time -= burst_reads * (access_pen_r - access_pen_b) +
+ burst_writes * (access_pen_w - access_pen_b);
return (double)((miss_read + hit_read) * access_pen_r + (miss_write + hit_write) * access_pen_w) \
- / (double)(lookup_time + mem_reads * access_pen_r + mem_writes * access_pen_w) \
+ / (double)(lookup_time + mem_access_time) \
* 100;
}
@@ -233,6 +250,8 @@ void Cache::reset() {
miss_write = 0;
mem_reads = 0;
mem_writes = 0;
+ burst_reads = 0;
+ burst_writes = 0;
// Trigger signals
emit hit_update(hit());
emit miss_update(miss());
@@ -292,6 +311,7 @@ bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::
if (write && cnf.write_policy() == MachineConfigCache::WP_TROUGH_NOALLOC) {
miss_write++;
emit miss_update(miss());
+ update_statistics();
return false;
}
// We have to kick something
@@ -346,13 +366,14 @@ bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::
else
miss_read++;
emit miss_update(miss());
- update_statistics();
for (unsigned i = 0; i < cnf.blocks(); i++) {
cd.data[i] = mem->read_word(base_address(tag, row) + (4*i));
change_counter++;
}
mem_reads += cnf.blocks();
+ burst_reads += cnf.blocks() - 1;
emit memory_reads_update(mem_reads);
+ update_statistics();
}
// Update replcement data
@@ -403,6 +424,7 @@ void Cache::kick(unsigned associat_indx, unsigned row) const {
for (unsigned i = 0; i < cnf.blocks(); i++)
mem->write_word(base_address(cd.tag, row) + (4*i), cd.data[i]);
mem_writes += cnf.blocks();
+ burst_writes += cnf.blocks() - 1;
emit memory_writes_update(mem_writes);
}
cd.valid = false;
diff --git a/qtmips_machine/cache.h b/qtmips_machine/cache.h
index 1500aae..e15909a 100644
--- a/qtmips_machine/cache.h
+++ b/qtmips_machine/cache.h
@@ -46,7 +46,8 @@ namespace machine {
class Cache : public MemoryAccess {
Q_OBJECT
public:
- Cache(MemoryAccess *m, const MachineConfigCache *c, unsigned memory_access_penalty_r = 1, unsigned memory_access_penalty_w = 1);
+ Cache(MemoryAccess *m, const MachineConfigCache *c, unsigned memory_access_penalty_r = 1,
+ unsigned memory_access_penalty_w = 1, unsigned memory_access_penalty_b = 0);
~Cache();
bool wword(std::uint32_t address, std::uint32_t value);
@@ -82,7 +83,7 @@ signals:
private:
MachineConfigCache cnf;
MemoryAccess *mem;
- unsigned access_pen_r, access_pen_w;
+ unsigned access_pen_r, access_pen_w, access_pen_b;
std::uint32_t uncached_start;
std::uint32_t uncached_last;
@@ -99,7 +100,7 @@ private:
} replc; // Data used for replacement policy
mutable unsigned hit_read, miss_read, hit_write, miss_write; // Hit and miss counters
- mutable unsigned mem_reads, mem_writes; // Dirrect access to memory
+ mutable unsigned mem_reads, mem_writes, burst_reads, burst_writes; // Dirrect access to memory
mutable std::uint32_t change_counter;
std::uint32_t debug_rword(std::uint32_t address) const;
diff --git a/qtmips_machine/machineconfig.cpp b/qtmips_machine/machineconfig.cpp
index 8a48ce1..4d9728d 100644
--- a/qtmips_machine/machineconfig.cpp
+++ b/qtmips_machine/machineconfig.cpp
@@ -46,6 +46,7 @@ using namespace machine;
#define DF_WRITE_PROTEC false
#define DF_MEM_ACC_READ 10
#define DF_MEM_ACC_WRITE 10
+#define DF_MEM_ACC_BURST 0
#define DF_ELF QString("")
//////////////////////////////////////////////////////////////////////////////
/// Default config of MachineConfigCache
@@ -185,6 +186,7 @@ MachineConfig::MachineConfig() {
write_protect = DF_WRITE_PROTEC;
mem_acc_read = DF_MEM_ACC_READ;
mem_acc_write = DF_MEM_ACC_WRITE;
+ mem_acc_burst = DF_MEM_ACC_BURST;
elf_path = DF_ELF;
cch_program = MachineConfigCache();
cch_data = MachineConfigCache();
@@ -198,6 +200,7 @@ MachineConfig::MachineConfig(const MachineConfig *cc) {
write_protect = cc->memory_write_protection();
mem_acc_read = cc->memory_access_time_read();
mem_acc_write = cc->memory_access_time_write();
+ mem_acc_burst = cc->memory_access_time_burst();
elf_path = cc->elf();
cch_program = cc->cache_program();
cch_data = cc->cache_data();
@@ -213,6 +216,7 @@ MachineConfig::MachineConfig(const QSettings *sts, const QString &prefix) {
write_protect = sts->value(N("MemoryWriteProtection"), DF_WRITE_PROTEC).toBool();
mem_acc_read = sts->value(N("MemoryRead"), DF_MEM_ACC_READ).toUInt();
mem_acc_write = sts->value(N("MemoryWrite"), DF_MEM_ACC_WRITE).toUInt();
+ mem_acc_burst = sts->value(N("MemoryBurts"), DF_MEM_ACC_BURST).toUInt();
elf_path = sts->value(N("Elf"), DF_ELF).toString();
cch_program = MachineConfigCache(sts, N("ProgramCache_"));
cch_data = MachineConfigCache(sts, N("DataCache_"));
@@ -222,6 +226,9 @@ void MachineConfig::store(QSettings *sts, const QString &prefix) {
sts->setValue(N("Pipelined"), pipelined());
sts->setValue(N("DelaySlot"), delay_slot());
sts->setValue(N("HazardUnit"), (unsigned)hazard_unit());
+ sts->setValue(N("MemoryRead"), memory_access_time_read());
+ sts->setValue(N("MemoryWrite"), memory_access_time_write());
+ sts->setValue(N("MemoryBurts"), memory_access_time_burst());
sts->setValue(N("Elf"), elf_path);
cch_program.store(sts, N("ProgramCache_"));
cch_data.store(sts, N("DataCache_"));
@@ -251,6 +258,7 @@ void MachineConfig::preset(enum ConfigPresets p) {
set_memory_write_protection(DF_WRITE_PROTEC);
set_memory_access_time_read(DF_MEM_ACC_READ);
set_memory_access_time_write(DF_MEM_ACC_WRITE);
+ set_memory_access_time_burst(DF_MEM_ACC_BURST);
access_cache_program()->preset(p);
access_cache_data()->preset(p);
@@ -284,6 +292,10 @@ void MachineConfig::set_memory_access_time_write(unsigned v) {
mem_acc_write = v;
}
+void MachineConfig::set_memory_access_time_burst(unsigned v) {
+ mem_acc_burst = v;
+}
+
void MachineConfig::set_elf(QString path) {
elf_path = path;
}
@@ -326,6 +338,10 @@ unsigned MachineConfig::memory_access_time_write() const {
return mem_acc_write > 1 ? mem_acc_write : 1;
}
+unsigned MachineConfig::memory_access_time_burst() const {
+ return mem_acc_burst;
+}
+
QString MachineConfig::elf() const {
return elf_path;
}
@@ -355,6 +371,7 @@ bool MachineConfig::operator==(const MachineConfig &c) const {
CMP(memory_write_protection) && \
CMP(memory_access_time_read) && \
CMP(memory_access_time_write) && \
+ CMP(memory_access_time_burst) && \
CMP(elf) && \
CMP(cache_program) && \
CMP(cache_data);
diff --git a/qtmips_machine/machineconfig.h b/qtmips_machine/machineconfig.h
index 14676ff..6f53d87 100644
--- a/qtmips_machine/machineconfig.h
+++ b/qtmips_machine/machineconfig.h
@@ -126,6 +126,7 @@ public:
// Set memory access times. Passed value is in cycles.
void set_memory_access_time_read(unsigned);
void set_memory_access_time_write(unsigned);
+ void set_memory_access_time_burst(unsigned);
// Set path to source elf file. This has to be set before core is initialized.
void set_elf(QString path);
// Configure cache
@@ -139,6 +140,7 @@ public:
bool memory_write_protection() const;
unsigned memory_access_time_read() const;
unsigned memory_access_time_write() const;
+ unsigned memory_access_time_burst() const;
QString elf() const;
const MachineConfigCache &cache_program() const;
const MachineConfigCache &cache_data() const;
@@ -153,7 +155,7 @@ private:
bool pipeline, delayslot;
enum HazardUnit hunit;
bool exec_protect, write_protect;
- unsigned mem_acc_read, mem_acc_write;
+ unsigned mem_acc_read, mem_acc_write, mem_acc_burst;
QString elf_path;
MachineConfigCache cch_program, cch_data;
};
diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp
index 7a64429..37e5461 100644
--- a/qtmips_machine/qtmipsmachine.cpp
+++ b/qtmips_machine/qtmipsmachine.cpp
@@ -62,8 +62,10 @@ QtMipsMachine::QtMipsMachine(const MachineConfig &cc) : QObject(), mcnf(&cc) {
perip_spi_led = new PeripSpiLed();
addressapce_insert_range(perip_spi_led, 0xffffc100, 0xffffc1ff, true);
- cch_program = new Cache(cpu_mem, &cc.cache_program(), cc.memory_access_time_read(), cc.memory_access_time_write());
- cch_data = new Cache(cpu_mem, &cc.cache_data(), cc.memory_access_time_read(), cc.memory_access_time_write());
+ cch_program = new Cache(cpu_mem, &cc.cache_program(), cc.memory_access_time_read(),
+ cc.memory_access_time_write(), cc.memory_access_time_burst());
+ cch_data = new Cache(cpu_mem, &cc.cache_data(), cc.memory_access_time_read(),
+ cc.memory_access_time_write(), cc.memory_access_time_burst());
if (cc.pipelined())
cr = new CorePipelined(regs, cch_program, cch_data, cc.hazard_unit());