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