InOrder: Import new inorder CPU model from MIPS.
[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, int tid)
150 {
151 resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, tid);
152 }
153
154 int
155 ResourcePool::slotsAvail(int res_idx)
156 {
157 return resources[res_idx]->slotsAvail();
158 }
159
160 int
161 ResourcePool::slotsInUse(int res_idx)
162 {
163 return resources[res_idx]->slotsInUse();
164 }
165
166 void
167 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
168 int delay, int res_idx, int tid)
169 {
170 assert(delay >= 0);
171
172 ResPoolEvent *res_pool_event = new ResPoolEvent(this);
173
174 switch (e_type)
175 {
176 case InOrderCPU::ActivateThread:
177 {
178 DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event for tick %i.\n",
179 curTick + delay);
180 res_pool_event->setEvent(e_type,
181 inst,
182 inst->squashingStage,
183 inst->bdelaySeqNum,
184 inst->readTid());
185 res_pool_event->schedule(curTick + cpu->cycles(delay));
186
187 }
188 break;
189
190 case InOrderCPU::SuspendThread:
191 case InOrderCPU::DeallocateThread:
192 {
193 DPRINTF(Resource, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n",
194 curTick + delay);
195
196 res_pool_event->setEvent(e_type,
197 inst,
198 inst->squashingStage,
199 inst->bdelaySeqNum,
200 tid);
201
202 res_pool_event->schedule(curTick + cpu->cycles(delay));
203
204 }
205 break;
206
207 case ResourcePool::InstGraduated:
208 {
209 DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n",
210 curTick + delay);
211
212 res_pool_event->setEvent(e_type,
213 inst,
214 inst->squashingStage,
215 inst->seqNum,
216 inst->readTid());
217 res_pool_event->schedule(curTick + cpu->cycles(delay));
218
219 }
220 break;
221
222 case ResourcePool::SquashAll:
223 {
224 DPRINTF(Resource, "Scheduling Squash Resource Pool Event for tick %i.\n",
225 curTick + delay);
226 res_pool_event->setEvent(e_type,
227 inst,
228 inst->squashingStage,
229 inst->bdelaySeqNum,
230 inst->readTid());
231 res_pool_event->schedule(curTick + cpu->cycles(delay));
232
233 }
234 break;
235
236 default:
237 DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%i.\n", e_type);
238 ; // If Resource Pool doesnt recognize event, we ignore it.
239 }
240 }
241
242 void
243 ResourcePool::unscheduleEvent(int res_idx, DynInstPtr inst)
244 {
245 resources[res_idx]->unscheduleEvent(inst);
246 }
247
248 void
249 ResourcePool::squashAll(DynInstPtr inst, int stage_num, InstSeqNum done_seq_num, unsigned tid)
250 {
251 DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above [sn:%i].\n",
252 stage_num, tid, done_seq_num);
253
254 int num_resources = resources.size();
255
256 for (int idx = 0; idx < num_resources; idx++) {
257 resources[idx]->squash(inst, stage_num, done_seq_num, tid);
258 }
259 }
260
261 void
262 ResourcePool::activateAll(unsigned tid)
263 {
264 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all resources.\n",
265 tid);
266
267 int num_resources = resources.size();
268
269 for (int idx = 0; idx < num_resources; idx++) {
270 resources[idx]->activateThread(tid);
271 }
272 }
273
274 void
275 ResourcePool::deactivateAll(unsigned tid)
276 {
277 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation 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]->deactivateThread(tid);
284 }
285 }
286
287 void
288 ResourcePool::instGraduated(InstSeqNum seq_num,unsigned tid)
289 {
290 DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n",
291 tid, seq_num);
292
293 int num_resources = resources.size();
294
295 for (int idx = 0; idx < num_resources; idx++) {
296 resources[idx]->instGraduated(seq_num, tid);
297 }
298 }
299
300 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool)
301 : Event(&mainEventQueue, CPU_Tick_Pri),
302 resPool(_resPool)
303 { eventType = (InOrderCPU::CPUEventType) Default; }
304
305 void
306 ResourcePool::ResPoolEvent::process()
307 {
308 switch (eventType)
309 {
310 case InOrderCPU::ActivateThread:
311 resPool->activateAll(tid);
312 break;
313
314 case InOrderCPU::SuspendThread:
315 case InOrderCPU::DeallocateThread:
316 resPool->deactivateAll(tid);
317 break;
318
319 case ResourcePool::InstGraduated:
320 resPool->instGraduated(seqNum, tid);
321 break;
322
323 case ResourcePool::SquashAll:
324 resPool->squashAll(inst, stageNum, seqNum, tid);
325 break;
326
327 default:
328 fatal("Unrecognized Event Type");
329 }
330
331 resPool->cpu->cpuEventRemoveList.push(this);
332 }
333
334
335 const char *
336 ResourcePool::ResPoolEvent::description()
337 {
338 return "Resource Pool event";
339 }
340
341 /** Schedule resource event, regardless of its current state. */
342 void
343 ResourcePool::ResPoolEvent::scheduleEvent(int delay)
344 {
345 if (squashed())
346 reschedule(curTick + resPool->cpu->cycles(delay));
347 else if (!scheduled())
348 schedule(curTick + resPool->cpu->cycles(delay));
349 }
350
351 /** Unschedule resource event, regardless of its current state. */
352 void
353 ResourcePool::ResPoolEvent::unscheduleEvent()
354 {
355 if (scheduled())
356 squash();
357 }