lsq_impl.hh revision 13560
15222Sksewell@umich.edu/*
25222Sksewell@umich.edu * Copyright (c) 2011-2012, 2014 ARM Limited
35222Sksewell@umich.edu * Copyright (c) 2013 Advanced Micro Devices, Inc.
45222Sksewell@umich.edu * All rights reserved
55222Sksewell@umich.edu *
65222Sksewell@umich.edu * The license below extends only to copyright in the software and shall
75222Sksewell@umich.edu * not be construed as granting a license to any other intellectual
85222Sksewell@umich.edu * property including but not limited to intellectual property relating
95222Sksewell@umich.edu * to a hardware implementation of the functionality of the software
105222Sksewell@umich.edu * licensed hereunder.  You may use the software subject to the license
115222Sksewell@umich.edu * terms below provided that you ensure that this notice is replicated
125222Sksewell@umich.edu * unmodified and in its entirety in all distributions of the software,
135222Sksewell@umich.edu * modified or unmodified, in source code or in binary form.
145222Sksewell@umich.edu *
155222Sksewell@umich.edu * Copyright (c) 2005-2006 The Regents of The University of Michigan
165222Sksewell@umich.edu * All rights reserved.
175222Sksewell@umich.edu *
185222Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
195222Sksewell@umich.edu * modification, are permitted provided that the following conditions are
205222Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
215222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
225222Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
235222Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
245222Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
255222Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
265222Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
275222Sksewell@umich.edu * this software without specific prior written permission.
285222Sksewell@umich.edu *
295222Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
305222Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
315222Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
325222Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
335222Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
345222Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
355222Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
365222Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
375222Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
385222Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
395222Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
405222Sksewell@umich.edu *
415222Sksewell@umich.edu * Authors: Korey Sewell
425222Sksewell@umich.edu */
435222Sksewell@umich.edu
445222Sksewell@umich.edu#ifndef __CPU_O3_LSQ_IMPL_HH__
455222Sksewell@umich.edu#define __CPU_O3_LSQ_IMPL_HH__
465222Sksewell@umich.edu
475222Sksewell@umich.edu#include <algorithm>
485222Sksewell@umich.edu#include <list>
495222Sksewell@umich.edu#include <string>
505222Sksewell@umich.edu
515222Sksewell@umich.edu#include "base/logging.hh"
525222Sksewell@umich.edu#include "cpu/o3/lsq.hh"
535222Sksewell@umich.edu#include "debug/Drain.hh"
545222Sksewell@umich.edu#include "debug/Fetch.hh"
555222Sksewell@umich.edu#include "debug/LSQ.hh"
565222Sksewell@umich.edu#include "debug/Writeback.hh"
575222Sksewell@umich.edu#include "params/DerivO3CPU.hh"
585222Sksewell@umich.edu
595222Sksewell@umich.eduusing namespace std;
605222Sksewell@umich.edu
615222Sksewell@umich.edutemplate <class Impl>
625222Sksewell@umich.eduLSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
635222Sksewell@umich.edu    : cpu(cpu_ptr), iewStage(iew_ptr),
645222Sksewell@umich.edu      lsqPolicy(params->smtLSQPolicy),
655222Sksewell@umich.edu      LQEntries(params->LQEntries),
665222Sksewell@umich.edu      SQEntries(params->SQEntries),
675222Sksewell@umich.edu      maxLQEntries(maxLSQAllocation(lsqPolicy, LQEntries, params->numThreads,
685222Sksewell@umich.edu                  params->smtLSQThreshold)),
695222Sksewell@umich.edu      maxSQEntries(maxLSQAllocation(lsqPolicy, SQEntries, params->numThreads,
705222Sksewell@umich.edu                  params->smtLSQThreshold)),
715222Sksewell@umich.edu      numThreads(params->numThreads)
725222Sksewell@umich.edu{
735222Sksewell@umich.edu    assert(numThreads > 0 && numThreads <= Impl::MaxThreads);
745222Sksewell@umich.edu
755222Sksewell@umich.edu    //**********************************************/
765222Sksewell@umich.edu    //************ Handle SMT Parameters ***********/
775222Sksewell@umich.edu    //**********************************************/
785222Sksewell@umich.edu
795222Sksewell@umich.edu    //Figure out fetch policy
805222Sksewell@umich.edu    if (lsqPolicy == SMTQueuePolicy::Dynamic) {
815222Sksewell@umich.edu        DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
825222Sksewell@umich.edu    } else if (lsqPolicy == SMTQueuePolicy::Partitioned) {
835222Sksewell@umich.edu        DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
845222Sksewell@umich.edu                "%i entries per LQ | %i entries per SQ\n",
855222Sksewell@umich.edu                maxLQEntries,maxSQEntries);
865222Sksewell@umich.edu    } else if (lsqPolicy == SMTQueuePolicy::Threshold) {
875222Sksewell@umich.edu
885222Sksewell@umich.edu        assert(params->smtLSQThreshold > LQEntries);
895222Sksewell@umich.edu        assert(params->smtLSQThreshold > SQEntries);
905222Sksewell@umich.edu
915222Sksewell@umich.edu        DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
925222Sksewell@umich.edu                "%i entries per LQ | %i entries per SQ\n",
935222Sksewell@umich.edu                maxLQEntries,maxSQEntries);
945222Sksewell@umich.edu    } else {
955222Sksewell@umich.edu        panic("Invalid LSQ sharing policy. Options are: Dynamic, "
965222Sksewell@umich.edu                    "Partitioned, Threshold");
975222Sksewell@umich.edu    }
985222Sksewell@umich.edu
995222Sksewell@umich.edu    thread.reserve(numThreads);
1005222Sksewell@umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++) {
1015222Sksewell@umich.edu        thread.emplace_back(maxLQEntries, maxSQEntries);
1025222Sksewell@umich.edu        thread[tid].init(cpu, iew_ptr, params, this, tid);
1035222Sksewell@umich.edu        thread[tid].setDcachePort(&cpu_ptr->getDataPort());
1045222Sksewell@umich.edu    }
1055222Sksewell@umich.edu}
1065222Sksewell@umich.edu
1075222Sksewell@umich.edu
1085222Sksewell@umich.edutemplate<class Impl>
1095222Sksewell@umich.edustd::string
1105222Sksewell@umich.eduLSQ<Impl>::name() const
1115222Sksewell@umich.edu{
1125222Sksewell@umich.edu    return iewStage->name() + ".lsq";
1135222Sksewell@umich.edu}
1145222Sksewell@umich.edu
1155222Sksewell@umich.edutemplate<class Impl>
1165222Sksewell@umich.eduvoid
1175222Sksewell@umich.eduLSQ<Impl>::regStats()
1185222Sksewell@umich.edu{
1195222Sksewell@umich.edu    //Initialize LSQs
1205222Sksewell@umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++) {
1215222Sksewell@umich.edu        thread[tid].regStats();
1225222Sksewell@umich.edu    }
1235222Sksewell@umich.edu}
1245222Sksewell@umich.edu
1255222Sksewell@umich.edutemplate<class Impl>
1265222Sksewell@umich.eduvoid
1275222Sksewell@umich.eduLSQ<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
1285222Sksewell@umich.edu{
1295222Sksewell@umich.edu    activeThreads = at_ptr;
1305222Sksewell@umich.edu    assert(activeThreads != 0);
1315222Sksewell@umich.edu}
1325222Sksewell@umich.edu
1335222Sksewell@umich.edutemplate <class Impl>
1345222Sksewell@umich.eduvoid
1355222Sksewell@umich.eduLSQ<Impl>::drainSanityCheck() const
1365222Sksewell@umich.edu{
1375222Sksewell@umich.edu    assert(isDrained());
1385222Sksewell@umich.edu
1395222Sksewell@umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++)
1405222Sksewell@umich.edu        thread[tid].drainSanityCheck();
1415222Sksewell@umich.edu}
1425222Sksewell@umich.edu
1435222Sksewell@umich.edutemplate <class Impl>
1445222Sksewell@umich.edubool
1455222Sksewell@umich.eduLSQ<Impl>::isDrained() const
1465222Sksewell@umich.edu{
1475222Sksewell@umich.edu    bool drained(true);
1485222Sksewell@umich.edu
1495222Sksewell@umich.edu    if (!lqEmpty()) {
1505222Sksewell@umich.edu        DPRINTF(Drain, "Not drained, LQ not empty.\n");
1515222Sksewell@umich.edu        drained = false;
1525222Sksewell@umich.edu    }
1535222Sksewell@umich.edu
1545222Sksewell@umich.edu    if (!sqEmpty()) {
1555222Sksewell@umich.edu        DPRINTF(Drain, "Not drained, SQ not empty.\n");
1565222Sksewell@umich.edu        drained = false;
1575222Sksewell@umich.edu    }
1585222Sksewell@umich.edu
1595222Sksewell@umich.edu    return drained;
1605222Sksewell@umich.edu}
1615222Sksewell@umich.edu
1625222Sksewell@umich.edutemplate <class Impl>
1635222Sksewell@umich.eduvoid
1645222Sksewell@umich.eduLSQ<Impl>::takeOverFrom()
1655222Sksewell@umich.edu{
1665222Sksewell@umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++) {
1675222Sksewell@umich.edu        thread[tid].takeOverFrom();
1685222Sksewell@umich.edu    }
1695222Sksewell@umich.edu}
1705222Sksewell@umich.edu
1715222Sksewell@umich.edutemplate <class Impl>
1725222Sksewell@umich.eduint
1735222Sksewell@umich.eduLSQ<Impl>::entryAmount(ThreadID num_threads)
1745222Sksewell@umich.edu{
1755222Sksewell@umich.edu    if (lsqPolicy == SMTQueuePolicy::Partitioned) {
1765222Sksewell@umich.edu        return LQEntries / num_threads;
1775222Sksewell@umich.edu    } else {
1785222Sksewell@umich.edu        return 0;
1795222Sksewell@umich.edu    }
1805222Sksewell@umich.edu}
1815222Sksewell@umich.edu
1825222Sksewell@umich.edutemplate <class Impl>
1835222Sksewell@umich.eduvoid
1845222Sksewell@umich.eduLSQ<Impl>::resetEntries()
1855222Sksewell@umich.edu{
1865222Sksewell@umich.edu    if (lsqPolicy != SMTQueuePolicy::Dynamic || numThreads > 1) {
1875222Sksewell@umich.edu        int active_threads = activeThreads->size();
1885222Sksewell@umich.edu
1895222Sksewell@umich.edu        int maxEntries;
1905222Sksewell@umich.edu
1915222Sksewell@umich.edu        if (lsqPolicy == SMTQueuePolicy::Partitioned) {
1925222Sksewell@umich.edu            maxEntries = LQEntries / active_threads;
1935222Sksewell@umich.edu        } else if (lsqPolicy == SMTQueuePolicy::Threshold &&
1945222Sksewell@umich.edu                   active_threads == 1) {
1955222Sksewell@umich.edu            maxEntries = LQEntries;
1965222Sksewell@umich.edu        } else {
1975222Sksewell@umich.edu            maxEntries = LQEntries;
1985222Sksewell@umich.edu        }
1995222Sksewell@umich.edu
2005222Sksewell@umich.edu        list<ThreadID>::iterator threads  = activeThreads->begin();
2015222Sksewell@umich.edu        list<ThreadID>::iterator end = activeThreads->end();
2025222Sksewell@umich.edu
2035222Sksewell@umich.edu        while (threads != end) {
2045222Sksewell@umich.edu            ThreadID tid = *threads++;
2055222Sksewell@umich.edu
2065222Sksewell@umich.edu            resizeEntries(maxEntries, tid);
2075222Sksewell@umich.edu        }
2085222Sksewell@umich.edu    }
2095222Sksewell@umich.edu}
2105222Sksewell@umich.edu
2115222Sksewell@umich.edutemplate<class Impl>
2125222Sksewell@umich.eduvoid
2135222Sksewell@umich.eduLSQ<Impl>::removeEntries(ThreadID tid)
2145222Sksewell@umich.edu{
2155222Sksewell@umich.edu    thread[tid].clearLQ();
2165222Sksewell@umich.edu    thread[tid].clearSQ();
2175222Sksewell@umich.edu}
2185222Sksewell@umich.edu
2195222Sksewell@umich.edutemplate<class Impl>
2205222Sksewell@umich.eduvoid
2215222Sksewell@umich.eduLSQ<Impl>::resizeEntries(unsigned size, ThreadID tid)
2225222Sksewell@umich.edu{
2235222Sksewell@umich.edu    thread[tid].resizeLQ(size);
2245222Sksewell@umich.edu    thread[tid].resizeSQ(size);
2255222Sksewell@umich.edu}
2265222Sksewell@umich.edu
2275222Sksewell@umich.edutemplate<class Impl>
2285222Sksewell@umich.eduvoid
2295222Sksewell@umich.eduLSQ<Impl>::tick()
2305222Sksewell@umich.edu{
2315222Sksewell@umich.edu    list<ThreadID>::iterator threads = activeThreads->begin();
2325222Sksewell@umich.edu    list<ThreadID>::iterator end = activeThreads->end();
2335222Sksewell@umich.edu
2345222Sksewell@umich.edu    while (threads != end) {
2355222Sksewell@umich.edu        ThreadID tid = *threads++;
2365222Sksewell@umich.edu
2375222Sksewell@umich.edu        thread[tid].tick();
2385222Sksewell@umich.edu    }
2395222Sksewell@umich.edu}
2405222Sksewell@umich.edu
2415222Sksewell@umich.edutemplate<class Impl>
2425222Sksewell@umich.eduvoid
2435222Sksewell@umich.eduLSQ<Impl>::insertLoad(const DynInstPtr &load_inst)
2445222Sksewell@umich.edu{
2455222Sksewell@umich.edu    ThreadID tid = load_inst->threadNumber;
2465222Sksewell@umich.edu
2475222Sksewell@umich.edu    thread[tid].insertLoad(load_inst);
2485222Sksewell@umich.edu}
2495222Sksewell@umich.edu
2505222Sksewell@umich.edutemplate<class Impl>
2515222Sksewell@umich.eduvoid
2525222Sksewell@umich.eduLSQ<Impl>::insertStore(const DynInstPtr &store_inst)
2535222Sksewell@umich.edu{
2545222Sksewell@umich.edu    ThreadID tid = store_inst->threadNumber;
2555222Sksewell@umich.edu
2565222Sksewell@umich.edu    thread[tid].insertStore(store_inst);
2575222Sksewell@umich.edu}
2585222Sksewell@umich.edu
2595222Sksewell@umich.edutemplate<class Impl>
2605222Sksewell@umich.eduFault
2615222Sksewell@umich.eduLSQ<Impl>::executeLoad(const DynInstPtr &inst)
2625222Sksewell@umich.edu{
2635222Sksewell@umich.edu    ThreadID tid = inst->threadNumber;
2645222Sksewell@umich.edu
2655222Sksewell@umich.edu    return thread[tid].executeLoad(inst);
2665222Sksewell@umich.edu}
2675222Sksewell@umich.edu
2685222Sksewell@umich.edutemplate<class Impl>
2695222Sksewell@umich.eduFault
2705222Sksewell@umich.eduLSQ<Impl>::executeStore(const DynInstPtr &inst)
2715222Sksewell@umich.edu{
2725222Sksewell@umich.edu    ThreadID tid = inst->threadNumber;
2735222Sksewell@umich.edu
2745222Sksewell@umich.edu    return thread[tid].executeStore(inst);
2755222Sksewell@umich.edu}
2765222Sksewell@umich.edu
2775222Sksewell@umich.edutemplate<class Impl>
2785222Sksewell@umich.eduvoid
2795222Sksewell@umich.eduLSQ<Impl>::writebackStores()
2805222Sksewell@umich.edu{
2815222Sksewell@umich.edu    list<ThreadID>::iterator threads = activeThreads->begin();
2825222Sksewell@umich.edu    list<ThreadID>::iterator end = activeThreads->end();
2835222Sksewell@umich.edu
2845222Sksewell@umich.edu    while (threads != end) {
2855222Sksewell@umich.edu        ThreadID tid = *threads++;
2865222Sksewell@umich.edu
2875222Sksewell@umich.edu        if (numStoresToWB(tid) > 0) {
2885222Sksewell@umich.edu            DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
2895222Sksewell@umich.edu                "available for Writeback.\n", tid, numStoresToWB(tid));
2905222Sksewell@umich.edu        }
2915222Sksewell@umich.edu
2925222Sksewell@umich.edu        thread[tid].writebackStores();
2935222Sksewell@umich.edu    }
2945222Sksewell@umich.edu}
2955222Sksewell@umich.edu
2965222Sksewell@umich.edutemplate<class Impl>
2975222Sksewell@umich.edubool
2985222Sksewell@umich.eduLSQ<Impl>::violation()
2995222Sksewell@umich.edu{
3005222Sksewell@umich.edu    /* Answers: Does Anybody Have a Violation?*/
3015222Sksewell@umich.edu    list<ThreadID>::iterator threads = activeThreads->begin();
3025222Sksewell@umich.edu    list<ThreadID>::iterator end = activeThreads->end();
3035222Sksewell@umich.edu
3045222Sksewell@umich.edu    while (threads != end) {
3055222Sksewell@umich.edu        ThreadID tid = *threads++;
3065222Sksewell@umich.edu
3075222Sksewell@umich.edu        if (thread[tid].violation())
3085222Sksewell@umich.edu            return true;
3095222Sksewell@umich.edu    }
3105222Sksewell@umich.edu
3115222Sksewell@umich.edu    return false;
3125222Sksewell@umich.edu}
3135222Sksewell@umich.edu
3145222Sksewell@umich.edutemplate <class Impl>
3155222Sksewell@umich.eduvoid
3165222Sksewell@umich.eduLSQ<Impl>::recvReqRetry()
3175222Sksewell@umich.edu{
3185222Sksewell@umich.edu    iewStage->cacheUnblocked();
3195222Sksewell@umich.edu
3205222Sksewell@umich.edu    for (ThreadID tid : *activeThreads) {
3215222Sksewell@umich.edu        thread[tid].recvRetry();
3225222Sksewell@umich.edu    }
3235222Sksewell@umich.edu}
3245222Sksewell@umich.edu
3255222Sksewell@umich.edutemplate <class Impl>
3265222Sksewell@umich.edubool
3275222Sksewell@umich.eduLSQ<Impl>::recvTimingResp(PacketPtr pkt)
3285222Sksewell@umich.edu{
3295222Sksewell@umich.edu    if (pkt->isError())
3305222Sksewell@umich.edu        DPRINTF(LSQ, "Got error packet back for address: %#X\n",
3315222Sksewell@umich.edu                pkt->getAddr());
3325222Sksewell@umich.edu
3335222Sksewell@umich.edu    thread[cpu->contextToThread(pkt->req->contextId())]
3345222Sksewell@umich.edu        .completeDataAccess(pkt);
3355222Sksewell@umich.edu
3365222Sksewell@umich.edu    if (pkt->isInvalidate()) {
3375222Sksewell@umich.edu        // This response also contains an invalidate; e.g. this can be the case
3385222Sksewell@umich.edu        // if cmd is ReadRespWithInvalidate.
3395222Sksewell@umich.edu        //
3405222Sksewell@umich.edu        // The calling order between completeDataAccess and checkSnoop matters.
3415222Sksewell@umich.edu        // By calling checkSnoop after completeDataAccess, we ensure that the
3425222Sksewell@umich.edu        // fault set by checkSnoop is not lost. Calling writeback (more
3435222Sksewell@umich.edu        // specifically inst->completeAcc) in completeDataAccess overwrites
3445222Sksewell@umich.edu        // fault, and in case this instruction requires squashing (as
3455222Sksewell@umich.edu        // determined by checkSnoop), the ReExec fault set by checkSnoop would
3465222Sksewell@umich.edu        // be lost otherwise.
3475222Sksewell@umich.edu
3485222Sksewell@umich.edu        DPRINTF(LSQ, "received invalidation with response for addr:%#x\n",
3495222Sksewell@umich.edu                pkt->getAddr());
3505222Sksewell@umich.edu
3515222Sksewell@umich.edu        for (ThreadID tid = 0; tid < numThreads; tid++) {
3525222Sksewell@umich.edu            thread[tid].checkSnoop(pkt);
3535222Sksewell@umich.edu        }
3545222Sksewell@umich.edu    }
3555222Sksewell@umich.edu
3565222Sksewell@umich.edu    delete pkt;
3575222Sksewell@umich.edu    return true;
3585222Sksewell@umich.edu}
3595222Sksewell@umich.edu
3605222Sksewell@umich.edutemplate <class Impl>
361void
362LSQ<Impl>::recvTimingSnoopReq(PacketPtr pkt)
363{
364    DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(),
365            pkt->cmdString());
366
367    // must be a snoop
368    if (pkt->isInvalidate()) {
369        DPRINTF(LSQ, "received invalidation for addr:%#x\n",
370                pkt->getAddr());
371        for (ThreadID tid = 0; tid < numThreads; tid++) {
372            thread[tid].checkSnoop(pkt);
373        }
374    }
375}
376
377template<class Impl>
378int
379LSQ<Impl>::getCount()
380{
381    unsigned total = 0;
382
383    list<ThreadID>::iterator threads = activeThreads->begin();
384    list<ThreadID>::iterator end = activeThreads->end();
385
386    while (threads != end) {
387        ThreadID tid = *threads++;
388
389        total += getCount(tid);
390    }
391
392    return total;
393}
394
395template<class Impl>
396int
397LSQ<Impl>::numLoads()
398{
399    unsigned total = 0;
400
401    list<ThreadID>::iterator threads = activeThreads->begin();
402    list<ThreadID>::iterator end = activeThreads->end();
403
404    while (threads != end) {
405        ThreadID tid = *threads++;
406
407        total += numLoads(tid);
408    }
409
410    return total;
411}
412
413template<class Impl>
414int
415LSQ<Impl>::numStores()
416{
417    unsigned total = 0;
418
419    list<ThreadID>::iterator threads = activeThreads->begin();
420    list<ThreadID>::iterator end = activeThreads->end();
421
422    while (threads != end) {
423        ThreadID tid = *threads++;
424
425        total += thread[tid].numStores();
426    }
427
428    return total;
429}
430
431template<class Impl>
432unsigned
433LSQ<Impl>::numFreeLoadEntries()
434{
435    unsigned total = 0;
436
437    list<ThreadID>::iterator threads = activeThreads->begin();
438    list<ThreadID>::iterator end = activeThreads->end();
439
440    while (threads != end) {
441        ThreadID tid = *threads++;
442
443        total += thread[tid].numFreeLoadEntries();
444    }
445
446    return total;
447}
448
449template<class Impl>
450unsigned
451LSQ<Impl>::numFreeStoreEntries()
452{
453    unsigned total = 0;
454
455    list<ThreadID>::iterator threads = activeThreads->begin();
456    list<ThreadID>::iterator end = activeThreads->end();
457
458    while (threads != end) {
459        ThreadID tid = *threads++;
460
461        total += thread[tid].numFreeStoreEntries();
462    }
463
464    return total;
465}
466
467template<class Impl>
468unsigned
469LSQ<Impl>::numFreeLoadEntries(ThreadID tid)
470{
471        return thread[tid].numFreeLoadEntries();
472}
473
474template<class Impl>
475unsigned
476LSQ<Impl>::numFreeStoreEntries(ThreadID tid)
477{
478        return thread[tid].numFreeStoreEntries();
479}
480
481template<class Impl>
482bool
483LSQ<Impl>::isFull()
484{
485    list<ThreadID>::iterator threads = activeThreads->begin();
486    list<ThreadID>::iterator end = activeThreads->end();
487
488    while (threads != end) {
489        ThreadID tid = *threads++;
490
491        if (!(thread[tid].lqFull() || thread[tid].sqFull()))
492            return false;
493    }
494
495    return true;
496}
497
498template<class Impl>
499bool
500LSQ<Impl>::isFull(ThreadID tid)
501{
502    //@todo: Change to Calculate All Entries for
503    //Dynamic Policy
504    if (lsqPolicy == SMTQueuePolicy::Dynamic)
505        return isFull();
506    else
507        return thread[tid].lqFull() || thread[tid].sqFull();
508}
509
510template<class Impl>
511bool
512LSQ<Impl>::isEmpty() const
513{
514    return lqEmpty() && sqEmpty();
515}
516
517template<class Impl>
518bool
519LSQ<Impl>::lqEmpty() const
520{
521    list<ThreadID>::const_iterator threads = activeThreads->begin();
522    list<ThreadID>::const_iterator end = activeThreads->end();
523
524    while (threads != end) {
525        ThreadID tid = *threads++;
526
527        if (!thread[tid].lqEmpty())
528            return false;
529    }
530
531    return true;
532}
533
534template<class Impl>
535bool
536LSQ<Impl>::sqEmpty() const
537{
538    list<ThreadID>::const_iterator threads = activeThreads->begin();
539    list<ThreadID>::const_iterator end = activeThreads->end();
540
541    while (threads != end) {
542        ThreadID tid = *threads++;
543
544        if (!thread[tid].sqEmpty())
545            return false;
546    }
547
548    return true;
549}
550
551template<class Impl>
552bool
553LSQ<Impl>::lqFull()
554{
555    list<ThreadID>::iterator threads = activeThreads->begin();
556    list<ThreadID>::iterator end = activeThreads->end();
557
558    while (threads != end) {
559        ThreadID tid = *threads++;
560
561        if (!thread[tid].lqFull())
562            return false;
563    }
564
565    return true;
566}
567
568template<class Impl>
569bool
570LSQ<Impl>::lqFull(ThreadID tid)
571{
572    //@todo: Change to Calculate All Entries for
573    //Dynamic Policy
574    if (lsqPolicy == SMTQueuePolicy::Dynamic)
575        return lqFull();
576    else
577        return thread[tid].lqFull();
578}
579
580template<class Impl>
581bool
582LSQ<Impl>::sqFull()
583{
584    list<ThreadID>::iterator threads = activeThreads->begin();
585    list<ThreadID>::iterator end = activeThreads->end();
586
587    while (threads != end) {
588        ThreadID tid = *threads++;
589
590        if (!sqFull(tid))
591            return false;
592    }
593
594    return true;
595}
596
597template<class Impl>
598bool
599LSQ<Impl>::sqFull(ThreadID tid)
600{
601     //@todo: Change to Calculate All Entries for
602    //Dynamic Policy
603    if (lsqPolicy == SMTQueuePolicy::Dynamic)
604        return sqFull();
605    else
606        return thread[tid].sqFull();
607}
608
609template<class Impl>
610bool
611LSQ<Impl>::isStalled()
612{
613    list<ThreadID>::iterator threads = activeThreads->begin();
614    list<ThreadID>::iterator end = activeThreads->end();
615
616    while (threads != end) {
617        ThreadID tid = *threads++;
618
619        if (!thread[tid].isStalled())
620            return false;
621    }
622
623    return true;
624}
625
626template<class Impl>
627bool
628LSQ<Impl>::isStalled(ThreadID tid)
629{
630    if (lsqPolicy == SMTQueuePolicy::Dynamic)
631        return isStalled();
632    else
633        return thread[tid].isStalled();
634}
635
636template<class Impl>
637bool
638LSQ<Impl>::hasStoresToWB()
639{
640    list<ThreadID>::iterator threads = activeThreads->begin();
641    list<ThreadID>::iterator end = activeThreads->end();
642
643    while (threads != end) {
644        ThreadID tid = *threads++;
645
646        if (hasStoresToWB(tid))
647            return true;
648    }
649
650    return false;
651}
652
653template<class Impl>
654bool
655LSQ<Impl>::willWB()
656{
657    list<ThreadID>::iterator threads = activeThreads->begin();
658    list<ThreadID>::iterator end = activeThreads->end();
659
660    while (threads != end) {
661        ThreadID tid = *threads++;
662
663        if (willWB(tid))
664            return true;
665    }
666
667    return false;
668}
669
670template<class Impl>
671void
672LSQ<Impl>::dumpInsts() const
673{
674    list<ThreadID>::const_iterator threads = activeThreads->begin();
675    list<ThreadID>::const_iterator end = activeThreads->end();
676
677    while (threads != end) {
678        ThreadID tid = *threads++;
679
680        thread[tid].dumpInsts();
681    }
682}
683
684#endif//__CPU_O3_LSQ_IMPL_HH__
685