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