diff options
author | Karel Kočí <cynerd@email.cz> | 2018-02-16 16:24:35 +0100 |
---|---|---|
committer | Karel Kočí <cynerd@email.cz> | 2018-03-06 21:58:49 +0100 |
commit | 1a20d908b6eefe32807f906b7294c562256a7518 (patch) | |
tree | 38cd063d902767d637b65426eecff538c9233672 | |
parent | a56b25212865c57251719a1d4a5d9d6a79b339c5 (diff) | |
download | qtmips-1a20d908b6eefe32807f906b7294c562256a7518.tar.gz qtmips-1a20d908b6eefe32807f906b7294c562256a7518.tar.bz2 qtmips-1a20d908b6eefe32807f906b7294c562256a7518.zip |
Fix forwarding checker for I and J and S* instructions
THere are exceptions when we care about forwarding and when we don't.
-rw-r--r-- | qtmips_machine/core.cpp | 30 | ||||
-rw-r--r-- | qtmips_machine/instruction.cpp | 275 | ||||
-rw-r--r-- | qtmips_machine/instruction.h | 9 |
3 files changed, 173 insertions, 141 deletions
diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index 75f7173..273842d 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -305,20 +305,26 @@ void CorePipelined::step() { bool stall = false; if (hazard_unit != MachineConfig::HU_NONE) { // Note: We make exception with $0 as that has no effect when written and is used in nop instruction -// TODO rt should be compared onlu if instruction is R or it's S* -#define HAZARD(STAGE) ((STAGE).regwrite && (STAGE).rwrite != 0 && ((STAGE).rwrite == dt_d.inst.rs() || (STAGE).rwrite == dt_d.inst.rt())) // Note: We make exception with $0 as that has no effect and is used in nop instruction + +#define HAZARD(STAGE) ( \ + (STAGE).regwrite && (STAGE).rwrite != 0 && \ + ((STAGE).rwrite == dt_d.inst.rs() || ( \ + ((STAGE).inst.type() == Instruction::T_R || (STAGE).inst.is_store()) && \ + (STAGE).rwrite == dt_d.inst.rt()) \ + )) // Note: We make exception with $0 as that has no effect and is used in nop instruction + if (HAZARD(dt_e)) { // Hazard with instruction in execute stage if (hazard_unit == MachineConfig::HU_STALL_FORWARD) { - if (dt_e.memread) - stall = true; - else { - // Forward result value - if (dt_e.rwrite == dt_d.inst.rs()) - dt_d.val_rs = dt_e.alu_val; - if (dt_e.rwrite == dt_d.inst.rt()) - dt_d.val_rt = dt_e.alu_val; - } + if (dt_e.memread) // TODO extend by branch instructions + stall = true; + else { + // Forward result value + if (dt_e.rwrite == dt_d.inst.rs()) + dt_d.val_rs = dt_e.alu_val; + if (dt_e.rwrite == dt_d.inst.rt()) + dt_d.val_rt = dt_e.alu_val; + } } else stall = true; } @@ -346,7 +352,7 @@ void CorePipelined::step() { fetch(); // clear decode latch (insert nope to execute stage) dtDecodeInit(dt_d); - } + } } void CorePipelined::reset() { diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index c4ca492..837b9b4 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -2,126 +2,36 @@ #include "qtmipsexception.h" using namespace machine; -Instruction::Instruction() { - this->dt = 0; -} - -Instruction::Instruction(std::uint32_t inst) { - this->dt = inst; -} - -Instruction::Instruction(std::uint8_t opcode, std::uint8_t rs, std::uint8_t rt, std::uint8_t rd, std::uint8_t shamt, std::uint8_t funct) { - this->dt = 0; - this->dt |= opcode << 26; - this->dt |= rs << 21; - this->dt |= rt << 16; - this->dt |= rd << 11; - this->dt |= shamt << 6; - this->dt |= funct; -} - -Instruction::Instruction(std::uint8_t opcode, std::uint8_t rs, std::uint8_t rt, std::uint16_t immediate) { - this->dt = 0; - this->dt |= opcode << 26; - this->dt |= rs << 21; - this->dt |= rt << 16; - this->dt |= immediate; -} - -Instruction::Instruction(std::uint8_t opcode, std::uint32_t address) { - this->dt = 0; - this->dt |= opcode << 26; - this->dt |= address; -} - -Instruction::Instruction(const Instruction &i) { - this->dt = i.data(); -} - -#define MASK(LEN,OFF) ((this->dt >> (OFF)) & ((1 << (LEN)) - 1)) - -std::uint8_t Instruction::opcode() const { - return (std::uint8_t) MASK(6, 26); -} - -std::uint8_t Instruction::rs() const { - return (std::uint8_t) MASK(5, 21); -} - -std::uint8_t Instruction::rt() const { - return (std::uint8_t) MASK(5, 16); -} - -std::uint8_t Instruction::rd() const { - return (std::uint8_t) MASK(5, 11); -} - -std::uint8_t Instruction::shamt() const { - return (std::uint8_t) MASK(5, 6); - -} - -std::uint8_t Instruction::funct() const { - return (std::uint8_t) MASK(6, 0); -} - -std::uint16_t Instruction::immediate() const { - return (std::uint16_t) MASK(16, 0); -} - -std::uint32_t Instruction::address() const { - return (std::uint32_t) MASK(26, 0); -} - -std::uint32_t Instruction::data() const { - return this->dt; -} - -bool Instruction::operator==(const Instruction &c) const { - return (this->data() == c.data()); -} - -bool Instruction::operator!=(const Instruction &c) const { - return ! this->operator==(c); -} - -Instruction &Instruction::operator=(const Instruction &c) { - if (this != &c) - this->dt = c.data(); - return *this; -} - - -enum InstructionType { - IT_R, - IT_I, - IT_J -}; struct InstructionMap { const char *name; - enum InstructionType type; + enum Instruction::Type type; + bool is_store; }; -#define IM_UNKNOWN {"UNKNOWN", IT_R} +#define IT_R Instruction::T_R +#define IT_I Instruction::T_I +#define IT_J Instruction::T_J + +#define IM_UNKNOWN {"UNKNOWN", Instruction::T_UNKNOWN, false} // This table is indexed by opcode static const struct InstructionMap instruction_map[] = { - {"ALU", IT_R}, // Alu operations - {"REGIMM", IT_I}, // REGIMM (BLTZ, BGEZ) - {"J", IT_J}, - {"JAL", IT_J}, - {"BEQ", IT_I}, - {"BNE", IT_I}, - {"BLEZ", IT_I}, - {"BGTZ", IT_I}, - {"ADDI", IT_I}, - {"ADDIU", IT_I}, - {"SLTI", IT_I}, - {"SLTIU", IT_I}, - {"ANDI", IT_I}, - {"ORI", IT_I}, - {"XORI", IT_I}, - {"LUI", IT_I}, + {"ALU", IT_R, false}, // Alu operations + {"REGIMM", IT_I, false}, // REGIMM (BLTZ, BGEZ) + {"J", IT_J, false}, + {"JAL", IT_J, false}, + {"BEQ", IT_I, false}, + {"BNE", IT_I, false}, + {"BLEZ", IT_I, false}, + {"BGTZ", IT_I, false}, + {"ADDI", IT_I, false}, + {"ADDIU", IT_I, false}, + {"SLTI", IT_I, false}, + {"SLTIU", IT_I, false}, + {"ANDI", IT_I, false}, + {"ORI", IT_I, false}, + {"XORI", IT_I, false}, + {"LUI", IT_I, false}, IM_UNKNOWN, // 16 IM_UNKNOWN, // 17 IM_UNKNOWN, // 18 @@ -138,22 +48,23 @@ static const struct InstructionMap instruction_map[] = { IM_UNKNOWN, // 29 IM_UNKNOWN, // 30 IM_UNKNOWN, // 31 - {"LB", IT_I}, - {"LH", IT_I}, - {"LWL", IT_I}, - {"LW", IT_I}, - {"LBU", IT_I}, - {"LHU", IT_I}, - {"LWR", IT_I}, + {"LB", IT_I, false}, + {"LH", IT_I, false}, + {"LWL", IT_I, false}, + {"LW", IT_I, false}, + {"LBU", IT_I, false}, + {"LHU", IT_I, false}, + {"LWR", IT_I, false}, IM_UNKNOWN, // 39 - {"SB", IT_I}, - {"SH", IT_I}, - {"SWL", IT_I}, - {"SW", IT_I}, + {"SB", IT_I, true}, + {"SH", IT_I, true}, + {"SWL", IT_I, true}, + {"SW", IT_I, true}, IM_UNKNOWN, // 44 IM_UNKNOWN, // 45 - {"SWR", IT_I}, - IM_UNKNOWN, // 47 + {"SWR", IT_I, true}, + IM_UNKNOWN, + // 47 IM_UNKNOWN, // 48 IM_UNKNOWN, // 49 IM_UNKNOWN, // 50 @@ -228,6 +139,110 @@ static const struct AluInstructionMap alu_instruction_map[] = { }; #undef AIM_UNKNOWN +Instruction::Instruction() { + this->dt = 0; +} + +Instruction::Instruction(std::uint32_t inst) { + this->dt = inst; +} + +Instruction::Instruction(std::uint8_t opcode, std::uint8_t rs, std::uint8_t rt, std::uint8_t rd, std::uint8_t shamt, std::uint8_t funct) { + this->dt = 0; + this->dt |= opcode << 26; + this->dt |= rs << 21; + this->dt |= rt << 16; + this->dt |= rd << 11; + this->dt |= shamt << 6; + this->dt |= funct; +} + +Instruction::Instruction(std::uint8_t opcode, std::uint8_t rs, std::uint8_t rt, std::uint16_t immediate) { + this->dt = 0; + this->dt |= opcode << 26; + this->dt |= rs << 21; + this->dt |= rt << 16; + this->dt |= immediate; +} + +Instruction::Instruction(std::uint8_t opcode, std::uint32_t address) { + this->dt = 0; + this->dt |= opcode << 26; + this->dt |= address; +} + +Instruction::Instruction(const Instruction &i) { + this->dt = i.data(); +} + +#define MASK(LEN,OFF) ((this->dt >> (OFF)) & ((1 << (LEN)) - 1)) + +std::uint8_t Instruction::opcode() const { + return (std::uint8_t) MASK(6, 26); +} + +std::uint8_t Instruction::rs() const { + return (std::uint8_t) MASK(5, 21); +} + +std::uint8_t Instruction::rt() const { + return (std::uint8_t) MASK(5, 16); +} + +std::uint8_t Instruction::rd() const { + return (std::uint8_t) MASK(5, 11); +} + +std::uint8_t Instruction::shamt() const { + return (std::uint8_t) MASK(5, 6); + +} + +std::uint8_t Instruction::funct() const { + return (std::uint8_t) MASK(6, 0); +} + +std::uint16_t Instruction::immediate() const { + return (std::uint16_t) MASK(16, 0); +} + +std::uint32_t Instruction::address() const { + return (std::uint32_t) MASK(26, 0); +} + +std::uint32_t Instruction::data() const { + return this->dt; +} + +enum Instruction::Type Instruction::type() const { + if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) + return T_UNKNOWN; + const struct InstructionMap &im = instruction_map[opcode()]; + return im.type; +} + +bool Instruction::is_store() const { + if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) + return false; + const struct InstructionMap &im = instruction_map[opcode()]; + return im.is_store; +} + +bool Instruction::operator==(const Instruction &c) const { + return (this->data() == c.data()); +} + +bool Instruction::operator!=(const Instruction &c) const { + return ! this->operator==(c); +} + +Instruction &Instruction::operator=(const Instruction &c) { + if (this != &c) + this->dt = c.data(); + return *this; +} + + QString Instruction::to_str() const { // TODO there are exception where some fields are zero and such so we should not print them in such case if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) @@ -237,16 +252,16 @@ QString Instruction::to_str() const { const struct InstructionMap &im = instruction_map[opcode()]; QString res; switch (im.type) { - case IT_I: + case T_I: res += im.name; res += " $" + QString::number(rt()) + ", $" + QString::number(rs()) + ", 0x" + QString::number(immediate(), 16).toUpper(); break; - case IT_J: + case T_J: res += im.name; // TODO we need to know instruction address to expand address section by it res += " " + QString::number(address(), 16).toUpper(); break; - case IT_R: + case T_R: { // Note that all R instructions we support has opcode == 0 and so they are processed by alu table if (funct() >= (sizeof(alu_instruction_map) / sizeof(struct AluInstructionMap))) @@ -256,6 +271,8 @@ QString Instruction::to_str() const { res += " $" + QString::number(rd()) + ", $" + QString::number(rs()) + ", $" + QString::number(rt()); break; } + case T_UNKNOWN: + return QString("UNKNOWN"); } return res; } diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h index d84b0cb..1e44a1a 100644 --- a/qtmips_machine/instruction.h +++ b/qtmips_machine/instruction.h @@ -15,6 +15,13 @@ public: Instruction(std::uint8_t opcode, std::uint32_t address); // Type J Instruction(const Instruction&); + enum Type { + T_R, + T_I, + T_J, + T_UNKNOWN + }; + std::uint8_t opcode() const; std::uint8_t rs() const; std::uint8_t rt() const; @@ -24,6 +31,8 @@ public: std::uint16_t immediate() const; std::uint32_t address() const; std::uint32_t data() const; + enum Type type() const; + bool is_store() const; // Store instructions requires some additional handling so identify them bool operator==(const Instruction &c) const; bool operator!=(const Instruction &c) const; |