/*
 * Copyright (c) 2013-2014,2017-2018,2020 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "cpu/minor/lsq.hh"

#include <iomanip>
#include <sstream>

#include "arch/locked_mem.hh"
#include "base/logging.hh"
#include "base/trace.hh"
#include "cpu/minor/exec_context.hh"
#include "cpu/minor/execute.hh"
#include "cpu/minor/pipeline.hh"
#include "cpu/utils.hh"
#include "debug/Activity.hh"
#include "debug/MinorMem.hh"

namespace Minor
{

LSQ::LSQRequest::LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
    PacketDataPtr data_, uint64_t *res_) :
    SenderState(),
    port(port_),
    inst(inst_),
    isLoad(isLoad_),
    data(data_),
    packet(NULL),
    request(),
    res(res_),
    skipped(false),
    issuedToMemory(false),
    isTranslationDelayed(false),
    state(NotIssued)
{
    request = std::make_shared<Request>();
}

void
LSQ::LSQRequest::tryToSuppressFault()
{
    SimpleThread &thread = *port.cpu.threads[inst->id.threadId];
    TheISA::PCState old_pc = thread.pcState();
    ExecContext context(port.cpu, thread, port.execute, inst);
    M5_VAR_USED Fault fault = inst->translationFault;

    // Give the instruction a chance to suppress a translation fault
    inst->translationFault = inst->staticInst->initiateAcc(&context, nullptr);
    if (inst->translationFault == NoFault) {
        DPRINTFS(MinorMem, (&port),
                 "Translation fault suppressed for inst:%s\n", *inst);
    } else {
        assert(inst->translationFault == fault);
    }
    thread.pcState(old_pc);
}

void
LSQ::LSQRequest::completeDisabledMemAccess()
{
    DPRINTFS(MinorMem, (&port), "Complete disabled mem access for inst:%s\n",
             *inst);

    SimpleThread &thread = *port.cpu.threads[inst->id.threadId];
    TheISA::PCState old_pc = thread.pcState();

    ExecContext context(port.cpu, thread, port.execute, inst);

    context.setMemAccPredicate(false);
    inst->staticInst->completeAcc(nullptr, &context, inst->traceData);

    thread.pcState(old_pc);
}

void
LSQ::LSQRequest::disableMemAccess()
{
    port.cpu.threads[inst->id.threadId]->setMemAccPredicate(false);
    DPRINTFS(MinorMem, (&port), "Disable mem access for inst:%s\n", *inst);
}

LSQ::AddrRangeCoverage
LSQ::LSQRequest::containsAddrRangeOf(
    Addr req1_addr, unsigned int req1_size,
    Addr req2_addr, unsigned int req2_size)
{
    /* 'end' here means the address of the byte just past the request
     *  blocks */
    Addr req2_end_addr = req2_addr + req2_size;
    Addr req1_end_addr = req1_addr + req1_size;

    AddrRangeCoverage ret;

    if (req1_addr >= req2_end_addr || req1_end_addr <= req2_addr)
        ret = NoAddrRangeCoverage;
    else if (req1_addr <= req2_addr && req1_end_addr >= req2_end_addr)
        ret = FullAddrRangeCoverage;
    else
        ret = PartialAddrRangeCoverage;

    return ret;
}

LSQ::AddrRangeCoverage
LSQ::LSQRequest::containsAddrRangeOf(LSQRequestPtr other_request)
{
    AddrRangeCoverage ret = containsAddrRangeOf(
        request->getPaddr(), request->getSize(),
        other_request->request->getPaddr(), other_request->request->getSize());
    /* If there is a strobe mask then store data forwarding might not be
     * correct. Instead of checking enablemant of every byte we just fall back
     * to PartialAddrRangeCoverage to prohibit store data forwarding */
    if (ret == FullAddrRangeCoverage && request->isMasked())
        ret = PartialAddrRangeCoverage;
    return ret;
}


bool
LSQ::LSQRequest::isBarrier()
{
    return inst->isInst() && inst->staticInst->isFullMemBarrier();
}

bool
LSQ::LSQRequest::needsToBeSentToStoreBuffer()
{
    return state == StoreToStoreBuffer;
}

void
LSQ::LSQRequest::setState(LSQRequestState new_state)
{
    DPRINTFS(MinorMem, (&port), "Setting state from %d to %d for request:"
        " %s\n", state, new_state, *inst);
    state = new_state;
}

bool
LSQ::LSQRequest::isComplete() const
{
    /* @todo, There is currently only one 'completed' state.  This
     *  may not be a good choice */
    return state == Complete;
}

void
LSQ::LSQRequest::reportData(std::ostream &os) const
{
    os << (isLoad ? 'R' : 'W') << ';';
    inst->reportData(os);
    os << ';' << state;
}

std::ostream &
operator <<(std::ostream &os, LSQ::AddrRangeCoverage coverage)
{
    switch (coverage) {
      case LSQ::PartialAddrRangeCoverage:
        os << "PartialAddrRangeCoverage";
        break;
      case LSQ::FullAddrRangeCoverage:
        os << "FullAddrRangeCoverage";
        break;
      case LSQ::NoAddrRangeCoverage:
        os << "NoAddrRangeCoverage";
        break;
      default:
        os << "AddrRangeCoverage-" << static_cast<int>(coverage);
        break;
    }
    return os;
}

std::ostream &
operator <<(std::ostream &os, LSQ::LSQRequest::LSQRequestState state)
{
    switch (state) {
      case LSQ::LSQRequest::NotIssued:
        os << "NotIssued";
        break;
      case LSQ::LSQRequest::InTranslation:
        os << "InTranslation";
        break;
      case LSQ::LSQRequest::Translated:
        os << "Translated";
        break;
      case LSQ::LSQRequest::Failed:
        os << "Failed";
        break;
      case LSQ::LSQRequest::RequestIssuing:
        os << "RequestIssuing";
        break;
      case LSQ::LSQRequest::StoreToStoreBuffer:
        os << "StoreToStoreBuffer";
        break;
      case LSQ::LSQRequest::StoreInStoreBuffer:
        os << "StoreInStoreBuffer";
        break;
      case LSQ::LSQRequest::StoreBufferIssuing:
        os << "StoreBufferIssuing";
        break;
      case LSQ::LSQRequest::RequestNeedsRetry:
        os << "RequestNeedsRetry";
        break;
      case LSQ::LSQRequest::StoreBufferNeedsRetry:
        os << "StoreBufferNeedsRetry";
        break;
      case LSQ::LSQRequest::Complete:
        os << "Complete";
        break;
      default:
        os << "LSQRequestState-" << static_cast<int>(state);
        break;
    }
    return os;
}

