2 * Copyright (c) 2007 MIPS Technologies, Inc.
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.
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.
28 * Authors: Korey Sewell
32 #include "cpu/inorder/resource_pool.hh"
33 #include "cpu/inorder/resources/resource_list.hh"
39 using namespace ThePipeline
;
41 ResourcePool::ResourcePool(InOrderCPU
*_cpu
, ThePipeline::Params
*params
)
44 //@todo: use this function to instantiate the resources in resource pool.
45 //This will help in the auto-generation of this pipeline model.
46 //ThePipeline::addResources(resources, memObjects);
48 // Declare Resource Objects
49 // name - id - bandwidth - latency - CPU - Parameters
50 // --------------------------------------------------
51 resources
.push_back(new FetchSeqUnit("Fetch-Seq-Unit", FetchSeq
,
52 StageWidth
* 2, 0, _cpu
, params
));
54 memObjects
.push_back(ICache
);
55 resources
.push_back(new CacheUnit("icache_port", ICache
,
56 StageWidth
* MaxThreads
, 0, _cpu
,
59 resources
.push_back(new DecodeUnit("Decode-Unit", Decode
,
60 StageWidth
, 0, _cpu
, params
));
62 resources
.push_back(new BranchPredictor("Branch-Predictor", BPred
,
63 StageWidth
, 0, _cpu
, params
));
65 resources
.push_back(new InstBuffer("Fetch-Buffer-T0", FetchBuff
, 4,
68 resources
.push_back(new UseDefUnit("RegFile-Manager", RegManager
,
69 StageWidth
* MaxThreads
, 0, _cpu
,
72 resources
.push_back(new AGENUnit("AGEN-Unit", AGEN
,
73 StageWidth
, 0, _cpu
, params
));
75 resources
.push_back(new ExecutionUnit("Execution-Unit", ExecUnit
,
76 StageWidth
, 0, _cpu
, params
));
78 resources
.push_back(new MultDivUnit("Mult-Div-Unit", MDU
, 5, 0, _cpu
,
81 memObjects
.push_back(DCache
);
82 resources
.push_back(new CacheUnit("dcache_port", DCache
,
83 StageWidth
* MaxThreads
, 0, _cpu
,
86 resources
.push_back(new GraduationUnit("Graduation-Unit", Grad
,
87 StageWidth
* MaxThreads
, 0, _cpu
,
90 resources
.push_back(new InstBuffer("Fetch-Buffer-T1", FetchBuff2
, 4,
94 ResourcePool::~ResourcePool()
96 cout
<< "Deleting resources ..." << endl
;
98 for (int i
=0; i
< resources
.size(); i
++) {
99 DPRINTF(Resource
, "Deleting resource: %s.\n", resources
[i
]->name());
109 for (int i
=0; i
< resources
.size(); i
++) {
110 DPRINTF(Resource
, "Initializing resource: %s.\n",
111 resources
[i
]->name());
113 resources
[i
]->init();
120 return cpu
->name() + ".ResourcePool";
125 ResourcePool::regStats()
127 DPRINTF(Resource
, "Registering Stats Throughout Resource Pool.\n");
129 int num_resources
= resources
.size();
131 for (int idx
= 0; idx
< num_resources
; idx
++) {
132 resources
[idx
]->regStats();
137 ResourcePool::getPort(const std::string
&if_name
, int idx
)
139 DPRINTF(Resource
, "Binding %s in Resource Pool.\n", if_name
);
141 for (int i
= 0; i
< memObjects
.size(); i
++) {
142 int obj_idx
= memObjects
[i
];
143 Port
*port
= resources
[obj_idx
]->getPort(if_name
, idx
);
145 DPRINTF(Resource
, "%s set to resource %s(#%i) in Resource Pool.\n",
146 if_name
, resources
[obj_idx
]->name(), obj_idx
);
155 ResourcePool::getPortIdx(const std::string
&port_name
)
157 DPRINTF(Resource
, "Finding Port Idx for %s.\n", port_name
);
159 for (int i
= 0; i
< memObjects
.size(); i
++) {
160 unsigned obj_idx
= memObjects
[i
];
161 Port
*port
= resources
[obj_idx
]->getPort(port_name
, obj_idx
);
163 DPRINTF(Resource
, "Returning Port Idx %i for %s.\n", obj_idx
,
173 ResourcePool::getResIdx(const std::string
&res_name
)
175 DPRINTF(Resource
, "Finding Resource Idx for %s.\n", res_name
);
177 int num_resources
= resources
.size();
179 for (int idx
= 0; idx
< num_resources
; idx
++) {
180 if (resources
[idx
]->name() == res_name
)
184 panic("Can't find resource idx for: %s\n", res_name
);
189 ResourcePool::getResIdx(const ThePipeline::ResourceId
&res_id
)
191 int num_resources
= resources
.size();
193 for (int idx
= 0; idx
< num_resources
; idx
++) {
194 if (resources
[idx
]->getId() == res_id
)
198 // todo: change return value to int and return a -1 here
199 // maybe even have enumerated type
201 panic("Can't find resource idx for: %i\n", res_id
);
207 ResourcePool::request(int res_idx
, DynInstPtr inst
)
209 //Make Sure This is a valid resource ID
210 assert(res_idx
>= 0 && res_idx
< resources
.size());
212 return resources
[res_idx
]->request(inst
);
216 ResourcePool::squash(DynInstPtr inst
, int res_idx
, InstSeqNum done_seq_num
,
219 resources
[res_idx
]->squash(inst
, ThePipeline::NumStages
-1, done_seq_num
,
224 ResourcePool::slotsAvail(int res_idx
)
226 return resources
[res_idx
]->slotsAvail();
230 ResourcePool::slotsInUse(int res_idx
)
232 return resources
[res_idx
]->slotsInUse();
235 //@todo: split this function and call this version schedulePoolEvent
236 // and use this scheduleEvent for scheduling a specific event on
238 //@todo: For arguments that arent being used in a ResPoolEvent, a dummyParam
239 // or some typedef can be used to signify what's important info
240 // to the event construction
242 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type
, DynInstPtr inst
,
243 int delay
, int res_idx
, ThreadID tid
)
249 case InOrderCPU::ActivateThread
:
251 DPRINTF(Resource
, "Scheduling Activate Thread Resource Pool Event "
252 "for tick %i, [tid:%i].\n", curTick
+ delay
,
254 ResPoolEvent
*res_pool_event
=
255 new ResPoolEvent(this,
258 inst
->squashingStage
,
261 mainEventQueue
.schedule(res_pool_event
,
262 cpu
->nextCycle(curTick
+ cpu
->ticks(delay
)));
266 case InOrderCPU::HaltThread
:
267 case InOrderCPU::DeactivateThread
:
270 DPRINTF(Resource
, "Scheduling Deactivate Thread Resource Pool "
271 "Event for tick %i.\n", curTick
+ delay
);
272 ResPoolEvent
*res_pool_event
=
273 new ResPoolEvent(this,
276 inst
->squashingStage
,
280 mainEventQueue
.schedule(res_pool_event
,
281 cpu
->nextCycle(curTick
+ cpu
->ticks(delay
)));
286 case InOrderCPU::SuspendThread
:
289 DPRINTF(Resource
, "Scheduling Suspend Thread Resource Pool Event for tick %i.\n",
290 cpu
->nextCycle(cpu
->nextCycle(curTick
+ cpu
->ticks(delay
))));
291 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this,
294 inst
->squashingStage
,
298 mainEventQueue
.schedule(res_pool_event
, cpu
->nextCycle(cpu
->nextCycle(curTick
+ cpu
->ticks(delay
))));
303 case ResourcePool::InstGraduated
:
305 DPRINTF(Resource
, "Scheduling Inst-Graduated Resource Pool "
306 "Event for tick %i.\n", curTick
+ delay
);
307 ResPoolEvent
*res_pool_event
=
308 new ResPoolEvent(this,e_type
,
310 inst
->squashingStage
,
313 mainEventQueue
.schedule(res_pool_event
,
314 cpu
->nextCycle(curTick
+ cpu
->ticks(delay
)));
319 case ResourcePool::SquashAll
:
321 DPRINTF(Resource
, "Scheduling Squash Resource Pool Event for "
322 "tick %i.\n", curTick
+ delay
);
323 ResPoolEvent
*res_pool_event
=
324 new ResPoolEvent(this,e_type
,
326 inst
->squashingStage
,
329 mainEventQueue
.schedule(res_pool_event
,
330 cpu
->nextCycle(curTick
+ cpu
->ticks(delay
)));
334 case InOrderCPU::SquashFromMemStall
:
336 DPRINTF(Resource
, "Scheduling Squash Due to Memory Stall Resource "
337 "Pool Event for tick %i.\n",
339 ResPoolEvent
*res_pool_event
=
340 new ResPoolEvent(this,e_type
,
342 inst
->squashingStage
,
345 mainEventQueue
.schedule(res_pool_event
,
346 cpu
->nextCycle(curTick
+ cpu
->ticks(delay
)));
350 case ResourcePool::UpdateAfterContextSwitch
:
352 DPRINTF(Resource
, "Scheduling UpdatePC Resource Pool Event for tick %i.\n",
354 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this,e_type
,
356 inst
->squashingStage
,
359 mainEventQueue
.schedule(res_pool_event
, cpu
->nextCycle(curTick
+ cpu
->ticks(delay
)));
365 DPRINTF(Resource
, "Ignoring Unrecognized CPU Event (%s).\n",
366 InOrderCPU::eventNames
[e_type
]);
371 ResourcePool::unscheduleEvent(int res_idx
, DynInstPtr inst
)
373 resources
[res_idx
]->unscheduleEvent(inst
);
377 ResourcePool::squashAll(DynInstPtr inst
, int stage_num
,
378 InstSeqNum done_seq_num
, ThreadID tid
)
380 DPRINTF(Resource
, "[tid:%i] Broadcasting Squash All Event "
381 " starting w/stage %i for all instructions above [sn:%i].\n",
382 tid
, stage_num
, done_seq_num
);
384 int num_resources
= resources
.size();
386 for (int idx
= 0; idx
< num_resources
; idx
++) {
387 resources
[idx
]->squash(inst
, stage_num
, done_seq_num
, tid
);
392 ResourcePool::squashDueToMemStall(DynInstPtr inst
, int stage_num
,
393 InstSeqNum done_seq_num
, ThreadID tid
)
395 DPRINTF(Resource
, "[tid:%i] Broadcasting SquashDueToMemStall Event"
396 " starting w/stage %i for all instructions above [sn:%i].\n",
397 tid
, stage_num
, done_seq_num
);
399 int num_resources
= resources
.size();
401 for (int idx
= 0; idx
< num_resources
; idx
++) {
402 resources
[idx
]->squashDueToMemStall(inst
, stage_num
, done_seq_num
,
408 ResourcePool::activateAll(ThreadID tid
)
410 bool do_activate
= cpu
->threadModel
!= InOrderCPU::SwitchOnCacheMiss
||
411 cpu
->numActiveThreads() < 1 ||
412 cpu
->activeThreadId() == tid
;
416 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Activation to all "
417 "resources.\n", tid
);
419 int num_resources
= resources
.size();
421 for (int idx
= 0; idx
< num_resources
; idx
++) {
422 resources
[idx
]->activateThread(tid
);
425 DPRINTF(Resource
, "[tid:%i] Ignoring Thread Activation to all "
426 "resources.\n", tid
);
431 ResourcePool::deactivateAll(ThreadID tid
)
433 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Deactivation to all "
434 "resources.\n", tid
);
436 int num_resources
= resources
.size();
438 for (int idx
= 0; idx
< num_resources
; idx
++) {
439 resources
[idx
]->deactivateThread(tid
);
444 ResourcePool::suspendAll(ThreadID tid
)
446 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Suspension to all resources.\n",
449 int num_resources
= resources
.size();
451 for (int idx
= 0; idx
< num_resources
; idx
++) {
452 resources
[idx
]->suspendThread(tid
);
457 ResourcePool::instGraduated(InstSeqNum seq_num
, ThreadID tid
)
459 DPRINTF(Resource
, "[tid:%i] Broadcasting [sn:%i] graduation to all "
460 "resources.\n", tid
, seq_num
);
462 int num_resources
= resources
.size();
464 for (int idx
= 0; idx
< num_resources
; idx
++) {
465 resources
[idx
]->instGraduated(seq_num
, tid
);
470 ResourcePool::updateAfterContextSwitch(DynInstPtr inst
, ThreadID tid
)
472 DPRINTF(Resource
, "[tid:%i] Broadcasting Update PC to all resources.\n",
475 int num_resources
= resources
.size();
477 for (int idx
= 0; idx
< num_resources
; idx
++) {
478 resources
[idx
]->updateAfterContextSwitch(inst
, tid
);
482 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool
*_resPool
,
483 InOrderCPU::CPUEventType e_type
,
488 : Event(CPU_Tick_Pri
), resPool(_resPool
),
489 eventType(e_type
), inst(_inst
), seqNum(seq_num
),
490 stageNum(stage_num
), tid(_tid
)
495 ResourcePool::ResPoolEvent::process()
499 case InOrderCPU::ActivateThread
:
500 resPool
->activateAll(tid
);
503 case InOrderCPU::DeactivateThread
:
504 case InOrderCPU::HaltThread
:
505 resPool
->deactivateAll(tid
);
508 case InOrderCPU::SuspendThread
:
509 resPool
->suspendAll(tid
);
512 case ResourcePool::InstGraduated
:
513 resPool
->instGraduated(seqNum
, tid
);
516 case ResourcePool::SquashAll
:
517 resPool
->squashAll(inst
, stageNum
, seqNum
, tid
);
520 case InOrderCPU::SquashFromMemStall
:
521 resPool
->squashDueToMemStall(inst
, stageNum
, seqNum
, tid
);
524 case ResourcePool::UpdateAfterContextSwitch
:
525 resPool
->updateAfterContextSwitch(inst
, tid
);
529 fatal("Unrecognized Event Type");
532 resPool
->cpu
->cpuEventRemoveList
.push(this);
537 ResourcePool::ResPoolEvent::description()
539 return "Resource Pool event";
542 /** Schedule resource event, regardless of its current state. */
544 ResourcePool::ResPoolEvent::scheduleEvent(int delay
)
547 mainEventQueue
.reschedule(this,resPool
->cpu
->nextCycle(curTick
+ resPool
->cpu
->ticks(delay
)));
548 else if (!scheduled())
549 mainEventQueue
.schedule(this, resPool
->cpu
->nextCycle(curTick
+ resPool
->cpu
->ticks(delay
)));
552 /** Unschedule resource event, regardless of its current state. */
554 ResourcePool::ResPoolEvent::unscheduleEvent()