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
35 #include "cpu/inorder/resources/resource_list.hh"
36 #include "cpu/inorder/resource_pool.hh"
37 #include "debug/Resource.hh"
40 using namespace ThePipeline
;
42 ResourcePool::ResourcePool(InOrderCPU
*_cpu
, ThePipeline::Params
*params
)
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);
49 int stage_width
= cpu
->stageWidth
;
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
));
57 memObjects
.push_back(ICache
);
58 resources
.push_back(new FetchUnit("icache_port", ICache
,
59 stage_width
* 2 + MaxThreads
, 0, _cpu
,
62 resources
.push_back(new DecodeUnit("decode_unit", Decode
,
63 stage_width
, 0, _cpu
, params
));
65 resources
.push_back(new BranchPredictor("branch_predictor", BPred
,
66 stage_width
, 0, _cpu
, params
));
68 resources
.push_back(new InstBuffer("fetch_buffer_t0", FetchBuff
, 4,
71 resources
.push_back(new UseDefUnit("regfile_manager", RegManager
,
72 stage_width
* 3, 0, _cpu
,
75 resources
.push_back(new AGENUnit("agen_unit", AGEN
,
76 stage_width
, 0, _cpu
, params
));
78 resources
.push_back(new ExecutionUnit("execution_unit", ExecUnit
,
79 stage_width
, 0, _cpu
, params
));
81 resources
.push_back(new MultDivUnit("mult_div_unit", MDU
,
87 memObjects
.push_back(DCache
);
88 resources
.push_back(new CacheUnit("dcache_port", DCache
,
89 stage_width
* 2 + MaxThreads
, 0, _cpu
,
92 gradObjects
.push_back(BPred
);
93 resources
.push_back(new GraduationUnit("graduation_unit", Grad
,
97 resources
.push_back(new InstBuffer("fetch_buffer_t1", FetchBuff2
, 4,
102 ResourcePool::~ResourcePool()
104 cout
<< "Deleting resources ..." << endl
;
106 for (int i
=0; i
< resources
.size(); i
++) {
107 DPRINTF(Resource
, "Deleting resource: %s.\n", resources
[i
]->name());
117 for (int i
=0; i
< resources
.size(); i
++) {
118 DPRINTF(Resource
, "Initializing resource: %s.\n",
119 resources
[i
]->name());
121 resources
[i
]->init();
128 return cpu
->name() + ".ResourcePool";
132 ResourcePool::print()
134 for (int i
=0; i
< resources
.size(); i
++) {
135 DPRINTF(InOrderDynInst
, "Res:%i %s\n",
136 i
, resources
[i
]->name());
143 ResourcePool::regStats()
145 DPRINTF(Resource
, "Registering Stats Throughout Resource Pool.\n");
147 int num_resources
= resources
.size();
149 for (int idx
= 0; idx
< num_resources
; idx
++) {
150 resources
[idx
]->regStats();
155 ResourcePool::getPort(const std::string
&if_name
, int idx
)
157 DPRINTF(Resource
, "Binding %s in Resource Pool.\n", if_name
);
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
);
163 DPRINTF(Resource
, "%s set to resource %s(#%i) in Resource Pool.\n",
164 if_name
, resources
[obj_idx
]->name(), obj_idx
);
173 ResourcePool::getPortIdx(const std::string
&port_name
)
175 DPRINTF(Resource
, "Finding Port Idx for %s.\n", port_name
);
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
);
181 DPRINTF(Resource
, "Returning Port Idx %i for %s.\n", obj_idx
,
191 ResourcePool::getResIdx(const std::string
&res_name
)
193 DPRINTF(Resource
, "Finding Resource Idx for %s.\n", res_name
);
195 int num_resources
= resources
.size();
197 for (int idx
= 0; idx
< num_resources
; idx
++) {
198 if (resources
[idx
]->name() == res_name
)
202 panic("Can't find resource idx for: %s\n", res_name
);
207 ResourcePool::getResIdx(const ThePipeline::ResourceId
&res_id
)
209 int num_resources
= resources
.size();
211 for (int idx
= 0; idx
< num_resources
; idx
++) {
212 if (resources
[idx
]->getId() == res_id
)
216 // todo: change return value to int and return a -1 here
217 // maybe even have enumerated type
219 panic("Can't find resource idx for: %i\n", res_id
);
225 ResourcePool::request(int res_idx
, DynInstPtr inst
)
227 //Make Sure This is a valid resource ID
228 assert(res_idx
>= 0 && res_idx
< resources
.size());
230 return resources
[res_idx
]->request(inst
);
234 ResourcePool::squash(DynInstPtr inst
, int res_idx
, InstSeqNum done_seq_num
,
237 resources
[res_idx
]->squash(inst
, ThePipeline::NumStages
-1, done_seq_num
,
242 ResourcePool::trap(Fault fault
, ThreadID tid
, DynInstPtr inst
)
244 DPRINTF(Resource
, "[tid:%i] Broadcasting Trap to all "
245 "resources.\n", tid
);
247 int num_resources
= resources
.size();
249 for (int idx
= 0; idx
< num_resources
; idx
++)
250 resources
[idx
]->trap(fault
, tid
, inst
);
254 ResourcePool::slotsAvail(int res_idx
)
256 return resources
[res_idx
]->slotsAvail();
260 ResourcePool::slotsInUse(int res_idx
)
262 return resources
[res_idx
]->slotsInUse();
265 //@todo: split this function and call this version schedulePoolEvent
266 // and use this scheduleEvent for scheduling a specific event on
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
272 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type
, DynInstPtr inst
,
273 int delay
, int res_idx
, ThreadID tid
)
277 Tick when
= cpu
->nextCycle(curTick() + cpu
->ticks(delay
));
281 case ResourcePool::InstGraduated
:
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,
290 inst
->squashingStage
,
294 cpu
->schedule(res_pool_event
, when
);
298 case ResourcePool::SquashAll
:
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,
307 inst
->squashingStage
,
311 cpu
->schedule(res_pool_event
, when
);
315 case ResourcePool::UpdateAfterContextSwitch
:
317 DPRINTF(Resource
, "Scheduling UpdatePC Resource Pool Event "
320 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this,
323 inst
->squashingStage
,
326 cpu
->schedule(res_pool_event
, when
);
331 DPRINTF(Resource
, "Ignoring Unrecognized CPU Event (%s).\n",
332 InOrderCPU::eventNames
[e_type
]);
337 ResourcePool::unscheduleEvent(int res_idx
, DynInstPtr inst
)
339 resources
[res_idx
]->unscheduleEvent(inst
);
343 ResourcePool::squashAll(DynInstPtr inst
, int stage_num
,
344 InstSeqNum done_seq_num
, ThreadID tid
)
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
);
350 int num_resources
= resources
.size();
352 for (int idx
= 0; idx
< num_resources
; idx
++) {
353 resources
[idx
]->squash(inst
, stage_num
, done_seq_num
, tid
);
358 ResourcePool::squashDueToMemStall(DynInstPtr inst
, int stage_num
,
359 InstSeqNum done_seq_num
, ThreadID tid
)
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
);
365 int num_resources
= resources
.size();
367 for (int idx
= 0; idx
< num_resources
; idx
++) {
368 resources
[idx
]->squashDueToMemStall(inst
, stage_num
, done_seq_num
,
374 ResourcePool::activateThread(ThreadID tid
)
376 bool do_activate
= cpu
->threadModel
!= InOrderCPU::SwitchOnCacheMiss
||
377 cpu
->numActiveThreads() < 1 ||
378 cpu
->activeThreadId() == tid
;
382 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Activation to all "
383 "resources.\n", tid
);
385 int num_resources
= resources
.size();
387 for (int idx
= 0; idx
< num_resources
; idx
++) {
388 resources
[idx
]->activateThread(tid
);
391 DPRINTF(Resource
, "[tid:%i] Ignoring Thread Activation to all "
392 "resources.\n", tid
);
397 ResourcePool::deactivateThread(ThreadID tid
)
399 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Deactivation to all "
400 "resources.\n", tid
);
402 int num_resources
= resources
.size();
404 for (int idx
= 0; idx
< num_resources
; idx
++) {
405 resources
[idx
]->deactivateThread(tid
);
410 ResourcePool::suspendThread(ThreadID tid
)
412 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Suspension to all "
413 "resources.\n", tid
);
415 int num_resources
= resources
.size();
417 for (int idx
= 0; idx
< num_resources
; idx
++) {
418 resources
[idx
]->suspendThread(tid
);
423 ResourcePool::instGraduated(InstSeqNum seq_num
, ThreadID tid
)
425 DPRINTF(Resource
, "[tid:%i] Broadcasting [sn:%i] graduation to "
426 "appropriate resources.\n", tid
, seq_num
);
428 int num_resources
= gradObjects
.size();
430 for (int idx
= 0; idx
< num_resources
; idx
++) {
431 resources
[gradObjects
[idx
]]->instGraduated(seq_num
, tid
);
436 ResourcePool::updateAfterContextSwitch(DynInstPtr inst
, ThreadID tid
)
438 DPRINTF(Resource
, "[tid:%i] Broadcasting Update PC to all resources.\n",
441 int num_resources
= resources
.size();
443 for (int idx
= 0; idx
< num_resources
; idx
++) {
444 resources
[idx
]->updateAfterContextSwitch(inst
, tid
);
448 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool
*_resPool
,
449 InOrderCPU::CPUEventType e_type
,
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
)
462 ResourcePool::ResPoolEvent::process()
464 switch ((int)eventType
)
467 case ResourcePool::InstGraduated
:
468 resPool
->instGraduated(seqNum
, tid
);
471 case ResourcePool::SquashAll
:
472 resPool
->squashAll(inst
, stageNum
, seqNum
, tid
);
475 case ResourcePool::UpdateAfterContextSwitch
:
476 resPool
->updateAfterContextSwitch(inst
, tid
);
480 fatal("Unrecognized Event Type");
483 resPool
->cpu
->cpuEventRemoveList
.push(this);
488 ResourcePool::ResPoolEvent::description()
490 return "Resource Pool event";
493 /** Schedule resource event, regardless of its current state. */
495 ResourcePool::ResPoolEvent::scheduleEvent(int delay
)
497 InOrderCPU
*cpu
= resPool
->cpu
;
498 assert(!scheduled() || squashed());
499 cpu
->reschedule(this, cpu
->nextCycle(curTick() + cpu
->ticks(delay
)), true);
502 /** Unschedule resource event, regardless of its current state. */
504 ResourcePool::ResPoolEvent::unscheduleEvent()