void
LSQ::clearMemBarrier(MinorDynInstPtr inst)
{
    bool is_last_barrier =
        inst->id.execSeqNum >= lastMemBarrier[inst->id.threadId];

    DPRINTF(MinorMem, "Moving %s barrier out of store buffer inst: %s\n",
        (is_last_barrier ? "last" : "a"), *inst);

    if (is_last_barrier)
        lastMemBarrier[inst->id.threadId] = 0;
}

void
LSQ::SingleDataRequest::finish(const Fault &fault_, const RequestPtr &request_,
                               ThreadContext *tc, BaseTLB::Mode mode)
{
    port.numAccessesInDTLB--;

    DPRINTFS(MinorMem, (&port), "Received translation response for"
             " request: %s delayed:%d %s\n", *inst, isTranslationDelayed,
             fault_ != NoFault ? fault_->name() : "");

    if (fault_ != NoFault) {
        inst->translationFault = fault_;
        if (isTranslationDelayed) {
            tryToSuppressFault();
            if (inst->translationFault == NoFault) {
                completeDisabledMemAccess();
                setState(Complete);
            }
        }
        setState(Translated);
    } else {
        setState(Translated);
        makePacket();
    }
    port.tryToSendToTransfers(this);

    /* Let's try and wake up the processor for the next cycle */
    port.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
}

void
LSQ::SingleDataRequest::startAddrTranslation()
{
    ThreadContext *thread = port.cpu.getContext(
        inst->id.threadId);

    const auto &byte_enable = request->getByteEnable();
    if (isAnyActiveElement(byte_enable.cbegin(), byte_enable.cend())) {
        port.numAccessesInDTLB++;

        setState(LSQ::LSQRequest::InTranslation);

        DPRINTFS(MinorMem, (&port), "Submitting DTLB request\n");
        /* Submit the translation request.  The response will come through
         *  finish/markDelayed on the LSQRequest as it bears the Translation
         *  interface */
        thread->getMMUPtr()->translateTiming(
            request, thread, this, (isLoad ? BaseTLB::Read : BaseTLB::Write));
    } else {
        disableMemAccess();
        setState(LSQ::LSQRequest::Complete);
    }
}

void
LSQ::SingleDataRequest::retireResponse(PacketPtr packet_)
{
    DPRINTFS(MinorMem, (&port), "Retiring packet\n");
    packet = packet_;
    packetInFlight = false;
    setState(Complete);
}

void
LSQ::SplitDataRequest::finish(const Fault &fault_, const RequestPtr &request_,
                              ThreadContext *tc, BaseTLB::Mode mode)
{
    port.numAccessesInDTLB--;

    M5_VAR_USED unsigned int expected_fragment_index =
        numTranslatedFragments;

    numInTranslationFragments--;
    numTranslatedFragments++;

    DPRINTFS(MinorMem, (&port), "Received translation response for fragment"
             " %d of request: %s delayed:%d %s\n", expected_fragment_index,
             *inst, isTranslationDelayed,
             fault_ != NoFault ? fault_->name() : "");

    assert(request_ == fragmentRequests[expected_fragment_index]);

    /* Wake up next cycle to get things going again in case the
     *  tryToSendToTransfers does take */
    port.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);

    if (fault_ != NoFault) {
        /* tryToSendToTransfers will handle the fault */
        inst->translationFault = fault_;

        DPRINTFS(MinorMem, (&port), "Faulting translation for fragment:"
            " %d of request: %s\n",
            expected_fragment_index, *inst);

        if (expected_fragment_index > 0 || isTranslationDelayed)
            tryToSuppressFault();
        if (expected_fragment_index == 0) {
            if (isTranslationDelayed && inst->translationFault == NoFault) {
                completeDisabledMemAccess();
                setState(Complete);
            } else {
                setState(Translated);
            }
        } else if (inst->translationFault == NoFault) {
            setState(Translated);
            numTranslatedFragments--;
            makeFragmentPackets();
        } else {
            setState(Translated);
        }
        port.tryToSendToTransfers(this);
    } else if (numTranslatedFragments == numFragments) {
        makeFragmentPackets();
        setState(Translated);
        port.tryToSendToTransfers(this);
    } else {
        /* Avoid calling translateTiming from within ::finish */
        assert(!translationEvent.scheduled());
        port.cpu.schedule(translationEvent, curTick());
    }
}

LSQ::SplitDataRequest::SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
    bool isLoad_, PacketDataPtr data_, uint64_t *res_) :
    LSQRequest(port_, inst_, isLoad_, data_, res_),
    translationEvent([this]{ sendNextFragmentToTranslation(); },
                     "translationEvent"),
    numFragments(0),
    numInTranslationFragments(0),
    numTranslatedFragments(0),
    numIssuedFragments(0),
    numRetiredFragments(0),
    fragmentRequests(),
    fragmentPackets()
{
    /* Don't know how many elements are needed until the request is
     *  populated by the caller. */
}

LSQ::SplitDataRequest::~SplitDataRequest()
{
    for (auto i = fragmentPackets.begin();
         i != fragmentPackets.end(); i++)
    {
        delete *i;
    }
}

