MEM: Remove the Broadcast destination from the packet
[gem5.git] / src / cpu / inorder / resource_pool.9stage.cc
1 /*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2007 MIPS Technologies, Inc.
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Korey Sewell
41 *
42 */
43
44 #include <list>
45 #include <vector>
46
47 #include "cpu/inorder/resources/resource_list.hh"
48 #include "cpu/inorder/resource_pool.hh"
49
50 using namespace std;
51 using namespace ThePipeline;
52
53 ResourcePool::ResourcePool(InOrderCPU *_cpu, InOrderCPUParams *params)
54 : cpu(_cpu), instUnit(NULL), dataUnit(NULL)
55 {
56 //@todo: use this function to instantiate the resources in resource pool. This will help in the
57 //auto-generation of this pipeline model.
58 //ThePipeline::addResources(resources, memObjects);
59
60 // Declare Resource Objects
61 // name - id - bandwidth - latency - CPU - Parameters
62 // --------------------------------------------------
63 resources.push_back(new FetchSeqUnit("fetch_seq_unit", FetchSeq,
64 StageWidth * 2, 0, _cpu, params));
65
66 resources.push_back(new TLBUnit("itlb", ITLB, StageWidth, 0, _cpu, params));
67
68
69 // Keep track of the instruction fetch unit so we can easily
70 // provide a pointer to it in the CPU.
71 instUnit = new FetchUnit("icache_port", ICache,
72 StageWidth * MaxThreads, 0, _cpu,
73 params);
74 resources.push_back(instUnit);
75
76 resources.push_back(new DecodeUnit("decode_unit", Decode, StageWidth, 0,
77 _cpu, params));
78
79 resources.push_back(new BranchPredictor("branch_predictor", BPred,
80 StageWidth, 0, _cpu, params));
81
82 for (int i = 0; i < params->numberOfThreads; i++) {
83 char fbuff_name[20];
84 sprintf(fbuff_name, "fetch_buffer_t%i", i);
85 resources.push_back(new InstBuffer(fbuff_name, FetchBuff + i, 4, 0,
86 _cpu, params));
87 }
88
89 resources.push_back(new UseDefUnit("regfile_manager", RegManager,
90 StageWidth * MaxThreads, 0, _cpu, params));
91
92 resources.push_back(new AGENUnit("agen_unit", AGEN, StageWidth, 0, _cpu,
93 params));
94
95 resources.push_back(new ExecutionUnit("execution_unit", ExecUnit,
96 StageWidth, 0, _cpu, params));
97
98 resources.push_back(new MultDivUnit("mult_div_unit", MDU, 5, 0, _cpu,
99 params));
100
101 resources.push_back(new TLBUnit("dtlb", DTLB, StageWidth, 0, _cpu, params));
102
103 // Keep track of the data load/store unit so we can easily provide
104 // a pointer to it in the CPU.
105 dataUnit = new CacheUnit("dcache_port", DCache,
106 StageWidth * MaxThreads, 0, _cpu,
107 params);
108 resources.push_back(dataUnit);
109
110 resources.push_back(new GraduationUnit("graduation_unit", Grad,
111 StageWidth * MaxThreads, 0, _cpu, params));
112 }
113
114 void
115 ResourcePool::init()
116 {
117 for (int i=0; i < resources.size(); i++) {
118 resources[i]->init();
119 }
120 }
121
122 string
123 ResourcePool::name()
124 {
125 return cpu->name() + ".ResourcePool";
126 }
127
128
129 void
130 ResourcePool::regStats()
131 {
132 DPRINTF(Resource, "Registering Stats Throughout Resource Pool.\n");
133
134 int num_resources = resources.size();
135
136 for (int idx = 0; idx < num_resources; idx++) {
137 resources[idx]->regStats();
138 }
139 }
140
141 ResReqPtr
142 ResourcePool::request(int res_idx, DynInstPtr inst)
143 {
144 //Make Sure This is a valid resource ID
145 assert(res_idx >= 0 && res_idx < resources.size());
146
147 return resources[res_idx]->request(inst);
148 }
149
150 void
151 ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num,
152 ThreadID tid)
153 {
154 resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, tid);
155 }
156
157 int
158 ResourcePool::slotsAvail(int res_idx)
159 {
160 return resources[res_idx]->slotsAvail();
161 }
162
163 int
164 ResourcePool::slotsInUse(int res_idx)
165 {
166 return resources[res_idx]->slotsInUse();
167 }
168
169 void
170 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
171 int delay, int res_idx, ThreadID tid)
172 {
173 assert(delay >= 0);
174
175 ResPoolEvent *res_pool_event = new ResPoolEvent(this);
176
177 switch (e_type)
178 {
179 case InOrderCPU::ActivateThread:
180 {
181 DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event for tick %i.\n",
182 curTick() + delay);
183 res_pool_event->setEvent(e_type,
184 inst,
185 inst->squashingStage,
186 inst->squashSeqNum,
187 inst->readTid());
188 res_pool_event->schedule(curTick() + cpu->cycles(delay));
189
190 }
191 break;
192
193 case InOrderCPU::SuspendThread:
194 case InOrderCPU::DeallocateThread:
195 {
196 DPRINTF(Resource, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n",
197 curTick() + delay);
198
199 res_pool_event->setEvent(e_type,
200 inst,
201 inst->squashingStage,
202 inst->squashSeqNum,
203 tid);
204
205 res_pool_event->schedule(curTick() + cpu->cycles(delay));
206
207 }
208 break;
209
210 case ResourcePool::InstGraduated:
211 {
212 DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n",
213 curTick() + delay);
214
215 res_pool_event->setEvent(e_type,
216 inst,
217 inst->squashingStage,
218 inst->seqNum,
219 inst->readTid());
220 res_pool_event->schedule(curTick() + cpu->cycles(delay));
221
222 }
223 break;
224
225 case ResourcePool::SquashAll:
226 {
227 DPRINTF(Resource, "Scheduling Squash Resource Pool Event for tick %i.\n",
228 curTick() + delay);
229 res_pool_event->setEvent(e_type,
230 inst,
231 inst->squashingStage,
232 inst->squashSeqNum,
233 inst->readTid());
234 res_pool_event->schedule(curTick() + cpu->cycles(delay));
235
236 }
237 break;
238
239 default:
240 DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%i.\n", e_type);
241 ; // If Resource Pool doesnt recognize event, we ignore it.
242 }
243 }
244
245 void
246 ResourcePool::unscheduleEvent(int res_idx, DynInstPtr inst)
247 {
248 resources[res_idx]->unscheduleEvent(inst);
249 }
250
251 void
252 ResourcePool::squashAll(DynInstPtr inst, int stage_num,
253 InstSeqNum done_seq_num, ThreadID tid)
254 {
255 DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above [sn:%i].\n",
256 stage_num, tid, done_seq_num);
257
258 int num_resources = resources.size();
259
260 for (int idx = 0; idx < num_resources; idx++) {
261 resources[idx]->squash(inst, stage_num, done_seq_num, tid);
262 }
263 }
264
265 void
266 ResourcePool::activateAll(ThreadID tid)
267 {
268 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all resources.\n",
269 tid);
270
271 int num_resources = resources.size();
272
273 for (int idx = 0; idx < num_resources; idx++) {
274 resources[idx]->activateThread(tid);
275 }
276 }
277
278 void
279 ResourcePool::deactivateAll(ThreadID tid)
280 {
281 DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all resources.\n",
282 tid);
283
284 int num_resources = resources.size();
285
286 for (int idx = 0; idx < num_resources; idx++) {
287 resources[idx]->deactivateThread(tid);
288 }
289 }
290
291 void
292 ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid)
293 {
294 DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n",
295 tid, seq_num);
296
297 int num_resources = resources.size();
298
299 for (int idx = 0; idx < num_resources; idx++) {
300 resources[idx]->instGraduated(seq_num, tid);
301 }
302 }
303
304 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool)
305 : Event(&mainEventQueue, CPU_Tick_Pri),
306 resPool(_resPool)
307 { eventType = (InOrderCPU::CPUEventType) Default; }
308
309 void
310 ResourcePool::ResPoolEvent::process()
311 {
312 switch (eventType)
313 {
314 case InOrderCPU::ActivateThread:
315 resPool->activateAll(tid);
316 break;
317
318 case InOrderCPU::SuspendThread:
319 case InOrderCPU::DeallocateThread:
320 resPool->deactivateAll(tid);
321 break;
322
323 case ResourcePool::InstGraduated:
324 resPool->instGraduated(seqNum, tid);
325 break;
326
327 case ResourcePool::SquashAll:
328 resPool->squashAll(inst, stageNum, seqNum, tid);
329 break;
330
331 default:
332 fatal("Unrecognized Event Type");
333 }
334
335 resPool->cpu->cpuEventRemoveList.push(this);
336 }
337
338
339 const char *
340 ResourcePool::ResPoolEvent::description()
341 {
342 return "Resource Pool event";
343 }
344
345 /** Schedule resource event, regardless of its current state. */
346 void
347 ResourcePool::ResPoolEvent::scheduleEvent(int delay)
348 {
349 if (squashed())
350 reschedule(curTick() + resPool->cpu->cycles(delay));
351 else if (!scheduled())
352 schedule(curTick() + resPool->cpu->cycles(delay));
353 }
354
355 /** Unschedule resource event, regardless of its current state. */
356 void
357 ResourcePool::ResPoolEvent::unscheduleEvent()
358 {
359 if (scheduled())
360 squash();
361 }