blob: 3ea18ec323828056957927e07f5889d7766cc9cb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#ifndef CORE_H
#define CORE_H
#include <QObject>
#include <qtmipsexception.h>
#include <machineconfig.h>
#include <registers.h>
#include <memory.h>
#include <instruction.h>
#include <alu.h>
namespace machine {
class Core : public QObject {
Q_OBJECT
public:
Core(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data);
void step(); // Do single step
void reset(); // Reset core (only core, memory and registers has to be reseted separately)
unsigned cycles(); // Returns number of executed cycles
signals:
void instruction_fetched(const machine::Instruction &inst);
void instruction_decoded(const machine::Instruction &inst);
void instruction_executed(const machine::Instruction &inst);
void instruction_memory(const machine::Instruction &inst);
void instruction_writeback(const machine::Instruction &inst);
void instruction_program_counter(const machine::Instruction &inst);
protected:
virtual void do_step() = 0;
virtual void do_reset() = 0;
Registers *regs;
MemoryAccess *mem_data, *mem_program;
struct dtFetch {
Instruction inst; // Loaded instruction
};
struct dtDecode {
Instruction inst;
bool memread; // If memory should be read
bool memwrite; // If memory should write input
bool alusrc; // If second value to alu is immediate value (rt used otherwise)
bool regd; // If rd is used (otherwise rt is used for write target)
bool regwrite; // If output should be written back to register (which one depends on regd)
enum AluOp aluop; // Decoded ALU operation
enum MemoryAccess::AccessControl memctl; // Decoded memory access type
std::uint32_t val_rs; // Value from register rs
std::uint32_t val_rt; // Value from register rt
};
struct dtExecute {
Instruction inst;
bool memread;
bool memwrite;
bool regwrite;
enum MemoryAccess::AccessControl memctl;
std::uint32_t val_rt;
std::uint8_t rwrite; // Writeback register (multiplexed between rt and rd according to regd)
std::uint32_t alu_val; // Result of ALU execution
};
struct dtMemory {
Instruction inst;
bool regwrite;
std::uint8_t rwrite;
std::uint32_t towrite_val;
};
struct dtFetch fetch();
struct dtDecode decode(const struct dtFetch&);
struct dtExecute execute(const struct dtDecode&);
struct dtMemory memory(const struct dtExecute&);
void writeback(const struct dtMemory&);
void handle_pc(const struct dtDecode&);
// Initialize structures to NOPE instruction
void dtFetchInit(struct dtFetch &dt);
void dtDecodeInit(struct dtDecode &dt);
void dtExecuteInit(struct dtExecute &dt);
void dtMemoryInit(struct dtMemory &dt);
private:
unsigned cycle_c;
};
class CoreSingle : public Core {
public:
CoreSingle(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, bool jmp_delay_slot);
~CoreSingle();
protected:
void do_step();
void do_reset();
private:
struct Core::dtDecode *jmp_delay_decode;
};
class CorePipelined : public Core {
public:
CorePipelined(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, enum MachineConfig::HazardUnit hazard_unit = MachineConfig::HU_STALL_FORWARD);
protected:
void do_step();
void do_reset();
private:
struct Core::dtFetch dt_f;
struct Core::dtDecode dt_d;
struct Core::dtExecute dt_e;
struct Core::dtMemory dt_m;
enum MachineConfig::HazardUnit hazard_unit;
};
}
#endif // CORE_H
|