/*
 * Copyright (c) 2013-2014,2017-2018,2020-2021 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 "base/compiler.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 gem5
{

GEM5_DEPRECATED_NAMESPACE(Minor, minor);
namespace minor
{

LSQ::LSQRequest::LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
        RegIndex zero_reg, PacketDataPtr data_, uint64_t *res_) :
    SenderState(),
    port(port_),
    zeroReg(zero_reg),
    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];
    std::unique_ptr<PCStateBase> old_pc(thread.pcState().clone());
    ExecContext context(port.cpu, thread, port.execute, inst, zeroReg);
    [[maybe_unused]] 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];
    std::unique_ptr<PCStateBase> old_pc(thread.pcState().clone());

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

    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, BaseMMU::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 ? BaseMMU::Read : BaseMMU::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, BaseMMU::Mode mode)
{
    port.numAccessesInDTLB--;

    [[maybe_unused]] 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_, port_.zeroReg, 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++)
    {
        [[maybe_unused]] 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 ?
        BaseMMU::Read : BaseMMU::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 << ',';
    }

    minor::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];

        std::unique_ptr<PCStateBase> old_pc(thread.pcState().clone());
        ExecContext context(cpu, thread, execute, request->inst, zeroReg);

        /* Handle LLSC requests and tests */
        if (is_load) {
            thread.getIsaPtr()->handleLockedRead(&context, request->request);
        } else {
            do_access = thread.getIsaPtr()->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,
    RegIndex zero_reg) :
    Named(name_),
    cpu(cpu_),
    execute(execute_),
    zeroReg(zero_reg),
    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);

    /* If the request is marked as NO_ACCESS, setup a local access
     * doing nothing */
    if (flags.isSet(Request::NO_ACCESS)) {
        assert(!request->request->isLocalAccess());
        request->request->setLocalAccessor(
            [] (ThreadContext *tc, PacketPtr pkt) { return Cycles(1); });
    }

    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
{
    minor::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++) {
            cpu.getContext(tid)->getIsaPtr()->handleLockedSnoop(
                    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()) {
                cpu.getContext(tid)->getIsaPtr()->handleLockedSnoop(pkt,
                        cacheBlockMask);
            }
        }
    }
}

} // namespace minor
} // namespace gem5
