lsq_impl.hh revision 2329
17090SN/A/*
27090SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan
37090SN/A * All rights reserved.
47090SN/A *
57090SN/A * Redistribution and use in source and binary forms, with or without
67090SN/A * modification, are permitted provided that the following conditions are
77090SN/A * met: redistributions of source code must retain the above copyright
87090SN/A * notice, this list of conditions and the following disclaimer;
97090SN/A * redistributions in binary form must reproduce the above copyright
107090SN/A * notice, this list of conditions and the following disclaimer in the
117090SN/A * documentation and/or other materials provided with the distribution;
127090SN/A * neither the name of the copyright holders nor the names of its
134486SN/A * contributors may be used to endorse or promote products derived from
144486SN/A * this software without specific prior written permission.
154486SN/A *
164486SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
174486SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
184486SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
194486SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204486SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
214486SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224486SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234486SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244486SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254486SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264486SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274486SN/A */
284486SN/A
294486SN/A#include <algorithm>
304486SN/A#include <string>
314486SN/A
324486SN/A#include "cpu/o3/lsq.hh"
334486SN/A
344486SN/Ausing namespace std;
354486SN/A
364486SN/Atemplate <class Impl>
374486SN/ALSQ<Impl>::LSQ(Params *params)
384486SN/A    : LQEntries(params->LQEntries), SQEntries(params->SQEntries),
397584SAli.Saidi@arm.com      numThreads(params->numberOfThreads)
407584SAli.Saidi@arm.com{
417754SWilliam.Wang@arm.com    DPRINTF(LSQ, "Creating LSQ object.\n");
424486SN/A
433630SN/A    //**********************************************/
443630SN/A    //************ Handle SMT Parameters ***********/
457587SAli.Saidi@arm.com    //**********************************************/
468212SAli.Saidi@ARM.com    string policy = params->smtLSQPolicy;
475478SN/A
485478SN/A    //Convert string to lowercase
497584SAli.Saidi@arm.com    std::transform(policy.begin(), policy.end(), policy.begin(),
503630SN/A                   (int(*)(int)) tolower);
517584SAli.Saidi@arm.com
527584SAli.Saidi@arm.com    //Figure out fetch policy
537584SAli.Saidi@arm.com    if (policy == "dynamic") {
547584SAli.Saidi@arm.com        lsqPolicy = Dynamic;
553898SN/A
567950SAli.Saidi@ARM.com        maxLQEntries = LQEntries;
577950SAli.Saidi@ARM.com        maxSQEntries = SQEntries;
587950SAli.Saidi@ARM.com
597950SAli.Saidi@ARM.com        DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
607950SAli.Saidi@ARM.com
617950SAli.Saidi@ARM.com    } else if (policy == "partitioned") {
627950SAli.Saidi@ARM.com        lsqPolicy = Partitioned;
637950SAli.Saidi@ARM.com
647587SAli.Saidi@arm.com        //@todo:make work if part_amt doesnt divide evenly.
657587SAli.Saidi@arm.com        maxLQEntries = LQEntries / numThreads;
667587SAli.Saidi@arm.com        maxSQEntries = SQEntries / numThreads;
677753SWilliam.Wang@arm.com
687753SWilliam.Wang@arm.com        DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
697753SWilliam.Wang@arm.com                "%i entries per LQ | %i entries per SQ",
707753SWilliam.Wang@arm.com                maxLQEntries,maxSQEntries);
717587SAli.Saidi@arm.com
727587SAli.Saidi@arm.com    } else if (policy == "threshold") {
738282SAli.Saidi@ARM.com        lsqPolicy = Threshold;
748282SAli.Saidi@ARM.com
758282SAli.Saidi@ARM.com        assert(params->smtLSQThreshold > LQEntries);
767584SAli.Saidi@arm.com        assert(params->smtLSQThreshold > SQEntries);
777584SAli.Saidi@arm.com
787584SAli.Saidi@arm.com        //Divide up by threshold amount
797584SAli.Saidi@arm.com        //@todo: Should threads check the max and the total
807584SAli.Saidi@arm.com        //amount of the LSQ
817584SAli.Saidi@arm.com        maxLQEntries  = params->smtLSQThreshold;
827584SAli.Saidi@arm.com        maxSQEntries  = params->smtLSQThreshold;
837584SAli.Saidi@arm.com
847584SAli.Saidi@arm.com        DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
857584SAli.Saidi@arm.com                "%i entries per LQ | %i entries per SQ",
867584SAli.Saidi@arm.com                maxLQEntries,maxSQEntries);
877584SAli.Saidi@arm.com
887584SAli.Saidi@arm.com    } else {
897584SAli.Saidi@arm.com        assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
907584SAli.Saidi@arm.com                    "Partitioned, Threshold}");
917584SAli.Saidi@arm.com    }
927584SAli.Saidi@arm.com
937584SAli.Saidi@arm.com    //Initialize LSQs
947584SAli.Saidi@arm.com    for (int tid=0; tid < numThreads; tid++) {
957584SAli.Saidi@arm.com        thread[tid].init(params, maxLQEntries, maxSQEntries, tid);
967584SAli.Saidi@arm.com    }
977584SAli.Saidi@arm.com}
987584SAli.Saidi@arm.com
997584SAli.Saidi@arm.com
1007584SAli.Saidi@arm.comtemplate<class Impl>
1017584SAli.Saidi@arm.comstd::string
1027584SAli.Saidi@arm.comLSQ<Impl>::name() const
1037584SAli.Saidi@arm.com{
1047584SAli.Saidi@arm.com    return iewStage->name() + ".lsq";
1057584SAli.Saidi@arm.com}
1067584SAli.Saidi@arm.com
1077584SAli.Saidi@arm.comtemplate<class Impl>
1087584SAli.Saidi@arm.comvoid
1097950SAli.Saidi@ARM.comLSQ<Impl>::setActiveThreads(list<unsigned> *at_ptr)
1107754SWilliam.Wang@arm.com{
1117950SAli.Saidi@ARM.com    activeThreads = at_ptr;
1127950SAli.Saidi@ARM.com    assert(activeThreads != 0);
1137950SAli.Saidi@ARM.com}
1147754SWilliam.Wang@arm.com
1157754SWilliam.Wang@arm.comtemplate<class Impl>
1167753SWilliam.Wang@arm.comvoid
1177753SWilliam.Wang@arm.comLSQ<Impl>::setCPU(FullCPU *cpu_ptr)
1187753SWilliam.Wang@arm.com{
1197950SAli.Saidi@ARM.com    cpu = cpu_ptr;
1207753SWilliam.Wang@arm.com
1217753SWilliam.Wang@arm.com    for (int tid=0; tid < numThreads; tid++) {
1227584SAli.Saidi@arm.com        thread[tid].setCPU(cpu_ptr);
1237584SAli.Saidi@arm.com    }
1243630SN/A}
1253630SN/A
1267753SWilliam.Wang@arm.comtemplate<class Impl>
1277753SWilliam.Wang@arm.comvoid
1287753SWilliam.Wang@arm.comLSQ<Impl>::setIEW(IEW *iew_ptr)
1297584SAli.Saidi@arm.com{
1307584SAli.Saidi@arm.com    iewStage = iew_ptr;
1317584SAli.Saidi@arm.com
1327584SAli.Saidi@arm.com    for (int tid=0; tid < numThreads; tid++) {
1337584SAli.Saidi@arm.com        thread[tid].setIEW(iew_ptr);
1347584SAli.Saidi@arm.com    }
1357753SWilliam.Wang@arm.com}
1367754SWilliam.Wang@arm.com
1377950SAli.Saidi@ARM.com#if 0
1388282SAli.Saidi@ARM.comtemplate<class Impl>
1398212SAli.Saidi@ARM.comvoid
1408212SAli.Saidi@ARM.comLSQ<Impl>::setPageTable(PageTable *pt_ptr)
1418212SAli.Saidi@ARM.com{
1428212SAli.Saidi@ARM.com    for (int tid=0; tid < numThreads; tid++) {
1438212SAli.Saidi@ARM.com        thread[tid].setPageTable(pt_ptr);
1448212SAli.Saidi@ARM.com    }
1457584SAli.Saidi@arm.com}
1467731SAli.Saidi@ARM.com#endif
1477696SAli.Saidi@ARM.com
1487696SAli.Saidi@ARM.comtemplate <class Impl>
1497696SAli.Saidi@ARM.comvoid
1507696SAli.Saidi@ARM.comLSQ<Impl>::switchOut()
1517696SAli.Saidi@ARM.com{
1527696SAli.Saidi@ARM.com    for (int tid = 0; tid < numThreads; tid++) {
1537696SAli.Saidi@ARM.com        thread[tid].switchOut();
1547696SAli.Saidi@ARM.com    }
1557696SAli.Saidi@ARM.com}
1567696SAli.Saidi@ARM.com
1577696SAli.Saidi@ARM.comtemplate <class Impl>
1587696SAli.Saidi@ARM.comvoid
1597696SAli.Saidi@ARM.comLSQ<Impl>::takeOverFrom()
1607696SAli.Saidi@ARM.com{
1617696SAli.Saidi@ARM.com    for (int tid = 0; tid < numThreads; tid++) {
1627696SAli.Saidi@ARM.com        thread[tid].takeOverFrom();
1637696SAli.Saidi@ARM.com    }
1647696SAli.Saidi@ARM.com}
1657696SAli.Saidi@ARM.com
1667696SAli.Saidi@ARM.comtemplate <class Impl>
1677696SAli.Saidi@ARM.comint
1687696SAli.Saidi@ARM.comLSQ<Impl>::entryAmount(int num_threads)
1698282SAli.Saidi@ARM.com{
1707696SAli.Saidi@ARM.com    if (lsqPolicy == Partitioned) {
1717696SAli.Saidi@ARM.com        return LQEntries / num_threads;
1727696SAli.Saidi@ARM.com    } else {
1737696SAli.Saidi@ARM.com        return 0;
1747696SAli.Saidi@ARM.com    }
1757696SAli.Saidi@ARM.com}
1767696SAli.Saidi@ARM.com
1777696SAli.Saidi@ARM.comtemplate <class Impl>
1787696SAli.Saidi@ARM.comvoid
1797753SWilliam.Wang@arm.comLSQ<Impl>::resetEntries()
1807754SWilliam.Wang@arm.com{
1817754SWilliam.Wang@arm.com    if (lsqPolicy != Dynamic || numThreads > 1) {
1828212SAli.Saidi@ARM.com        int active_threads = (*activeThreads).size();
1837696SAli.Saidi@ARM.com
1847696SAli.Saidi@ARM.com        list<unsigned>::iterator threads  = (*activeThreads).begin();
1857696SAli.Saidi@ARM.com        list<unsigned>::iterator list_end = (*activeThreads).end();
1867696SAli.Saidi@ARM.com
1877696SAli.Saidi@ARM.com        int maxEntries;
1887696SAli.Saidi@ARM.com
1897696SAli.Saidi@ARM.com        if (lsqPolicy == Partitioned) {
1907696SAli.Saidi@ARM.com            maxEntries = LQEntries / active_threads;
1917696SAli.Saidi@ARM.com        } else if (lsqPolicy == Threshold && active_threads == 1) {
1927696SAli.Saidi@ARM.com            maxEntries = LQEntries;
1937696SAli.Saidi@ARM.com        } else {
1947696SAli.Saidi@ARM.com            maxEntries = LQEntries;
1957696SAli.Saidi@ARM.com        }
1967696SAli.Saidi@ARM.com
1977696SAli.Saidi@ARM.com        while (threads != list_end) {
1987696SAli.Saidi@ARM.com            resizeEntries(maxEntries,*threads++);
1997696SAli.Saidi@ARM.com        }
2007754SWilliam.Wang@arm.com    }
2017754SWilliam.Wang@arm.com}
2027754SWilliam.Wang@arm.com
2037696SAli.Saidi@ARM.comtemplate<class Impl>
2047696SAli.Saidi@ARM.comvoid
2057696SAli.Saidi@ARM.comLSQ<Impl>::removeEntries(unsigned tid)
2067696SAli.Saidi@ARM.com{
2077696SAli.Saidi@ARM.com    thread[tid].clearLQ();
2087696SAli.Saidi@ARM.com    thread[tid].clearSQ();
2097754SWilliam.Wang@arm.com}
2107754SWilliam.Wang@arm.com
2117950SAli.Saidi@ARM.comtemplate<class Impl>
2127696SAli.Saidi@ARM.comvoid
2137696SAli.Saidi@ARM.comLSQ<Impl>::resizeEntries(unsigned size,unsigned tid)
2147584SAli.Saidi@arm.com{
2157584SAli.Saidi@arm.com    thread[tid].resizeLQ(size);
2167584SAli.Saidi@arm.com    thread[tid].resizeSQ(size);
2177584SAli.Saidi@arm.com}
2187584SAli.Saidi@arm.com
2197584SAli.Saidi@arm.comtemplate<class Impl>
2207584SAli.Saidi@arm.comvoid
2217584SAli.Saidi@arm.comLSQ<Impl>::tick()
2227584SAli.Saidi@arm.com{
2237584SAli.Saidi@arm.com    list<unsigned>::iterator active_threads = (*activeThreads).begin();
2247584SAli.Saidi@arm.com
2257584SAli.Saidi@arm.com    while (active_threads != (*activeThreads).end()) {
2267584SAli.Saidi@arm.com        unsigned tid = *active_threads++;
2277584SAli.Saidi@arm.com
2287584SAli.Saidi@arm.com        thread[tid].tick();
2297584SAli.Saidi@arm.com    }
2307584SAli.Saidi@arm.com}
2317584SAli.Saidi@arm.com
2324104SN/Atemplate<class Impl>
2334104SN/Avoid
2347584SAli.Saidi@arm.comLSQ<Impl>::insertLoad(DynInstPtr &load_inst)
2357584SAli.Saidi@arm.com{
2364104SN/A    unsigned tid = load_inst->threadNumber;
2373630SN/A
2383630SN/A    thread[tid].insertLoad(load_inst);
2393630SN/A}
2403630SN/A
2417584SAli.Saidi@arm.comtemplate<class Impl>
2427584SAli.Saidi@arm.comvoid
2437584SAli.Saidi@arm.comLSQ<Impl>::insertStore(DynInstPtr &store_inst)
2447584SAli.Saidi@arm.com{
2457753SWilliam.Wang@arm.com    unsigned tid = store_inst->threadNumber;
2467754SWilliam.Wang@arm.com
2477754SWilliam.Wang@arm.com    thread[tid].insertStore(store_inst);
2487584SAli.Saidi@arm.com}
2497584SAli.Saidi@arm.com
2507584SAli.Saidi@arm.comtemplate<class Impl>
2517584SAli.Saidi@arm.comFault
2527584SAli.Saidi@arm.comLSQ<Impl>::executeLoad(DynInstPtr &inst)
2537584SAli.Saidi@arm.com{
2547584SAli.Saidi@arm.com    unsigned tid = inst->threadNumber;
2557584SAli.Saidi@arm.com
2567584SAli.Saidi@arm.com    return thread[tid].executeLoad(inst);
2577584SAli.Saidi@arm.com}
2587584SAli.Saidi@arm.com
2597584SAli.Saidi@arm.comtemplate<class Impl>
2607584SAli.Saidi@arm.comFault
2617584SAli.Saidi@arm.comLSQ<Impl>::executeStore(DynInstPtr &inst)
2627584SAli.Saidi@arm.com{
2637584SAli.Saidi@arm.com    unsigned tid = inst->threadNumber;
264
265    return thread[tid].executeStore(inst);
266}
267
268template<class Impl>
269void
270LSQ<Impl>::writebackStores()
271{
272    list<unsigned>::iterator active_threads = (*activeThreads).begin();
273
274    while (active_threads != (*activeThreads).end()) {
275        unsigned tid = *active_threads++;
276
277        if (numStoresToWB(tid) > 0) {
278            DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
279                "available for Writeback.\n", tid, numStoresToWB(tid));
280        }
281
282        thread[tid].writebackStores();
283    }
284}
285
286template<class Impl>
287bool
288LSQ<Impl>::violation()
289{
290    /* Answers: Does Anybody Have a Violation?*/
291    list<unsigned>::iterator active_threads = (*activeThreads).begin();
292
293    while (active_threads != (*activeThreads).end()) {
294        unsigned tid = *active_threads++;
295        if (thread[tid].violation())
296            return true;
297    }
298
299    return false;
300}
301
302template<class Impl>
303int
304LSQ<Impl>::getCount()
305{
306    unsigned total = 0;
307
308    list<unsigned>::iterator active_threads = (*activeThreads).begin();
309
310    while (active_threads != (*activeThreads).end()) {
311        unsigned tid = *active_threads++;
312        total += getCount(tid);
313    }
314
315    return total;
316}
317
318template<class Impl>
319int
320LSQ<Impl>::numLoads()
321{
322    unsigned total = 0;
323
324    list<unsigned>::iterator active_threads = (*activeThreads).begin();
325
326    while (active_threads != (*activeThreads).end()) {
327        unsigned tid = *active_threads++;
328        total += numLoads(tid);
329    }
330
331    return total;
332}
333
334template<class Impl>
335int
336LSQ<Impl>::numStores()
337{
338    unsigned total = 0;
339
340    list<unsigned>::iterator active_threads = (*activeThreads).begin();
341
342    while (active_threads != (*activeThreads).end()) {
343        unsigned tid = *active_threads++;
344        total += thread[tid].numStores();
345    }
346
347    return total;
348}
349
350template<class Impl>
351int
352LSQ<Impl>::numLoadsReady()
353{
354    unsigned total = 0;
355
356    list<unsigned>::iterator active_threads = (*activeThreads).begin();
357
358    while (active_threads != (*activeThreads).end()) {
359        unsigned tid = *active_threads++;
360        total += thread[tid].numLoadsReady();
361    }
362
363    return total;
364}
365
366template<class Impl>
367unsigned
368LSQ<Impl>::numFreeEntries()
369{
370    unsigned total = 0;
371
372    list<unsigned>::iterator active_threads = (*activeThreads).begin();
373
374    while (active_threads != (*activeThreads).end()) {
375        unsigned tid = *active_threads++;
376        total += thread[tid].numFreeEntries();
377    }
378
379    return total;
380}
381
382template<class Impl>
383unsigned
384LSQ<Impl>::numFreeEntries(unsigned tid)
385{
386    //if( lsqPolicy == Dynamic )
387    //return numFreeEntries();
388    //else
389        return thread[tid].numFreeEntries();
390}
391
392template<class Impl>
393bool
394LSQ<Impl>::isFull()
395{
396    list<unsigned>::iterator active_threads = (*activeThreads).begin();
397
398    while (active_threads != (*activeThreads).end()) {
399        unsigned tid = *active_threads++;
400        if (! (thread[tid].lqFull() || thread[tid].sqFull()) )
401            return false;
402    }
403
404    return true;
405}
406
407template<class Impl>
408bool
409LSQ<Impl>::isFull(unsigned tid)
410{
411    //@todo: Change to Calculate All Entries for
412    //Dynamic Policy
413    if( lsqPolicy == Dynamic )
414        return isFull();
415    else
416        return thread[tid].lqFull() || thread[tid].sqFull();
417}
418
419template<class Impl>
420bool
421LSQ<Impl>::lqFull()
422{
423    list<unsigned>::iterator active_threads = (*activeThreads).begin();
424
425    while (active_threads != (*activeThreads).end()) {
426        unsigned tid = *active_threads++;
427        if (!thread[tid].lqFull())
428            return false;
429    }
430
431    return true;
432}
433
434template<class Impl>
435bool
436LSQ<Impl>::lqFull(unsigned tid)
437{
438    //@todo: Change to Calculate All Entries for
439    //Dynamic Policy
440    if( lsqPolicy == Dynamic )
441        return lqFull();
442    else
443        return thread[tid].lqFull();
444}
445
446template<class Impl>
447bool
448LSQ<Impl>::sqFull()
449{
450    list<unsigned>::iterator active_threads = (*activeThreads).begin();
451
452    while (active_threads != (*activeThreads).end()) {
453        unsigned tid = *active_threads++;
454        if (!sqFull(tid))
455            return false;
456    }
457
458    return true;
459}
460
461template<class Impl>
462bool
463LSQ<Impl>::sqFull(unsigned tid)
464{
465     //@todo: Change to Calculate All Entries for
466    //Dynamic Policy
467    if( lsqPolicy == Dynamic )
468        return sqFull();
469    else
470        return thread[tid].sqFull();
471}
472
473template<class Impl>
474bool
475LSQ<Impl>::isStalled()
476{
477    list<unsigned>::iterator active_threads = (*activeThreads).begin();
478
479    while (active_threads != (*activeThreads).end()) {
480        unsigned tid = *active_threads++;
481        if (!thread[tid].isStalled())
482            return false;
483    }
484
485    return true;
486}
487
488template<class Impl>
489bool
490LSQ<Impl>::isStalled(unsigned tid)
491{
492    if( lsqPolicy == Dynamic )
493        return isStalled();
494    else
495        return thread[tid].isStalled();
496}
497
498template<class Impl>
499bool
500LSQ<Impl>::hasStoresToWB()
501{
502    list<unsigned>::iterator active_threads = (*activeThreads).begin();
503
504    while (active_threads != (*activeThreads).end()) {
505        unsigned tid = *active_threads++;
506        if (!hasStoresToWB(tid))
507            return false;
508    }
509
510    return true;
511}
512
513template<class Impl>
514bool
515LSQ<Impl>::willWB()
516{
517    list<unsigned>::iterator active_threads = (*activeThreads).begin();
518
519    while (active_threads != (*activeThreads).end()) {
520        unsigned tid = *active_threads++;
521        if (!willWB(tid))
522            return false;
523    }
524
525    return true;
526}
527
528template<class Impl>
529void
530LSQ<Impl>::dumpInsts()
531{
532    list<unsigned>::iterator active_threads = (*activeThreads).begin();
533
534    while (active_threads != (*activeThreads).end()) {
535        unsigned tid = *active_threads++;
536        thread[tid].dumpInsts();
537    }
538}
539