void
LSQ::SplitDataRequest::makeFragmentRequests()
{
    Addr base_addr = request->getVaddr();
    unsigned int whole_size = request->getSize();
    unsigned int line_width = port.lineWidth;

    unsigned int fragment_size;
    Addr fragment_addr;

    std::vector<bool> fragment_write_byte_en;

    /* Assume that this transfer is across potentially many block snap
     * boundaries:
     *
     * |      _|________|________|________|___     |
     * |     |0| 1      | 2      | 3      | 4 |    |
     * |     |_|________|________|________|___|    |
     * |       |        |        |        |        |
     *
     *  The first transfer (0) can be up to lineWidth in size.
     *  All the middle transfers (1-3) are lineWidth in size
     *  The last transfer (4) can be from zero to lineWidth - 1 in size
     */
    unsigned int first_fragment_offset =
        addrBlockOffset(base_addr, line_width);
    unsigned int last_fragment_size =
        addrBlockOffset(base_addr + whole_size, line_width);
    unsigned int first_fragment_size =
        line_width - first_fragment_offset;

    unsigned int middle_fragments_total_size =
        whole_size - (first_fragment_size + last_fragment_size);

    assert(addrBlockOffset(middle_fragments_total_size, line_width) == 0);

    unsigned int middle_fragment_count =
        middle_fragments_total_size / line_width;

    numFragments = 1 /* first */ + middle_fragment_count +
        (last_fragment_size == 0 ? 0 : 1);

    DPRINTFS(MinorMem, (&port), "Dividing transfer into %d fragmentRequests."
        " First fragment size: %d Last fragment size: %d\n",
        numFragments, first_fragment_size,
        (last_fragment_size == 0 ? line_width : last_fragment_size));

    assert(((middle_fragment_count * line_width) +
        first_fragment_size + last_fragment_size) == whole_size);

    fragment_addr = base_addr;
    fragment_size = first_fragment_size;

    /* Just past the last address in the request */
    Addr end_addr = base_addr + whole_size;

    auto& byte_enable = request->getByteEnable();
    unsigned int num_disabled_fragments = 0;

    for (unsigned int fragment_index = 0; fragment_index < numFragments;
         fragment_index++)
    {
        M5_VAR_USED bool is_last_fragment = false;

        if (fragment_addr == base_addr) {
            /* First fragment */
            fragment_size = first_fragment_size;
        } else {
            if ((fragment_addr + line_width) > end_addr) {
                /* Adjust size of last fragment */
                fragment_size = end_addr - fragment_addr;
                is_last_fragment = true;
            } else {
                /* Middle fragments */
                fragment_size = line_width;
            }
        }

        RequestPtr fragment = std::make_shared<Request>();
        bool disabled_fragment = false;

        fragment->setContext(request->contextId());
        // Set up byte-enable mask for the current fragment
        auto it_start = byte_enable.begin() +
            (fragment_addr - base_addr);
        auto it_end = byte_enable.begin() +
            (fragment_addr - base_addr) + fragment_size;
        if (isAnyActiveElement(it_start, it_end)) {
            fragment->setVirt(
                fragment_addr, fragment_size, request->getFlags(),
                request->requestorId(),
                request->getPC());
            fragment->setByteEnable(std::vector<bool>(it_start, it_end));
        } else {
            disabled_fragment = true;
        }

        if (!disabled_fragment) {
            DPRINTFS(MinorMem, (&port), "Generating fragment addr: 0x%x"
                " size: %d (whole request addr: 0x%x size: %d) %s\n",
                fragment_addr, fragment_size, base_addr, whole_size,
                (is_last_fragment ? "last fragment" : ""));

            fragmentRequests.push_back(fragment);
        } else {
            num_disabled_fragments++;
        }

        fragment_addr += fragment_size;
    }
    assert(numFragments >= num_disabled_fragments);
    numFragments -= num_disabled_fragments;
}

void
LSQ::SplitDataRequest::makeFragmentPackets()
{
    assert(numTranslatedFragments > 0);
    Addr base_addr = request->getVaddr();

    DPRINTFS(MinorMem, (&port), "Making packets for request: %s\n", *inst);

    for (unsigned int fragment_index = 0;
         fragment_index < numTranslatedFragments;
         fragment_index++)
    {
        RequestPtr fragment = fragmentRequests[fragment_index];

        DPRINTFS(MinorMem, (&port), "Making packet %d for request: %s"
            " (%d, 0x%x)\n",
            fragment_index, *inst,
            (fragment->hasPaddr() ? "has paddr" : "no paddr"),
            (fragment->hasPaddr() ? fragment->getPaddr() : 0));

        Addr fragment_addr = fragment->getVaddr();
        unsigned int fragment_size = fragment->getSize();

        uint8_t *request_data = NULL;

        if (!isLoad) {
            /* Split data for Packets.  Will become the property of the
             *  outgoing Packets */
            request_data = new uint8_t[fragment_size];
            std::memcpy(request_data, data + (fragment_addr - base_addr),
                fragment_size);
        }

        assert(fragment->hasPaddr());

        PacketPtr fragment_packet =
            makePacketForRequest(fragment, isLoad, this, request_data);

        fragmentPackets.push_back(fragment_packet);
        /* Accumulate flags in parent request */
        request->setFlags(fragment->getFlags());
    }

    /* Might as well make the overall/response packet here */
    /* Get the physical address for the whole request/packet from the first
     *  fragment */
    request->setPaddr(fragmentRequests[0]->getPaddr());
    makePacket();
}

void
LSQ::SplitDataRequest::startAddrTranslation()
{
    makeFragmentRequests();

    if (numFragments > 0) {
        setState(LSQ::LSQRequest::InTranslation);
        numInTranslationFragments = 0;
        numTranslatedFragments = 0;

        /* @todo, just do these in sequence for now with
         * a loop of:
         * do {
         *  sendNextFragmentToTranslation ; translateTiming ; finish
         * } while (numTranslatedFragments != numFragments);
         */

        /* Do first translation */
        sendNextFragmentToTranslation();
    } else {
        disableMemAccess();
        setState(LSQ::LSQRequest::Complete);
    }
}

PacketPtr
LSQ::SplitDataRequest::getHeadPacket()
{
    assert(numIssuedFragments < numTranslatedFragments);

    return fragmentPackets[numIssuedFragments];
}

void
LSQ::SplitDataRequest::stepToNextPacket()
{
    assert(numIssuedFragments < numTranslatedFragments);

    numIssuedFragments++;
}

void
LSQ::SplitDataRequest::retireResponse(PacketPtr response)
{
    assert(inst->translationFault == NoFault);
    assert(numRetiredFragments < numTranslatedFragments);

    DPRINTFS(MinorMem, (&port), "Retiring fragment addr: 0x%x size: %d"
        " offset: 0x%x (retired fragment num: %d)\n",
        response->req->getVaddr(), response->req->getSize(),
        request->getVaddr() - response->req->getVaddr(),
        numRetiredFragments);

    numRetiredFragments++;

    if (skipped) {
        /* Skip because we already knew the request had faulted or been
         *  skipped */
        DPRINTFS(MinorMem, (&port), "Skipping this fragment\n");
    } else if (response->isError()) {
        /* Mark up the error and leave to execute to handle it */
        DPRINTFS(MinorMem, (&port), "Fragment has an error, skipping\n");
        setSkipped();
        packet->copyError(response);
    } else {
        if (isLoad) {
            if (!data) {
                /* For a split transfer, a Packet must be constructed
                 *  to contain all returning data.  This is that packet's
                 *  data */
                data = new uint8_t[request->getSize()];
            }

            /* Populate the portion of the overall response data represented
             *  by the response fragment */
            std::memcpy(
                data + (response->req->getVaddr() - request->getVaddr()),
                response->getConstPtr<uint8_t>(),
                response->req->getSize());
        }
    }

    /* Complete early if we're skipping are no more in-flight accesses */
    if (skipped && !hasPacketsInMemSystem()) {
        DPRINTFS(MinorMem, (&port), "Completed skipped burst\n");
        setState(Complete);
        if (packet->needsResponse())
            packet->makeResponse();
    }

    if (numRetiredFragments == numTranslatedFragments)
        setState(Complete);

    if (!skipped && isComplete()) {
        DPRINTFS(MinorMem, (&port), "Completed burst %d\n", packet != NULL);

        DPRINTFS(MinorMem, (&port), "Retired packet isRead: %d isWrite: %d"
             " needsResponse: %d packetSize: %s requestSize: %s responseSize:"
             " %s\n", packet->isRead(), packet->isWrite(),
             packet->needsResponse(), packet->getSize(), request->getSize(),
             response->getSize());

        /* A request can become complete by several paths, this is a sanity
         *  check to make sure the packet's data is created */
        if (!data) {
            data = new uint8_t[request->getSize()];
        }

        if (isLoad) {
            DPRINTFS(MinorMem, (&port), "Copying read data\n");
            std::memcpy(packet->getPtr<uint8_t>(), data, request->getSize());
        }
        packet->makeResponse();
    }

    /* Packets are all deallocated together in ~SplitLSQRequest */
}

