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