-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDependencyChecker.cpp
More file actions
206 lines (185 loc) · 6.56 KB
/
DependencyChecker.cpp
File metadata and controls
206 lines (185 loc) · 6.56 KB
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include "DependencyChecker.h"
DependencyChecker::DependencyChecker(int numRegisters)
/* Creates RegisterInfo entries for each of the 32 registers and creates lists for
* dependencies and instructions.
*/
{
RegisterInfo r;
// Create entries for all registers
for(int i = 0; i < numRegisters; i++){
myCurrentState.insert(make_pair(i, r));
}
}
void DependencyChecker::addInstruction(Instruction i)
/* Adds an instruction to the list of instructions and checks to see if that
* instruction results in any new data dependencies. If new data dependencies
* are created with the addition of this instruction, appropriate entries
* are added to the list of dependences.
*/
{
InstType iType = i.getInstType();
Opcode op = i.getOpcode(); //get opcode
switch(iType){
case RTYPE:
// get rs and rt and check Read Dependence if it exists
if (myOpcodeTable.RSposition(op) != -1) {
unsigned int rs = i.getRS();
checkForReadDependence(rs);
}
if (myOpcodeTable.RTposition(op) != -1) {
unsigned int rt = i.getRT();
checkForReadDependence(rt);
}
//get rd and check Write Dependence if it exists
if (myOpcodeTable.RDposition(op) != -1) {
unsigned int rd = i.getRD();
checkForWriteDependence(rd);
}
break;
case ITYPE:
// get rs and check Read Dependence if it exists
if (myOpcodeTable.RSposition(op) != -1) {
unsigned int rs = i.getRS();
checkForReadDependence(rs);
}
// get rd and check Write Dependence if it exists
if (myOpcodeTable.RTposition(op) != -1) {
unsigned int rt = i.getRT();
checkForWriteDependence(rt);
}
break;
case JTYPE:
// nothing needs to be done here
break;
default:
// nothing needs to be done here
break;
}
// add instruction to Instruction list
myInstructions.push_back(i);
}
void DependencyChecker::checkForReadDependence(unsigned int reg)
/* Determines if a read data dependence occurs when reg is read by the current
* instruction. If so, adds an entry to the list of dependences. Also updates
* the appropriate RegisterInfo entry regardless of dependence detection.
*/
{
RegisterInfo regInfoPrev = myCurrentState.at(reg); //the latest info of reg
// we do not care about RAR, so just check for RAW, and
// we add the Dependence to the dependence list if there is such a RAW dependence
if (regInfoPrev.accessType == WRITE) {
Dependence dp;
dp.dependenceType = RAW;
dp.registerNumber = reg;
dp.previousInstructionNumber = regInfoPrev.lastInstructionToAccess;
dp.currentInstructionNumber = myInstructions.size();
myDependences.push_back(dp);
}
// construct a value, and update the value corresponding to the key for
// my current state
RegisterInfo regInfo;
regInfo.lastInstructionToAccess = myInstructions.size();
regInfo.accessType = READ;
myCurrentState[reg] = regInfo;
}
void DependencyChecker::checkForWriteDependence(unsigned int reg)
/* Determines if a write data dependence occurs when reg is written by the current
* instruction. If so, adds an entry to the list of dependences. Also updates
* the appropriate RegisterInfo entry regardless of dependence detection.
*/
{
RegisterInfo regInfoPrev = myCurrentState.at(reg); //the latest info of reg
// check for WAR and WAW, and
// we add the Dependence to the dependence list if there is such
// a WAR/WAW dependence
if (regInfoPrev.accessType != A_UNDEFINED) {
Dependence dp;
if (regInfoPrev.accessType == WRITE)
dp.dependenceType = WAW;
else
dp.dependenceType = WAR;
dp.registerNumber = reg;
dp.previousInstructionNumber = regInfoPrev.lastInstructionToAccess;
dp.currentInstructionNumber = myInstructions.size();
myDependences.push_back(dp);
}
// construct a value, and update the value corresponding to the key for
// my current state
RegisterInfo regInfo;
regInfo.lastInstructionToAccess = myInstructions.size();
regInfo.accessType = WRITE;
myCurrentState[reg] = regInfo;
}
bool DependencyChecker::isRAW(int i1Num, int i2Num)
/* Given two instruction numbers i1Num and i2Num, check whether there is a RAW dependence
* between instruction i1 and i2(more specifically, whether the read register of i2 is
* the same as the write register of i1).
* Returns true is there is a RAW, and returns false if otherwise.
*/
{
// iterate through the list of RAW instructions, return true if find a match,
// otherwise return false
list<Dependence>::iterator diter;
for (diter = myDependences.begin(); diter != myDependences.end(); diter++) {
if ((*diter).dependenceType == RAW &&
(*diter).previousInstructionNumber == i1Num &&
(*diter).currentInstructionNumber == i2Num ) {
return true;
}
}
return false;
}
void DependencyChecker::printRAWDependences()
/* Prints out the RAW dependences followed by the correponding instructions
*/
{
list<Dependence>::iterator depIter;
for (depIter = myDependences.begin(); depIter != myDependences.end(); depIter++) {
if ((*depIter).dependenceType == RAW) {
cout << "RAW Dependence between instruction ";
list<Instruction>::iterator instIter = myInstructions.begin();
int i1Num = (*depIter).previousInstructionNumber;
int i2Num = (*depIter).currentInstructionNumber;
advance(instIter, i1Num);
cout << i1Num << " " << (*instIter).getAssembly() << " and ";
advance(instIter, i2Num - i1Num);
cout << i2Num << " " << (*instIter).getAssembly() << endl;
}
// cout << i1Num << " and " << i2Num << endl;
}
}
void DependencyChecker::printDependences()
/* Prints out the sequence of instructions followed by the sequence of data
* dependencies.
*/
{
// First, print all instructions
list<Instruction>::iterator liter;
int i = 0;
cout << "INSTRUCTIONS:" << endl;
for(liter = myInstructions.begin(); liter != myInstructions.end(); liter++){
cout << i << ": " << (*liter).getAssembly() << endl;
i++;
}
// Second, print all dependences
list<Dependence>::iterator diter;
cout << "DEPENDENCES: \nType Register (FirstInstr#, SecondInstr#) " << endl;
for(diter = myDependences.begin(); diter != myDependences.end(); diter++){
switch( (*diter).dependenceType){
case RAW:
cout << "RAW \t";
break;
case WAR:
cout << "WAR \t";
break;
case WAW:
cout << "WAW \t";
break;
default:
break;
}
cout << "$" << (*diter).registerNumber << " \t";
cout << "(" << (*diter).previousInstructionNumber << ", ";
cout << (*diter).currentInstructionNumber << ")" << endl;
}
}