void
LSQ::SplitDataRequest::sendNextFragmentToTranslation()
{
    unsigned int fragment_index = numTranslatedFragments;

    ThreadContext *thread = port.cpu.getContext(
        inst->id.threadId);

    DPRINTFS(MinorMem, (&port), "Submitting DTLB request for fragment: %d\n",
        fragment_index);

    port.numAccessesInDTLB++;
    numInTranslationFragments++;

    thread->getMMUPtr()->translateTiming(
        fragmentRequests[fragment_index], thread, this, (isLoad ?
        BaseTLB::Read : BaseTLB::Write));
}

bool
LSQ::StoreBuffer::canInsert() const
{
    /* @todo, support store amalgamation */
    return slots.size() < numSlots;
}

void
LSQ::StoreBuffer::deleteRequest(LSQRequestPtr request)
{
    auto found = std::find(slots.begin(), slots.end(), request);

    if (found != slots.end()) {
        DPRINTF(MinorMem, "Deleting request: %s %s %s from StoreBuffer\n",
            request, *found, *(request->inst));
        slots.erase(found);

        delete request;
    }
}

void
LSQ::StoreBuffer::insert(LSQRequestPtr request)
{
    if (!canInsert()) {
        warn("%s: store buffer insertion without space to insert from"
            " inst: %s\n", name(), *(request->inst));
    }

    DPRINTF(MinorMem, "Pushing store: %s into store buffer\n", request);

    numUnissuedAccesses++;

    if (request->state != LSQRequest::Complete)
        request->setState(LSQRequest::StoreInStoreBuffer);

    slots.push_back(request);

    /* Let's try and wake up the processor for the next cycle to step
     *  the store buffer */
    lsq.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
}

LSQ::AddrRangeCoverage
LSQ::StoreBuffer::canForwardDataToLoad(LSQRequestPtr request,
    unsigned int &found_slot)
{
    unsigned int slot_index = slots.size() - 1;
    auto i = slots.rbegin();
    AddrRangeCoverage ret = NoAddrRangeCoverage;

    /* Traverse the store buffer in reverse order (most to least recent)
     *  and try to find a slot whose address range overlaps this request */
    while (ret == NoAddrRangeCoverage && i != slots.rend()) {
        LSQRequestPtr slot = *i;

        /* Cache maintenance instructions go down via the store path but
         * they carry no data and they shouldn't be considered
         * for forwarding */
        if (slot->packet &&
            slot->inst->id.threadId == request->inst->id.threadId &&
            !slot->packet->req->isCacheMaintenance()) {
            AddrRangeCoverage coverage = slot->containsAddrRangeOf(request);

            if (coverage != NoAddrRangeCoverage) {
                DPRINTF(MinorMem, "Forwarding: slot: %d result: %s thisAddr:"
                    " 0x%x thisSize: %d slotAddr: 0x%x slotSize: %d\n",
                    slot_index, coverage,
                    request->request->getPaddr(), request->request->getSize(),
                    slot->request->getPaddr(), slot->request->getSize());

                found_slot = slot_index;
                ret = coverage;
            }
        }

        i++;
        slot_index--;
    }

    return ret;
}

/** Fill the given packet with appropriate date from slot slot_number */
void
LSQ::StoreBuffer::forwardStoreData(LSQRequestPtr load,
    unsigned int slot_number)
{
    assert(slot_number < slots.size());
    assert(load->packet);
    assert(load->isLoad);

    LSQRequestPtr store = slots[slot_number];

    assert(store->packet);
    assert(store->containsAddrRangeOf(load) == FullAddrRangeCoverage);

    Addr load_addr = load->request->getPaddr();
    Addr store_addr = store->request->getPaddr();
    Addr addr_offset = load_addr - store_addr;

    unsigned int load_size = load->request->getSize();

    DPRINTF(MinorMem, "Forwarding %d bytes for addr: 0x%x from store buffer"
        " slot: %d addr: 0x%x addressOffset: 0x%x\n",
        load_size, load_addr, slot_number,
        store_addr, addr_offset);

    void *load_packet_data = load->packet->getPtr<void>();
    void *store_packet_data = store->packet->getPtr<uint8_t>() + addr_offset;

    std::memcpy(load_packet_data, store_packet_data, load_size);
}

void
LSQ::StoreBuffer::countIssuedStore(LSQRequestPtr request)
{
    /* Barriers are accounted for as they are cleared from
     *  the queue, not after their transfers are complete */
    if (!request->isBarrier())
        numUnissuedAccesses--;
}

void
LSQ::StoreBuffer::step()
{
    DPRINTF(MinorMem, "StoreBuffer step numUnissuedAccesses: %d\n",
        numUnissuedAccesses);

    if (numUnissuedAccesses != 0 && lsq.state == LSQ::MemoryRunning) {
        /* Clear all the leading barriers */
        while (!slots.empty() &&
            slots.front()->isComplete() && slots.front()->isBarrier())
        {
            LSQRequestPtr barrier = slots.front();

            DPRINTF(MinorMem, "Clearing barrier for inst: %s\n",
                *(barrier->inst));

            numUnissuedAccesses--;
            lsq.clearMemBarrier(barrier->inst);
            slots.pop_front();

            delete barrier;
        }

        auto i = slots.begin();
        bool issued = true;
        unsigned int issue_count = 0;

        /* Skip trying if the memory system is busy */
        if (lsq.state == LSQ::MemoryNeedsRetry)
            issued = false;

        /* Try to issue all stores in order starting from the head
         *  of the queue.  Responses are allowed to be retired
         *  out of order */
        while (issued &&
            issue_count < storeLimitPerCycle &&
            lsq.canSendToMemorySystem() &&
            i != slots.end())
        {
            LSQRequestPtr request = *i;

            DPRINTF(MinorMem, "Considering request: %s, sentAllPackets: %d"
                " state: %s\n",
                *(request->inst), request->sentAllPackets(),
                request->state);

            if (request->isBarrier() && request->isComplete()) {
                /* Give up at barriers */
                issued = false;
            } else if (!(request->state == LSQRequest::StoreBufferIssuing &&
                request->sentAllPackets()))
            {
                DPRINTF(MinorMem, "Trying to send request: %s to memory"
                    " system\n", *(request->inst));

                if (lsq.tryToSend(request)) {
                    countIssuedStore(request);
                    issue_count++;
                } else {
                    /* Don't step on to the next store buffer entry if this
                     *  one hasn't issued all its packets as the store
                     *  buffer must still enforce ordering */
                    issued = false;
                }
            }
            i++;
        }
    }
}

