lsq_unit_impl.hh revision 11357
14276Sgblack@eecs.umich.edu
24276Sgblack@eecs.umich.edu/*
34276Sgblack@eecs.umich.edu * Copyright (c) 2010-2014 ARM Limited
44276Sgblack@eecs.umich.edu * Copyright (c) 2013 Advanced Micro Devices, Inc.
54276Sgblack@eecs.umich.edu * All rights reserved
64276Sgblack@eecs.umich.edu *
74276Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall
84276Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual
94276Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating
104276Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software
114276Sgblack@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
124276Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
134276Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
144276Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
154276Sgblack@eecs.umich.edu *
164276Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan
174276Sgblack@eecs.umich.edu * All rights reserved.
184276Sgblack@eecs.umich.edu *
194276Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
204276Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
214276Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
224276Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
234276Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
244276Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
254276Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
264276Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
274276Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
284276Sgblack@eecs.umich.edu * this software without specific prior written permission.
294276Sgblack@eecs.umich.edu *
304276Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
314276Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
324276Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
334276Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
344276Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
354276Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
364276Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
374276Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
384276Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
394276Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
404276Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
414276Sgblack@eecs.umich.edu *
424276Sgblack@eecs.umich.edu * Authors: Kevin Lim
434276Sgblack@eecs.umich.edu *          Korey Sewell
444276Sgblack@eecs.umich.edu */
454276Sgblack@eecs.umich.edu
464276Sgblack@eecs.umich.edu#ifndef __CPU_O3_LSQ_UNIT_IMPL_HH__
474276Sgblack@eecs.umich.edu#define __CPU_O3_LSQ_UNIT_IMPL_HH__
484276Sgblack@eecs.umich.edu
494276Sgblack@eecs.umich.edu#include "arch/generic/debugfaults.hh"
504276Sgblack@eecs.umich.edu#include "arch/locked_mem.hh"
514276Sgblack@eecs.umich.edu#include "base/str.hh"
524276Sgblack@eecs.umich.edu#include "config/the_isa.hh"
534276Sgblack@eecs.umich.edu#include "cpu/checker/cpu.hh"
544276Sgblack@eecs.umich.edu#include "cpu/o3/lsq.hh"
554276Sgblack@eecs.umich.edu#include "cpu/o3/lsq_unit.hh"
564276Sgblack@eecs.umich.edu#include "debug/Activity.hh"
574276Sgblack@eecs.umich.edu#include "debug/IEW.hh"
584276Sgblack@eecs.umich.edu#include "debug/LSQUnit.hh"
594276Sgblack@eecs.umich.edu#include "debug/O3PipeView.hh"
604276Sgblack@eecs.umich.edu#include "mem/packet.hh"
614711Sgblack@eecs.umich.edu#include "mem/request.hh"
624276Sgblack@eecs.umich.edu
634276Sgblack@eecs.umich.edutemplate<class Impl>
644276Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt,
654276Sgblack@eecs.umich.edu                                              LSQUnit *lsq_ptr)
664276Sgblack@eecs.umich.edu    : Event(Default_Pri, AutoDelete),
674276Sgblack@eecs.umich.edu      inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
684276Sgblack@eecs.umich.edu{
694276Sgblack@eecs.umich.edu}
704712Sgblack@eecs.umich.edu
714711Sgblack@eecs.umich.edutemplate<class Impl>
724712Sgblack@eecs.umich.eduvoid
734828Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::process()
744712Sgblack@eecs.umich.edu{
754276Sgblack@eecs.umich.edu    assert(!lsqPtr->cpu->switchedOut());
764276Sgblack@eecs.umich.edu
774276Sgblack@eecs.umich.edu    lsqPtr->writeback(inst, pkt);
784276Sgblack@eecs.umich.edu
794276Sgblack@eecs.umich.edu    if (pkt->senderState)
804276Sgblack@eecs.umich.edu        delete pkt->senderState;
814712Sgblack@eecs.umich.edu
824712Sgblack@eecs.umich.edu    delete pkt->req;
834730Sgblack@eecs.umich.edu    delete pkt;
844760Sgblack@eecs.umich.edu}
854730Sgblack@eecs.umich.edu
864712Sgblack@eecs.umich.edutemplate<class Impl>
874712Sgblack@eecs.umich.educonst char *
884712Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::description() const
894276Sgblack@eecs.umich.edu{
904760Sgblack@eecs.umich.edu    return "Store writeback";
914760Sgblack@eecs.umich.edu}
924760Sgblack@eecs.umich.edu
935020Sgblack@eecs.umich.edutemplate<class Impl>
945020Sgblack@eecs.umich.eduvoid
955020Sgblack@eecs.umich.eduLSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
965020Sgblack@eecs.umich.edu{
975020Sgblack@eecs.umich.edu    LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState);
985020Sgblack@eecs.umich.edu    DynInstPtr inst = state->inst;
995020Sgblack@eecs.umich.edu    DPRINTF(IEW, "Writeback event [sn:%lli].\n", inst->seqNum);
1005020Sgblack@eecs.umich.edu    DPRINTF(Activity, "Activity: Writeback event [sn:%lli].\n", inst->seqNum);
1015020Sgblack@eecs.umich.edu
1025020Sgblack@eecs.umich.edu    if (state->cacheBlocked) {
1035020Sgblack@eecs.umich.edu        // This is the first half of a previous split load,
1045020Sgblack@eecs.umich.edu        // where the 2nd half blocked, ignore this response
1055020Sgblack@eecs.umich.edu        DPRINTF(IEW, "[sn:%lli]: Response from first half of earlier "
1065020Sgblack@eecs.umich.edu                "blocked split load recieved. Ignoring.\n", inst->seqNum);
1074760Sgblack@eecs.umich.edu        delete state;
1084760Sgblack@eecs.umich.edu        return;
1094760Sgblack@eecs.umich.edu    }
1105020Sgblack@eecs.umich.edu
1115020Sgblack@eecs.umich.edu    // If this is a split access, wait until all packets are received.
1125020Sgblack@eecs.umich.edu    if (TheISA::HasUnalignedMemAcc && !state->complete()) {
1135020Sgblack@eecs.umich.edu        return;
1145020Sgblack@eecs.umich.edu    }
1154760Sgblack@eecs.umich.edu
1164760Sgblack@eecs.umich.edu    assert(!cpu->switchedOut());
1174760Sgblack@eecs.umich.edu    if (!inst->isSquashed()) {
1185020Sgblack@eecs.umich.edu        if (!state->noWB) {
1195020Sgblack@eecs.umich.edu            if (!TheISA::HasUnalignedMemAcc || !state->isSplit ||
1205029Sgblack@eecs.umich.edu                !state->isLoad) {
1215029Sgblack@eecs.umich.edu                writeback(inst, pkt);
1225020Sgblack@eecs.umich.edu            } else {
1235020Sgblack@eecs.umich.edu                writeback(inst, state->mainPkt);
1245020Sgblack@eecs.umich.edu            }
1255020Sgblack@eecs.umich.edu        }
1264760Sgblack@eecs.umich.edu
1274760Sgblack@eecs.umich.edu        if (inst->isStore()) {
1284760Sgblack@eecs.umich.edu            completeStore(state->idx);
1295020Sgblack@eecs.umich.edu        }
1305020Sgblack@eecs.umich.edu    }
1315020Sgblack@eecs.umich.edu
1325020Sgblack@eecs.umich.edu    if (TheISA::HasUnalignedMemAcc && state->isSplit && state->isLoad) {
1334760Sgblack@eecs.umich.edu        delete state->mainPkt->req;
1344760Sgblack@eecs.umich.edu        delete state->mainPkt;
1354276Sgblack@eecs.umich.edu    }
1364276Sgblack@eecs.umich.edu
1374712Sgblack@eecs.umich.edu    pkt->req->setAccessLatency();
1384712Sgblack@eecs.umich.edu    cpu->ppDataAccessComplete->notify(std::make_pair(inst, pkt));
1394712Sgblack@eecs.umich.edu
1404712Sgblack@eecs.umich.edu    delete state;
1414712Sgblack@eecs.umich.edu}
1424712Sgblack@eecs.umich.edu
1434712Sgblack@eecs.umich.edutemplate <class Impl>
1444712Sgblack@eecs.umich.eduLSQUnit<Impl>::LSQUnit()
1454276Sgblack@eecs.umich.edu    : loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false),
1465020Sgblack@eecs.umich.edu      isStoreBlocked(false), storeInFlight(false), hasPendingPkt(false),
1475020Sgblack@eecs.umich.edu      pendingPkt(nullptr)
1485020Sgblack@eecs.umich.edu{
1495020Sgblack@eecs.umich.edu}
1505020Sgblack@eecs.umich.edu
1515020Sgblack@eecs.umich.edutemplate<class Impl>
1525020Sgblack@eecs.umich.eduvoid
1535020Sgblack@eecs.umich.eduLSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params,
1545020Sgblack@eecs.umich.edu        LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries,
1555020Sgblack@eecs.umich.edu        unsigned id)
1565020Sgblack@eecs.umich.edu{
1575020Sgblack@eecs.umich.edu    cpu = cpu_ptr;
1585020Sgblack@eecs.umich.edu    iewStage = iew_ptr;
1595020Sgblack@eecs.umich.edu
1605020Sgblack@eecs.umich.edu    lsq = lsq_ptr;
1615020Sgblack@eecs.umich.edu
1625020Sgblack@eecs.umich.edu    lsqID = id;
1634276Sgblack@eecs.umich.edu
1645020Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
1655020Sgblack@eecs.umich.edu
1665020Sgblack@eecs.umich.edu    // Add 1 for the sentinel entry (they are circular queues).
1675020Sgblack@eecs.umich.edu    LQEntries = maxLQEntries + 1;
1685020Sgblack@eecs.umich.edu    SQEntries = maxSQEntries + 1;
1695020Sgblack@eecs.umich.edu
1705020Sgblack@eecs.umich.edu    //Due to uint8_t index in LSQSenderState
1715020Sgblack@eecs.umich.edu    assert(LQEntries <= 256);
1725020Sgblack@eecs.umich.edu    assert(SQEntries <= 256);
1735020Sgblack@eecs.umich.edu
1745020Sgblack@eecs.umich.edu    loadQueue.resize(LQEntries);
1755020Sgblack@eecs.umich.edu    storeQueue.resize(SQEntries);
1765020Sgblack@eecs.umich.edu
1775020Sgblack@eecs.umich.edu    depCheckShift = params->LSQDepCheckShift;
1785020Sgblack@eecs.umich.edu    checkLoads = params->LSQCheckLoads;
1795020Sgblack@eecs.umich.edu    cachePorts = params->cachePorts;
1805020Sgblack@eecs.umich.edu    needsTSO = params->needsTSO;
1815020Sgblack@eecs.umich.edu
1825020Sgblack@eecs.umich.edu    resetState();
1835020Sgblack@eecs.umich.edu}
1845020Sgblack@eecs.umich.edu
1855020Sgblack@eecs.umich.edu
1865020Sgblack@eecs.umich.edutemplate<class Impl>
1875020Sgblack@eecs.umich.eduvoid
1885020Sgblack@eecs.umich.eduLSQUnit<Impl>::resetState()
1895020Sgblack@eecs.umich.edu{
1905020Sgblack@eecs.umich.edu    loads = stores = storesToWB = 0;
1915020Sgblack@eecs.umich.edu
1925020Sgblack@eecs.umich.edu    loadHead = loadTail = 0;
1935020Sgblack@eecs.umich.edu
1945020Sgblack@eecs.umich.edu    storeHead = storeWBIdx = storeTail = 0;
1955020Sgblack@eecs.umich.edu
1965020Sgblack@eecs.umich.edu    usedPorts = 0;
1975020Sgblack@eecs.umich.edu
1985020Sgblack@eecs.umich.edu    retryPkt = NULL;
1995020Sgblack@eecs.umich.edu    memDepViolator = NULL;
2005020Sgblack@eecs.umich.edu
2015020Sgblack@eecs.umich.edu    stalled = false;
2025020Sgblack@eecs.umich.edu
2035020Sgblack@eecs.umich.edu    cacheBlockMask = ~(cpu->cacheLineSize() - 1);
2045020Sgblack@eecs.umich.edu}
2055020Sgblack@eecs.umich.edu
2065020Sgblack@eecs.umich.edutemplate<class Impl>
2075020Sgblack@eecs.umich.edustd::string
2084276Sgblack@eecs.umich.eduLSQUnit<Impl>::name() const
2094276Sgblack@eecs.umich.edu{
2104712Sgblack@eecs.umich.edu    if (Impl::MaxThreads == 1) {
2114712Sgblack@eecs.umich.edu        return iewStage->name() + ".lsq";
2124712Sgblack@eecs.umich.edu    } else {
2134712Sgblack@eecs.umich.edu        return iewStage->name() + ".lsq.thread" + std::to_string(lsqID);
2144712Sgblack@eecs.umich.edu    }
2154712Sgblack@eecs.umich.edu}
2164730Sgblack@eecs.umich.edu
2174712Sgblack@eecs.umich.edutemplate<class Impl>
2184276Sgblack@eecs.umich.eduvoid
2194276Sgblack@eecs.umich.eduLSQUnit<Impl>::regStats()
2204712Sgblack@eecs.umich.edu{
2214712Sgblack@eecs.umich.edu    lsqForwLoads
2224712Sgblack@eecs.umich.edu        .name(name() + ".forwLoads")
2234712Sgblack@eecs.umich.edu        .desc("Number of loads that had data forwarded from stores");
2244712Sgblack@eecs.umich.edu
2254712Sgblack@eecs.umich.edu    invAddrLoads
2264712Sgblack@eecs.umich.edu        .name(name() + ".invAddrLoads")
2274712Sgblack@eecs.umich.edu        .desc("Number of loads ignored due to an invalid address");
2284276Sgblack@eecs.umich.edu
2294760Sgblack@eecs.umich.edu    lsqSquashedLoads
2304760Sgblack@eecs.umich.edu        .name(name() + ".squashedLoads")
2314760Sgblack@eecs.umich.edu        .desc("Number of loads squashed");
2324760Sgblack@eecs.umich.edu
2334760Sgblack@eecs.umich.edu    lsqIgnoredResponses
2344760Sgblack@eecs.umich.edu        .name(name() + ".ignoredResponses")
2354760Sgblack@eecs.umich.edu        .desc("Number of memory responses ignored because the instruction is squashed");
2364760Sgblack@eecs.umich.edu
2374760Sgblack@eecs.umich.edu    lsqMemOrderViolation
2384760Sgblack@eecs.umich.edu        .name(name() + ".memOrderViolation")
2394760Sgblack@eecs.umich.edu        .desc("Number of memory ordering violations");
2404760Sgblack@eecs.umich.edu
2414760Sgblack@eecs.umich.edu    lsqSquashedStores
2424760Sgblack@eecs.umich.edu        .name(name() + ".squashedStores")
2434760Sgblack@eecs.umich.edu        .desc("Number of stores squashed");
2444760Sgblack@eecs.umich.edu
2454760Sgblack@eecs.umich.edu    invAddrSwpfs
2464760Sgblack@eecs.umich.edu        .name(name() + ".invAddrSwpfs")
2474760Sgblack@eecs.umich.edu        .desc("Number of software prefetches ignored due to an invalid address");
2484760Sgblack@eecs.umich.edu
2494760Sgblack@eecs.umich.edu    lsqBlockedLoads
2504276Sgblack@eecs.umich.edu        .name(name() + ".blockedLoads")
2515020Sgblack@eecs.umich.edu        .desc("Number of blocked loads due to partial load-store forwarding");
2525020Sgblack@eecs.umich.edu
2535020Sgblack@eecs.umich.edu    lsqRescheduledLoads
2545020Sgblack@eecs.umich.edu        .name(name() + ".rescheduledLoads")
2555020Sgblack@eecs.umich.edu        .desc("Number of loads that were rescheduled");
2565020Sgblack@eecs.umich.edu
2575020Sgblack@eecs.umich.edu    lsqCacheBlocked
2585020Sgblack@eecs.umich.edu        .name(name() + ".cacheBlocked")
2595020Sgblack@eecs.umich.edu        .desc("Number of times an access to memory failed due to the cache being blocked");
2605020Sgblack@eecs.umich.edu}
2615020Sgblack@eecs.umich.edu
2625020Sgblack@eecs.umich.edutemplate<class Impl>
2635020Sgblack@eecs.umich.eduvoid
2645020Sgblack@eecs.umich.eduLSQUnit<Impl>::setDcachePort(MasterPort *dcache_port)
2655020Sgblack@eecs.umich.edu{
2665020Sgblack@eecs.umich.edu    dcachePort = dcache_port;
2675020Sgblack@eecs.umich.edu}
2685020Sgblack@eecs.umich.edu
2695020Sgblack@eecs.umich.edutemplate<class Impl>
2705020Sgblack@eecs.umich.eduvoid
2715020Sgblack@eecs.umich.eduLSQUnit<Impl>::clearLQ()
2725020Sgblack@eecs.umich.edu{
2735020Sgblack@eecs.umich.edu    loadQueue.clear();
2745020Sgblack@eecs.umich.edu}
2755020Sgblack@eecs.umich.edu
2765020Sgblack@eecs.umich.edutemplate<class Impl>
2775020Sgblack@eecs.umich.eduvoid
2785020Sgblack@eecs.umich.eduLSQUnit<Impl>::clearSQ()
2795020Sgblack@eecs.umich.edu{
2805020Sgblack@eecs.umich.edu    storeQueue.clear();
2815020Sgblack@eecs.umich.edu}
2825020Sgblack@eecs.umich.edu
2835020Sgblack@eecs.umich.edutemplate<class Impl>
2845020Sgblack@eecs.umich.eduvoid
2855020Sgblack@eecs.umich.eduLSQUnit<Impl>::drainSanityCheck() const
2864276Sgblack@eecs.umich.edu{
2875020Sgblack@eecs.umich.edu    for (int i = 0; i < loadQueue.size(); ++i)
2885020Sgblack@eecs.umich.edu        assert(!loadQueue[i]);
2895020Sgblack@eecs.umich.edu
2905020Sgblack@eecs.umich.edu    assert(storesToWB == 0);
2915020Sgblack@eecs.umich.edu    assert(!retryPkt);
2925020Sgblack@eecs.umich.edu}
2935020Sgblack@eecs.umich.edu
2945020Sgblack@eecs.umich.edutemplate<class Impl>
2955020Sgblack@eecs.umich.eduvoid
2965020Sgblack@eecs.umich.eduLSQUnit<Impl>::takeOverFrom()
2975020Sgblack@eecs.umich.edu{
2985020Sgblack@eecs.umich.edu    resetState();
2995020Sgblack@eecs.umich.edu}
3005020Sgblack@eecs.umich.edu
3015020Sgblack@eecs.umich.edutemplate<class Impl>
3025020Sgblack@eecs.umich.eduvoid
3035020Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeLQ(unsigned size)
3045020Sgblack@eecs.umich.edu{
3055020Sgblack@eecs.umich.edu    unsigned size_plus_sentinel = size + 1;
3065020Sgblack@eecs.umich.edu    assert(size_plus_sentinel >= LQEntries);
3075020Sgblack@eecs.umich.edu
3085020Sgblack@eecs.umich.edu    if (size_plus_sentinel > LQEntries) {
3095020Sgblack@eecs.umich.edu        while (size_plus_sentinel > loadQueue.size()) {
3105020Sgblack@eecs.umich.edu            DynInstPtr dummy;
3115020Sgblack@eecs.umich.edu            loadQueue.push_back(dummy);
3125020Sgblack@eecs.umich.edu            LQEntries++;
3135020Sgblack@eecs.umich.edu        }
3145020Sgblack@eecs.umich.edu    } else {
3155020Sgblack@eecs.umich.edu        LQEntries = size_plus_sentinel;
3165020Sgblack@eecs.umich.edu    }
3175020Sgblack@eecs.umich.edu
3185020Sgblack@eecs.umich.edu    assert(LQEntries <= 256);
3195020Sgblack@eecs.umich.edu}
3205020Sgblack@eecs.umich.edu
3215020Sgblack@eecs.umich.edutemplate<class Impl>
3225020Sgblack@eecs.umich.eduvoid
3235020Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeSQ(unsigned size)
3245020Sgblack@eecs.umich.edu{
3255020Sgblack@eecs.umich.edu    unsigned size_plus_sentinel = size + 1;
3265020Sgblack@eecs.umich.edu    if (size_plus_sentinel > SQEntries) {
3275020Sgblack@eecs.umich.edu        while (size_plus_sentinel > storeQueue.size()) {
3285020Sgblack@eecs.umich.edu            SQEntry dummy;
3295020Sgblack@eecs.umich.edu            storeQueue.push_back(dummy);
3305020Sgblack@eecs.umich.edu            SQEntries++;
3315020Sgblack@eecs.umich.edu        }
3325020Sgblack@eecs.umich.edu    } else {
3334276Sgblack@eecs.umich.edu        SQEntries = size_plus_sentinel;
3345020Sgblack@eecs.umich.edu    }
3355020Sgblack@eecs.umich.edu
3365020Sgblack@eecs.umich.edu    assert(SQEntries <= 256);
3375020Sgblack@eecs.umich.edu}
3385020Sgblack@eecs.umich.edu
3395020Sgblack@eecs.umich.edutemplate <class Impl>
3405020Sgblack@eecs.umich.eduvoid
3415020Sgblack@eecs.umich.eduLSQUnit<Impl>::insert(DynInstPtr &inst)
3425020Sgblack@eecs.umich.edu{
3435020Sgblack@eecs.umich.edu    assert(inst->isMemRef());
3445020Sgblack@eecs.umich.edu
3455020Sgblack@eecs.umich.edu    assert(inst->isLoad() || inst->isStore());
3465020Sgblack@eecs.umich.edu
3475020Sgblack@eecs.umich.edu    if (inst->isLoad()) {
3485020Sgblack@eecs.umich.edu        insertLoad(inst);
3495020Sgblack@eecs.umich.edu    } else {
3505020Sgblack@eecs.umich.edu        insertStore(inst);
3515020Sgblack@eecs.umich.edu    }
3525020Sgblack@eecs.umich.edu
3535020Sgblack@eecs.umich.edu    inst->setInLSQ();
3545020Sgblack@eecs.umich.edu}
3555020Sgblack@eecs.umich.edu
3565020Sgblack@eecs.umich.edutemplate <class Impl>
3575020Sgblack@eecs.umich.eduvoid
3584276Sgblack@eecs.umich.eduLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
3595020Sgblack@eecs.umich.edu{
3605020Sgblack@eecs.umich.edu    assert((loadTail + 1) % LQEntries != loadHead);
3615020Sgblack@eecs.umich.edu    assert(loads < LQEntries);
3625020Sgblack@eecs.umich.edu
3635020Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
3645020Sgblack@eecs.umich.edu            load_inst->pcState(), loadTail, load_inst->seqNum);
3655020Sgblack@eecs.umich.edu
3665020Sgblack@eecs.umich.edu    load_inst->lqIdx = loadTail;
3675020Sgblack@eecs.umich.edu
3685020Sgblack@eecs.umich.edu    if (stores == 0) {
3695020Sgblack@eecs.umich.edu        load_inst->sqIdx = -1;
3705020Sgblack@eecs.umich.edu    } else {
3715020Sgblack@eecs.umich.edu        load_inst->sqIdx = storeTail;
3725020Sgblack@eecs.umich.edu    }
3735020Sgblack@eecs.umich.edu
3745020Sgblack@eecs.umich.edu    loadQueue[loadTail] = load_inst;
3755020Sgblack@eecs.umich.edu
3765020Sgblack@eecs.umich.edu    incrLdIdx(loadTail);
3775020Sgblack@eecs.umich.edu
3785020Sgblack@eecs.umich.edu    ++loads;
3795020Sgblack@eecs.umich.edu}
3805020Sgblack@eecs.umich.edu
3815020Sgblack@eecs.umich.edutemplate <class Impl>
3825020Sgblack@eecs.umich.eduvoid
3835020Sgblack@eecs.umich.eduLSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
3845020Sgblack@eecs.umich.edu{
3855020Sgblack@eecs.umich.edu    // Make sure it is not full before inserting an instruction.
3865020Sgblack@eecs.umich.edu    assert((storeTail + 1) % SQEntries != storeHead);
3874276Sgblack@eecs.umich.edu    assert(stores < SQEntries);
3885020Sgblack@eecs.umich.edu
3895020Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
3905020Sgblack@eecs.umich.edu            store_inst->pcState(), storeTail, store_inst->seqNum);
3915020Sgblack@eecs.umich.edu
3925020Sgblack@eecs.umich.edu    store_inst->sqIdx = storeTail;
3935020Sgblack@eecs.umich.edu    store_inst->lqIdx = loadTail;
3945020Sgblack@eecs.umich.edu
3955020Sgblack@eecs.umich.edu    storeQueue[storeTail] = SQEntry(store_inst);
3965020Sgblack@eecs.umich.edu
3975020Sgblack@eecs.umich.edu    incrStIdx(storeTail);
3985020Sgblack@eecs.umich.edu
3995020Sgblack@eecs.umich.edu    ++stores;
4005020Sgblack@eecs.umich.edu}
4015020Sgblack@eecs.umich.edu
4025020Sgblack@eecs.umich.edutemplate <class Impl>
4035020Sgblack@eecs.umich.edutypename Impl::DynInstPtr
4045020Sgblack@eecs.umich.eduLSQUnit<Impl>::getMemDepViolator()
4055020Sgblack@eecs.umich.edu{
4065020Sgblack@eecs.umich.edu    DynInstPtr temp = memDepViolator;
4075020Sgblack@eecs.umich.edu
4085020Sgblack@eecs.umich.edu    memDepViolator = NULL;
4095020Sgblack@eecs.umich.edu
4105020Sgblack@eecs.umich.edu    return temp;
4115020Sgblack@eecs.umich.edu}
4125020Sgblack@eecs.umich.edu
4135020Sgblack@eecs.umich.edutemplate <class Impl>
4145020Sgblack@eecs.umich.eduunsigned
4155020Sgblack@eecs.umich.eduLSQUnit<Impl>::numFreeLoadEntries()
4165020Sgblack@eecs.umich.edu{
4175020Sgblack@eecs.umich.edu        //LQ has an extra dummy entry to differentiate
4185020Sgblack@eecs.umich.edu        //empty/full conditions. Subtract 1 from the free entries.
4195020Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "LQ size: %d, #loads occupied: %d\n", LQEntries, loads);
4205020Sgblack@eecs.umich.edu        return LQEntries - loads - 1;
4215020Sgblack@eecs.umich.edu}
4224276Sgblack@eecs.umich.edu
4235020Sgblack@eecs.umich.edutemplate <class Impl>
4245020Sgblack@eecs.umich.eduunsigned
4255020Sgblack@eecs.umich.eduLSQUnit<Impl>::numFreeStoreEntries()
4265020Sgblack@eecs.umich.edu{
4275020Sgblack@eecs.umich.edu        //SQ has an extra dummy entry to differentiate
4285020Sgblack@eecs.umich.edu        //empty/full conditions. Subtract 1 from the free entries.
4295020Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "SQ size: %d, #stores occupied: %d\n", SQEntries, stores);
4305020Sgblack@eecs.umich.edu        return SQEntries - stores - 1;
4315020Sgblack@eecs.umich.edu
4325020Sgblack@eecs.umich.edu }
4335020Sgblack@eecs.umich.edu
4345020Sgblack@eecs.umich.edutemplate <class Impl>
4355020Sgblack@eecs.umich.eduvoid
4365020Sgblack@eecs.umich.eduLSQUnit<Impl>::checkSnoop(PacketPtr pkt)
4375020Sgblack@eecs.umich.edu{
4385020Sgblack@eecs.umich.edu    // Should only ever get invalidations in here
4395020Sgblack@eecs.umich.edu    assert(pkt->isInvalidate());
4405020Sgblack@eecs.umich.edu
4415020Sgblack@eecs.umich.edu    int load_idx = loadHead;
4425020Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
4435020Sgblack@eecs.umich.edu
4445020Sgblack@eecs.umich.edu    // Only Invalidate packet calls checkSnoop
4455020Sgblack@eecs.umich.edu    assert(pkt->isInvalidate());
4465020Sgblack@eecs.umich.edu    for (int x = 0; x < cpu->numContexts(); x++) {
4475020Sgblack@eecs.umich.edu        ThreadContext *tc = cpu->getContext(x);
4485020Sgblack@eecs.umich.edu        bool no_squash = cpu->thread[x]->noSquashFromTC;
4495020Sgblack@eecs.umich.edu        cpu->thread[x]->noSquashFromTC = true;
4505020Sgblack@eecs.umich.edu        TheISA::handleLockedSnoop(tc, pkt, cacheBlockMask);
4515020Sgblack@eecs.umich.edu        cpu->thread[x]->noSquashFromTC = no_squash;
4525020Sgblack@eecs.umich.edu    }
4534276Sgblack@eecs.umich.edu
4544727Sgblack@eecs.umich.edu    Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
4554727Sgblack@eecs.umich.edu
4564727Sgblack@eecs.umich.edu    DynInstPtr ld_inst = loadQueue[load_idx];
4574727Sgblack@eecs.umich.edu    if (ld_inst) {
4584727Sgblack@eecs.umich.edu        Addr load_addr_low = ld_inst->physEffAddrLow & cacheBlockMask;
4594727Sgblack@eecs.umich.edu        Addr load_addr_high = ld_inst->physEffAddrHigh & cacheBlockMask;
4604727Sgblack@eecs.umich.edu
4614727Sgblack@eecs.umich.edu        // Check that this snoop didn't just invalidate our lock flag
4624727Sgblack@eecs.umich.edu        if (ld_inst->effAddrValid() && (load_addr_low == invalidate_addr
4634727Sgblack@eecs.umich.edu                                        || load_addr_high == invalidate_addr)
4644727Sgblack@eecs.umich.edu            && ld_inst->memReqFlags & Request::LLSC)
4654727Sgblack@eecs.umich.edu            TheISA::handleLockedSnoopHit(ld_inst.get());
4664727Sgblack@eecs.umich.edu    }
4674727Sgblack@eecs.umich.edu
4684727Sgblack@eecs.umich.edu    // If this is the only load in the LSQ we don't care
4694727Sgblack@eecs.umich.edu    if (load_idx == loadTail)
4704727Sgblack@eecs.umich.edu        return;
4714727Sgblack@eecs.umich.edu
4724727Sgblack@eecs.umich.edu    incrLdIdx(load_idx);
4734727Sgblack@eecs.umich.edu
4744727Sgblack@eecs.umich.edu    bool force_squash = false;
4754760Sgblack@eecs.umich.edu
4764760Sgblack@eecs.umich.edu    while (load_idx != loadTail) {
4774760Sgblack@eecs.umich.edu        DynInstPtr ld_inst = loadQueue[load_idx];
4784760Sgblack@eecs.umich.edu
4794760Sgblack@eecs.umich.edu        if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
4804760Sgblack@eecs.umich.edu            incrLdIdx(load_idx);
4814760Sgblack@eecs.umich.edu            continue;
4824760Sgblack@eecs.umich.edu        }
4834760Sgblack@eecs.umich.edu
4844760Sgblack@eecs.umich.edu        Addr load_addr_low = ld_inst->physEffAddrLow & cacheBlockMask;
4854760Sgblack@eecs.umich.edu        Addr load_addr_high = ld_inst->physEffAddrHigh & cacheBlockMask;
4864760Sgblack@eecs.umich.edu
4874760Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n",
4884760Sgblack@eecs.umich.edu                    ld_inst->seqNum, load_addr_low, invalidate_addr);
4894760Sgblack@eecs.umich.edu
4904760Sgblack@eecs.umich.edu        if ((load_addr_low == invalidate_addr
4914760Sgblack@eecs.umich.edu             || load_addr_high == invalidate_addr) || force_squash) {
4924760Sgblack@eecs.umich.edu            if (needsTSO) {
4934760Sgblack@eecs.umich.edu                // If we have a TSO system, as all loads must be ordered with
4944760Sgblack@eecs.umich.edu                // all other loads, this load as well as *all* subsequent loads
4954276Sgblack@eecs.umich.edu                // need to be squashed to prevent possible load reordering.
4964276Sgblack@eecs.umich.edu                force_squash = true;
4974712Sgblack@eecs.umich.edu            }
4984712Sgblack@eecs.umich.edu            if (ld_inst->possibleLoadViolation() || force_squash) {
4994814Sgblack@eecs.umich.edu                DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
5004712Sgblack@eecs.umich.edu                        pkt->getAddr(), ld_inst->seqNum);
5014712Sgblack@eecs.umich.edu
5024712Sgblack@eecs.umich.edu                // Mark the load for re-execution
5034712Sgblack@eecs.umich.edu                ld_inst->fault = std::make_shared<ReExec>();
5044712Sgblack@eecs.umich.edu            } else {
5054276Sgblack@eecs.umich.edu                DPRINTF(LSQUnit, "HitExternal Snoop for addr %#x [sn:%lli]\n",
5064276Sgblack@eecs.umich.edu                        pkt->getAddr(), ld_inst->seqNum);
5074712Sgblack@eecs.umich.edu
5084712Sgblack@eecs.umich.edu                // Make sure that we don't lose a snoop hitting a LOCKED
5094712Sgblack@eecs.umich.edu                // address since the LOCK* flags don't get updated until
5104712Sgblack@eecs.umich.edu                // commit.
5114712Sgblack@eecs.umich.edu                if (ld_inst->memReqFlags & Request::LLSC)
5124712Sgblack@eecs.umich.edu                    TheISA::handleLockedSnoopHit(ld_inst.get());
5134712Sgblack@eecs.umich.edu
5144724Sgblack@eecs.umich.edu                // If a older load checks this and it's true
5154276Sgblack@eecs.umich.edu                // then we might have missed the snoop
5164276Sgblack@eecs.umich.edu                // in which case we need to invalidate to be sure
5174864Sgblack@eecs.umich.edu                ld_inst->hitExternalSnoop(true);
5184864Sgblack@eecs.umich.edu            }
5194712Sgblack@eecs.umich.edu        }
5204712Sgblack@eecs.umich.edu        incrLdIdx(load_idx);
5214712Sgblack@eecs.umich.edu    }
5224712Sgblack@eecs.umich.edu    return;
5234746Sgblack@eecs.umich.edu}
5244746Sgblack@eecs.umich.edu
5254746Sgblack@eecs.umich.edutemplate <class Impl>
5264746Sgblack@eecs.umich.eduFault
5274746Sgblack@eecs.umich.eduLSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst)
5284276Sgblack@eecs.umich.edu{
5294276Sgblack@eecs.umich.edu    Addr inst_eff_addr1 = inst->effAddr >> depCheckShift;
5304712Sgblack@eecs.umich.edu    Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift;
5314712Sgblack@eecs.umich.edu
5324712Sgblack@eecs.umich.edu    /** @todo in theory you only need to check an instruction that has executed
5334712Sgblack@eecs.umich.edu     * however, there isn't a good way in the pipeline at the moment to check
5344712Sgblack@eecs.umich.edu     * all instructions that will execute before the store writes back. Thus,
5354712Sgblack@eecs.umich.edu     * like the implementation that came before it, we're overly conservative.
5364746Sgblack@eecs.umich.edu     */
5374746Sgblack@eecs.umich.edu    while (load_idx != loadTail) {
5384746Sgblack@eecs.umich.edu        DynInstPtr ld_inst = loadQueue[load_idx];
5394746Sgblack@eecs.umich.edu        if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
5404746Sgblack@eecs.umich.edu            incrLdIdx(load_idx);
5414276Sgblack@eecs.umich.edu            continue;
5424276Sgblack@eecs.umich.edu        }
5435020Sgblack@eecs.umich.edu
5445020Sgblack@eecs.umich.edu        Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift;
5455020Sgblack@eecs.umich.edu        Addr ld_eff_addr2 =
5465020Sgblack@eecs.umich.edu            (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift;
5475020Sgblack@eecs.umich.edu
5485020Sgblack@eecs.umich.edu        if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
5495020Sgblack@eecs.umich.edu            if (inst->isLoad()) {
5505020Sgblack@eecs.umich.edu                // If this load is to the same block as an external snoop
5515020Sgblack@eecs.umich.edu                // invalidate that we've observed then the load needs to be
5525020Sgblack@eecs.umich.edu                // squashed as it could have newer data
5535020Sgblack@eecs.umich.edu                if (ld_inst->hitExternalSnoop()) {
5545020Sgblack@eecs.umich.edu                    if (!memDepViolator ||
5555020Sgblack@eecs.umich.edu                            ld_inst->seqNum < memDepViolator->seqNum) {
5565020Sgblack@eecs.umich.edu                        DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] "
5575020Sgblack@eecs.umich.edu                                "and [sn:%lli] at address %#x\n",
5585020Sgblack@eecs.umich.edu                                inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
5595020Sgblack@eecs.umich.edu                        memDepViolator = ld_inst;
5605020Sgblack@eecs.umich.edu
5615020Sgblack@eecs.umich.edu                        ++lsqMemOrderViolation;
5625020Sgblack@eecs.umich.edu
5635020Sgblack@eecs.umich.edu                        return std::make_shared<GenericISA::M5PanicFault>(
5645020Sgblack@eecs.umich.edu                            "Detected fault with inst [sn:%lli] and "
5655020Sgblack@eecs.umich.edu                            "[sn:%lli] at address %#x\n",
5665020Sgblack@eecs.umich.edu                            inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
5675020Sgblack@eecs.umich.edu                    }
5685020Sgblack@eecs.umich.edu                }
5695020Sgblack@eecs.umich.edu
5705020Sgblack@eecs.umich.edu                // Otherwise, mark the load has a possible load violation
5715020Sgblack@eecs.umich.edu                // and if we see a snoop before it's commited, we need to squash
5725020Sgblack@eecs.umich.edu                ld_inst->possibleLoadViolation(true);
5735020Sgblack@eecs.umich.edu                DPRINTF(LSQUnit, "Found possible load violation at addr: %#x"
5745020Sgblack@eecs.umich.edu                        " between instructions [sn:%lli] and [sn:%lli]\n",
5754276Sgblack@eecs.umich.edu                        inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
5764726Sgblack@eecs.umich.edu            } else {
5775020Sgblack@eecs.umich.edu                // A load/store incorrectly passed this store.
5785020Sgblack@eecs.umich.edu                // Check if we already have a violator, or if it's newer
5795020Sgblack@eecs.umich.edu                // squash and refetch.
5805020Sgblack@eecs.umich.edu                if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum)
5815020Sgblack@eecs.umich.edu                    break;
5825020Sgblack@eecs.umich.edu
5835020Sgblack@eecs.umich.edu                DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and "
5845020Sgblack@eecs.umich.edu                        "[sn:%lli] at address %#x\n",
5855020Sgblack@eecs.umich.edu                        inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
5865020Sgblack@eecs.umich.edu                memDepViolator = ld_inst;
5875020Sgblack@eecs.umich.edu
5885020Sgblack@eecs.umich.edu                ++lsqMemOrderViolation;
5895020Sgblack@eecs.umich.edu
5905020Sgblack@eecs.umich.edu                return std::make_shared<GenericISA::M5PanicFault>(
5915020Sgblack@eecs.umich.edu                    "Detected fault with "
5925020Sgblack@eecs.umich.edu                    "inst [sn:%lli] and [sn:%lli] at address %#x\n",
5935020Sgblack@eecs.umich.edu                    inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
5945020Sgblack@eecs.umich.edu            }
5955020Sgblack@eecs.umich.edu        }
5965020Sgblack@eecs.umich.edu
5975020Sgblack@eecs.umich.edu        incrLdIdx(load_idx);
5985020Sgblack@eecs.umich.edu    }
5995020Sgblack@eecs.umich.edu    return NoFault;
6005020Sgblack@eecs.umich.edu}
6015020Sgblack@eecs.umich.edu
6025020Sgblack@eecs.umich.edu
6035020Sgblack@eecs.umich.edu
6045020Sgblack@eecs.umich.edu
6055020Sgblack@eecs.umich.edutemplate <class Impl>
6065020Sgblack@eecs.umich.eduFault
6075020Sgblack@eecs.umich.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst)
6085020Sgblack@eecs.umich.edu{
6095020Sgblack@eecs.umich.edu    using namespace TheISA;
6105020Sgblack@eecs.umich.edu    // Execute a specific load.
6115020Sgblack@eecs.umich.edu    Fault load_fault = NoFault;
6125020Sgblack@eecs.umich.edu
6135020Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
6144276Sgblack@eecs.umich.edu            inst->pcState(), inst->seqNum);
6155020Sgblack@eecs.umich.edu
6165020Sgblack@eecs.umich.edu    assert(!inst->isSquashed());
6175020Sgblack@eecs.umich.edu
6185020Sgblack@eecs.umich.edu    load_fault = inst->initiateAcc();
6195020Sgblack@eecs.umich.edu
6205020Sgblack@eecs.umich.edu    if (inst->isTranslationDelayed() &&
6215020Sgblack@eecs.umich.edu        load_fault == NoFault)
6225020Sgblack@eecs.umich.edu        return load_fault;
6235020Sgblack@eecs.umich.edu
6245020Sgblack@eecs.umich.edu    // If the instruction faulted or predicated false, then we need to send it
6255020Sgblack@eecs.umich.edu    // along to commit without the instruction completing.
6265020Sgblack@eecs.umich.edu    if (load_fault != NoFault || !inst->readPredicate()) {
6275020Sgblack@eecs.umich.edu        // Send this instruction to commit, also make sure iew stage
6285020Sgblack@eecs.umich.edu        // realizes there is activity.  Mark it as executed unless it
6295020Sgblack@eecs.umich.edu        // is a strictly ordered load that needs to hit the head of
6305020Sgblack@eecs.umich.edu        // commit.
6315020Sgblack@eecs.umich.edu        if (!inst->readPredicate())
6325020Sgblack@eecs.umich.edu            inst->forwardOldRegs();
6335020Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n",
6345020Sgblack@eecs.umich.edu                inst->seqNum,
6355020Sgblack@eecs.umich.edu                (load_fault != NoFault ? "fault" : "predication"));
6365020Sgblack@eecs.umich.edu        if (!(inst->hasRequest() && inst->strictlyOrdered()) ||
6375020Sgblack@eecs.umich.edu            inst->isAtCommit()) {
6385020Sgblack@eecs.umich.edu            inst->setExecuted();
6394276Sgblack@eecs.umich.edu        }
6405022Sgblack@eecs.umich.edu        iewStage->instToCommit(inst);
6415022Sgblack@eecs.umich.edu        iewStage->activityThisCycle();
6425022Sgblack@eecs.umich.edu    } else {
6435022Sgblack@eecs.umich.edu        assert(inst->effAddrValid());
6445022Sgblack@eecs.umich.edu        int load_idx = inst->lqIdx;
6455022Sgblack@eecs.umich.edu        incrLdIdx(load_idx);
6465022Sgblack@eecs.umich.edu
6475022Sgblack@eecs.umich.edu        if (checkLoads)
6485022Sgblack@eecs.umich.edu            return checkViolations(load_idx, inst);
6495022Sgblack@eecs.umich.edu    }
6505022Sgblack@eecs.umich.edu
6515022Sgblack@eecs.umich.edu    return load_fault;
6525022Sgblack@eecs.umich.edu}
6535022Sgblack@eecs.umich.edu
6545022Sgblack@eecs.umich.edutemplate <class Impl>
6555022Sgblack@eecs.umich.eduFault
6565022Sgblack@eecs.umich.eduLSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
6575022Sgblack@eecs.umich.edu{
6585022Sgblack@eecs.umich.edu    using namespace TheISA;
6595022Sgblack@eecs.umich.edu    // Make sure that a store exists.
6605022Sgblack@eecs.umich.edu    assert(stores != 0);
6615022Sgblack@eecs.umich.edu
6625022Sgblack@eecs.umich.edu    int store_idx = store_inst->sqIdx;
6635022Sgblack@eecs.umich.edu
6645022Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
6655022Sgblack@eecs.umich.edu            store_inst->pcState(), store_inst->seqNum);
6665022Sgblack@eecs.umich.edu
6675022Sgblack@eecs.umich.edu    assert(!store_inst->isSquashed());
6685022Sgblack@eecs.umich.edu
6695022Sgblack@eecs.umich.edu    // Check the recently completed loads to see if any match this store's
6705022Sgblack@eecs.umich.edu    // address.  If so, then we have a memory ordering violation.
6715022Sgblack@eecs.umich.edu    int load_idx = store_inst->lqIdx;
6725022Sgblack@eecs.umich.edu
6735022Sgblack@eecs.umich.edu    Fault store_fault = store_inst->initiateAcc();
6744276Sgblack@eecs.umich.edu
6755020Sgblack@eecs.umich.edu    if (store_inst->isTranslationDelayed() &&
6765020Sgblack@eecs.umich.edu        store_fault == NoFault)
6775020Sgblack@eecs.umich.edu        return store_fault;
6785020Sgblack@eecs.umich.edu
6795020Sgblack@eecs.umich.edu    if (!store_inst->readPredicate())
6805020Sgblack@eecs.umich.edu        store_inst->forwardOldRegs();
6815020Sgblack@eecs.umich.edu
6825020Sgblack@eecs.umich.edu    if (storeQueue[store_idx].size == 0) {
6835020Sgblack@eecs.umich.edu        DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n",
6845020Sgblack@eecs.umich.edu                store_inst->pcState(), store_inst->seqNum);
6855020Sgblack@eecs.umich.edu
6865020Sgblack@eecs.umich.edu        return store_fault;
6875020Sgblack@eecs.umich.edu    } else if (!store_inst->readPredicate()) {
6885020Sgblack@eecs.umich.edu        DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n",
6895020Sgblack@eecs.umich.edu                store_inst->seqNum);
6905020Sgblack@eecs.umich.edu        return store_fault;
6915020Sgblack@eecs.umich.edu    }
6925020Sgblack@eecs.umich.edu
6935020Sgblack@eecs.umich.edu    assert(store_fault == NoFault);
6945020Sgblack@eecs.umich.edu
6955020Sgblack@eecs.umich.edu    if (store_inst->isStoreConditional()) {
6965020Sgblack@eecs.umich.edu        // Store conditionals need to set themselves as able to
6975020Sgblack@eecs.umich.edu        // writeback if we haven't had a fault by here.
6985020Sgblack@eecs.umich.edu        storeQueue[store_idx].canWB = true;
6994276Sgblack@eecs.umich.edu
7004276Sgblack@eecs.umich.edu        ++storesToWB;
7015022Sgblack@eecs.umich.edu    }
7025022Sgblack@eecs.umich.edu
7035022Sgblack@eecs.umich.edu    return checkViolations(load_idx, store_inst);
7045022Sgblack@eecs.umich.edu
7055022Sgblack@eecs.umich.edu}
7065022Sgblack@eecs.umich.edu
7075022Sgblack@eecs.umich.edutemplate <class Impl>
7085022Sgblack@eecs.umich.eduvoid
7095022Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoad()
7105022Sgblack@eecs.umich.edu{
7115022Sgblack@eecs.umich.edu    assert(loadQueue[loadHead]);
7125022Sgblack@eecs.umich.edu
7135022Sgblack@eecs.umich.edu    DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
7145022Sgblack@eecs.umich.edu            loadQueue[loadHead]->pcState());
7155022Sgblack@eecs.umich.edu
7165022Sgblack@eecs.umich.edu    loadQueue[loadHead] = NULL;
7175022Sgblack@eecs.umich.edu
7185022Sgblack@eecs.umich.edu    incrLdIdx(loadHead);
7195022Sgblack@eecs.umich.edu
7205022Sgblack@eecs.umich.edu    --loads;
7215022Sgblack@eecs.umich.edu}
7225022Sgblack@eecs.umich.edu
7235022Sgblack@eecs.umich.edutemplate <class Impl>
7245022Sgblack@eecs.umich.eduvoid
7255022Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst)
7265022Sgblack@eecs.umich.edu{
7275022Sgblack@eecs.umich.edu    assert(loads == 0 || loadQueue[loadHead]);
7285022Sgblack@eecs.umich.edu
7294276Sgblack@eecs.umich.edu    while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
7305020Sgblack@eecs.umich.edu        commitLoad();
7315020Sgblack@eecs.umich.edu    }
7325020Sgblack@eecs.umich.edu}
7335020Sgblack@eecs.umich.edu
7345020Sgblack@eecs.umich.edutemplate <class Impl>
7355020Sgblack@eecs.umich.eduvoid
7365020Sgblack@eecs.umich.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
7375020Sgblack@eecs.umich.edu{
7385020Sgblack@eecs.umich.edu    assert(stores == 0 || storeQueue[storeHead].inst);
7395020Sgblack@eecs.umich.edu
7405020Sgblack@eecs.umich.edu    int store_idx = storeHead;
7415020Sgblack@eecs.umich.edu
7425020Sgblack@eecs.umich.edu    while (store_idx != storeTail) {
7435020Sgblack@eecs.umich.edu        assert(storeQueue[store_idx].inst);
7445020Sgblack@eecs.umich.edu        // Mark any stores that are now committed and have not yet
7455020Sgblack@eecs.umich.edu        // been marked as able to write back.
7465020Sgblack@eecs.umich.edu        if (!storeQueue[store_idx].canWB) {
7475020Sgblack@eecs.umich.edu            if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
7485020Sgblack@eecs.umich.edu                break;
7495020Sgblack@eecs.umich.edu            }
7505020Sgblack@eecs.umich.edu            DPRINTF(LSQUnit, "Marking store as able to write back, PC "
7515020Sgblack@eecs.umich.edu                    "%s [sn:%lli]\n",
7525020Sgblack@eecs.umich.edu                    storeQueue[store_idx].inst->pcState(),
7535020Sgblack@eecs.umich.edu                    storeQueue[store_idx].inst->seqNum);
7544276Sgblack@eecs.umich.edu
7554276Sgblack@eecs.umich.edu            storeQueue[store_idx].canWB = true;
7564276Sgblack@eecs.umich.edu
7574276Sgblack@eecs.umich.edu            ++storesToWB;
7584276Sgblack@eecs.umich.edu        }
7594276Sgblack@eecs.umich.edu
7604276Sgblack@eecs.umich.edu        incrStIdx(store_idx);
761    }
762}
763
764template <class Impl>
765void
766LSQUnit<Impl>::writebackPendingStore()
767{
768    if (hasPendingPkt) {
769        assert(pendingPkt != NULL);
770
771        // If the cache is blocked, this will store the packet for retry.
772        if (sendStore(pendingPkt)) {
773            storePostSend(pendingPkt);
774        }
775        pendingPkt = NULL;
776        hasPendingPkt = false;
777    }
778}
779
780template <class Impl>
781void
782LSQUnit<Impl>::writebackStores()
783{
784    // First writeback the second packet from any split store that didn't
785    // complete last cycle because there weren't enough cache ports available.
786    if (TheISA::HasUnalignedMemAcc) {
787        writebackPendingStore();
788    }
789
790    while (storesToWB > 0 &&
791           storeWBIdx != storeTail &&
792           storeQueue[storeWBIdx].inst &&
793           storeQueue[storeWBIdx].canWB &&
794           ((!needsTSO) || (!storeInFlight)) &&
795           usedPorts < cachePorts) {
796
797        if (isStoreBlocked) {
798            DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
799                    " is blocked!\n");
800            break;
801        }
802
803        // Store didn't write any data so no need to write it back to
804        // memory.
805        if (storeQueue[storeWBIdx].size == 0) {
806            completeStore(storeWBIdx);
807
808            incrStIdx(storeWBIdx);
809
810            continue;
811        }
812
813        ++usedPorts;
814
815        if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
816            incrStIdx(storeWBIdx);
817
818            continue;
819        }
820
821        assert(storeQueue[storeWBIdx].req);
822        assert(!storeQueue[storeWBIdx].committed);
823
824        if (TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit) {
825            assert(storeQueue[storeWBIdx].sreqLow);
826            assert(storeQueue[storeWBIdx].sreqHigh);
827        }
828
829        DynInstPtr inst = storeQueue[storeWBIdx].inst;
830
831        Request *req = storeQueue[storeWBIdx].req;
832        RequestPtr sreqLow = storeQueue[storeWBIdx].sreqLow;
833        RequestPtr sreqHigh = storeQueue[storeWBIdx].sreqHigh;
834
835        storeQueue[storeWBIdx].committed = true;
836
837        assert(!inst->memData);
838        inst->memData = new uint8_t[req->getSize()];
839
840        if (storeQueue[storeWBIdx].isAllZeros)
841            memset(inst->memData, 0, req->getSize());
842        else
843            memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize());
844
845        PacketPtr data_pkt;
846        PacketPtr snd_data_pkt = NULL;
847
848        LSQSenderState *state = new LSQSenderState;
849        state->isLoad = false;
850        state->idx = storeWBIdx;
851        state->inst = inst;
852
853        if (!TheISA::HasUnalignedMemAcc || !storeQueue[storeWBIdx].isSplit) {
854
855            // Build a single data packet if the store isn't split.
856            data_pkt = Packet::createWrite(req);
857            data_pkt->dataStatic(inst->memData);
858            data_pkt->senderState = state;
859        } else {
860            // Create two packets if the store is split in two.
861            data_pkt = Packet::createWrite(sreqLow);
862            snd_data_pkt = Packet::createWrite(sreqHigh);
863
864            data_pkt->dataStatic(inst->memData);
865            snd_data_pkt->dataStatic(inst->memData + sreqLow->getSize());
866
867            data_pkt->senderState = state;
868            snd_data_pkt->senderState = state;
869
870            state->isSplit = true;
871            state->outstanding = 2;
872
873            // Can delete the main request now.
874            delete req;
875            req = sreqLow;
876        }
877
878        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
879                "to Addr:%#x, data:%#x [sn:%lli]\n",
880                storeWBIdx, inst->pcState(),
881                req->getPaddr(), (int)*(inst->memData),
882                inst->seqNum);
883
884        // @todo: Remove this SC hack once the memory system handles it.
885        if (inst->isStoreConditional()) {
886            assert(!storeQueue[storeWBIdx].isSplit);
887            // Disable recording the result temporarily.  Writing to
888            // misc regs normally updates the result, but this is not
889            // the desired behavior when handling store conditionals.
890            inst->recordResult(false);
891            bool success = TheISA::handleLockedWrite(inst.get(), req, cacheBlockMask);
892            inst->recordResult(true);
893
894            if (!success) {
895                // Instantly complete this store.
896                DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed.  "
897                        "Instantly completing it.\n",
898                        inst->seqNum);
899                WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
900                cpu->schedule(wb, curTick() + 1);
901                if (cpu->checker) {
902                    // Make sure to set the LLSC data for verification
903                    // if checker is loaded
904                    inst->reqToVerify->setExtraData(0);
905                    inst->completeAcc(data_pkt);
906                }
907                completeStore(storeWBIdx);
908                incrStIdx(storeWBIdx);
909                continue;
910            }
911        } else {
912            // Non-store conditionals do not need a writeback.
913            state->noWB = true;
914        }
915
916        bool split =
917            TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit;
918
919        ThreadContext *thread = cpu->tcBase(lsqID);
920
921        if (req->isMmappedIpr()) {
922            assert(!inst->isStoreConditional());
923            TheISA::handleIprWrite(thread, data_pkt);
924            delete data_pkt;
925            if (split) {
926                assert(snd_data_pkt->req->isMmappedIpr());
927                TheISA::handleIprWrite(thread, snd_data_pkt);
928                delete snd_data_pkt;
929                delete sreqLow;
930                delete sreqHigh;
931            }
932            delete state;
933            delete req;
934            completeStore(storeWBIdx);
935            incrStIdx(storeWBIdx);
936        } else if (!sendStore(data_pkt)) {
937            DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will"
938                    "retry later\n",
939                    inst->seqNum);
940
941            // Need to store the second packet, if split.
942            if (split) {
943                state->pktToSend = true;
944                state->pendingPacket = snd_data_pkt;
945            }
946        } else {
947
948            // If split, try to send the second packet too
949            if (split) {
950                assert(snd_data_pkt);
951
952                // Ensure there are enough ports to use.
953                if (usedPorts < cachePorts) {
954                    ++usedPorts;
955                    if (sendStore(snd_data_pkt)) {
956                        storePostSend(snd_data_pkt);
957                    } else {
958                        DPRINTF(IEW, "D-Cache became blocked when writing"
959                                " [sn:%lli] second packet, will retry later\n",
960                                inst->seqNum);
961                    }
962                } else {
963
964                    // Store the packet for when there's free ports.
965                    assert(pendingPkt == NULL);
966                    pendingPkt = snd_data_pkt;
967                    hasPendingPkt = true;
968                }
969            } else {
970
971                // Not a split store.
972                storePostSend(data_pkt);
973            }
974        }
975    }
976
977    // Not sure this should set it to 0.
978    usedPorts = 0;
979
980    assert(stores >= 0 && storesToWB >= 0);
981}
982
983/*template <class Impl>
984void
985LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
986{
987    list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
988                                              mshrSeqNums.end(),
989                                              seqNum);
990
991    if (mshr_it != mshrSeqNums.end()) {
992        mshrSeqNums.erase(mshr_it);
993        DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
994    }
995}*/
996
997template <class Impl>
998void
999LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
1000{
1001    DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
1002            "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
1003
1004    int load_idx = loadTail;
1005    decrLdIdx(load_idx);
1006
1007    while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
1008        DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
1009                "[sn:%lli]\n",
1010                loadQueue[load_idx]->pcState(),
1011                loadQueue[load_idx]->seqNum);
1012
1013        if (isStalled() && load_idx == stallingLoadIdx) {
1014            stalled = false;
1015            stallingStoreIsn = 0;
1016            stallingLoadIdx = 0;
1017        }
1018
1019        // Clear the smart pointer to make sure it is decremented.
1020        loadQueue[load_idx]->setSquashed();
1021        loadQueue[load_idx] = NULL;
1022        --loads;
1023
1024        // Inefficient!
1025        loadTail = load_idx;
1026
1027        decrLdIdx(load_idx);
1028        ++lsqSquashedLoads;
1029    }
1030
1031    if (memDepViolator && squashed_num < memDepViolator->seqNum) {
1032        memDepViolator = NULL;
1033    }
1034
1035    int store_idx = storeTail;
1036    decrStIdx(store_idx);
1037
1038    while (stores != 0 &&
1039           storeQueue[store_idx].inst->seqNum > squashed_num) {
1040        // Instructions marked as can WB are already committed.
1041        if (storeQueue[store_idx].canWB) {
1042            break;
1043        }
1044
1045        DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
1046                "idx:%i [sn:%lli]\n",
1047                storeQueue[store_idx].inst->pcState(),
1048                store_idx, storeQueue[store_idx].inst->seqNum);
1049
1050        // I don't think this can happen.  It should have been cleared
1051        // by the stalling load.
1052        if (isStalled() &&
1053            storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
1054            panic("Is stalled should have been cleared by stalling load!\n");
1055            stalled = false;
1056            stallingStoreIsn = 0;
1057        }
1058
1059        // Clear the smart pointer to make sure it is decremented.
1060        storeQueue[store_idx].inst->setSquashed();
1061        storeQueue[store_idx].inst = NULL;
1062        storeQueue[store_idx].canWB = 0;
1063
1064        // Must delete request now that it wasn't handed off to
1065        // memory.  This is quite ugly.  @todo: Figure out the proper
1066        // place to really handle request deletes.
1067        delete storeQueue[store_idx].req;
1068        if (TheISA::HasUnalignedMemAcc && storeQueue[store_idx].isSplit) {
1069            delete storeQueue[store_idx].sreqLow;
1070            delete storeQueue[store_idx].sreqHigh;
1071
1072            storeQueue[store_idx].sreqLow = NULL;
1073            storeQueue[store_idx].sreqHigh = NULL;
1074        }
1075
1076        storeQueue[store_idx].req = NULL;
1077        --stores;
1078
1079        // Inefficient!
1080        storeTail = store_idx;
1081
1082        decrStIdx(store_idx);
1083        ++lsqSquashedStores;
1084    }
1085}
1086
1087template <class Impl>
1088void
1089LSQUnit<Impl>::storePostSend(PacketPtr pkt)
1090{
1091    if (isStalled() &&
1092        storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
1093        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1094                "load idx:%i\n",
1095                stallingStoreIsn, stallingLoadIdx);
1096        stalled = false;
1097        stallingStoreIsn = 0;
1098        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
1099    }
1100
1101    if (!storeQueue[storeWBIdx].inst->isStoreConditional()) {
1102        // The store is basically completed at this time. This
1103        // only works so long as the checker doesn't try to
1104        // verify the value in memory for stores.
1105        storeQueue[storeWBIdx].inst->setCompleted();
1106
1107        if (cpu->checker) {
1108            cpu->checker->verify(storeQueue[storeWBIdx].inst);
1109        }
1110    }
1111
1112    if (needsTSO) {
1113        storeInFlight = true;
1114    }
1115
1116    incrStIdx(storeWBIdx);
1117}
1118
1119template <class Impl>
1120void
1121LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
1122{
1123    iewStage->wakeCPU();
1124
1125    // Squashed instructions do not need to complete their access.
1126    if (inst->isSquashed()) {
1127        assert(!inst->isStore());
1128        ++lsqIgnoredResponses;
1129        return;
1130    }
1131
1132    if (!inst->isExecuted()) {
1133        inst->setExecuted();
1134
1135        if (inst->fault == NoFault) {
1136            // Complete access to copy data to proper place.
1137            inst->completeAcc(pkt);
1138        } else {
1139            // If the instruction has an outstanding fault, we cannot complete
1140            // the access as this discards the current fault.
1141
1142            // If we have an outstanding fault, the fault should only be of
1143            // type ReExec.
1144            assert(dynamic_cast<ReExec*>(inst->fault.get()) != nullptr);
1145
1146            DPRINTF(LSQUnit, "Not completing instruction [sn:%lli] access "
1147                    "due to pending fault.\n", inst->seqNum);
1148        }
1149    }
1150
1151    // Need to insert instruction into queue to commit
1152    iewStage->instToCommit(inst);
1153
1154    iewStage->activityThisCycle();
1155
1156    // see if this load changed the PC
1157    iewStage->checkMisprediction(inst);
1158}
1159
1160template <class Impl>
1161void
1162LSQUnit<Impl>::completeStore(int store_idx)
1163{
1164    assert(storeQueue[store_idx].inst);
1165    storeQueue[store_idx].completed = true;
1166    --storesToWB;
1167    // A bit conservative because a store completion may not free up entries,
1168    // but hopefully avoids two store completions in one cycle from making
1169    // the CPU tick twice.
1170    cpu->wakeCPU();
1171    cpu->activityThisCycle();
1172
1173    if (store_idx == storeHead) {
1174        do {
1175            incrStIdx(storeHead);
1176
1177            --stores;
1178        } while (storeQueue[storeHead].completed &&
1179                 storeHead != storeTail);
1180
1181        iewStage->updateLSQNextCycle = true;
1182    }
1183
1184    DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
1185            "idx:%i\n",
1186            storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
1187
1188#if TRACING_ON
1189    if (DTRACE(O3PipeView)) {
1190        storeQueue[store_idx].inst->storeTick =
1191            curTick() - storeQueue[store_idx].inst->fetchTick;
1192    }
1193#endif
1194
1195    if (isStalled() &&
1196        storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
1197        DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1198                "load idx:%i\n",
1199                stallingStoreIsn, stallingLoadIdx);
1200        stalled = false;
1201        stallingStoreIsn = 0;
1202        iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
1203    }
1204
1205    storeQueue[store_idx].inst->setCompleted();
1206
1207    if (needsTSO) {
1208        storeInFlight = false;
1209    }
1210
1211    // Tell the checker we've completed this instruction.  Some stores
1212    // may get reported twice to the checker, but the checker can
1213    // handle that case.
1214    if (cpu->checker) {
1215        cpu->checker->verify(storeQueue[store_idx].inst);
1216    }
1217}
1218
1219template <class Impl>
1220bool
1221LSQUnit<Impl>::sendStore(PacketPtr data_pkt)
1222{
1223    if (!dcachePort->sendTimingReq(data_pkt)) {
1224        // Need to handle becoming blocked on a store.
1225        isStoreBlocked = true;
1226        ++lsqCacheBlocked;
1227        assert(retryPkt == NULL);
1228        retryPkt = data_pkt;
1229        return false;
1230    }
1231    return true;
1232}
1233
1234template <class Impl>
1235void
1236LSQUnit<Impl>::recvRetry()
1237{
1238    if (isStoreBlocked) {
1239        DPRINTF(LSQUnit, "Receiving retry: store blocked\n");
1240        assert(retryPkt != NULL);
1241
1242        LSQSenderState *state =
1243            dynamic_cast<LSQSenderState *>(retryPkt->senderState);
1244
1245        if (dcachePort->sendTimingReq(retryPkt)) {
1246            // Don't finish the store unless this is the last packet.
1247            if (!TheISA::HasUnalignedMemAcc || !state->pktToSend ||
1248                    state->pendingPacket == retryPkt) {
1249                state->pktToSend = false;
1250                storePostSend(retryPkt);
1251            }
1252            retryPkt = NULL;
1253            isStoreBlocked = false;
1254
1255            // Send any outstanding packet.
1256            if (TheISA::HasUnalignedMemAcc && state->pktToSend) {
1257                assert(state->pendingPacket);
1258                if (sendStore(state->pendingPacket)) {
1259                    storePostSend(state->pendingPacket);
1260                }
1261            }
1262        } else {
1263            // Still blocked!
1264            ++lsqCacheBlocked;
1265        }
1266    }
1267}
1268
1269template <class Impl>
1270inline void
1271LSQUnit<Impl>::incrStIdx(int &store_idx) const
1272{
1273    if (++store_idx >= SQEntries)
1274        store_idx = 0;
1275}
1276
1277template <class Impl>
1278inline void
1279LSQUnit<Impl>::decrStIdx(int &store_idx) const
1280{
1281    if (--store_idx < 0)
1282        store_idx += SQEntries;
1283}
1284
1285template <class Impl>
1286inline void
1287LSQUnit<Impl>::incrLdIdx(int &load_idx) const
1288{
1289    if (++load_idx >= LQEntries)
1290        load_idx = 0;
1291}
1292
1293template <class Impl>
1294inline void
1295LSQUnit<Impl>::decrLdIdx(int &load_idx) const
1296{
1297    if (--load_idx < 0)
1298        load_idx += LQEntries;
1299}
1300
1301template <class Impl>
1302void
1303LSQUnit<Impl>::dumpInsts() const
1304{
1305    cprintf("Load store queue: Dumping instructions.\n");
1306    cprintf("Load queue size: %i\n", loads);
1307    cprintf("Load queue: ");
1308
1309    int load_idx = loadHead;
1310
1311    while (load_idx != loadTail && loadQueue[load_idx]) {
1312        const DynInstPtr &inst(loadQueue[load_idx]);
1313        cprintf("%s.[sn:%i] ", inst->pcState(), inst->seqNum);
1314
1315        incrLdIdx(load_idx);
1316    }
1317    cprintf("\n");
1318
1319    cprintf("Store queue size: %i\n", stores);
1320    cprintf("Store queue: ");
1321
1322    int store_idx = storeHead;
1323
1324    while (store_idx != storeTail && storeQueue[store_idx].inst) {
1325        const DynInstPtr &inst(storeQueue[store_idx].inst);
1326        cprintf("%s.[sn:%i] ", inst->pcState(), inst->seqNum);
1327
1328        incrStIdx(store_idx);
1329    }
1330
1331    cprintf("\n");
1332}
1333
1334#endif//__CPU_O3_LSQ_UNIT_IMPL_HH__
1335