-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsim_pipe.h
180 lines (131 loc) · 5.69 KB
/
sim_pipe.h
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#ifndef SIM_PIPE_H_
#define SIM_PIPE_H_
#include <stdio.h>
#include <math.h>
#include "assem.h"
#define UNDEFINED (signed)0xFFFFFFFF //constant used to initialize registers
#define NUM_SP_REGISTERS 9
#define NUM_GP_REGISTERS 32
#define NUM_OPCODES 23
#define NUM_STAGES 5
#define RD_MASK 0x03E00000
#define RS_MASK 0x001F0000
#define RT_MASK 0x0000F800
#define IMM_SIGN 0x0008000
#define IMM_SIGN_EXTEND 0xFFFF0000
#define OPCODE(X) ((opcode_t)((X & 0xFC000000) >> (INST_SIZE-OP_SIZE)))
//gets reference of register as int
#define RD(X) ((X & RD_MASK) >> (INST_SIZE - OP_SIZE - REG_REF_SIZE * 1))
#define RS(X) ((X & RS_MASK) >> (INST_SIZE - OP_SIZE - REG_REF_SIZE * 2))
#define RT(X) ((X & RT_MASK) >> (INST_SIZE - OP_SIZE - REG_REF_SIZE * 3))
typedef enum {PC, NPC, IR, A, B, IMM, COND, ALU_OUTPUT, LMD} sp_register_t;
// The NOP instruction should be automatically inserted by the processor to implement pipeline bubbles
typedef enum {LW, SW, ADD, ADDI, SUB, SUBI, XOR, XORI, OR, ORI, AND, ANDI, MULT, DIV, BEQZ, BNEZ, BLTZ, BGTZ, BLEZ, BGEZ, JUMP, EOP, NOP} opcode_t;
typedef enum {ARITH_I, ARITH, MEMORY, BRANCH, TRAP, UNDEF_INST} inst_t;
typedef enum {IF, ID, EX, MEM, WB} stage_t;
typedef enum {DATA, CONTROL, STRUCTURAL} hazard_t;
typedef enum {RS_T, RT_T, RD_T} operand_t;
class sim_pipe{
unsigned mem_latency;
unsigned clock_cycles;
unsigned inst_executed;
unsigned num_NOPS; //keeps track of NOPS to insert
unsigned total_NOPS;
int mem_latency_tracker;
/* Add the data members required by your simulator's implementation here */
int *gp_registers;
int sp_registers[NUM_STAGES][NUM_SP_REGISTERS];
//data memory - should be initialize to all 0xFF
byte *data_memory;
//instruction memory
byte *inst_memory;
//memory size in bytes
unsigned data_memory_size;
unsigned inst_memory_size;
//assembler declaration
assembler as;
//hazard control
bool data_hazard;
bool control_hazard;
bool structural_hazard;
bool is_prev_hazard;
hazard_t prev_hazard;
public:
//instantiates the simulator with a data memory of given size (in bytes) and latency (in clock cycles)
/* Note:
- initialize the registers to UNDEFINED value
- initialize the data memory to all 0xFF values
*/
sim_pipe(unsigned data_mem_size, unsigned data_mem_latency);
//de-allocates the simulator
~sim_pipe();
//loads the assembly program in file "filename" in instruction memory at the specified address
void load_program(const char *filename, unsigned base_address=0x0);
//runs the simulator for "cycles" clock cycles (run the program to completion if cycles=0)
void run(unsigned cycles=0);
//resets the state of the simulator
/* Note:
- registers should be reset to UNDEFINED value
- data memory should be reset to all 0xFF values
*/
bool pipeline(); //contains the pipeline logic
void exec_IF();
void exec_ID();
void exec_EX();
void exec_MEM();
bool exec_WB();
void reset();
// returns value of the specified special purpose register for a given stage (at the "entrance" of that stage)
// if that special purpose register is not used in that stage, returns UNDEFINED
//
// Examples (refer to page C-37 in the 5th edition textbook, A-32 in 4th edition of textbook)::
// - get_sp_register(PC, IF) returns the value of PC
// - get_sp_register(NPC, ID) returns the value of IF/ID.NPC
// - get_sp_register(NPC, EX) returns the value of ID/EX.NPC
// - get_sp_register(ALU_OUTPUT, MEM) returns the value of EX/MEM.ALU_OUTPUT
// - get_sp_register(ALU_OUTPUT, WB) returns the value of MEM/WB.ALU_OUTPUT
// - get_sp_register(LMD, ID) returns UNDEFINED
/* Note: you are allowed to use a custom format for the IR register.
Therefore, the test cases won't check the value of IR using this method.
You can add an extra method to retrieve the content of IR */
unsigned get_sp_register(sp_register_t reg, stage_t stage);
//returns value of the specified general purpose register
int get_gp_register(unsigned reg);
//returns ir register for stage
int get_ir_reg(stage_t s);
//returns PC in IF stage
int get_PC();
// set the value of the given general purpose register to "value"
void set_gp_register(unsigned reg, int value);
//returns instruction at location in instruction memory
int get_inst(unsigned base_address);
//returns the IPC
float get_IPC();
//returns the number of instructions fully executed
unsigned get_instructions_executed();
//returns the number of stalls added by processor
unsigned get_stalls();
//returns the number of clock cycles
unsigned get_clock_cycles();
//prints the content of the data memory within the specified address range
void print_memory(unsigned start_address, unsigned end_address);
//print instruction memory for debugging
void print_inst_memory(unsigned start_address, unsigned end_address);
// writes an integer value to data memory at the specified address (use little-endian format: https://en.wikipedia.org/wiki/Endianness)
void write_memory(unsigned address, unsigned value);
//read integer starting at base value
int read_memory(unsigned address);
//prints the values of the registers
void print_registers();
//get instruction type from IR register
int get_inst_type(int inst);
//detect hazards
bool isDataHazard();
bool isControlHazard();
bool isPrevHazard();
//inject NOP into pipeline
void insert_NOP(hazard_t hazard_type);
void clear_stage(stage_t);
int get_register_ref(int inst, operand_t arg); //get register in instruction at position
};
#endif /*SIM_PIPE_H_*/