void
LSQ::completeMemBarrierInst(MinorDynInstPtr inst,
    bool committed)
{
    if (committed) {
        /* Not already sent to the store buffer as a store request? */
        if (!inst->inStoreBuffer) {
            /* Insert an entry into the store buffer to tick off barriers
             *  until there are none in flight */
            storeBuffer.insert(new BarrierDataRequest(*this, inst));
        }
    } else {
        /* Clear the barrier anyway if it wasn't actually committed */
        clearMemBarrier(inst);
    }
}

void
LSQ::StoreBuffer::minorTrace() const
{
    unsigned int size = slots.size();
    unsigned int i = 0;
    std::ostringstream os;

    while (i < size) {
        LSQRequestPtr request = slots[i];

        request->reportData(os);

        i++;
        if (i < numSlots)
            os << ',';
    }

    while (i < numSlots) {
        os << '-';

        i++;
        if (i < numSlots)
            os << ',';
    }

    MINORTRACE("addr=%s num_unissued_stores=%d\n", os.str(),
        numUnissuedAccesses);
}

void
LSQ::tryToSendToTransfers(LSQRequestPtr request)
{
    if (state == MemoryNeedsRetry) {
        DPRINTF(MinorMem, "Request needs retry, not issuing to"
            " memory until retry arrives\n");
        return;
    }

    if (request->state == LSQRequest::InTranslation) {
        DPRINTF(MinorMem, "Request still in translation, not issuing to"
            " memory\n");
        return;
    }

    assert(request->state == LSQRequest::Translated ||
        request->state == LSQRequest::RequestIssuing ||
        request->state == LSQRequest::Failed ||
        request->state == LSQRequest::Complete);

    if (requests.empty() || requests.front() != request) {
        DPRINTF(MinorMem, "Request not at front of requests queue, can't"
            " issue to memory\n");
        return;
    }

    if (transfers.unreservedRemainingSpace() == 0) {
        DPRINTF(MinorMem, "No space to insert request into transfers"
            " queue\n");
        return;
    }

    if (request->isComplete() || request->state == LSQRequest::Failed) {
        DPRINTF(MinorMem, "Passing a %s transfer on to transfers"
            " queue\n", (request->isComplete() ? "completed" : "failed"));
        request->setState(LSQRequest::Complete);
        request->setSkipped();
        moveFromRequestsToTransfers(request);
        return;
    }

    if (!execute.instIsRightStream(request->inst)) {
        /* Wrong stream, try to abort the transfer but only do so if
         *  there are no packets in flight */
        if (request->hasPacketsInMemSystem()) {
            DPRINTF(MinorMem, "Request's inst. is from the wrong stream,"
                " waiting for responses before aborting request\n");
        } else {
            DPRINTF(MinorMem, "Request's inst. is from the wrong stream,"
                " aborting request\n");
            request->setState(LSQRequest::Complete);
            request->setSkipped();
            moveFromRequestsToTransfers(request);
        }
        return;
    }

    if (request->inst->translationFault != NoFault) {
        if (request->inst->staticInst->isPrefetch()) {
            DPRINTF(MinorMem, "Not signalling fault for faulting prefetch\n");
        }
        DPRINTF(MinorMem, "Moving faulting request into the transfers"
            " queue\n");
        request->setState(LSQRequest::Complete);
        request->setSkipped();
        moveFromRequestsToTransfers(request);
        return;
    }

    bool is_load = request->isLoad;
    bool is_llsc = request->request->isLLSC();
    bool is_release = request->request->isRelease();
    bool is_swap = request->request->isSwap();
    bool is_atomic = request->request->isAtomic();
    bool bufferable = !(request->request->isStrictlyOrdered() ||
                        is_llsc || is_swap || is_atomic || is_release);

    if (is_load) {
        if (numStoresInTransfers != 0) {
            DPRINTF(MinorMem, "Load request with stores still in transfers"
                " queue, stalling\n");
            return;
        }
    } else {
        /* Store.  Can it be sent to the store buffer? */
        if (bufferable && !request->request->isLocalAccess()) {
            request->setState(LSQRequest::StoreToStoreBuffer);
            moveFromRequestsToTransfers(request);
            DPRINTF(MinorMem, "Moving store into transfers queue\n");
            return;
        }
    }

    // Process store conditionals or store release after all previous
    // stores are completed
    if (((!is_load && is_llsc) || is_release) &&
        !storeBuffer.isDrained()) {
        DPRINTF(MinorMem, "Memory access needs to wait for store buffer"
                          " to drain\n");
        return;
    }

    /* Check if this is the head instruction (and so must be executable as
     *  its stream sequence number was checked above) for loads which must
     *  not be speculatively issued and stores which must be issued here */
    if (!bufferable) {
        if (!execute.instIsHeadInst(request->inst)) {
            DPRINTF(MinorMem, "Memory access not the head inst., can't be"
                " sure it can be performed, not issuing\n");
            return;
        }

        unsigned int forwarding_slot = 0;

        if (storeBuffer.canForwardDataToLoad(request, forwarding_slot) !=
            NoAddrRangeCoverage)
        {
            // There's at least another request that targets the same
            // address and is staying in the storeBuffer. Since our
            // request is non-bufferable (e.g., strictly ordered or atomic),
            // we must wait for the other request in the storeBuffer to
            // complete before we can issue this non-bufferable request.
            // This is to make sure that the order they access the cache is
            // correct.
            DPRINTF(MinorMem, "Memory access can receive forwarded data"
                " from the store buffer, but need to wait for store buffer"
                " to drain\n");
            return;
        }
    }

    /* True: submit this packet to the transfers queue to be sent to the
     * memory system.
     * False: skip the memory and push a packet for this request onto
     * requests */
    bool do_access = true;

    if (!is_llsc) {
        /* Check for match in the store buffer */
        if (is_load) {
            unsigned int forwarding_slot = 0;
            AddrRangeCoverage forwarding_result =
                storeBuffer.canForwardDataToLoad(request,
                forwarding_slot);

            switch (forwarding_result) {
              case FullAddrRangeCoverage:
                /* Forward data from the store buffer into this request and
                 *  repurpose this request's packet into a response packet */
                storeBuffer.forwardStoreData(request, forwarding_slot);
                request->packet->makeResponse();

                /* Just move between queues, no access */
                do_access = false;
                break;
              case PartialAddrRangeCoverage:
                DPRINTF(MinorMem, "Load partly satisfied by store buffer"
                    " data. Must wait for the store to complete\n");
                return;
                break;
              case NoAddrRangeCoverage:
                DPRINTF(MinorMem, "No forwardable data from store buffer\n");
                /* Fall through to try access */
                break;
            }
        }
    } else {
        if (!canSendToMemorySystem()) {
            DPRINTF(MinorMem, "Can't send request to memory system yet\n");
            return;
        }

        SimpleThread &thread = *cpu.threads[request->inst->id.threadId];

        TheISA::PCState old_pc = thread.pcState();
        ExecContext context(cpu, thread, execute, request->inst);

        /* Handle LLSC requests and tests */
        if (is_load) {
            TheISA::handleLockedRead(&context, request->request);
        } else {
            do_access = TheISA::handleLockedWrite(&context,
                request->request, cacheBlockMask);

            if (!do_access) {
                DPRINTF(MinorMem, "Not perfoming a memory "
                    "access for store conditional\n");
            }
        }
        thread.pcState(old_pc);
    }

    /* See the do_access comment above */
    if (do_access) {
        if (!canSendToMemorySystem()) {
            DPRINTF(MinorMem, "Can't send request to memory system yet\n");
            return;
        }

        /* Remember if this is an access which can't be idly
         *  discarded by an interrupt */
        if (!bufferable && !request->issuedToMemory) {
            numAccessesIssuedToMemory++;
            request->issuedToMemory = true;
        }

        if (tryToSend(request)) {
            moveFromRequestsToTransfers(request);
        }
    } else {
        request->setState(LSQRequest::Complete);
        moveFromRequestsToTransfers(request);
    }
}

