Fixes for functional path.
[gem5.git] / src / cpu / o3 / lsq_impl.hh
1 /*
2 * Copyright (c) 2005-2006 The Regents of The University of Michigan
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 #include <algorithm>
32 #include <list>
33 #include <string>
34
35 #include "cpu/o3/lsq.hh"
36
37 template <class Impl>
38 Tick
39 LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
40 {
41 panic("O3CPU model does not work with atomic mode!");
42 return curTick;
43 }
44
45 template <class Impl>
46 void
47 LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
48 {
49 warn("O3CPU doesn't update things on a recvFunctional.");
50 }
51
52 template <class Impl>
53 void
54 LSQ<Impl>::DcachePort::recvStatusChange(Status status)
55 {
56 if (status == RangeChange)
57 return;
58
59 panic("O3CPU doesn't expect recvStatusChange callback!");
60 }
61
62 template <class Impl>
63 bool
64 LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
65 {
66 lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);
67 return true;
68 }
69
70 template <class Impl>
71 void
72 LSQ<Impl>::DcachePort::recvRetry()
73 {
74 if (lsq->retryTid == -1)
75 {
76 //Squashed, so drop it
77 return;
78 }
79 lsq->thread[lsq->retryTid].recvRetry();
80 // Speculatively clear the retry Tid. This will get set again if
81 // the LSQUnit was unable to complete its access.
82 lsq->retryTid = -1;
83 }
84
85 template <class Impl>
86 LSQ<Impl>::LSQ(Params *params)
87 : dcachePort(this), LQEntries(params->LQEntries),
88 SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
89 retryTid(-1)
90 {
91 DPRINTF(LSQ, "Creating LSQ object.\n");
92
93 //**********************************************/
94 //************ Handle SMT Parameters ***********/
95 //**********************************************/
96 std::string policy = params->smtLSQPolicy;
97
98 //Convert string to lowercase
99 std::transform(policy.begin(), policy.end(), policy.begin(),
100 (int(*)(int)) tolower);
101
102 //Figure out fetch policy
103 if (policy == "dynamic") {
104 lsqPolicy = Dynamic;
105
106 maxLQEntries = LQEntries;
107 maxSQEntries = SQEntries;
108
109 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
110
111 } else if (policy == "partitioned") {
112 lsqPolicy = Partitioned;
113
114 //@todo:make work if part_amt doesnt divide evenly.
115 maxLQEntries = LQEntries / numThreads;
116 maxSQEntries = SQEntries / numThreads;
117
118 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
119 "%i entries per LQ | %i entries per SQ",
120 maxLQEntries,maxSQEntries);
121
122 } else if (policy == "threshold") {
123 lsqPolicy = Threshold;
124
125 assert(params->smtLSQThreshold > LQEntries);
126 assert(params->smtLSQThreshold > SQEntries);
127
128 //Divide up by threshold amount
129 //@todo: Should threads check the max and the total
130 //amount of the LSQ
131 maxLQEntries = params->smtLSQThreshold;
132 maxSQEntries = params->smtLSQThreshold;
133
134 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
135 "%i entries per LQ | %i entries per SQ",
136 maxLQEntries,maxSQEntries);
137
138 } else {
139 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
140 "Partitioned, Threshold}");
141 }
142
143 //Initialize LSQs
144 for (int tid=0; tid < numThreads; tid++) {
145 thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
146 thread[tid].setDcachePort(&dcachePort);
147 }
148 }
149
150
151 template<class Impl>
152 std::string
153 LSQ<Impl>::name() const
154 {
155 return iewStage->name() + ".lsq";
156 }
157
158 template<class Impl>
159 void
160 LSQ<Impl>::regStats()
161 {
162 //Initialize LSQs
163 for (int tid=0; tid < numThreads; tid++) {
164 thread[tid].regStats();
165 }
166 }
167
168 template<class Impl>
169 void
170 LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
171 {
172 activeThreads = at_ptr;
173 assert(activeThreads != 0);
174 }
175
176 template<class Impl>
177 void
178 LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
179 {
180 cpu = cpu_ptr;
181
182 dcachePort.setName(name());
183
184 for (int tid=0; tid < numThreads; tid++) {
185 thread[tid].setCPU(cpu_ptr);
186 }
187 }
188
189 template<class Impl>
190 void
191 LSQ<Impl>::setIEW(IEW *iew_ptr)
192 {
193 iewStage = iew_ptr;
194
195 for (int tid=0; tid < numThreads; tid++) {
196 thread[tid].setIEW(iew_ptr);
197 }
198 }
199
200 template <class Impl>
201 void
202 LSQ<Impl>::switchOut()
203 {
204 for (int tid = 0; tid < numThreads; tid++) {
205 thread[tid].switchOut();
206 }
207 }
208
209 template <class Impl>
210 void
211 LSQ<Impl>::takeOverFrom()
212 {
213 for (int tid = 0; tid < numThreads; tid++) {
214 thread[tid].takeOverFrom();
215 }
216 }
217
218 template <class Impl>
219 int
220 LSQ<Impl>::entryAmount(int num_threads)
221 {
222 if (lsqPolicy == Partitioned) {
223 return LQEntries / num_threads;
224 } else {
225 return 0;
226 }
227 }
228
229 template <class Impl>
230 void
231 LSQ<Impl>::resetEntries()
232 {
233 if (lsqPolicy != Dynamic || numThreads > 1) {
234 int active_threads = (*activeThreads).size();
235
236 std::list<unsigned>::iterator threads = (*activeThreads).begin();
237 std::list<unsigned>::iterator list_end = (*activeThreads).end();
238
239 int maxEntries;
240
241 if (lsqPolicy == Partitioned) {
242 maxEntries = LQEntries / active_threads;
243 } else if (lsqPolicy == Threshold && active_threads == 1) {
244 maxEntries = LQEntries;
245 } else {
246 maxEntries = LQEntries;
247 }
248
249 while (threads != list_end) {
250 resizeEntries(maxEntries,*threads++);
251 }
252 }
253 }
254
255 template<class Impl>
256 void
257 LSQ<Impl>::removeEntries(unsigned tid)
258 {
259 thread[tid].clearLQ();
260 thread[tid].clearSQ();
261 }
262
263 template<class Impl>
264 void
265 LSQ<Impl>::resizeEntries(unsigned size,unsigned tid)
266 {
267 thread[tid].resizeLQ(size);
268 thread[tid].resizeSQ(size);
269 }
270
271 template<class Impl>
272 void
273 LSQ<Impl>::tick()
274 {
275 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
276
277 while (active_threads != (*activeThreads).end()) {
278 unsigned tid = *active_threads++;
279
280 thread[tid].tick();
281 }
282 }
283
284 template<class Impl>
285 void
286 LSQ<Impl>::insertLoad(DynInstPtr &load_inst)
287 {
288 unsigned tid = load_inst->threadNumber;
289
290 thread[tid].insertLoad(load_inst);
291 }
292
293 template<class Impl>
294 void
295 LSQ<Impl>::insertStore(DynInstPtr &store_inst)
296 {
297 unsigned tid = store_inst->threadNumber;
298
299 thread[tid].insertStore(store_inst);
300 }
301
302 template<class Impl>
303 Fault
304 LSQ<Impl>::executeLoad(DynInstPtr &inst)
305 {
306 unsigned tid = inst->threadNumber;
307
308 return thread[tid].executeLoad(inst);
309 }
310
311 template<class Impl>
312 Fault
313 LSQ<Impl>::executeStore(DynInstPtr &inst)
314 {
315 unsigned tid = inst->threadNumber;
316
317 return thread[tid].executeStore(inst);
318 }
319
320 template<class Impl>
321 void
322 LSQ<Impl>::writebackStores()
323 {
324 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
325
326 while (active_threads != (*activeThreads).end()) {
327 unsigned tid = *active_threads++;
328
329 if (numStoresToWB(tid) > 0) {
330 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
331 "available for Writeback.\n", tid, numStoresToWB(tid));
332 }
333
334 thread[tid].writebackStores();
335 }
336 }
337
338 template<class Impl>
339 bool
340 LSQ<Impl>::violation()
341 {
342 /* Answers: Does Anybody Have a Violation?*/
343 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
344
345 while (active_threads != (*activeThreads).end()) {
346 unsigned tid = *active_threads++;
347 if (thread[tid].violation())
348 return true;
349 }
350
351 return false;
352 }
353
354 template<class Impl>
355 int
356 LSQ<Impl>::getCount()
357 {
358 unsigned total = 0;
359
360 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
361
362 while (active_threads != (*activeThreads).end()) {
363 unsigned tid = *active_threads++;
364 total += getCount(tid);
365 }
366
367 return total;
368 }
369
370 template<class Impl>
371 int
372 LSQ<Impl>::numLoads()
373 {
374 unsigned total = 0;
375
376 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
377
378 while (active_threads != (*activeThreads).end()) {
379 unsigned tid = *active_threads++;
380 total += numLoads(tid);
381 }
382
383 return total;
384 }
385
386 template<class Impl>
387 int
388 LSQ<Impl>::numStores()
389 {
390 unsigned total = 0;
391
392 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
393
394 while (active_threads != (*activeThreads).end()) {
395 unsigned tid = *active_threads++;
396 total += thread[tid].numStores();
397 }
398
399 return total;
400 }
401
402 template<class Impl>
403 int
404 LSQ<Impl>::numLoadsReady()
405 {
406 unsigned total = 0;
407
408 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
409
410 while (active_threads != (*activeThreads).end()) {
411 unsigned tid = *active_threads++;
412 total += thread[tid].numLoadsReady();
413 }
414
415 return total;
416 }
417
418 template<class Impl>
419 unsigned
420 LSQ<Impl>::numFreeEntries()
421 {
422 unsigned total = 0;
423
424 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
425
426 while (active_threads != (*activeThreads).end()) {
427 unsigned tid = *active_threads++;
428 total += thread[tid].numFreeEntries();
429 }
430
431 return total;
432 }
433
434 template<class Impl>
435 unsigned
436 LSQ<Impl>::numFreeEntries(unsigned tid)
437 {
438 //if( lsqPolicy == Dynamic )
439 //return numFreeEntries();
440 //else
441 return thread[tid].numFreeEntries();
442 }
443
444 template<class Impl>
445 bool
446 LSQ<Impl>::isFull()
447 {
448 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
449
450 while (active_threads != (*activeThreads).end()) {
451 unsigned tid = *active_threads++;
452 if (! (thread[tid].lqFull() || thread[tid].sqFull()) )
453 return false;
454 }
455
456 return true;
457 }
458
459 template<class Impl>
460 bool
461 LSQ<Impl>::isFull(unsigned tid)
462 {
463 //@todo: Change to Calculate All Entries for
464 //Dynamic Policy
465 if( lsqPolicy == Dynamic )
466 return isFull();
467 else
468 return thread[tid].lqFull() || thread[tid].sqFull();
469 }
470
471 template<class Impl>
472 bool
473 LSQ<Impl>::lqFull()
474 {
475 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
476
477 while (active_threads != (*activeThreads).end()) {
478 unsigned tid = *active_threads++;
479 if (!thread[tid].lqFull())
480 return false;
481 }
482
483 return true;
484 }
485
486 template<class Impl>
487 bool
488 LSQ<Impl>::lqFull(unsigned tid)
489 {
490 //@todo: Change to Calculate All Entries for
491 //Dynamic Policy
492 if( lsqPolicy == Dynamic )
493 return lqFull();
494 else
495 return thread[tid].lqFull();
496 }
497
498 template<class Impl>
499 bool
500 LSQ<Impl>::sqFull()
501 {
502 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
503
504 while (active_threads != (*activeThreads).end()) {
505 unsigned tid = *active_threads++;
506 if (!sqFull(tid))
507 return false;
508 }
509
510 return true;
511 }
512
513 template<class Impl>
514 bool
515 LSQ<Impl>::sqFull(unsigned tid)
516 {
517 //@todo: Change to Calculate All Entries for
518 //Dynamic Policy
519 if( lsqPolicy == Dynamic )
520 return sqFull();
521 else
522 return thread[tid].sqFull();
523 }
524
525 template<class Impl>
526 bool
527 LSQ<Impl>::isStalled()
528 {
529 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
530
531 while (active_threads != (*activeThreads).end()) {
532 unsigned tid = *active_threads++;
533 if (!thread[tid].isStalled())
534 return false;
535 }
536
537 return true;
538 }
539
540 template<class Impl>
541 bool
542 LSQ<Impl>::isStalled(unsigned tid)
543 {
544 if( lsqPolicy == Dynamic )
545 return isStalled();
546 else
547 return thread[tid].isStalled();
548 }
549
550 template<class Impl>
551 bool
552 LSQ<Impl>::hasStoresToWB()
553 {
554 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
555
556 if ((*activeThreads).empty())
557 return false;
558
559 while (active_threads != (*activeThreads).end()) {
560 unsigned tid = *active_threads++;
561 if (!hasStoresToWB(tid))
562 return false;
563 }
564
565 return true;
566 }
567
568 template<class Impl>
569 bool
570 LSQ<Impl>::willWB()
571 {
572 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
573
574 while (active_threads != (*activeThreads).end()) {
575 unsigned tid = *active_threads++;
576 if (!willWB(tid))
577 return false;
578 }
579
580 return true;
581 }
582
583 template<class Impl>
584 void
585 LSQ<Impl>::dumpInsts()
586 {
587 std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
588
589 while (active_threads != (*activeThreads).end()) {
590 unsigned tid = *active_threads++;
591 thread[tid].dumpInsts();
592 }
593 }