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