bool
LSQ::tryToSend(LSQRequestPtr request)
{
    bool ret = false;

    if (!canSendToMemorySystem()) {
        DPRINTF(MinorMem, "Can't send request: %s yet, no space in memory\n",
            *(request->inst));
    } else {
        PacketPtr packet = request->getHeadPacket();

        DPRINTF(MinorMem, "Trying to send request: %s addr: 0x%x\n",
            *(request->inst), packet->req->getVaddr());

        /* The sender state of the packet *must* be an LSQRequest
         *  so the response can be correctly handled */
        assert(packet->findNextSenderState<LSQRequest>());

        if (request->request->isLocalAccess()) {
            ThreadContext *thread =
                cpu.getContext(cpu.contextToThread(
                                request->request->contextId()));

            if (request->isLoad)
                DPRINTF(MinorMem, "IPR read inst: %s\n", *(request->inst));
            else
                DPRINTF(MinorMem, "IPR write inst: %s\n", *(request->inst));

            request->request->localAccessor(thread, packet);

            request->stepToNextPacket();
            ret = request->sentAllPackets();

            if (!ret) {
                DPRINTF(MinorMem, "IPR access has another packet: %s\n",
                    *(request->inst));
            }

            if (ret)
                request->setState(LSQRequest::Complete);
            else
                request->setState(LSQRequest::RequestIssuing);
        } else if (dcachePort.sendTimingReq(packet)) {
            DPRINTF(MinorMem, "Sent data memory request\n");

            numAccessesInMemorySystem++;

            request->stepToNextPacket();

            ret = request->sentAllPackets();

            switch (request->state) {
              case LSQRequest::Translated:
              case LSQRequest::RequestIssuing:
                /* Fully or partially issued a request in the transfers
                 *  queue */
                request->setState(LSQRequest::RequestIssuing);
                break;
              case LSQRequest::StoreInStoreBuffer:
              case LSQRequest::StoreBufferIssuing:
                /* Fully or partially issued a request in the store
                 *  buffer */
                request->setState(LSQRequest::StoreBufferIssuing);
                break;
              default:
                panic("Unrecognized LSQ request state %d.", request->state);
            }

            state = MemoryRunning;
        } else {
            DPRINTF(MinorMem,
                "Sending data memory request - needs retry\n");

            /* Needs to be resent, wait for that */
            state = MemoryNeedsRetry;
            retryRequest = request;

            switch (request->state) {
              case LSQRequest::Translated:
              case LSQRequest::RequestIssuing:
                request->setState(LSQRequest::RequestNeedsRetry);
                break;
              case LSQRequest::StoreInStoreBuffer:
              case LSQRequest::StoreBufferIssuing:
                request->setState(LSQRequest::StoreBufferNeedsRetry);
                break;
              default:
                panic("Unrecognized LSQ request state %d.", request->state);
            }
        }
    }

    if (ret)
        threadSnoop(request);

    return ret;
}

void
LSQ::moveFromRequestsToTransfers(LSQRequestPtr request)
{
    assert(!requests.empty() && requests.front() == request);
    assert(transfers.unreservedRemainingSpace() != 0);

    /* Need to count the number of stores in the transfers
     *  queue so that loads know when their store buffer forwarding
     *  results will be correct (only when all those stores
     *  have reached the store buffer) */
    if (!request->isLoad)
        numStoresInTransfers++;

    requests.pop();
    transfers.push(request);
}

bool
LSQ::canSendToMemorySystem()
{
    return state == MemoryRunning &&
        numAccessesInMemorySystem < inMemorySystemLimit;
}

bool
LSQ::recvTimingResp(PacketPtr response)
{
    LSQRequestPtr request =
        safe_cast<LSQRequestPtr>(response->popSenderState());

    DPRINTF(MinorMem, "Received response packet inst: %s"
        " addr: 0x%x cmd: %s\n",
        *(request->inst), response->getAddr(),
        response->cmd.toString());

    numAccessesInMemorySystem--;

    if (response->isError()) {
        DPRINTF(MinorMem, "Received error response packet: %s\n",
            *request->inst);
    }

    switch (request->state) {
      case LSQRequest::RequestIssuing:
      case LSQRequest::RequestNeedsRetry:
        /* Response to a request from the transfers queue */
        request->retireResponse(response);

        DPRINTF(MinorMem, "Has outstanding packets?: %d %d\n",
            request->hasPacketsInMemSystem(), request->isComplete());

        break;
      case LSQRequest::StoreBufferIssuing:
      case LSQRequest::StoreBufferNeedsRetry:
        /* Response to a request from the store buffer */
        request->retireResponse(response);

        /* Remove completed requests unless they are barriers (which will
         *  need to be removed in order */
        if (request->isComplete()) {
            if (!request->isBarrier()) {
                storeBuffer.deleteRequest(request);
            } else {
                DPRINTF(MinorMem, "Completed transfer for barrier: %s"
                    " leaving the request as it is also a barrier\n",
                    *(request->inst));
            }
        }
        break;
      default:
        panic("Shouldn't be allowed to receive a response from another state");
    }

    /* We go to idle even if there are more things in the requests queue
     * as it's the job of step to actually step us on to the next
     * transaction */

    /* Let's try and wake up the processor for the next cycle */
    cpu.wakeupOnEvent(Pipeline::ExecuteStageId);

    /* Never busy */
    return true;
}

