From da3d8fdd609be7cd1836be717032555af0732b88 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Thu, 21 Feb 2019 00:43:46 +0100 Subject: Add burst time and store timing in the config. Signed-off-by: Pavel Pisa --- qtmips_gui/NewDialog.ui | 17 +++++++++++++++++ qtmips_gui/newdialog.cpp | 26 ++++++++++++++++++++++++++ qtmips_gui/newdialog.h | 3 +++ qtmips_machine/cache.cpp | 30 ++++++++++++++++++++++++++---- qtmips_machine/cache.h | 7 ++++--- qtmips_machine/machineconfig.cpp | 17 +++++++++++++++++ qtmips_machine/machineconfig.h | 4 +++- qtmips_machine/qtmipsmachine.cpp | 6 ++++-- 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 @@ + + + + Burst: + + + + + + + 0 + + + 999999999 + + + 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()); -- cgit v1.2.3