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