void
LSQ::recvReqRetry()
{
    DPRINTF(MinorMem, "Received retry request\n");

    assert(state == MemoryNeedsRetry);

    switch (retryRequest->state) {
      case LSQRequest::RequestNeedsRetry:
        /* Retry in the requests queue */
        retryRequest->setState(LSQRequest::Translated);
        break;
      case LSQRequest::StoreBufferNeedsRetry:
        /* Retry in the store buffer */
        retryRequest->setState(LSQRequest::StoreInStoreBuffer);
        break;
      default:
        panic("Unrecognized retry request state %d.", retryRequest->state);
    }

    /* Set state back to MemoryRunning so that the following
     *  tryToSend can actually send.  Note that this won't
     *  allow another transfer in as tryToSend should
     *  issue a memory request and either succeed for this
     *  request or return the LSQ back to MemoryNeedsRetry */
    state = MemoryRunning;

    /* Try to resend the request */
    if (tryToSend(retryRequest)) {
        /* Successfully sent, need to move the request */
        switch (retryRequest->state) {
          case LSQRequest::RequestIssuing:
            /* In the requests queue */
            moveFromRequestsToTransfers(retryRequest);
            break;
          case LSQRequest::StoreBufferIssuing:
            /* In the store buffer */
            storeBuffer.countIssuedStore(retryRequest);
            break;
          default:
            panic("Unrecognized retry request state %d.", retryRequest->state);
        }

        retryRequest = NULL;
    }
}

LSQ::LSQ(std::string name_, std::string dcache_port_name_,
    MinorCPU &cpu_, Execute &execute_,
    unsigned int in_memory_system_limit, unsigned int line_width,
    unsigned int requests_queue_size, unsigned int transfers_queue_size,
    unsigned int store_buffer_size,
    unsigned int store_buffer_cycle_store_limit) :
    Named(name_),
    cpu(cpu_),
    execute(execute_),
    dcachePort(dcache_port_name_, *this, cpu_),
    lastMemBarrier(cpu.numThreads, 0),
    state(MemoryRunning),
    inMemorySystemLimit(in_memory_system_limit),
    lineWidth((line_width == 0 ? cpu.cacheLineSize() : line_width)),
    requests(name_ + ".requests", "addr", requests_queue_size),
    transfers(name_ + ".transfers", "addr", transfers_queue_size),
    storeBuffer(name_ + ".storeBuffer",
        *this, store_buffer_size, store_buffer_cycle_store_limit),
    numAccessesInMemorySystem(0),
    numAccessesInDTLB(0),
    numStoresInTransfers(0),
    numAccessesIssuedToMemory(0),
    retryRequest(NULL),
    cacheBlockMask(~(cpu_.cacheLineSize() - 1))
{
    if (in_memory_system_limit < 1) {
        fatal("%s: executeMaxAccessesInMemory must be >= 1 (%d)\n", name_,
            in_memory_system_limit);
    }

    if (store_buffer_cycle_store_limit < 1) {
        fatal("%s: executeLSQMaxStoreBufferStoresPerCycle must be"
            " >= 1 (%d)\n", name_, store_buffer_cycle_store_limit);
    }

    if (requests_queue_size < 1) {
        fatal("%s: executeLSQRequestsQueueSize must be"
            " >= 1 (%d)\n", name_, requests_queue_size);
    }

    if (transfers_queue_size < 1) {
        fatal("%s: executeLSQTransfersQueueSize must be"
            " >= 1 (%d)\n", name_, transfers_queue_size);
    }

    if (store_buffer_size < 1) {
        fatal("%s: executeLSQStoreBufferSize must be"
            " >= 1 (%d)\n", name_, store_buffer_size);
    }

    if ((lineWidth & (lineWidth - 1)) != 0) {
        fatal("%s: lineWidth: %d must be a power of 2\n", name(), lineWidth);
    }
}

LSQ::~LSQ()
{ }

LSQ::LSQRequest::~LSQRequest()
{
    if (packet)
        delete packet;
    if (data)
        delete [] data;
}

/**
 *  Step the memory access mechanism on to its next state.  In reality, most
 *  of the stepping is done by the callbacks on the LSQ but this
 *  function is responsible for issuing memory requests lodged in the
 *  requests queue.
 */
void
LSQ::step()
{
    /* Try to move address-translated requests between queues and issue
     *  them */
    if (!requests.empty())
        tryToSendToTransfers(requests.front());

    storeBuffer.step();
}

LSQ::LSQRequestPtr
LSQ::findResponse(MinorDynInstPtr inst)
{
    LSQ::LSQRequestPtr ret = NULL;

    if (!transfers.empty()) {
        LSQRequestPtr request = transfers.front();

        /* Same instruction and complete access or a store that's
         *  capable of being moved to the store buffer */
        if (request->inst->id == inst->id) {
            bool complete = request->isComplete();
            bool can_store = storeBuffer.canInsert();
            bool to_store_buffer = request->state ==
                LSQRequest::StoreToStoreBuffer;

            if ((complete && !(request->isBarrier() && !can_store)) ||
                (to_store_buffer && can_store))
            {
                ret = request;
            }
        }
    }

    if (ret) {
        DPRINTF(MinorMem, "Found matching memory response for inst: %s\n",
            *inst);
    } else {
        DPRINTF(MinorMem, "No matching memory response for inst: %s\n",
            *inst);
    }

    return ret;
}

void
LSQ::popResponse(LSQ::LSQRequestPtr response)
{
    assert(!transfers.empty() && transfers.front() == response);

    transfers.pop();

    if (!response->isLoad)
        numStoresInTransfers--;

    if (response->issuedToMemory)
        numAccessesIssuedToMemory--;

    if (response->state != LSQRequest::StoreInStoreBuffer) {
        DPRINTF(MinorMem, "Deleting %s request: %s\n",
            (response->isLoad ? "load" : "store"),
            *(response->inst));

        delete response;
    }
}

void
LSQ::sendStoreToStoreBuffer(LSQRequestPtr request)
{
    assert(request->state == LSQRequest::StoreToStoreBuffer);

    DPRINTF(MinorMem, "Sending store: %s to store buffer\n",
        *(request->inst));

    request->inst->inStoreBuffer = true;

    storeBuffer.insert(request);
}

bool
LSQ::isDrained()
{
    return requests.empty() && transfers.empty() &&
        storeBuffer.isDrained();
}

bool
LSQ::needsToTick()
{
    bool ret = false;

    if (canSendToMemorySystem()) {
        bool have_translated_requests = !requests.empty() &&
            requests.front()->state != LSQRequest::InTranslation &&
            transfers.unreservedRemainingSpace() != 0;

        ret = have_translated_requests ||
            storeBuffer.numUnissuedStores() != 0;
    }

    if (ret)
        DPRINTF(Activity, "Need to tick\n");

    return ret;
}

