aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
authorKarel Kočí <cynerd@email.cz>2018-02-16 16:24:35 +0100
committerKarel Kočí <cynerd@email.cz>2018-03-06 21:58:49 +0100
commit1a20d908b6eefe32807f906b7294c562256a7518 (patch)
tree38cd063d902767d637b65426eecff538c9233672 /qtmips_machine
parenta56b25212865c57251719a1d4a5d9d6a79b339c5 (diff)
downloadqtmips-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.
Diffstat (limited to 'qtmips_machine')
-rw-r--r--qtmips_machine/core.cpp30
-rw-r--r--qtmips_machine/instruction.cpp275
-rw-r--r--qtmips_machine/instruction.h9
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;