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