Fault
LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
                 unsigned int size, Addr addr, Request::Flags flags,
                 uint64_t *res, AtomicOpFunctorPtr amo_op,
                 const std::vector<bool>& byte_enable)
{
    assert(inst->translationFault == NoFault || inst->inLSQ);

    if (inst->inLSQ) {
        return inst->translationFault;
    }

    bool needs_burst = transferNeedsBurst(addr, size, lineWidth);

    if (needs_burst && inst->staticInst->isAtomic()) {
        // AMO requests that access across a cache line boundary are not
        // allowed since the cache does not guarantee AMO ops to be executed
        // atomically in two cache lines
        // For ISAs such as x86 that requires AMO operations to work on
        // accesses that cross cache-line boundaries, the cache needs to be
        // modified to support locking both cache lines to guarantee the
        // atomicity.
        panic("Do not expect cross-cache-line atomic memory request\n");
    }

    LSQRequestPtr request;

    /* Copy given data into the request.  The request will pass this to the
     *  packet and then it will own the data */
    uint8_t *request_data = NULL;

    DPRINTF(MinorMem, "Pushing request (%s) addr: 0x%x size: %d flags:"
        " 0x%x%s lineWidth : 0x%x\n",
        (isLoad ? "load" : "store/atomic"), addr, size, flags,
            (needs_burst ? " (needs burst)" : ""), lineWidth);

    if (!isLoad) {
        /* Request_data becomes the property of a ...DataRequest (see below)
         *  and destroyed by its destructor */
        request_data = new uint8_t[size];
        if (inst->staticInst->isAtomic() ||
            (flags & Request::STORE_NO_DATA)) {
            /* For atomic or store-no-data, just use zeroed data */
            std::memset(request_data, 0, size);
        } else {
            std::memcpy(request_data, data, size);
        }
    }

    if (needs_burst) {
        request = new SplitDataRequest(
            *this, inst, isLoad, request_data, res);
    } else {
        request = new SingleDataRequest(
            *this, inst, isLoad, request_data, res);
    }

    if (inst->traceData)
        inst->traceData->setMem(addr, size, flags);

    int cid = cpu.threads[inst->id.threadId]->getTC()->contextId();
    request->request->setContext(cid);
    request->request->setVirt(
        addr, size, flags, cpu.dataRequestorId(),
        /* I've no idea why we need the PC, but give it */
        inst->pc.instAddr(), std::move(amo_op));
    request->request->setByteEnable(byte_enable);

    requests.push(request);
    inst->inLSQ = true;
    request->startAddrTranslation();

    return inst->translationFault;
}

void
LSQ::pushFailedRequest(MinorDynInstPtr inst)
{
    LSQRequestPtr request = new FailedDataRequest(*this, inst);
    requests.push(request);
}

void
LSQ::minorTrace() const
{
    MINORTRACE("state=%s in_tlb_mem=%d/%d stores_in_transfers=%d"
        " lastMemBarrier=%d\n",
        state, numAccessesInDTLB, numAccessesInMemorySystem,
        numStoresInTransfers, lastMemBarrier[0]);
    requests.minorTrace();
    transfers.minorTrace();
    storeBuffer.minorTrace();
}

LSQ::StoreBuffer::StoreBuffer(std::string name_, LSQ &lsq_,
    unsigned int store_buffer_size,
    unsigned int store_limit_per_cycle) :
    Named(name_), lsq(lsq_),
    numSlots(store_buffer_size),
    storeLimitPerCycle(store_limit_per_cycle),
    slots(),
    numUnissuedAccesses(0)
{
}

PacketPtr
makePacketForRequest(const RequestPtr &request, bool isLoad,
    Packet::SenderState *sender_state, PacketDataPtr data)
{
    PacketPtr ret = isLoad ? Packet::createRead(request)
                           : Packet::createWrite(request);

    if (sender_state)
        ret->pushSenderState(sender_state);

    if (isLoad) {
        ret->allocate();
    } else if (!request->isCacheMaintenance()) {
        // CMOs are treated as stores but they don't have data. All
        // stores otherwise need to allocate for data.
        ret->dataDynamic(data);
    }

    return ret;
}

void
LSQ::issuedMemBarrierInst(MinorDynInstPtr inst)
{
    assert(inst->isInst() && inst->staticInst->isFullMemBarrier());
    assert(inst->id.execSeqNum > lastMemBarrier[inst->id.threadId]);

    /* Remember the barrier.  We only have a notion of one
     *  barrier so this may result in some mem refs being
     *  delayed if they are between barriers */
    lastMemBarrier[inst->id.threadId] = inst->id.execSeqNum;
}

void
LSQ::LSQRequest::makePacket()
{
    assert(inst->translationFault == NoFault);

    /* Make the function idempotent */
    if (packet)
        return;

    packet = makePacketForRequest(request, isLoad, this, data);
    /* Null the ret data so we know not to deallocate it when the
     * ret is destroyed.  The data now belongs to the ret and
     * the ret is responsible for its destruction */
    data = NULL;
}

std::ostream &
operator <<(std::ostream &os, LSQ::MemoryState state)
{
    switch (state) {
      case LSQ::MemoryRunning:
        os << "MemoryRunning";
        break;
      case LSQ::MemoryNeedsRetry:
        os << "MemoryNeedsRetry";
        break;
      default:
        os << "MemoryState-" << static_cast<int>(state);
        break;
    }
    return os;
}

void
LSQ::recvTimingSnoopReq(PacketPtr pkt)
{
    /* LLSC operations in Minor can't be speculative and are executed from
     * the head of the requests queue.  We shouldn't need to do more than
     * this action on snoops. */
    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
        if (cpu.getCpuAddrMonitor(tid)->doMonitor(pkt)) {
            cpu.wakeup(tid);
        }
    }

    if (pkt->isInvalidate() || pkt->isWrite()) {
        for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
            TheISA::handleLockedSnoop(cpu.getContext(tid), pkt,
                                      cacheBlockMask);
        }
    }
}

void
LSQ::threadSnoop(LSQRequestPtr request)
{
    /* LLSC operations in Minor can't be speculative and are executed from
     * the head of the requests queue.  We shouldn't need to do more than
     * this action on snoops. */
    ThreadID req_tid = request->inst->id.threadId;
    PacketPtr pkt = request->packet;

    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
        if (tid != req_tid) {
            if (cpu.getCpuAddrMonitor(tid)->doMonitor(pkt)) {
                cpu.wakeup(tid);
            }

            if (pkt->isInvalidate() || pkt->isWrite()) {
                TheISA::handleLockedSnoop(cpu.getContext(tid), pkt,
                                          cacheBlockMask);
            }
        }
    }
}

}
