From 15dbd208fa6c1ac4dc0684c95c43cc40b2462cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Sun, 8 Apr 2018 11:55:52 +0200 Subject: Integrate cache with rest of the machine core --- qtmips_machine/cache.cpp | 32 +++++++++++++++++++++++++------- qtmips_machine/cache.h | 8 ++++---- qtmips_machine/core.cpp | 19 ++++++++++--------- qtmips_machine/core.h | 8 ++++---- qtmips_machine/qtmipsmachine.cpp | 17 ++++++++++++----- qtmips_machine/qtmipsmachine.h | 5 +++-- qtmips_machine/tests/testcore.cpp | 12 ++++++------ 7 files changed, 64 insertions(+), 37 deletions(-) (limited to 'qtmips_machine') diff --git a/qtmips_machine/cache.cpp b/qtmips_machine/cache.cpp index f37db38..7432119 100644 --- a/qtmips_machine/cache.cpp +++ b/qtmips_machine/cache.cpp @@ -2,8 +2,15 @@ using namespace machine; -Cache::Cache(Memory *m, MachineConfigCache *cc) : cnf(cc) { +Cache::Cache(Memory *m, const MachineConfigCache *cc) : cnf(cc) { mem = m; + // Zero hit and miss rate + hitc = 0; + missc = 0; + // Skip any other initialization if cache is disabled + if (!cc->enabled()) + return; + // Allocate cache data structure dt = new struct cache_data*[cc->associativity()]; for (unsigned i = 0; i < cc->associativity(); i++) { @@ -27,12 +34,14 @@ Cache::Cache(Memory *m, MachineConfigCache *cc) : cnf(cc) { default: break; } - // Zero hit and miss rate - hitc = 0; - missc = 0; } void Cache::wword(std::uint32_t address, std::uint32_t value) { + if (!cnf.enabled()) { + mem->write_word(address, value); + return; + } + std::uint32_t *data; access(address, &data, false); *data = value; @@ -42,27 +51,36 @@ void Cache::wword(std::uint32_t address, std::uint32_t value) { } std::uint32_t Cache::rword(std::uint32_t address) const { + if (!cnf.enabled()) + return mem->read_word(address); + std::uint32_t *data; access(address, &data, true); return *data; } void Cache::flush() { + if (!cnf.enabled()) + return; + for (unsigned as = 0; as < cnf.associativity(); as++) for (unsigned st = 0; st < cnf.sets(); st++) if (dt[as][st].valid) kick(as, st); } -unsigned Cache::hit() { +unsigned Cache::hit() const { return hitc; } -unsigned Cache::miss() { +unsigned Cache::miss() const { return missc; } void Cache::reset() { + if (!cnf.enabled()) + return; + // Set all cells to ne invalid for (unsigned as = 0; as < cnf.associativity(); as++) for (unsigned st = 0; st < cnf.sets(); st++) @@ -73,7 +91,7 @@ void Cache::reset() { missc = 0; } -const MachineConfigCache &Cache::config() { +const MachineConfigCache &Cache::config() const { return cnf; } diff --git a/qtmips_machine/cache.h b/qtmips_machine/cache.h index 9372a1a..8fe7475 100644 --- a/qtmips_machine/cache.h +++ b/qtmips_machine/cache.h @@ -11,19 +11,19 @@ namespace machine { class Cache : public MemoryAccess { Q_OBJECT public: - Cache(Memory *m, MachineConfigCache *c); + Cache(Memory *m, const MachineConfigCache *c); void wword(std::uint32_t address, std::uint32_t value); std::uint32_t rword(std::uint32_t address) const; void flush(); // flush/sync cache - unsigned hit(); // Number of recorded hits - unsigned miss(); // Number of recorded misses + unsigned hit() const; // Number of recorded hits + unsigned miss() const; // Number of recorded misses void reset(); // Reset whole state of cache - const MachineConfigCache &config(); + const MachineConfigCache &config() const; // TODO getters for cells private: diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index 273842d..98b60e9 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -90,13 +90,14 @@ static const struct DecodeMap dmap[] = { NOPE // 63 }; -Core::Core(Registers *regs, MemoryAccess *mem) { +Core::Core(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data) { this->regs = regs; - this->mem = mem; + this->mem_program = mem_program; + this->mem_data = mem_data; } struct Core::dtFetch Core::fetch() { - Instruction inst(mem->read_word(regs->read_pc())); + Instruction inst(mem_program->read_word(regs->read_pc())); emit instruction_fetched(inst); return { .inst = inst @@ -152,9 +153,9 @@ struct Core::dtMemory Core::memory(const struct dtExecute &dt) { std::uint32_t towrite_val = dt.alu_val; if (dt.memwrite) - mem->write_ctl(dt.memctl, dt.alu_val, dt.val_rt); + mem_data->write_ctl(dt.memctl, dt.alu_val, dt.val_rt); else if (dt.memread) - towrite_val = mem->read_ctl(dt.memctl, dt.alu_val); + towrite_val = mem_data->read_ctl(dt.memctl, dt.alu_val); return { .inst = dt.inst, @@ -256,8 +257,8 @@ void Core::dtMemoryInit(struct dtMemory &dt) { dt.towrite_val = 0; } -CoreSingle::CoreSingle(Registers *regs, MemoryAccess *mem, bool jmp_delay_slot) : \ - Core(regs, mem) { +CoreSingle::CoreSingle(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, bool jmp_delay_slot) : \ + Core(regs, mem_program, mem_data) { if (jmp_delay_slot) jmp_delay_decode = new struct Core::dtDecode(); else @@ -288,8 +289,8 @@ void CoreSingle::reset() { Core::dtDecodeInit(*jmp_delay_decode); } -CorePipelined::CorePipelined(Registers *regs, MemoryAccess *mem, enum MachineConfig::HazardUnit hazard_unit) : \ - Core(regs, mem) { +CorePipelined::CorePipelined(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, enum MachineConfig::HazardUnit hazard_unit) : \ + Core(regs, mem_program, mem_data) { this->hazard_unit = hazard_unit; reset(); } diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index a0bc2a2..98f3e4a 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -14,7 +14,7 @@ namespace machine { class Core : public QObject { Q_OBJECT public: - Core(Registers *regs, MemoryAccess *mem); + Core(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data); virtual void step() = 0; // Do single step @@ -30,7 +30,7 @@ signals: protected: Registers *regs; - MemoryAccess *mem; + MemoryAccess *mem_data, *mem_program; struct dtFetch { Instruction inst; // Loaded instruction @@ -80,7 +80,7 @@ protected: class CoreSingle : public Core { public: - CoreSingle(Registers *regs, MemoryAccess *mem, bool jmp_delay_slot); + CoreSingle(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, bool jmp_delay_slot); ~CoreSingle(); void step(); @@ -93,7 +93,7 @@ private: class CorePipelined : public Core { public: - CorePipelined(Registers *regs, MemoryAccess *mem, enum MachineConfig::HazardUnit hazard_unit = MachineConfig::HU_STALL_FORWARD); + CorePipelined(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, enum MachineConfig::HazardUnit hazard_unit = MachineConfig::HU_STALL_FORWARD); void step(); diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp index e96924a..4a2b0f2 100644 --- a/qtmips_machine/qtmipsmachine.cpp +++ b/qtmips_machine/qtmipsmachine.cpp @@ -13,11 +13,13 @@ QtMipsMachine::QtMipsMachine(const MachineConfig &cc) : QObject(), mcnf(&cc) { regs = new Registers(); mem = new Memory(*mem_program_only); + cch_program = new Cache(mem, &cc.cache_program()); + cch_data = new Cache(mem, &cc.cache_data()); if (cc.pipelined()) - cr = new CorePipelined(regs, mem, cc.hazard_unit()); + cr = new CorePipelined(regs, cch_program, cch_data, cc.hazard_unit()); else - cr = new CoreSingle(regs, mem, cc.delay_slot()); + cr = new CoreSingle(regs, cch_program, cch_data, cc.delay_slot()); run_t = new QTimer(this); set_speed(0); // In default run as fast as possible @@ -40,8 +42,12 @@ const Memory *QtMipsMachine::memory() { return mem; } -const Cache *QtMipsMachine::cache() { - return cch; +const Cache *QtMipsMachine::cache_program() { + return cch_program; +} + +const Cache *QtMipsMachine::cache_data() { + return cch_data; } const Core *QtMipsMachine::core() { @@ -105,7 +111,8 @@ void QtMipsMachine::restart() { pause(); regs->reset(); mem->reset(*mem_program_only); - // TODO cache + cch_program->reset(); + cch_data->reset(); cr->reset(); set_status(ST_READY); } diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h index 05e2917..46405e5 100644 --- a/qtmips_machine/qtmipsmachine.h +++ b/qtmips_machine/qtmipsmachine.h @@ -23,7 +23,8 @@ public: const Registers *registers(); const Memory *memory(); - const Cache *cache(); + const Cache *cache_program(); + const Cache *cache_data(); const Core *core(); const CoreSingle *core_singe(); const CorePipelined *core_pipelined(); @@ -55,7 +56,7 @@ private: Registers *regs; Memory *mem, *mem_program_only; - Cache *cch; + Cache *cch_program, *cch_data; Core *cr; QTimer *run_t; diff --git a/qtmips_machine/tests/testcore.cpp b/qtmips_machine/tests/testcore.cpp index 3a1ce48..30cf3c7 100644 --- a/qtmips_machine/tests/testcore.cpp +++ b/qtmips_machine/tests/testcore.cpp @@ -186,7 +186,7 @@ void MachineTests::singlecore_regs() { mem.write_word(res.read_pc(), i.data()); // Store single instruction (anything else should be 0 so NOP effectively) Memory mem_used(mem); // Create memory copy - CoreSingle core(&init, &mem_used, true); + CoreSingle core(&init, &mem_used, &mem_used, true); core.step(); // Single step should be enought as this is risc without pipeline res.pc_inc(); // We did single step so increment program counter accordingly @@ -206,7 +206,7 @@ void MachineTests::pipecore_regs() { res.pc_jmp(0x14); - CorePipelined core(&init, &mem_used); + CorePipelined core(&init, &mem_used, &mem_used); for (int i = 0; i < 5; i++) core.step(); // Fire steps for five pipelines stages @@ -275,7 +275,7 @@ void MachineTests::singlecore_jmp() { Memory mem_used(mem); Registers regs_used(regs); - CoreSingle core(®s_used, &mem_used, true); + CoreSingle core(®s_used, &mem_used, &mem_used, true); core.step(); QCOMPARE(regs.read_pc() + 4, regs_used.read_pc()); // First execute delay slot core.step(); @@ -296,7 +296,7 @@ void MachineTests::pipecore_jmp() { Memory mem_used(mem); Registers regs_used(regs); - CorePipelined core(®s_used, &mem_used); + CorePipelined core(®s_used, &mem_used, &mem_used); core.step(); QCOMPARE(regs.read_pc() + 4, regs_used.read_pc()); // First just fetch core.step(); @@ -400,7 +400,7 @@ void MachineTests::singlecore_mem() { mem_init.write_word(regs_init.read_pc(), i.data()); mem_res.write_word(regs_init.read_pc(), i.data()); - CoreSingle core(®s_init, &mem_init, true); + CoreSingle core(®s_init, &mem_init, &mem_init, true); core.step(); regs_res.pc_inc(); @@ -419,7 +419,7 @@ void MachineTests::pipecore_mem() { mem_init.write_word(regs_init.read_pc(), i.data()); mem_res.write_word(regs_init.read_pc(), i.data()); - CorePipelined core(®s_init, &mem_init); + CorePipelined core(®s_init, &mem_init, &mem_init); for (int i = 0; i < 5; i++) core.step(); // Fire steps for five pipelines stages -- cgit v1.2.3