Yet another merge with the main repository.
[gem5.git] / src / cpu / inorder / resource_pool.9stage.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
38 using namespace std;
39 using namespace ThePipeline;
40
41 ResourcePool::ResourcePool(InOrderCPU *_cpu, InOrderCPUParams *params)
42 : cpu(_cpu)
43 {
44 //@todo: use this function to instantiate the resources in resource pool. This will help in the
45 //auto-generation of this pipeline model.
46 //ThePipeline::addResources(resources, memObjects);
47
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));
53
54 resources.push_back(new TLBUnit("itlb", ITLB, StageWidth, 0, _cpu, params));
55
56 memObjects.push_back(ICache);
57 resources.push_back(new CacheUnit("icache_port", ICache,
58 StageWidth * MaxThreads, 0, _cpu, params));
59
60 resources.push_back(new DecodeUnit("decode_unit", Decode, StageWidth, 0,
61 _cpu, params));
62
63 resources.push_back(new BranchPredictor("branch_predictor", BPred,
64 StageWidth, 0, _cpu, params));
65
66 for (int i = 0; i < params->numberOfThreads; i++) {
67 char fbuff_name[20];
68 sprintf(fbuff_name, "fetch_buffer_t%i", i);
69 resources.push_back(new InstBuffer(fbuff_name, FetchBuff + i, 4, 0,
70 _cpu, params));
71 }
72
73 resources.push_back(new UseDefUnit("regfile_manager", RegManager,
74 StageWidth * MaxThreads, 0, _cpu, params));
75
76 resources.push_back(new AGENUnit("agen_unit", AGEN, StageWidth, 0, _cpu,
77 params));
78
79 resources.push_back(new ExecutionUnit("execution_unit", ExecUnit,
80 StageWidth, 0, _cpu, params));
81
82 resources.push_back(new MultDivUnit("mult_div_unit", MDU, 5, 0, _cpu,
83 params));
84
85 resources.push_back(new TLBUnit("dtlb", DTLB, StageWidth, 0, _cpu, params));
86
87 memObjects.push_back(DCache);
88 resources.push_back(new CacheUnit("dcache_port", DCache,
89 StageWidth * MaxThreads, 0, _cpu, params));
90
91 resources.push_back(new GraduationUnit("graduation_unit", Grad,
92 StageWidth * MaxThreads, 0, _cpu, params));
93 }
94
95 void
96 ResourcePool::init()
97 {
98 for (int i=0; i < resources.size(); i++) {
99 resources[i]->init();
100 }
101 }
102
103 string
104 ResourcePool::name()
105 {
106 return cpu->name() + ".ResourcePool";
107 }
108
109
110 void
111 ResourcePool::regStats()
112 {
113 DPRINTF(Resource, "Registering Stats Throughout Resource Pool.\n");
114
115 int num_resources = resources.size();
116
117 for (int idx = 0; idx < num_resources; idx++) {
118 resources[idx]->regStats();
119 }
120 }
121
122 Port *
123 ResourcePool::getPort(const std::string &if_name, int idx)
124 {
125 for (int i = 0; i < memObjects.size(); i++) {
126 int obj_idx = memObjects[i];
127 Port *port = resources[obj_idx]->getPort(if_name, idx);
128 if (port != NULL) {
129 return port;
130 }
131 }
132
133 return NULL;
134 }
135
136 unsigned
137 ResourcePool::getPortIdx(const std::string &port_name)
138 {
139 for (int i = 0; i < memObjects.size(); i++) {
140 unsigned obj_idx = memObjects[i];
141 Port *port = resources[obj_idx]->getPort(port_name, obj_idx);
142 if (port != NULL) {
143 return obj_idx;
144 }
145 }
146
147 return 0;
148 }
149
150 ResReqPtr
151 ResourcePool::request(int res_idx, DynInstPtr inst)
152 {
153 //Make Sure This is a valid resource ID
154 assert(res_idx >= 0 && res_idx < resources.size());
155
156 return resources[res_idx]->request(inst);
157 }
158
159 void
160 ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num,
161 ThreadID tid)
162 {
163 resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, tid);
164 }
165
166 int
167 ResourcePool::slotsAvail(int res_idx)
168 {
169 return resources[res_idx]->slotsAvail();
170 }
171
172 int
173 ResourcePool::slotsInUse(int res_idx)
174 {
175 return resources[res_idx]->slotsInUse();
176 }
177
178 void
179 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
180 int delay, int res_idx, ThreadID tid)
181 {
182 assert(delay >= 0);
183
184 ResPoolEvent *res_pool_event = new ResPoolEvent(this);
185
186 switch (e_type)
187 {
188 case InOrderCPU::ActivateThread:
189 {
190 DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event for tick %i.\n",
191 curTick() + delay);
192 res_pool_event->setEvent(e_type,
193 inst,
194 inst->squashingStage,
195 inst->squashSeqNum,
196 inst->readTid());
197 res_pool_event->schedule(curTick() + cpu->cycles(delay));
198
199 }
200 break;
201
202 case InOrderCPU::SuspendThread:
203 case InOrderCPU::DeallocateThread:
204 {
205 DPRINTF(Resource, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n",
206 curTick() + delay);
207
208 res_pool_event->setEvent(e_type,
209 inst,
210 inst->squashingStage,
211 inst->squashSeqNum,
212 tid);
213
214 res_pool_event->schedule(curTick() + cpu->cycles(delay));
215
216 }
217 break;
218
219 case ResourcePool::InstGraduated:
220 {
221 DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n",
222 curTick() + delay);
223
224 res_pool_event->setEvent(e_type,
225 inst,
226 inst->squashingStage,
227 inst->seqNum,
228 inst->readTid());
229 res_pool_event->schedule(curTick() + cpu->cycles(delay));
230
231 }
232 break;
233
234 case ResourcePool::SquashAll:
235 {
236 DPRINTF(Resource, "Scheduling Squash Resource Pool Event for tick %i.\n",
237 curTick() + delay);
238 res_pool_event->setEvent(e_type,
239 inst,
240 inst->squashingStage,
241 inst->squashSeqNum,
242 inst->readTid());
243 res_pool_event->schedule(curTick() + cpu->cycles(delay));
244
245 }
246 break;
247
248 default:
249 DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%i.\n", e_type);
250 ; // If Resource Pool doesnt recognize event, we ignore it.
251 }
252 }
253
254 void
255 ResourcePool::unscheduleEvent(int res_idx, DynInstPtr inst)
256 {
257 resources[res_idx]->unscheduleEvent(inst);
258 }
259
260 void
261 ResourcePool::squashAll(DynInstPtr inst, int stage_num,
262 InstSeqNum done_seq_num, ThreadID tid)
263 {
264 DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above [sn:%i].\n",
265 stage_num, tid, done_seq_num);
266
267 int num_resources = resources.size();
268
269 for (int idx = 0; idx < num_resources; idx++) {
270 resources[idx]->squash(inst, stage_num, done_seq_num, tid);
271 }
272 }
273
274 void
275 ResourcePool::activateAll(ThreadID tid)
276 {
277 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all resources.\n",
278 tid);
279
280 int num_resources = resources.size();
281
282 for (int idx = 0; idx < num_resources; idx++) {
283 resources[idx]->activateThread(tid);
284 }
285 }
286
287 void
288 ResourcePool::deactivateAll(ThreadID tid)
289 {
290 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all resources.\n",
291 tid);
292
293 int num_resources = resources.size();
294
295 for (int idx = 0; idx < num_resources; idx++) {
296 resources[idx]->deactivateThread(tid);
297 }
298 }
299
300 void
301 ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid)
302 {
303 DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n",
304 tid, seq_num);
305
306 int num_resources = resources.size();
307
308 for (int idx = 0; idx < num_resources; idx++) {
309 resources[idx]->instGraduated(seq_num, tid);
310 }
311 }
312
313 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool)
314 : Event(&mainEventQueue, CPU_Tick_Pri),
315 resPool(_resPool)
316 { eventType = (InOrderCPU::CPUEventType) Default; }
317
318 void
319 ResourcePool::ResPoolEvent::process()
320 {
321 switch (eventType)
322 {
323 case InOrderCPU::ActivateThread:
324 resPool->activateAll(tid);
325 break;
326
327 case InOrderCPU::SuspendThread:
328 case InOrderCPU::DeallocateThread:
329 resPool->deactivateAll(tid);
330 break;
331
332 case ResourcePool::InstGraduated:
333 resPool->instGraduated(seqNum, tid);
334 break;
335
336 case ResourcePool::SquashAll:
337 resPool->squashAll(inst, stageNum, seqNum, tid);
338 break;
339
340 default:
341 fatal("Unrecognized Event Type");
342 }
343
344 resPool->cpu->cpuEventRemoveList.push(this);
345 }
346
347
348 const char *
349 ResourcePool::ResPoolEvent::description()
350 {
351 return "Resource Pool event";
352 }
353
354 /** Schedule resource event, regardless of its current state. */
355 void
356 ResourcePool::ResPoolEvent::scheduleEvent(int delay)
357 {
358 if (squashed())
359 reschedule(curTick() + resPool->cpu->cycles(delay));
360 else if (!scheduled())
361 schedule(curTick() + resPool->cpu->cycles(delay));
362 }
363
364 /** Unschedule resource event, regardless of its current state. */
365 void
366 ResourcePool::ResPoolEvent::unscheduleEvent()
367 {
368 if (scheduled())
369 squash();
370 }