GCC: Get everything working with gcc 4.6.1.
[gem5.git] / src / cpu / inorder / resource_pool.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 <list>
33 #include <vector>
34
35 #include "cpu/inorder/resources/resource_list.hh"
36 #include "cpu/inorder/resource_pool.hh"
37 #include "debug/Resource.hh"
38
39 using namespace std;
40 using namespace ThePipeline;
41
42 ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
43 : cpu(_cpu)
44 {
45 //@todo: use this function to instantiate the resources in resource pool.
46 //This will help in the auto-generation of this pipeline model.
47 //ThePipeline::addResources(resources, memObjects);
48
49 int stage_width = cpu->stageWidth;
50
51 // Declare Resource Objects
52 // name - id - bandwidth - latency - CPU - Parameters
53 // --------------------------------------------------
54 resources.push_back(new FetchSeqUnit("fetch_seq_unit", FetchSeq,
55 stage_width * 2, 0, _cpu, params));
56
57 memObjects.push_back(ICache);
58 resources.push_back(new FetchUnit("icache_port", ICache,
59 stage_width * 2 + MaxThreads, 0, _cpu,
60 params));
61
62 resources.push_back(new DecodeUnit("decode_unit", Decode,
63 stage_width, 0, _cpu, params));
64
65 resources.push_back(new BranchPredictor("branch_predictor", BPred,
66 stage_width, 0, _cpu, params));
67
68 resources.push_back(new InstBuffer("fetch_buffer_t0", FetchBuff, 4,
69 0, _cpu, params));
70
71 resources.push_back(new UseDefUnit("regfile_manager", RegManager,
72 stage_width * 3, 0, _cpu,
73 params));
74
75 resources.push_back(new AGENUnit("agen_unit", AGEN,
76 stage_width, 0, _cpu, params));
77
78 resources.push_back(new ExecutionUnit("execution_unit", ExecUnit,
79 stage_width, 0, _cpu, params));
80
81 resources.push_back(new MultDivUnit("mult_div_unit", MDU,
82 stage_width * 2,
83 0,
84 _cpu,
85 params));
86
87 memObjects.push_back(DCache);
88 resources.push_back(new CacheUnit("dcache_port", DCache,
89 stage_width * 2 + MaxThreads, 0, _cpu,
90 params));
91
92 gradObjects.push_back(BPred);
93 resources.push_back(new GraduationUnit("graduation_unit", Grad,
94 stage_width, 0, _cpu,
95 params));
96
97 resources.push_back(new InstBuffer("fetch_buffer_t1", FetchBuff2, 4,
98 0, _cpu, params));
99
100 }
101
102 ResourcePool::~ResourcePool()
103 {
104 cout << "Deleting resources ..." << endl;
105
106 for (int i=0; i < resources.size(); i++) {
107 DPRINTF(Resource, "Deleting resource: %s.\n", resources[i]->name());
108
109 delete resources[i];
110 }
111 }
112
113
114 void
115 ResourcePool::init()
116 {
117 for (int i=0; i < resources.size(); i++) {
118 DPRINTF(Resource, "Initializing resource: %s.\n",
119 resources[i]->name());
120
121 resources[i]->init();
122 }
123 }
124
125 string
126 ResourcePool::name()
127 {
128 return cpu->name() + ".ResourcePool";
129 }
130
131 void
132 ResourcePool::print()
133 {
134 for (int i=0; i < resources.size(); i++) {
135 DPRINTF(InOrderDynInst, "Res:%i %s\n",
136 i, resources[i]->name());
137 }
138
139 }
140
141
142 void
143 ResourcePool::regStats()
144 {
145 DPRINTF(Resource, "Registering Stats Throughout Resource Pool.\n");
146
147 int num_resources = resources.size();
148
149 for (int idx = 0; idx < num_resources; idx++) {
150 resources[idx]->regStats();
151 }
152 }
153
154 Port *
155 ResourcePool::getPort(const std::string &if_name, int idx)
156 {
157 DPRINTF(Resource, "Binding %s in Resource Pool.\n", if_name);
158
159 for (int i = 0; i < memObjects.size(); i++) {
160 int obj_idx = memObjects[i];
161 Port *port = resources[obj_idx]->getPort(if_name, idx);
162 if (port != NULL) {
163 DPRINTF(Resource, "%s set to resource %s(#%i) in Resource Pool.\n",
164 if_name, resources[obj_idx]->name(), obj_idx);
165 return port;
166 }
167 }
168
169 return NULL;
170 }
171
172 unsigned
173 ResourcePool::getPortIdx(const std::string &port_name)
174 {
175 DPRINTF(Resource, "Finding Port Idx for %s.\n", port_name);
176
177 for (int i = 0; i < memObjects.size(); i++) {
178 unsigned obj_idx = memObjects[i];
179 Port *port = resources[obj_idx]->getPort(port_name, obj_idx);
180 if (port != NULL) {
181 DPRINTF(Resource, "Returning Port Idx %i for %s.\n", obj_idx,
182 port_name);
183 return obj_idx;
184 }
185 }
186
187 return 0;
188 }
189
190 unsigned
191 ResourcePool::getResIdx(const std::string &res_name)
192 {
193 DPRINTF(Resource, "Finding Resource Idx for %s.\n", res_name);
194
195 int num_resources = resources.size();
196
197 for (int idx = 0; idx < num_resources; idx++) {
198 if (resources[idx]->name() == res_name)
199 return idx;
200 }
201
202 panic("Can't find resource idx for: %s\n", res_name);
203 return 0;
204 }
205
206 unsigned
207 ResourcePool::getResIdx(const ThePipeline::ResourceId &res_id)
208 {
209 int num_resources = resources.size();
210
211 for (int idx = 0; idx < num_resources; idx++) {
212 if (resources[idx]->getId() == res_id)
213 return idx;
214 }
215
216 // todo: change return value to int and return a -1 here
217 // maybe even have enumerated type
218 // panic for now...
219 panic("Can't find resource idx for: %i\n", res_id);
220
221 return 0;
222 }
223
224 ResReqPtr
225 ResourcePool::request(int res_idx, DynInstPtr inst)
226 {
227 //Make Sure This is a valid resource ID
228 assert(res_idx >= 0 && res_idx < resources.size());
229
230 return resources[res_idx]->request(inst);
231 }
232
233 void
234 ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num,
235 ThreadID tid)
236 {
237 resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num,
238 tid);
239 }
240
241 void
242 ResourcePool::trap(Fault fault, ThreadID tid, DynInstPtr inst)
243 {
244 DPRINTF(Resource, "[tid:%i] Broadcasting Trap to all "
245 "resources.\n", tid);
246
247 int num_resources = resources.size();
248
249 for (int idx = 0; idx < num_resources; idx++)
250 resources[idx]->trap(fault, tid, inst);
251 }
252
253 int
254 ResourcePool::slotsAvail(int res_idx)
255 {
256 return resources[res_idx]->slotsAvail();
257 }
258
259 int
260 ResourcePool::slotsInUse(int res_idx)
261 {
262 return resources[res_idx]->slotsInUse();
263 }
264
265 //@todo: split this function and call this version schedulePoolEvent
266 // and use this scheduleEvent for scheduling a specific event on
267 // a resource
268 //@todo: For arguments that arent being used in a ResPoolEvent, a dummyParam
269 // or some typedef can be used to signify what's important info
270 // to the event construction
271 void
272 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
273 int delay, int res_idx, ThreadID tid)
274 {
275 assert(delay >= 0);
276
277 Tick when = cpu->nextCycle(curTick() + cpu->ticks(delay));
278
279 switch ((int)e_type)
280 {
281 case ResourcePool::InstGraduated:
282 {
283 DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool "
284 "Event for tick %i.\n", curTick() + delay);
285 ResPoolEventPri grad_pri = ResGrad_Pri;
286 ResPoolEvent *res_pool_event =
287 new ResPoolEvent(this,
288 e_type,
289 inst,
290 inst->squashingStage,
291 inst->seqNum,
292 inst->readTid(),
293 grad_pri);
294 cpu->schedule(res_pool_event, when);
295 }
296 break;
297
298 case ResourcePool::SquashAll:
299 {
300 DPRINTF(Resource, "Scheduling Squash Resource Pool Event for "
301 "tick %i.\n", curTick() + delay);
302 ResPoolEventPri squash_pri = ResSquash_Pri;
303 ResPoolEvent *res_pool_event =
304 new ResPoolEvent(this,
305 e_type,
306 inst,
307 inst->squashingStage,
308 inst->squashSeqNum,
309 inst->readTid(),
310 squash_pri);
311 cpu->schedule(res_pool_event, when);
312 }
313 break;
314
315 case ResourcePool::UpdateAfterContextSwitch:
316 {
317 DPRINTF(Resource, "Scheduling UpdatePC Resource Pool Event "
318 "for tick %i.\n",
319 curTick() + delay);
320 ResPoolEvent *res_pool_event = new ResPoolEvent(this,
321 e_type,
322 inst,
323 inst->squashingStage,
324 inst->seqNum,
325 inst->readTid());
326 cpu->schedule(res_pool_event, when);
327 }
328 break;
329
330 default:
331 DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n",
332 InOrderCPU::eventNames[e_type]);
333 }
334 }
335
336 void
337 ResourcePool::unscheduleEvent(int res_idx, DynInstPtr inst)
338 {
339 resources[res_idx]->unscheduleEvent(inst);
340 }
341
342 void
343 ResourcePool::squashAll(DynInstPtr inst, int stage_num,
344 InstSeqNum done_seq_num, ThreadID tid)
345 {
346 DPRINTF(Resource, "[tid:%i] Broadcasting Squash All Event "
347 " starting w/stage %i for all instructions above [sn:%i].\n",
348 tid, stage_num, done_seq_num);
349
350 int num_resources = resources.size();
351
352 for (int idx = 0; idx < num_resources; idx++) {
353 resources[idx]->squash(inst, stage_num, done_seq_num, tid);
354 }
355 }
356
357 void
358 ResourcePool::squashDueToMemStall(DynInstPtr inst, int stage_num,
359 InstSeqNum done_seq_num, ThreadID tid)
360 {
361 DPRINTF(Resource, "[tid:%i] Broadcasting SquashDueToMemStall Event"
362 " starting w/stage %i for all instructions above [sn:%i].\n",
363 tid, stage_num, done_seq_num);
364
365 int num_resources = resources.size();
366
367 for (int idx = 0; idx < num_resources; idx++) {
368 resources[idx]->squashDueToMemStall(inst, stage_num, done_seq_num,
369 tid);
370 }
371 }
372
373 void
374 ResourcePool::activateThread(ThreadID tid)
375 {
376 bool do_activate = cpu->threadModel != InOrderCPU::SwitchOnCacheMiss ||
377 cpu->numActiveThreads() < 1 ||
378 cpu->activeThreadId() == tid;
379
380
381 if (do_activate) {
382 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all "
383 "resources.\n", tid);
384
385 int num_resources = resources.size();
386
387 for (int idx = 0; idx < num_resources; idx++) {
388 resources[idx]->activateThread(tid);
389 }
390 } else {
391 DPRINTF(Resource, "[tid:%i] Ignoring Thread Activation to all "
392 "resources.\n", tid);
393 }
394 }
395
396 void
397 ResourcePool::deactivateThread(ThreadID tid)
398 {
399 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all "
400 "resources.\n", tid);
401
402 int num_resources = resources.size();
403
404 for (int idx = 0; idx < num_resources; idx++) {
405 resources[idx]->deactivateThread(tid);
406 }
407 }
408
409 void
410 ResourcePool::suspendThread(ThreadID tid)
411 {
412 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Suspension to all "
413 "resources.\n", tid);
414
415 int num_resources = resources.size();
416
417 for (int idx = 0; idx < num_resources; idx++) {
418 resources[idx]->suspendThread(tid);
419 }
420 }
421
422 void
423 ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid)
424 {
425 DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to "
426 "appropriate resources.\n", tid, seq_num);
427
428 int num_resources = gradObjects.size();
429
430 for (int idx = 0; idx < num_resources; idx++) {
431 resources[gradObjects[idx]]->instGraduated(seq_num, tid);
432 }
433 }
434
435 void
436 ResourcePool::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
437 {
438 DPRINTF(Resource, "[tid:%i] Broadcasting Update PC to all resources.\n",
439 tid);
440
441 int num_resources = resources.size();
442
443 for (int idx = 0; idx < num_resources; idx++) {
444 resources[idx]->updateAfterContextSwitch(inst, tid);
445 }
446 }
447
448 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool,
449 InOrderCPU::CPUEventType e_type,
450 DynInstPtr _inst,
451 int stage_num,
452 InstSeqNum seq_num,
453 ThreadID _tid,
454 ResPoolEventPri res_pri)
455 : Event(res_pri), resPool(_resPool),
456 eventType(e_type), inst(_inst), seqNum(seq_num),
457 stageNum(stage_num), tid(_tid)
458 { }
459
460
461 void
462 ResourcePool::ResPoolEvent::process()
463 {
464 switch ((int)eventType)
465 {
466
467 case ResourcePool::InstGraduated:
468 resPool->instGraduated(seqNum, tid);
469 break;
470
471 case ResourcePool::SquashAll:
472 resPool->squashAll(inst, stageNum, seqNum, tid);
473 break;
474
475 case ResourcePool::UpdateAfterContextSwitch:
476 resPool->updateAfterContextSwitch(inst, tid);
477 break;
478
479 default:
480 fatal("Unrecognized Event Type");
481 }
482
483 resPool->cpu->cpuEventRemoveList.push(this);
484 }
485
486
487 const char *
488 ResourcePool::ResPoolEvent::description()
489 {
490 return "Resource Pool event";
491 }
492
493 /** Schedule resource event, regardless of its current state. */
494 void
495 ResourcePool::ResPoolEvent::scheduleEvent(int delay)
496 {
497 InOrderCPU *cpu = resPool->cpu;
498 assert(!scheduled() || squashed());
499 cpu->reschedule(this, cpu->nextCycle(curTick() + cpu->ticks(delay)), true);
500 }
501
502 /** Unschedule resource event, regardless of its current state. */
503 void
504 ResourcePool::ResPoolEvent::unscheduleEvent()
505 {
506 if (scheduled())
507 squash();
508 }