Clock: Add a Cycles wrapper class and use where applicable
[gem5.git] / src / cpu / inorder / reg_dep_map.cc
1 /*
2 * Copyright (c) 2007 MIPS Technologies, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Korey Sewell
29 *
30 */
31
32 #include "arch/isa_traits.hh"
33 #include "config/the_isa.hh"
34 #include "cpu/inorder/cpu.hh"
35 #include "cpu/inorder/inorder_dyn_inst.hh"
36 #include "cpu/inorder/pipeline_traits.hh"
37 #include "cpu/inorder/reg_dep_map.hh"
38 #include "debug/RegDepMap.hh"
39
40 using namespace std;
41 using namespace TheISA;
42 using namespace ThePipeline;
43
44 RegDepMap::RegDepMap(int size)
45 {
46 regMap.resize(InOrderCPU::NumRegTypes);
47 regMap[InOrderCPU::IntType].resize(NumIntRegs);
48 regMap[InOrderCPU::FloatType].resize(NumFloatRegs);
49 regMap[InOrderCPU::MiscType].resize(NumMiscRegs);
50 }
51
52 RegDepMap::~RegDepMap()
53 {
54 clear();
55 }
56
57 string
58 RegDepMap::name()
59 {
60 return cpu->name() + ".RegDepMap";
61 }
62
63 std::string RegDepMap::mapNames[InOrderCPU::NumRegTypes] =
64 {"IntReg", "FloatReg", "MiscReg"};
65
66 void
67 RegDepMap::setCPU(InOrderCPU *_cpu)
68 {
69 cpu = _cpu;
70
71 }
72
73 void
74 RegDepMap::clear()
75 {
76 for (int i = 0; i < regMap.size(); i++) {
77 for (int j = 0; j < regMap[j].size(); j++)
78 regMap[i][j].clear();
79 regMap[i].clear();
80 }
81 regMap.clear();
82 }
83
84 void
85 RegDepMap::insert(DynInstPtr inst)
86 {
87 int dest_regs = inst->numDestRegs();
88
89 DPRINTF(RegDepMap, "Setting Output Dependencies for [sn:%i] "
90 ", %s (dest. regs = %i).\n",
91 inst->seqNum,
92 inst->instName(),
93 dest_regs);
94
95 for (int i = 0; i < dest_regs; i++) {
96 InOrderCPU::RegType reg_type;
97 TheISA::RegIndex raw_idx = inst->destRegIdx(i);
98 TheISA::RegIndex flat_idx = cpu->flattenRegIdx(raw_idx,
99 reg_type,
100 inst->threadNumber);
101
102 DPRINTF(RegDepMap, "[sn:%i] #%i flattened %i to %i.\n",
103 inst->seqNum, i, raw_idx, flat_idx);
104
105 inst->flattenDestReg(i, flat_idx);
106
107 if (flat_idx == TheISA::ZeroReg && reg_type == InOrderCPU::IntType) {
108 DPRINTF(RegDepMap, "[sn:%i]: Ignoring Insert-Dependency tracking for "
109 "ISA-ZeroReg (Int. Reg %i).\n", inst->seqNum,
110 flat_idx);
111 continue;
112 }
113
114 insert(reg_type, flat_idx, inst);
115 }
116 }
117
118
119 void
120 RegDepMap::insert(uint8_t reg_type, RegIndex idx, DynInstPtr inst)
121 {
122 DPRINTF(RegDepMap, "Inserting [sn:%i] onto %s dep. list for "
123 "reg. idx %i.\n", inst->seqNum, mapNames[reg_type],
124 idx);
125
126 regMap[reg_type][idx].push_back(inst);
127
128 inst->setRegDepEntry();
129 }
130
131 void
132 RegDepMap::remove(DynInstPtr inst)
133 {
134 if (inst->isRegDepEntry()) {
135 int dest_regs = inst->numDestRegs();
136
137 DPRINTF(RegDepMap, "Removing [sn:%i]'s entries from reg. dep. map. for "
138 ", %s (dest. regs = %i).\n",
139 inst->seqNum,
140 inst->instName(),
141 dest_regs);
142
143
144 for (int i = 0; i < dest_regs; i++) {
145 RegIndex flat_idx = inst->flattenedDestRegIdx(i);
146 InOrderCPU::RegType reg_type = cpu->getRegType(inst->destRegIdx(i));
147
148 // Merge Dyn Inst & CPU Result Types
149 if (flat_idx == TheISA::ZeroReg &&
150 reg_type == InOrderCPU::IntType) {
151 DPRINTF(RegDepMap, "[sn:%i]: Ignoring Remove-Dependency tracking for "
152 "ISA-ZeroReg (Int. Reg %i).\n", inst->seqNum,
153 flat_idx);
154 continue;
155 }
156
157
158 remove(reg_type, flat_idx, inst);
159 }
160
161 inst->clearRegDepEntry();
162 }
163 }
164
165 void
166 RegDepMap::remove(uint8_t reg_type, RegIndex idx, DynInstPtr inst)
167 {
168 std::list<DynInstPtr>::iterator list_it = regMap[reg_type][idx].begin();
169 std::list<DynInstPtr>::iterator list_end = regMap[reg_type][idx].end();
170
171
172 while (list_it != list_end) {
173 if((*list_it) == inst) {
174 DPRINTF(RegDepMap, "Removing [sn:%i] from %s dep. list for "
175 "reg. idx %i.\n", inst->seqNum, mapNames[reg_type],
176 idx);
177 regMap[reg_type][idx].erase(list_it);
178 return;
179 }
180 list_it++;
181 }
182 panic("[sn:%i] Did not find entry for %i, type:%i\n", inst->seqNum, idx, reg_type);
183 }
184
185 void
186 RegDepMap::removeFront(uint8_t reg_type, RegIndex idx, DynInstPtr inst)
187 {
188 std::list<DynInstPtr>::iterator list_it = regMap[reg_type][idx].begin();
189
190 DPRINTF(RegDepMap, "[tid:%u]: Removing dependency entry on reg. idx "
191 "%i for [sn:%i].\n", inst->readTid(), idx, inst->seqNum);
192
193 assert(list_it != regMap[reg_type][idx].end());
194
195 assert(inst == (*list_it));
196
197 regMap[reg_type][idx].erase(list_it);
198 }
199
200 bool
201 RegDepMap::canRead(uint8_t reg_type, RegIndex idx, DynInstPtr inst)
202 {
203 if (regMap[reg_type][idx].size() == 0)
204 return true;
205
206 std::list<DynInstPtr>::iterator list_it = regMap[reg_type][idx].begin();
207
208 if (inst->seqNum <= (*list_it)->seqNum) {
209 return true;
210 } else {
211 DPRINTF(RegDepMap, "[sn:%i] Can't read from RegFile, [sn:%i] has "
212 "not written it's value back yet.\n",
213 inst->seqNum, (*list_it)->seqNum);
214 return false;
215 }
216 }
217
218 ThePipeline::DynInstPtr
219 RegDepMap::canForward(uint8_t reg_type, unsigned reg_idx, DynInstPtr inst)
220 {
221 std::list<DynInstPtr>::iterator list_it = regMap[reg_type][reg_idx].begin();
222 std::list<DynInstPtr>::iterator list_end = regMap[reg_type][reg_idx].end();
223
224 DynInstPtr forward_inst = NULL;
225
226 // Look for instruction immediately in front of requestor to supply
227 // data
228 while (list_it != list_end &&
229 (*list_it)->seqNum < inst->seqNum) {
230 forward_inst = (*list_it);
231 list_it++;
232 }
233
234 if (forward_inst) {
235 int dest_reg_idx = forward_inst->getDestIdxNum(reg_idx);
236 assert(dest_reg_idx != -1);
237
238 DPRINTF(RegDepMap, "[sn:%i] Found potential forwarding value for reg %i "
239 " w/ [sn:%i] dest. reg. #%i\n",
240 inst->seqNum, reg_idx, forward_inst->seqNum, dest_reg_idx);
241
242 if (forward_inst->isExecuted() &&
243 forward_inst->readResultTime(dest_reg_idx) < curTick()) {
244 return forward_inst;
245 } else {
246 if (!forward_inst->isExecuted()) {
247 DPRINTF(RegDepMap, "[sn:%i] Can't get value through "
248 "forwarding, [sn:%i] %s has not been executed yet.\n",
249 inst->seqNum, forward_inst->seqNum, forward_inst->instName());
250 } else if (forward_inst->readResultTime(dest_reg_idx) >= curTick()) {
251 DPRINTF(RegDepMap, "[sn:%i] Can't get value through "
252 "forwarding, [sn:%i] executed on tick:%i.\n",
253 inst->seqNum, forward_inst->seqNum,
254 forward_inst->readResultTime(dest_reg_idx));
255 }
256
257 return NULL;
258 }
259 } else {
260 DPRINTF(RegDepMap, "[sn:%i] No instruction found to forward from.\n",
261 inst->seqNum);
262 return NULL;
263 }
264 }
265
266 bool
267 RegDepMap::canWrite(uint8_t reg_type, RegIndex idx, DynInstPtr inst)
268 {
269 if (regMap[reg_type][idx].size() == 0)
270 return true;
271
272 std::list<DynInstPtr>::iterator list_it = regMap[reg_type][idx].begin();
273
274 if (inst->seqNum <= (*list_it)->seqNum) {
275 return true;
276 } else {
277 DPRINTF(RegDepMap, "[sn:%i] Can't write from RegFile: [sn:%i] "
278 "has not written it's value back yet.\n", inst->seqNum,
279 (*list_it)->seqNum);
280 }
281
282 return false;
283 }
284
285 void
286 RegDepMap::dump()
287 {
288 for (int reg_type = 0; reg_type < InOrderCPU::NumRegTypes; reg_type++) {
289 for (int idx=0; idx < regMap.size(); idx++) {
290 if (regMap[idx].size() > 0) {
291 cprintf("Reg #%i (size:%i): ", idx, regMap[reg_type][idx].size());
292
293 std::list<DynInstPtr>::iterator list_it =
294 regMap[reg_type][idx].begin();
295 std::list<DynInstPtr>::iterator list_end =
296 regMap[reg_type][idx].end();
297
298 while (list_it != list_end) {
299 cprintf("[sn:%i] ", (*list_it)->seqNum);
300 list_it++;
301 }
302 cprintf("\n");
303 }
304 }
305 }
306 }