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