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"
51 using namespace ThePipeline
;
53 ResourcePool::ResourcePool(InOrderCPU
*_cpu
, InOrderCPUParams
*params
)
54 : cpu(_cpu
), instUnit(NULL
), dataUnit(NULL
)
56 //@todo: use this function to instantiate the resources in resource pool. This will help in the
57 //auto-generation of this pipeline model.
58 //ThePipeline::addResources(resources, memObjects);
60 // Declare Resource Objects
61 // name - id - bandwidth - latency - CPU - Parameters
62 // --------------------------------------------------
63 resources
.push_back(new FetchSeqUnit("fetch_seq_unit", FetchSeq
,
64 StageWidth
* 2, 0, _cpu
, params
));
66 resources
.push_back(new TLBUnit("itlb", ITLB
, StageWidth
, 0, _cpu
, params
));
69 // Keep track of the instruction fetch unit so we can easily
70 // provide a pointer to it in the CPU.
71 instUnit
= new FetchUnit("icache_port", ICache
,
72 StageWidth
* MaxThreads
, 0, _cpu
,
74 resources
.push_back(instUnit
);
76 resources
.push_back(new DecodeUnit("decode_unit", Decode
, StageWidth
, 0,
79 resources
.push_back(new BranchPredictor("branch_predictor", BPred
,
80 StageWidth
, 0, _cpu
, params
));
82 for (int i
= 0; i
< params
->numberOfThreads
; i
++) {
84 sprintf(fbuff_name
, "fetch_buffer_t%i", i
);
85 resources
.push_back(new InstBuffer(fbuff_name
, FetchBuff
+ i
, 4, 0,
89 resources
.push_back(new UseDefUnit("regfile_manager", RegManager
,
90 StageWidth
* MaxThreads
, 0, _cpu
, params
));
92 resources
.push_back(new AGENUnit("agen_unit", AGEN
, StageWidth
, 0, _cpu
,
95 resources
.push_back(new ExecutionUnit("execution_unit", ExecUnit
,
96 StageWidth
, 0, _cpu
, params
));
98 resources
.push_back(new MultDivUnit("mult_div_unit", MDU
, 5, 0, _cpu
,
101 resources
.push_back(new TLBUnit("dtlb", DTLB
, StageWidth
, 0, _cpu
, params
));
103 // Keep track of the data load/store unit so we can easily provide
104 // a pointer to it in the CPU.
105 dataUnit
= new CacheUnit("dcache_port", DCache
,
106 StageWidth
* MaxThreads
, 0, _cpu
,
108 resources
.push_back(dataUnit
);
110 resources
.push_back(new GraduationUnit("graduation_unit", Grad
,
111 StageWidth
* MaxThreads
, 0, _cpu
, params
));
117 for (int i
=0; i
< resources
.size(); i
++) {
118 resources
[i
]->init();
125 return cpu
->name() + ".ResourcePool";
130 ResourcePool::regStats()
132 DPRINTF(Resource
, "Registering Stats Throughout Resource Pool.\n");
134 int num_resources
= resources
.size();
136 for (int idx
= 0; idx
< num_resources
; idx
++) {
137 resources
[idx
]->regStats();
142 ResourcePool::request(int res_idx
, DynInstPtr inst
)
144 //Make Sure This is a valid resource ID
145 assert(res_idx
>= 0 && res_idx
< resources
.size());
147 return resources
[res_idx
]->request(inst
);
151 ResourcePool::squash(DynInstPtr inst
, int res_idx
, InstSeqNum done_seq_num
,
154 resources
[res_idx
]->squash(inst
, ThePipeline::NumStages
-1, done_seq_num
, tid
);
158 ResourcePool::slotsAvail(int res_idx
)
160 return resources
[res_idx
]->slotsAvail();
164 ResourcePool::slotsInUse(int res_idx
)
166 return resources
[res_idx
]->slotsInUse();
170 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type
, DynInstPtr inst
,
171 int delay
, int res_idx
, ThreadID tid
)
175 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this);
179 case InOrderCPU::ActivateThread
:
181 DPRINTF(Resource
, "Scheduling Activate Thread Resource Pool Event for tick %i.\n",
183 res_pool_event
->setEvent(e_type
,
185 inst
->squashingStage
,
188 res_pool_event
->schedule(curTick() + cpu
->cycles(delay
));
193 case InOrderCPU::SuspendThread
:
194 case InOrderCPU::DeallocateThread
:
196 DPRINTF(Resource
, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n",
199 res_pool_event
->setEvent(e_type
,
201 inst
->squashingStage
,
205 res_pool_event
->schedule(curTick() + cpu
->cycles(delay
));
210 case ResourcePool::InstGraduated
:
212 DPRINTF(Resource
, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n",
215 res_pool_event
->setEvent(e_type
,
217 inst
->squashingStage
,
220 res_pool_event
->schedule(curTick() + cpu
->cycles(delay
));
225 case ResourcePool::SquashAll
:
227 DPRINTF(Resource
, "Scheduling Squash Resource Pool Event for tick %i.\n",
229 res_pool_event
->setEvent(e_type
,
231 inst
->squashingStage
,
234 res_pool_event
->schedule(curTick() + cpu
->cycles(delay
));
240 DPRINTF(Resource
, "Ignoring Unrecognized CPU Event Type #%i.\n", e_type
);
241 ; // If Resource Pool doesnt recognize event, we ignore it.
246 ResourcePool::unscheduleEvent(int res_idx
, DynInstPtr inst
)
248 resources
[res_idx
]->unscheduleEvent(inst
);
252 ResourcePool::squashAll(DynInstPtr inst
, int stage_num
,
253 InstSeqNum done_seq_num
, ThreadID tid
)
255 DPRINTF(Resource
, "[tid:%i] Stage %i squashing all instructions above [sn:%i].\n",
256 stage_num
, tid
, done_seq_num
);
258 int num_resources
= resources
.size();
260 for (int idx
= 0; idx
< num_resources
; idx
++) {
261 resources
[idx
]->squash(inst
, stage_num
, done_seq_num
, tid
);
266 ResourcePool::activateAll(ThreadID tid
)
268 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Activation to all resources.\n",
271 int num_resources
= resources
.size();
273 for (int idx
= 0; idx
< num_resources
; idx
++) {
274 resources
[idx
]->activateThread(tid
);
279 ResourcePool::deactivateAll(ThreadID tid
)
281 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Deactivation to all resources.\n",
284 int num_resources
= resources
.size();
286 for (int idx
= 0; idx
< num_resources
; idx
++) {
287 resources
[idx
]->deactivateThread(tid
);
292 ResourcePool::instGraduated(InstSeqNum seq_num
, ThreadID tid
)
294 DPRINTF(Resource
, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n",
297 int num_resources
= resources
.size();
299 for (int idx
= 0; idx
< num_resources
; idx
++) {
300 resources
[idx
]->instGraduated(seq_num
, tid
);
304 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool
*_resPool
)
305 : Event(&mainEventQueue
, CPU_Tick_Pri
),
307 { eventType
= (InOrderCPU::CPUEventType
) Default
; }
310 ResourcePool::ResPoolEvent::process()
314 case InOrderCPU::ActivateThread
:
315 resPool
->activateAll(tid
);
318 case InOrderCPU::SuspendThread
:
319 case InOrderCPU::DeallocateThread
:
320 resPool
->deactivateAll(tid
);
323 case ResourcePool::InstGraduated
:
324 resPool
->instGraduated(seqNum
, tid
);
327 case ResourcePool::SquashAll
:
328 resPool
->squashAll(inst
, stageNum
, seqNum
, tid
);
332 fatal("Unrecognized Event Type");
335 resPool
->cpu
->cpuEventRemoveList
.push(this);
340 ResourcePool::ResPoolEvent::description()
342 return "Resource Pool event";
345 /** Schedule resource event, regardless of its current state. */
347 ResourcePool::ResPoolEvent::scheduleEvent(int delay
)
350 reschedule(curTick() + resPool
->cpu
->cycles(delay
));
351 else if (!scheduled())
352 schedule(curTick() + resPool
->cpu
->cycles(delay
));
355 /** Unschedule resource event, regardless of its current state. */
357 ResourcePool::ResPoolEvent::unscheduleEvent()