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