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