lsq_impl.hh revision 2698:d5f35d41e017
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
139template <class Impl>
140void
141LSQ<Impl>::switchOut()
142{
143    for (int tid = 0; tid < numThreads; tid++) {
144        thread[tid].switchOut();
145    }
146}
147
148template <class Impl>
149void
150LSQ<Impl>::takeOverFrom()
151{
152    for (int tid = 0; tid < numThreads; tid++) {
153        thread[tid].takeOverFrom();
154    }
155}
156
157template <class Impl>
158int
159LSQ<Impl>::entryAmount(int num_threads)
160{
161    if (lsqPolicy == Partitioned) {
162        return LQEntries / num_threads;
163    } else {
164        return 0;
165    }
166}
167
168template <class Impl>
169void
170LSQ<Impl>::resetEntries()
171{
172    if (lsqPolicy != Dynamic || numThreads > 1) {
173        int active_threads = (*activeThreads).size();
174
175        list<unsigned>::iterator threads  = (*activeThreads).begin();
176        list<unsigned>::iterator list_end = (*activeThreads).end();
177
178        int maxEntries;
179
180        if (lsqPolicy == Partitioned) {
181            maxEntries = LQEntries / active_threads;
182        } else if (lsqPolicy == Threshold && active_threads == 1) {
183            maxEntries = LQEntries;
184        } else {
185            maxEntries = LQEntries;
186        }
187
188        while (threads != list_end) {
189            resizeEntries(maxEntries,*threads++);
190        }
191    }
192}
193
194template<class Impl>
195void
196LSQ<Impl>::removeEntries(unsigned tid)
197{
198    thread[tid].clearLQ();
199    thread[tid].clearSQ();
200}
201
202template<class Impl>
203void
204LSQ<Impl>::resizeEntries(unsigned size,unsigned tid)
205{
206    thread[tid].resizeLQ(size);
207    thread[tid].resizeSQ(size);
208}
209
210template<class Impl>
211void
212LSQ<Impl>::tick()
213{
214    list<unsigned>::iterator active_threads = (*activeThreads).begin();
215
216    while (active_threads != (*activeThreads).end()) {
217        unsigned tid = *active_threads++;
218
219        thread[tid].tick();
220    }
221}
222
223template<class Impl>
224void
225LSQ<Impl>::insertLoad(DynInstPtr &load_inst)
226{
227    unsigned tid = load_inst->threadNumber;
228
229    thread[tid].insertLoad(load_inst);
230}
231
232template<class Impl>
233void
234LSQ<Impl>::insertStore(DynInstPtr &store_inst)
235{
236    unsigned tid = store_inst->threadNumber;
237
238    thread[tid].insertStore(store_inst);
239}
240
241template<class Impl>
242Fault
243LSQ<Impl>::executeLoad(DynInstPtr &inst)
244{
245    unsigned tid = inst->threadNumber;
246
247    return thread[tid].executeLoad(inst);
248}
249
250template<class Impl>
251Fault
252LSQ<Impl>::executeStore(DynInstPtr &inst)
253{
254    unsigned tid = inst->threadNumber;
255
256    return thread[tid].executeStore(inst);
257}
258
259template<class Impl>
260void
261LSQ<Impl>::writebackStores()
262{
263    list<unsigned>::iterator active_threads = (*activeThreads).begin();
264
265    while (active_threads != (*activeThreads).end()) {
266        unsigned tid = *active_threads++;
267
268        if (numStoresToWB(tid) > 0) {
269            DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
270                "available for Writeback.\n", tid, numStoresToWB(tid));
271        }
272
273        thread[tid].writebackStores();
274    }
275}
276
277template<class Impl>
278bool
279LSQ<Impl>::violation()
280{
281    /* Answers: Does Anybody Have a Violation?*/
282    list<unsigned>::iterator active_threads = (*activeThreads).begin();
283
284    while (active_threads != (*activeThreads).end()) {
285        unsigned tid = *active_threads++;
286        if (thread[tid].violation())
287            return true;
288    }
289
290    return false;
291}
292
293template<class Impl>
294int
295LSQ<Impl>::getCount()
296{
297    unsigned total = 0;
298
299    list<unsigned>::iterator active_threads = (*activeThreads).begin();
300
301    while (active_threads != (*activeThreads).end()) {
302        unsigned tid = *active_threads++;
303        total += getCount(tid);
304    }
305
306    return total;
307}
308
309template<class Impl>
310int
311LSQ<Impl>::numLoads()
312{
313    unsigned total = 0;
314
315    list<unsigned>::iterator active_threads = (*activeThreads).begin();
316
317    while (active_threads != (*activeThreads).end()) {
318        unsigned tid = *active_threads++;
319        total += numLoads(tid);
320    }
321
322    return total;
323}
324
325template<class Impl>
326int
327LSQ<Impl>::numStores()
328{
329    unsigned total = 0;
330
331    list<unsigned>::iterator active_threads = (*activeThreads).begin();
332
333    while (active_threads != (*activeThreads).end()) {
334        unsigned tid = *active_threads++;
335        total += thread[tid].numStores();
336    }
337
338    return total;
339}
340
341template<class Impl>
342int
343LSQ<Impl>::numLoadsReady()
344{
345    unsigned total = 0;
346
347    list<unsigned>::iterator active_threads = (*activeThreads).begin();
348
349    while (active_threads != (*activeThreads).end()) {
350        unsigned tid = *active_threads++;
351        total += thread[tid].numLoadsReady();
352    }
353
354    return total;
355}
356
357template<class Impl>
358unsigned
359LSQ<Impl>::numFreeEntries()
360{
361    unsigned total = 0;
362
363    list<unsigned>::iterator active_threads = (*activeThreads).begin();
364
365    while (active_threads != (*activeThreads).end()) {
366        unsigned tid = *active_threads++;
367        total += thread[tid].numFreeEntries();
368    }
369
370    return total;
371}
372
373template<class Impl>
374unsigned
375LSQ<Impl>::numFreeEntries(unsigned tid)
376{
377    //if( lsqPolicy == Dynamic )
378    //return numFreeEntries();
379    //else
380        return thread[tid].numFreeEntries();
381}
382
383template<class Impl>
384bool
385LSQ<Impl>::isFull()
386{
387    list<unsigned>::iterator active_threads = (*activeThreads).begin();
388
389    while (active_threads != (*activeThreads).end()) {
390        unsigned tid = *active_threads++;
391        if (! (thread[tid].lqFull() || thread[tid].sqFull()) )
392            return false;
393    }
394
395    return true;
396}
397
398template<class Impl>
399bool
400LSQ<Impl>::isFull(unsigned tid)
401{
402    //@todo: Change to Calculate All Entries for
403    //Dynamic Policy
404    if( lsqPolicy == Dynamic )
405        return isFull();
406    else
407        return thread[tid].lqFull() || thread[tid].sqFull();
408}
409
410template<class Impl>
411bool
412LSQ<Impl>::lqFull()
413{
414    list<unsigned>::iterator active_threads = (*activeThreads).begin();
415
416    while (active_threads != (*activeThreads).end()) {
417        unsigned tid = *active_threads++;
418        if (!thread[tid].lqFull())
419            return false;
420    }
421
422    return true;
423}
424
425template<class Impl>
426bool
427LSQ<Impl>::lqFull(unsigned tid)
428{
429    //@todo: Change to Calculate All Entries for
430    //Dynamic Policy
431    if( lsqPolicy == Dynamic )
432        return lqFull();
433    else
434        return thread[tid].lqFull();
435}
436
437template<class Impl>
438bool
439LSQ<Impl>::sqFull()
440{
441    list<unsigned>::iterator active_threads = (*activeThreads).begin();
442
443    while (active_threads != (*activeThreads).end()) {
444        unsigned tid = *active_threads++;
445        if (!sqFull(tid))
446            return false;
447    }
448
449    return true;
450}
451
452template<class Impl>
453bool
454LSQ<Impl>::sqFull(unsigned tid)
455{
456     //@todo: Change to Calculate All Entries for
457    //Dynamic Policy
458    if( lsqPolicy == Dynamic )
459        return sqFull();
460    else
461        return thread[tid].sqFull();
462}
463
464template<class Impl>
465bool
466LSQ<Impl>::isStalled()
467{
468    list<unsigned>::iterator active_threads = (*activeThreads).begin();
469
470    while (active_threads != (*activeThreads).end()) {
471        unsigned tid = *active_threads++;
472        if (!thread[tid].isStalled())
473            return false;
474    }
475
476    return true;
477}
478
479template<class Impl>
480bool
481LSQ<Impl>::isStalled(unsigned tid)
482{
483    if( lsqPolicy == Dynamic )
484        return isStalled();
485    else
486        return thread[tid].isStalled();
487}
488
489template<class Impl>
490bool
491LSQ<Impl>::hasStoresToWB()
492{
493    list<unsigned>::iterator active_threads = (*activeThreads).begin();
494
495    while (active_threads != (*activeThreads).end()) {
496        unsigned tid = *active_threads++;
497        if (!hasStoresToWB(tid))
498            return false;
499    }
500
501    return true;
502}
503
504template<class Impl>
505bool
506LSQ<Impl>::willWB()
507{
508    list<unsigned>::iterator active_threads = (*activeThreads).begin();
509
510    while (active_threads != (*activeThreads).end()) {
511        unsigned tid = *active_threads++;
512        if (!willWB(tid))
513            return false;
514    }
515
516    return true;
517}
518
519template<class Impl>
520void
521LSQ<Impl>::dumpInsts()
522{
523    list<unsigned>::iterator active_threads = (*activeThreads).begin();
524
525    while (active_threads != (*activeThreads).end()) {
526        unsigned tid = *active_threads++;
527        thread[tid].dumpInsts();
528    }
529}
530