2 * Copyright (c) 2012 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2007 MIPS Technologies, Inc.
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 * Authors: Korey Sewell
47 #include "cpu/inorder/resources/resource_list.hh"
48 #include "cpu/inorder/resource_pool.hh"
49 #include "debug/Resource.hh"
52 using namespace ThePipeline
;
54 ResourcePool::ResourcePool(InOrderCPU
*_cpu
, ThePipeline::Params
*params
)
55 : cpu(_cpu
), instUnit(NULL
), dataUnit(NULL
)
57 //@todo: use this function to instantiate the resources in resource pool.
58 //This will help in the auto-generation of this pipeline model.
59 //ThePipeline::addResources(resources, memObjects);
61 int stage_width
= cpu
->stageWidth
;
63 // Declare Resource Objects
64 // name - id - bandwidth - latency - CPU - Parameters
65 // --------------------------------------------------
66 resources
.push_back(new FetchSeqUnit("fetch_seq_unit", FetchSeq
,
67 stage_width
* 2, Cycles(0),
70 // Keep track of the instruction fetch unit so we can easily
71 // provide a pointer to it in the CPU.
72 instUnit
= new FetchUnit("icache_port", ICache
,
73 stage_width
* 2 + MaxThreads
, Cycles(0), _cpu
,
75 resources
.push_back(instUnit
);
77 resources
.push_back(new DecodeUnit("decode_unit", Decode
,
78 stage_width
, Cycles(0), _cpu
,
81 resources
.push_back(new BranchPredictor("branch_predictor", BPred
,
82 stage_width
, Cycles(0),
85 resources
.push_back(new InstBuffer("fetch_buffer_t0", FetchBuff
, 4,
86 Cycles(0), _cpu
, params
));
88 resources
.push_back(new UseDefUnit("regfile_manager", RegManager
,
89 stage_width
* 3, Cycles(0), _cpu
,
92 resources
.push_back(new AGENUnit("agen_unit", AGEN
,
93 stage_width
, Cycles(0), _cpu
,
96 resources
.push_back(new ExecutionUnit("execution_unit", ExecUnit
,
97 stage_width
, Cycles(0), _cpu
,
100 resources
.push_back(new MultDivUnit("mult_div_unit", MDU
,
101 stage_width
* 2, Cycles(0),
104 // Keep track of the data load/store unit so we can easily provide
105 // a pointer to it in the CPU.
106 dataUnit
= new CacheUnit("dcache_port", DCache
,
107 stage_width
* 2 + MaxThreads
, Cycles(0), _cpu
,
109 resources
.push_back(dataUnit
);
111 gradObjects
.push_back(BPred
);
112 resources
.push_back(new GraduationUnit("graduation_unit", Grad
,
113 stage_width
, Cycles(0), _cpu
,
116 resources
.push_back(new InstBuffer("fetch_buffer_t1", FetchBuff2
, 4,
117 Cycles(0), _cpu
, params
));
121 ResourcePool::~ResourcePool()
123 cout
<< "Deleting resources ..." << endl
;
125 for (int i
=0; i
< resources
.size(); i
++) {
126 DPRINTF(Resource
, "Deleting resource: %s.\n", resources
[i
]->name());
136 for (int i
=0; i
< resources
.size(); i
++) {
137 DPRINTF(Resource
, "Initializing resource: %s.\n",
138 resources
[i
]->name());
140 resources
[i
]->init();
147 return cpu
->name() + ".ResourcePool";
151 ResourcePool::print()
153 for (int i
=0; i
< resources
.size(); i
++) {
154 DPRINTF(InOrderDynInst
, "Res:%i %s\n",
155 i
, resources
[i
]->name());
162 ResourcePool::regStats()
164 DPRINTF(Resource
, "Registering Stats Throughout Resource Pool.\n");
166 int num_resources
= resources
.size();
168 for (int idx
= 0; idx
< num_resources
; idx
++) {
169 resources
[idx
]->regStats();
174 ResourcePool::getResIdx(const ThePipeline::ResourceId
&res_id
)
176 int num_resources
= resources
.size();
178 for (int idx
= 0; idx
< num_resources
; idx
++) {
179 if (resources
[idx
]->getId() == res_id
)
183 // todo: change return value to int and return a -1 here
184 // maybe even have enumerated type
186 panic("Can't find resource idx for: %i\n", res_id
);
192 ResourcePool::request(int res_idx
, DynInstPtr inst
)
194 //Make Sure This is a valid resource ID
195 assert(res_idx
>= 0 && res_idx
< resources
.size());
197 return resources
[res_idx
]->request(inst
);
201 ResourcePool::squash(DynInstPtr inst
, int res_idx
, InstSeqNum done_seq_num
,
204 resources
[res_idx
]->squash(inst
, ThePipeline::NumStages
-1, done_seq_num
,
209 ResourcePool::trap(Fault fault
, ThreadID tid
, DynInstPtr inst
)
211 DPRINTF(Resource
, "[tid:%i] Broadcasting Trap to all "
212 "resources.\n", tid
);
214 int num_resources
= resources
.size();
216 for (int idx
= 0; idx
< num_resources
; idx
++)
217 resources
[idx
]->trap(fault
, tid
, inst
);
221 ResourcePool::slotsAvail(int res_idx
)
223 return resources
[res_idx
]->slotsAvail();
227 ResourcePool::slotsInUse(int res_idx
)
229 return resources
[res_idx
]->slotsInUse();
232 //@todo: split this function and call this version schedulePoolEvent
233 // and use this scheduleEvent for scheduling a specific event on
235 //@todo: For arguments that arent being used in a ResPoolEvent, a dummyParam
236 // or some typedef can be used to signify what's important info
237 // to the event construction
239 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type
, DynInstPtr inst
,
240 Cycles delay
, int res_idx
, ThreadID tid
)
244 Tick when
= cpu
->clockEdge(delay
);
248 case ResourcePool::InstGraduated
:
250 DPRINTF(Resource
, "Scheduling Inst-Graduated Resource Pool "
251 "Event for tick %i.\n", curTick() + delay
);
252 ResPoolEventPri grad_pri
= ResGrad_Pri
;
253 ResPoolEvent
*res_pool_event
=
254 new ResPoolEvent(this,
257 inst
->squashingStage
,
261 cpu
->schedule(res_pool_event
, when
);
265 case ResourcePool::SquashAll
:
267 DPRINTF(Resource
, "Scheduling Squash Resource Pool Event for "
268 "tick %i.\n", curTick() + delay
);
269 ResPoolEventPri squash_pri
= ResSquash_Pri
;
270 ResPoolEvent
*res_pool_event
=
271 new ResPoolEvent(this,
274 inst
->squashingStage
,
278 cpu
->schedule(res_pool_event
, when
);
282 case ResourcePool::UpdateAfterContextSwitch
:
284 DPRINTF(Resource
, "Scheduling UpdatePC Resource Pool Event "
287 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this,
290 inst
->squashingStage
,
293 cpu
->schedule(res_pool_event
, when
);
298 DPRINTF(Resource
, "Ignoring Unrecognized CPU Event (%s).\n",
299 InOrderCPU::eventNames
[e_type
]);
304 ResourcePool::unscheduleEvent(int res_idx
, DynInstPtr inst
)
306 resources
[res_idx
]->unscheduleEvent(inst
);
310 ResourcePool::squashAll(DynInstPtr inst
, int stage_num
,
311 InstSeqNum done_seq_num
, ThreadID tid
)
313 DPRINTF(Resource
, "[tid:%i] Broadcasting Squash All Event "
314 " starting w/stage %i for all instructions above [sn:%i].\n",
315 tid
, stage_num
, done_seq_num
);
317 int num_resources
= resources
.size();
319 for (int idx
= 0; idx
< num_resources
; idx
++) {
320 resources
[idx
]->squash(inst
, stage_num
, done_seq_num
, tid
);
325 ResourcePool::squashDueToMemStall(DynInstPtr inst
, int stage_num
,
326 InstSeqNum done_seq_num
, ThreadID tid
)
328 DPRINTF(Resource
, "[tid:%i] Broadcasting SquashDueToMemStall Event"
329 " starting w/stage %i for all instructions above [sn:%i].\n",
330 tid
, stage_num
, done_seq_num
);
332 int num_resources
= resources
.size();
334 for (int idx
= 0; idx
< num_resources
; idx
++) {
335 resources
[idx
]->squashDueToMemStall(inst
, stage_num
, done_seq_num
,
341 ResourcePool::activateThread(ThreadID tid
)
343 bool do_activate
= cpu
->threadModel
!= InOrderCPU::SwitchOnCacheMiss
||
344 cpu
->numActiveThreads() < 1 ||
345 cpu
->activeThreadId() == tid
;
349 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Activation to all "
350 "resources.\n", tid
);
352 int num_resources
= resources
.size();
354 for (int idx
= 0; idx
< num_resources
; idx
++) {
355 resources
[idx
]->activateThread(tid
);
358 DPRINTF(Resource
, "[tid:%i] Ignoring Thread Activation to all "
359 "resources.\n", tid
);
364 ResourcePool::deactivateThread(ThreadID tid
)
366 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Deactivation to all "
367 "resources.\n", tid
);
369 int num_resources
= resources
.size();
371 for (int idx
= 0; idx
< num_resources
; idx
++) {
372 resources
[idx
]->deactivateThread(tid
);
377 ResourcePool::suspendThread(ThreadID tid
)
379 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Suspension to all "
380 "resources.\n", tid
);
382 int num_resources
= resources
.size();
384 for (int idx
= 0; idx
< num_resources
; idx
++) {
385 resources
[idx
]->suspendThread(tid
);
390 ResourcePool::instGraduated(InstSeqNum seq_num
, ThreadID tid
)
392 DPRINTF(Resource
, "[tid:%i] Broadcasting [sn:%i] graduation to "
393 "appropriate resources.\n", tid
, seq_num
);
395 int num_resources
= gradObjects
.size();
397 for (int idx
= 0; idx
< num_resources
; idx
++) {
398 resources
[gradObjects
[idx
]]->instGraduated(seq_num
, tid
);
403 ResourcePool::updateAfterContextSwitch(DynInstPtr inst
, ThreadID tid
)
405 DPRINTF(Resource
, "[tid:%i] Broadcasting Update PC to all resources.\n",
408 int num_resources
= resources
.size();
410 for (int idx
= 0; idx
< num_resources
; idx
++) {
411 resources
[idx
]->updateAfterContextSwitch(inst
, tid
);
415 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool
*_resPool
,
416 InOrderCPU::CPUEventType e_type
,
421 ResPoolEventPri res_pri
)
422 : Event(res_pri
), resPool(_resPool
),
423 eventType(e_type
), inst(_inst
), seqNum(seq_num
),
424 stageNum(stage_num
), tid(_tid
)
429 ResourcePool::ResPoolEvent::process()
431 switch ((int)eventType
)
434 case ResourcePool::InstGraduated
:
435 resPool
->instGraduated(seqNum
, tid
);
438 case ResourcePool::SquashAll
:
439 resPool
->squashAll(inst
, stageNum
, seqNum
, tid
);
442 case ResourcePool::UpdateAfterContextSwitch
:
443 resPool
->updateAfterContextSwitch(inst
, tid
);
447 fatal("Unrecognized Event Type");
450 resPool
->cpu
->cpuEventRemoveList
.push(this);
455 ResourcePool::ResPoolEvent::description() const
457 return "Resource Pool event";
460 /** Schedule resource event, regardless of its current state. */
462 ResourcePool::ResPoolEvent::scheduleEvent(Cycles delay
)
464 InOrderCPU
*cpu
= resPool
->cpu
;
465 assert(!scheduled() || squashed());
466 cpu
->reschedule(this, cpu
->clockEdge(delay
), true);
469 /** Unschedule resource event, regardless of its current state. */
471 ResourcePool::ResPoolEvent::unscheduleEvent()