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