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