-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathreserv_station.cpp
141 lines (131 loc) · 3.62 KB
/
reserv_station.cpp
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
#include "./headers/reserv_station.h"
#include "./headers/mips.h"
extern config *CPU_cfg;
extern clk_tick sys_clk;
extern memory main_mem;
extern vector<int*> clk_wait_list;
extern FU_CDB fCDB;
extern ROB *CPU_ROB;
resStation::resStation(FU_Q *Q, valType t):type(t)
{
prnt_Q = Q;
busy = false;
to_start = false;
dest = -1;
Rj = Rk = true;
}
void resStation::set_code(opCode c)
{
code = c;
}
void resStation::set_lsqE(LSQEntry *e)
{
lsqE = e;
}
bool resStation::fill_rs(int _dest_robi, const instr* _instr, int _Qj, int _Qk, memCell _Vj, memCell _Vk)
{
sub = _instr->code == SUB || _instr->code == SUB_D;
busy = true;
dest = _dest_robi;
code = _instr->code;
Qj = _Qj;
Qk = _Qk;
offset = _instr->offset;
Vj = _Vj;
Vk = _Vk;
Rj = Qj<0? true:false;
Rk = Qk<0? true:false;
if (code == LD)
lsqE = main_mem.LD_enQ(dest, -1);
else if (code == SD)
{
memCell SD_source;
int SD_source_rob = -1;
get_reg_or_rob(_instr->dest, SD_source_rob, SD_source);
lsqE = main_mem.SD_enQ(dest, SD_source_rob, -1, SD_source);
}
if (Rj&&Rk)
{
msg_log("Operands ready, sending to FU, dest ROB = " + to_string(dest), 2);
prnt_Q->enQ(code, dest, &rest, &Vj, &Vk, lsqE, offset, &busy);
}
else
to_start = true;
msg_log("Res Station filled, ROB = " + to_string(dest), 3);
return true;
}
bool resStation::get_state()
{
return busy;
}
void resStation::squash(int ROB_i)
{
int R_f = CPU_ROB->get_front();
int R_r = CPU_ROB->get_rear();
if (is_prev_index(ROB_i, dest, R_f, R_r) || is_prev_index(ROB_i, Qj, R_f, R_r) || is_prev_index(ROB_i, Qk, R_f, R_r))
busy = false;
}
void resStation::reserv_automat()
{
next_vdd = 0;
while (true)
{
at_rising_edge(next_vdd);
if (busy)
{
if (fCDB.get_source() == dest)
{
msg_log("WriteBack to ROB = " + to_string(dest), 2);
ROBEntry *R = CPU_ROB->get_entry(dest);
fCDB.get_val(&R->value);
R->wrtnBack = true;
R->output.wBack = sys_clk.get_prog_cyc();
at_falling_edge(next_vdd);
R->finished = true;
at_rising_edge(next_vdd);
busy = false;
at_falling_edge(next_vdd);
continue;
}
else if (!Rj || !Rk)
{
if (fCDB.get_source() == Qj)
{
fCDB.get_val(&Vj);
Rj = true;
}
if (fCDB.get_source() == Qk)
{
fCDB.get_val(&Vk);
Rk = true;
}
}
}
at_falling_edge(next_vdd);
if (!Rj || !Rk)
{
msg_log("ROB = " + to_string(dest) + " waiting for operands" + (Rj?"":(" Qj = "+to_string(Qj))) + (Rk?"":(" Qk = "+to_string(Qk))), 3);
}
if (busy && to_start && Rj && Rk)
{
msg_log("Operands ready, sending to FU, dest ROB = " + to_string(dest), 2);
to_start = false;
if (type == FLTP)
Vk.f = sub? -Vk.f : Vk.f;
else
Vk.i = sub? -Vk.i : Vk.i;
prnt_Q->enQ(code, dest, &rest, &Vj, &Vk, lsqE, offset, &busy);
}
}
}
void* rs_thread_container(void *arg)
{
auto p = (resStation*) arg;
p->reserv_automat();
return nullptr;
}
void init_resStation(resStation *rs)
{
while(pthread_create(&(rs->handle), NULL, &rs_thread_container, (void*)rs));
clk_wait_list.push_back(&rs->next_vdd);
}