lsq.cc revision 11567:560d7fbbddd1
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andrew Bardsley
38 */
39
40#include <iomanip>
41#include <sstream>
42
43#include "arch/locked_mem.hh"
44#include "arch/mmapped_ipr.hh"
45#include "cpu/minor/cpu.hh"
46#include "cpu/minor/exec_context.hh"
47#include "cpu/minor/execute.hh"
48#include "cpu/minor/lsq.hh"
49#include "cpu/minor/pipeline.hh"
50#include "debug/Activity.hh"
51#include "debug/MinorMem.hh"
52
53namespace Minor
54{
55
56/** Returns the offset of addr into an aligned a block of size block_size */
57static Addr
58addrBlockOffset(Addr addr, unsigned int block_size)
59{
60    return addr & (block_size - 1);
61}
62
63/** Returns true if the given [addr .. addr+size-1] transfer needs to be
64 *  fragmented across a block size of block_size */
65static bool
66transferNeedsBurst(Addr addr, unsigned int size, unsigned int block_size)
67{
68    return (addrBlockOffset(addr, block_size) + size) > block_size;
69}
70
71LSQ::LSQRequest::LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
72    PacketDataPtr data_, uint64_t *res_) :
73    SenderState(),
74    port(port_),
75    inst(inst_),
76    isLoad(isLoad_),
77    data(data_),
78    packet(NULL),
79    request(),
80    fault(NoFault),
81    res(res_),
82    skipped(false),
83    issuedToMemory(false),
84    state(NotIssued)
85{ }
86
87LSQ::AddrRangeCoverage
88LSQ::LSQRequest::containsAddrRangeOf(
89    Addr req1_addr, unsigned int req1_size,
90    Addr req2_addr, unsigned int req2_size)
91{
92    /* 'end' here means the address of the byte just past the request
93     *  blocks */
94    Addr req2_end_addr = req2_addr + req2_size;
95    Addr req1_end_addr = req1_addr + req1_size;
96
97    AddrRangeCoverage ret;
98
99    if (req1_addr > req2_end_addr || req1_end_addr < req2_addr)
100        ret = NoAddrRangeCoverage;
101    else if (req1_addr <= req2_addr && req1_end_addr >= req2_end_addr)
102        ret = FullAddrRangeCoverage;
103    else
104        ret = PartialAddrRangeCoverage;
105
106    return ret;
107}
108
109LSQ::AddrRangeCoverage
110LSQ::LSQRequest::containsAddrRangeOf(LSQRequestPtr other_request)
111{
112    return containsAddrRangeOf(request.getPaddr(), request.getSize(),
113        other_request->request.getPaddr(), other_request->request.getSize());
114}
115
116bool
117LSQ::LSQRequest::isBarrier()
118{
119    return inst->isInst() && inst->staticInst->isMemBarrier();
120}
121
122bool
123LSQ::LSQRequest::needsToBeSentToStoreBuffer()
124{
125    return state == StoreToStoreBuffer;
126}
127
128void
129LSQ::LSQRequest::setState(LSQRequestState new_state)
130{
131    DPRINTFS(MinorMem, (&port), "Setting state from %d to %d for request:"
132        " %s\n", state, new_state, *inst);
133    state = new_state;
134}
135
136bool
137LSQ::LSQRequest::isComplete() const
138{
139    /* @todo, There is currently only one 'completed' state.  This
140     *  may not be a good choice */
141    return state == Complete;
142}
143
144void
145LSQ::LSQRequest::reportData(std::ostream &os) const
146{
147    os << (isLoad ? 'R' : 'W') << ';';
148    inst->reportData(os);
149    os << ';' << state;
150}
151
152std::ostream &
153operator <<(std::ostream &os, LSQ::AddrRangeCoverage coverage)
154{
155    switch (coverage) {
156      case LSQ::PartialAddrRangeCoverage:
157        os << "PartialAddrRangeCoverage";
158        break;
159      case LSQ::FullAddrRangeCoverage:
160        os << "FullAddrRangeCoverage";
161        break;
162      case LSQ::NoAddrRangeCoverage:
163        os << "NoAddrRangeCoverage";
164        break;
165      default:
166        os << "AddrRangeCoverage-" << static_cast<int>(coverage);
167        break;
168    }
169    return os;
170}
171
172std::ostream &
173operator <<(std::ostream &os, LSQ::LSQRequest::LSQRequestState state)
174{
175    switch (state) {
176      case LSQ::LSQRequest::NotIssued:
177        os << "NotIssued";
178        break;
179      case LSQ::LSQRequest::InTranslation:
180        os << "InTranslation";
181        break;
182      case LSQ::LSQRequest::Translated:
183        os << "Translated";
184        break;
185      case LSQ::LSQRequest::Failed:
186        os << "Failed";
187        break;
188      case LSQ::LSQRequest::RequestIssuing:
189        os << "RequestIssuing";
190        break;
191      case LSQ::LSQRequest::StoreToStoreBuffer:
192        os << "StoreToStoreBuffer";
193        break;
194      case LSQ::LSQRequest::StoreInStoreBuffer:
195        os << "StoreInStoreBuffer";
196        break;
197      case LSQ::LSQRequest::StoreBufferIssuing:
198        os << "StoreBufferIssuing";
199        break;
200      case LSQ::LSQRequest::RequestNeedsRetry:
201        os << "RequestNeedsRetry";
202        break;
203      case LSQ::LSQRequest::StoreBufferNeedsRetry:
204        os << "StoreBufferNeedsRetry";
205        break;
206      case LSQ::LSQRequest::Complete:
207        os << "Complete";
208        break;
209      default:
210        os << "LSQRequestState-" << static_cast<int>(state);
211        break;
212    }
213    return os;
214}
215
216void
217LSQ::clearMemBarrier(MinorDynInstPtr inst)
218{
219    bool is_last_barrier =
220        inst->id.execSeqNum >= lastMemBarrier[inst->id.threadId];
221
222    DPRINTF(MinorMem, "Moving %s barrier out of store buffer inst: %s\n",
223        (is_last_barrier ? "last" : "a"), *inst);
224
225    if (is_last_barrier)
226        lastMemBarrier[inst->id.threadId] = 0;
227}
228
229void
230LSQ::SingleDataRequest::finish(const Fault &fault_, RequestPtr request_,
231                               ThreadContext *tc, BaseTLB::Mode mode)
232{
233    fault = fault_;
234
235    port.numAccessesInDTLB--;
236
237    DPRINTFS(MinorMem, (&port), "Received translation response for"
238        " request: %s\n", *inst);
239
240    makePacket();
241
242    setState(Translated);
243    port.tryToSendToTransfers(this);
244
245    /* Let's try and wake up the processor for the next cycle */
246    port.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
247}
248
249void
250LSQ::SingleDataRequest::startAddrTranslation()
251{
252    ThreadContext *thread = port.cpu.getContext(
253        inst->id.threadId);
254
255    port.numAccessesInDTLB++;
256
257    setState(LSQ::LSQRequest::InTranslation);
258
259    DPRINTFS(MinorMem, (&port), "Submitting DTLB request\n");
260    /* Submit the translation request.  The response will come through
261     *  finish/markDelayed on the LSQRequest as it bears the Translation
262     *  interface */
263    thread->getDTBPtr()->translateTiming(
264        &request, thread, this, (isLoad ? BaseTLB::Read : BaseTLB::Write));
265}
266
267void
268LSQ::SingleDataRequest::retireResponse(PacketPtr packet_)
269{
270    DPRINTFS(MinorMem, (&port), "Retiring packet\n");
271    packet = packet_;
272    packetInFlight = false;
273    setState(Complete);
274}
275
276void
277LSQ::SplitDataRequest::finish(const Fault &fault_, RequestPtr request_,
278                              ThreadContext *tc, BaseTLB::Mode mode)
279{
280    fault = fault_;
281
282    port.numAccessesInDTLB--;
283
284    unsigned int M5_VAR_USED expected_fragment_index =
285        numTranslatedFragments;
286
287    numInTranslationFragments--;
288    numTranslatedFragments++;
289
290    DPRINTFS(MinorMem, (&port), "Received translation response for fragment"
291        " %d of request: %s\n", expected_fragment_index, *inst);
292
293    assert(request_ == fragmentRequests[expected_fragment_index]);
294
295    /* Wake up next cycle to get things going again in case the
296     *  tryToSendToTransfers does take */
297    port.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
298
299    if (fault != NoFault) {
300        /* tryToSendToTransfers will handle the fault */
301
302        DPRINTFS(MinorMem, (&port), "Faulting translation for fragment:"
303            " %d of request: %s\n",
304            expected_fragment_index, *inst);
305
306        setState(Translated);
307        port.tryToSendToTransfers(this);
308    } else if (numTranslatedFragments == numFragments) {
309        makeFragmentPackets();
310
311        setState(Translated);
312        port.tryToSendToTransfers(this);
313    } else {
314        /* Avoid calling translateTiming from within ::finish */
315        assert(!translationEvent.scheduled());
316        port.cpu.schedule(translationEvent, curTick());
317    }
318}
319
320LSQ::SplitDataRequest::SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
321    bool isLoad_, PacketDataPtr data_, uint64_t *res_) :
322    LSQRequest(port_, inst_, isLoad_, data_, res_),
323    translationEvent(*this),
324    numFragments(0),
325    numInTranslationFragments(0),
326    numTranslatedFragments(0),
327    numIssuedFragments(0),
328    numRetiredFragments(0),
329    fragmentRequests(),
330    fragmentPackets()
331{
332    /* Don't know how many elements are needed until the request is
333     *  populated by the caller. */
334}
335
336LSQ::SplitDataRequest::~SplitDataRequest()
337{
338    for (auto i = fragmentRequests.begin();
339        i != fragmentRequests.end(); i++)
340    {
341        delete *i;
342    }
343
344    for (auto i = fragmentPackets.begin();
345         i != fragmentPackets.end(); i++)
346    {
347        delete *i;
348    }
349}
350
351void
352LSQ::SplitDataRequest::makeFragmentRequests()
353{
354    Addr base_addr = request.getVaddr();
355    unsigned int whole_size = request.getSize();
356    unsigned int line_width = port.lineWidth;
357
358    unsigned int fragment_size;
359    Addr fragment_addr;
360
361    /* Assume that this transfer is across potentially many block snap
362     * boundaries:
363     *
364     * |      _|________|________|________|___     |
365     * |     |0| 1      | 2      | 3      | 4 |    |
366     * |     |_|________|________|________|___|    |
367     * |       |        |        |        |        |
368     *
369     *  The first transfer (0) can be up to lineWidth in size.
370     *  All the middle transfers (1-3) are lineWidth in size
371     *  The last transfer (4) can be from zero to lineWidth - 1 in size
372     */
373    unsigned int first_fragment_offset =
374        addrBlockOffset(base_addr, line_width);
375    unsigned int last_fragment_size =
376        addrBlockOffset(base_addr + whole_size, line_width);
377    unsigned int first_fragment_size =
378        line_width - first_fragment_offset;
379
380    unsigned int middle_fragments_total_size =
381        whole_size - (first_fragment_size + last_fragment_size);
382
383    assert(addrBlockOffset(middle_fragments_total_size, line_width) == 0);
384
385    unsigned int middle_fragment_count =
386        middle_fragments_total_size / line_width;
387
388    numFragments = 1 /* first */ + middle_fragment_count +
389        (last_fragment_size == 0 ? 0 : 1);
390
391    DPRINTFS(MinorMem, (&port), "Dividing transfer into %d fragmentRequests."
392        " First fragment size: %d Last fragment size: %d\n",
393        numFragments, first_fragment_size,
394        (last_fragment_size == 0 ? line_width : last_fragment_size));
395
396    assert(((middle_fragment_count * line_width) +
397        first_fragment_size + last_fragment_size) == whole_size);
398
399    fragment_addr = base_addr;
400    fragment_size = first_fragment_size;
401
402    /* Just past the last address in the request */
403    Addr end_addr = base_addr + whole_size;
404
405    for (unsigned int fragment_index = 0; fragment_index < numFragments;
406         fragment_index++)
407    {
408        bool M5_VAR_USED is_last_fragment = false;
409
410        if (fragment_addr == base_addr) {
411            /* First fragment */
412            fragment_size = first_fragment_size;
413        } else {
414            if ((fragment_addr + line_width) > end_addr) {
415                /* Adjust size of last fragment */
416                fragment_size = end_addr - fragment_addr;
417                is_last_fragment = true;
418            } else {
419                /* Middle fragments */
420                fragment_size = line_width;
421            }
422        }
423
424        Request *fragment = new Request();
425
426        fragment->setContext(request.contextId());
427        fragment->setVirt(0 /* asid */,
428            fragment_addr, fragment_size, request.getFlags(),
429            request.masterId(),
430            request.getPC());
431
432        DPRINTFS(MinorMem, (&port), "Generating fragment addr: 0x%x size: %d"
433            " (whole request addr: 0x%x size: %d) %s\n",
434            fragment_addr, fragment_size, base_addr, whole_size,
435            (is_last_fragment ? "last fragment" : ""));
436
437        fragment_addr += fragment_size;
438
439        fragmentRequests.push_back(fragment);
440    }
441}
442
443void
444LSQ::SplitDataRequest::makeFragmentPackets()
445{
446    Addr base_addr = request.getVaddr();
447
448    DPRINTFS(MinorMem, (&port), "Making packets for request: %s\n", *inst);
449
450    for (unsigned int fragment_index = 0; fragment_index < numFragments;
451         fragment_index++)
452    {
453        Request *fragment = fragmentRequests[fragment_index];
454
455        DPRINTFS(MinorMem, (&port), "Making packet %d for request: %s"
456            " (%d, 0x%x)\n",
457            fragment_index, *inst,
458            (fragment->hasPaddr() ? "has paddr" : "no paddr"),
459            (fragment->hasPaddr() ? fragment->getPaddr() : 0));
460
461        Addr fragment_addr = fragment->getVaddr();
462        unsigned int fragment_size = fragment->getSize();
463
464        uint8_t *request_data = NULL;
465
466        if (!isLoad) {
467            /* Split data for Packets.  Will become the property of the
468             *  outgoing Packets */
469            request_data = new uint8_t[fragment_size];
470            std::memcpy(request_data, data + (fragment_addr - base_addr),
471                fragment_size);
472        }
473
474        assert(fragment->hasPaddr());
475
476        PacketPtr fragment_packet =
477            makePacketForRequest(*fragment, isLoad, this, request_data);
478
479        fragmentPackets.push_back(fragment_packet);
480        /* Accumulate flags in parent request */
481        request.setFlags(fragment->getFlags());
482    }
483
484    /* Might as well make the overall/response packet here */
485    /* Get the physical address for the whole request/packet from the first
486     *  fragment */
487    request.setPaddr(fragmentRequests[0]->getPaddr());
488    makePacket();
489}
490
491void
492LSQ::SplitDataRequest::startAddrTranslation()
493{
494    setState(LSQ::LSQRequest::InTranslation);
495
496    makeFragmentRequests();
497
498    numInTranslationFragments = 0;
499    numTranslatedFragments = 0;
500
501    /* @todo, just do these in sequence for now with
502     * a loop of:
503     * do {
504     *  sendNextFragmentToTranslation ; translateTiming ; finish
505     * } while (numTranslatedFragments != numFragments);
506     */
507
508    /* Do first translation */
509    sendNextFragmentToTranslation();
510}
511
512PacketPtr
513LSQ::SplitDataRequest::getHeadPacket()
514{
515    assert(numIssuedFragments < numFragments);
516
517    return fragmentPackets[numIssuedFragments];
518}
519
520void
521LSQ::SplitDataRequest::stepToNextPacket()
522{
523    assert(numIssuedFragments < numFragments);
524
525    numIssuedFragments++;
526}
527
528void
529LSQ::SplitDataRequest::retireResponse(PacketPtr response)
530{
531    assert(numRetiredFragments < numFragments);
532
533    DPRINTFS(MinorMem, (&port), "Retiring fragment addr: 0x%x size: %d"
534        " offset: 0x%x (retired fragment num: %d) %s\n",
535        response->req->getVaddr(), response->req->getSize(),
536        request.getVaddr() - response->req->getVaddr(),
537        numRetiredFragments,
538        (fault == NoFault ? "" : fault->name()));
539
540    numRetiredFragments++;
541
542    if (skipped) {
543        /* Skip because we already knew the request had faulted or been
544         *  skipped */
545        DPRINTFS(MinorMem, (&port), "Skipping this fragment\n");
546    } else if (response->isError()) {
547        /* Mark up the error and leave to execute to handle it */
548        DPRINTFS(MinorMem, (&port), "Fragment has an error, skipping\n");
549        setSkipped();
550        packet->copyError(response);
551    } else {
552        if (isLoad) {
553            if (!data) {
554                /* For a split transfer, a Packet must be constructed
555                 *  to contain all returning data.  This is that packet's
556                 *  data */
557                data = new uint8_t[request.getSize()];
558            }
559
560            /* Populate the portion of the overall response data represented
561             *  by the response fragment */
562            std::memcpy(
563                data + (response->req->getVaddr() - request.getVaddr()),
564                response->getConstPtr<uint8_t>(),
565                response->req->getSize());
566        }
567    }
568
569    /* Complete early if we're skipping are no more in-flight accesses */
570    if (skipped && !hasPacketsInMemSystem()) {
571        DPRINTFS(MinorMem, (&port), "Completed skipped burst\n");
572        setState(Complete);
573        if (packet->needsResponse())
574            packet->makeResponse();
575    }
576
577    if (numRetiredFragments == numFragments)
578        setState(Complete);
579
580    if (!skipped && isComplete()) {
581        DPRINTFS(MinorMem, (&port), "Completed burst %d\n", packet != NULL);
582
583        DPRINTFS(MinorMem, (&port), "Retired packet isRead: %d isWrite: %d"
584             " needsResponse: %d packetSize: %s requestSize: %s responseSize:"
585             " %s\n", packet->isRead(), packet->isWrite(),
586             packet->needsResponse(), packet->getSize(), request.getSize(),
587             response->getSize());
588
589        /* A request can become complete by several paths, this is a sanity
590         *  check to make sure the packet's data is created */
591        if (!data) {
592            data = new uint8_t[request.getSize()];
593        }
594
595        if (isLoad) {
596            DPRINTFS(MinorMem, (&port), "Copying read data\n");
597            std::memcpy(packet->getPtr<uint8_t>(), data, request.getSize());
598        }
599        packet->makeResponse();
600    }
601
602    /* Packets are all deallocated together in ~SplitLSQRequest */
603}
604
605void
606LSQ::SplitDataRequest::sendNextFragmentToTranslation()
607{
608    unsigned int fragment_index = numTranslatedFragments;
609
610    ThreadContext *thread = port.cpu.getContext(
611        inst->id.threadId);
612
613    DPRINTFS(MinorMem, (&port), "Submitting DTLB request for fragment: %d\n",
614        fragment_index);
615
616    port.numAccessesInDTLB++;
617    numInTranslationFragments++;
618
619    thread->getDTBPtr()->translateTiming(
620        fragmentRequests[fragment_index], thread, this, (isLoad ?
621        BaseTLB::Read : BaseTLB::Write));
622}
623
624bool
625LSQ::StoreBuffer::canInsert() const
626{
627    /* @todo, support store amalgamation */
628    return slots.size() < numSlots;
629}
630
631void
632LSQ::StoreBuffer::deleteRequest(LSQRequestPtr request)
633{
634    auto found = std::find(slots.begin(), slots.end(), request);
635
636    if (found != slots.end()) {
637        DPRINTF(MinorMem, "Deleting request: %s %s %s from StoreBuffer\n",
638            request, *found, *(request->inst));
639        slots.erase(found);
640
641        delete request;
642    }
643}
644
645void
646LSQ::StoreBuffer::insert(LSQRequestPtr request)
647{
648    if (!canInsert()) {
649        warn("%s: store buffer insertion without space to insert from"
650            " inst: %s\n", name(), *(request->inst));
651    }
652
653    DPRINTF(MinorMem, "Pushing store: %s into store buffer\n", request);
654
655    numUnissuedAccesses++;
656
657    if (request->state != LSQRequest::Complete)
658        request->setState(LSQRequest::StoreInStoreBuffer);
659
660    slots.push_back(request);
661
662    /* Let's try and wake up the processor for the next cycle to step
663     *  the store buffer */
664    lsq.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
665}
666
667LSQ::AddrRangeCoverage
668LSQ::StoreBuffer::canForwardDataToLoad(LSQRequestPtr request,
669    unsigned int &found_slot)
670{
671    unsigned int slot_index = slots.size() - 1;
672    auto i = slots.rbegin();
673    AddrRangeCoverage ret = NoAddrRangeCoverage;
674
675    /* Traverse the store buffer in reverse order (most to least recent)
676     *  and try to find a slot whose address range overlaps this request */
677    while (ret == NoAddrRangeCoverage && i != slots.rend()) {
678        LSQRequestPtr slot = *i;
679
680        if (slot->packet &&
681            slot->inst->id.threadId == request->inst->id.threadId) {
682            AddrRangeCoverage coverage = slot->containsAddrRangeOf(request);
683
684            if (coverage != NoAddrRangeCoverage) {
685                DPRINTF(MinorMem, "Forwarding: slot: %d result: %s thisAddr:"
686                    " 0x%x thisSize: %d slotAddr: 0x%x slotSize: %d\n",
687                    slot_index, coverage,
688                    request->request.getPaddr(), request->request.getSize(),
689                    slot->request.getPaddr(), slot->request.getSize());
690
691                found_slot = slot_index;
692                ret = coverage;
693            }
694        }
695
696        i++;
697        slot_index--;
698    }
699
700    return ret;
701}
702
703/** Fill the given packet with appropriate date from slot slot_number */
704void
705LSQ::StoreBuffer::forwardStoreData(LSQRequestPtr load,
706    unsigned int slot_number)
707{
708    assert(slot_number < slots.size());
709    assert(load->packet);
710    assert(load->isLoad);
711
712    LSQRequestPtr store = slots[slot_number];
713
714    assert(store->packet);
715    assert(store->containsAddrRangeOf(load) == FullAddrRangeCoverage);
716
717    Addr load_addr = load->request.getPaddr();
718    Addr store_addr = store->request.getPaddr();
719    Addr addr_offset = load_addr - store_addr;
720
721    unsigned int load_size = load->request.getSize();
722
723    DPRINTF(MinorMem, "Forwarding %d bytes for addr: 0x%x from store buffer"
724        " slot: %d addr: 0x%x addressOffset: 0x%x\n",
725        load_size, load_addr, slot_number,
726        store_addr, addr_offset);
727
728    void *load_packet_data = load->packet->getPtr<void>();
729    void *store_packet_data = store->packet->getPtr<uint8_t>() + addr_offset;
730
731    std::memcpy(load_packet_data, store_packet_data, load_size);
732}
733
734void
735LSQ::StoreBuffer::countIssuedStore(LSQRequestPtr request)
736{
737    /* Barriers are accounted for as they are cleared from
738     *  the queue, not after their transfers are complete */
739    if (!request->isBarrier())
740        numUnissuedAccesses--;
741}
742
743void
744LSQ::StoreBuffer::step()
745{
746    DPRINTF(MinorMem, "StoreBuffer step numUnissuedAccesses: %d\n",
747        numUnissuedAccesses);
748
749    if (numUnissuedAccesses != 0 && lsq.state == LSQ::MemoryRunning) {
750        /* Clear all the leading barriers */
751        while (!slots.empty() &&
752            slots.front()->isComplete() && slots.front()->isBarrier())
753        {
754            LSQRequestPtr barrier = slots.front();
755
756            DPRINTF(MinorMem, "Clearing barrier for inst: %s\n",
757                *(barrier->inst));
758
759            numUnissuedAccesses--;
760            lsq.clearMemBarrier(barrier->inst);
761            slots.pop_front();
762
763            delete barrier;
764        }
765
766        auto i = slots.begin();
767        bool issued = true;
768        unsigned int issue_count = 0;
769
770        /* Skip trying if the memory system is busy */
771        if (lsq.state == LSQ::MemoryNeedsRetry)
772            issued = false;
773
774        /* Try to issue all stores in order starting from the head
775         *  of the queue.  Responses are allowed to be retired
776         *  out of order */
777        while (issued &&
778            issue_count < storeLimitPerCycle &&
779            lsq.canSendToMemorySystem() &&
780            i != slots.end())
781        {
782            LSQRequestPtr request = *i;
783
784            DPRINTF(MinorMem, "Considering request: %s, sentAllPackets: %d"
785                " state: %s\n",
786                *(request->inst), request->sentAllPackets(),
787                request->state);
788
789            if (request->isBarrier() && request->isComplete()) {
790                /* Give up at barriers */
791                issued = false;
792            } else if (!(request->state == LSQRequest::StoreBufferIssuing &&
793                request->sentAllPackets()))
794            {
795                DPRINTF(MinorMem, "Trying to send request: %s to memory"
796                    " system\n", *(request->inst));
797
798                if (lsq.tryToSend(request)) {
799                    countIssuedStore(request);
800                    issue_count++;
801                } else {
802                    /* Don't step on to the next store buffer entry if this
803                     *  one hasn't issued all its packets as the store
804                     *  buffer must still enforce ordering */
805                    issued = false;
806                }
807            }
808            i++;
809        }
810    }
811}
812
813void
814LSQ::completeMemBarrierInst(MinorDynInstPtr inst,
815    bool committed)
816{
817    if (committed) {
818        /* Not already sent to the store buffer as a store request? */
819        if (!inst->inStoreBuffer) {
820            /* Insert an entry into the store buffer to tick off barriers
821             *  until there are none in flight */
822            storeBuffer.insert(new BarrierDataRequest(*this, inst));
823        }
824    } else {
825        /* Clear the barrier anyway if it wasn't actually committed */
826        clearMemBarrier(inst);
827    }
828}
829
830void
831LSQ::StoreBuffer::minorTrace() const
832{
833    unsigned int size = slots.size();
834    unsigned int i = 0;
835    std::ostringstream os;
836
837    while (i < size) {
838        LSQRequestPtr request = slots[i];
839
840        request->reportData(os);
841
842        i++;
843        if (i < numSlots)
844            os << ',';
845    }
846
847    while (i < numSlots) {
848        os << '-';
849
850        i++;
851        if (i < numSlots)
852            os << ',';
853    }
854
855    MINORTRACE("addr=%s num_unissued_stores=%d\n", os.str(),
856        numUnissuedAccesses);
857}
858
859void
860LSQ::tryToSendToTransfers(LSQRequestPtr request)
861{
862    if (state == MemoryNeedsRetry) {
863        DPRINTF(MinorMem, "Request needs retry, not issuing to"
864            " memory until retry arrives\n");
865        return;
866    }
867
868    if (request->state == LSQRequest::InTranslation) {
869        DPRINTF(MinorMem, "Request still in translation, not issuing to"
870            " memory\n");
871        return;
872    }
873
874    assert(request->state == LSQRequest::Translated ||
875        request->state == LSQRequest::RequestIssuing ||
876        request->state == LSQRequest::Failed ||
877        request->state == LSQRequest::Complete);
878
879    if (requests.empty() || requests.front() != request) {
880        DPRINTF(MinorMem, "Request not at front of requests queue, can't"
881            " issue to memory\n");
882        return;
883    }
884
885    if (transfers.unreservedRemainingSpace() == 0) {
886        DPRINTF(MinorMem, "No space to insert request into transfers"
887            " queue\n");
888        return;
889    }
890
891    if (request->isComplete() || request->state == LSQRequest::Failed) {
892        DPRINTF(MinorMem, "Passing a %s transfer on to transfers"
893            " queue\n", (request->isComplete() ? "completed" : "failed"));
894        request->setState(LSQRequest::Complete);
895        request->setSkipped();
896        moveFromRequestsToTransfers(request);
897        return;
898    }
899
900    if (!execute.instIsRightStream(request->inst)) {
901        /* Wrong stream, try to abort the transfer but only do so if
902         *  there are no packets in flight */
903        if (request->hasPacketsInMemSystem()) {
904            DPRINTF(MinorMem, "Request's inst. is from the wrong stream,"
905                " waiting for responses before aborting request\n");
906        } else {
907            DPRINTF(MinorMem, "Request's inst. is from the wrong stream,"
908                " aborting request\n");
909            request->setState(LSQRequest::Complete);
910            request->setSkipped();
911            moveFromRequestsToTransfers(request);
912        }
913        return;
914    }
915
916    if (request->fault != NoFault) {
917        if (request->inst->staticInst->isPrefetch()) {
918            DPRINTF(MinorMem, "Not signalling fault for faulting prefetch\n");
919        }
920        DPRINTF(MinorMem, "Moving faulting request into the transfers"
921            " queue\n");
922        request->setState(LSQRequest::Complete);
923        request->setSkipped();
924        moveFromRequestsToTransfers(request);
925        return;
926    }
927
928    bool is_load = request->isLoad;
929    bool is_llsc = request->request.isLLSC();
930    bool is_swap = request->request.isSwap();
931    bool bufferable = !(request->request.isStrictlyOrdered() ||
932        is_llsc || is_swap);
933
934    if (is_load) {
935        if (numStoresInTransfers != 0) {
936            DPRINTF(MinorMem, "Load request with stores still in transfers"
937                " queue, stalling\n");
938            return;
939        }
940    } else {
941        /* Store.  Can it be sent to the store buffer? */
942        if (bufferable && !request->request.isMmappedIpr()) {
943            request->setState(LSQRequest::StoreToStoreBuffer);
944            moveFromRequestsToTransfers(request);
945            DPRINTF(MinorMem, "Moving store into transfers queue\n");
946            return;
947        }
948    }
949
950    /* Check if this is the head instruction (and so must be executable as
951     *  its stream sequence number was checked above) for loads which must
952     *  not be speculatively issued and stores which must be issued here */
953    if (!bufferable) {
954        if (!execute.instIsHeadInst(request->inst)) {
955            DPRINTF(MinorMem, "Memory access not the head inst., can't be"
956                " sure it can be performed, not issuing\n");
957            return;
958        }
959
960        unsigned int forwarding_slot = 0;
961
962        if (storeBuffer.canForwardDataToLoad(request, forwarding_slot) !=
963            NoAddrRangeCoverage)
964        {
965            DPRINTF(MinorMem, "Memory access can receive forwarded data"
966                " from the store buffer, need to wait for store buffer to"
967                " drain\n");
968            return;
969        }
970    }
971
972    /* True: submit this packet to the transfers queue to be sent to the
973     * memory system.
974     * False: skip the memory and push a packet for this request onto
975     * requests */
976    bool do_access = true;
977
978    if (!is_llsc) {
979        /* Check for match in the store buffer */
980        if (is_load) {
981            unsigned int forwarding_slot = 0;
982            AddrRangeCoverage forwarding_result =
983                storeBuffer.canForwardDataToLoad(request,
984                forwarding_slot);
985
986            switch (forwarding_result) {
987              case FullAddrRangeCoverage:
988                /* Forward data from the store buffer into this request and
989                 *  repurpose this request's packet into a response packet */
990                storeBuffer.forwardStoreData(request, forwarding_slot);
991                request->packet->makeResponse();
992
993                /* Just move between queues, no access */
994                do_access = false;
995                break;
996              case PartialAddrRangeCoverage:
997                DPRINTF(MinorMem, "Load partly satisfied by store buffer"
998                    " data. Must wait for the store to complete\n");
999                return;
1000                break;
1001              case NoAddrRangeCoverage:
1002                DPRINTF(MinorMem, "No forwardable data from store buffer\n");
1003                /* Fall through to try access */
1004                break;
1005            }
1006        }
1007    } else {
1008        if (!canSendToMemorySystem()) {
1009            DPRINTF(MinorMem, "Can't send request to memory system yet\n");
1010            return;
1011        }
1012
1013        SimpleThread &thread = *cpu.threads[request->inst->id.threadId];
1014
1015        TheISA::PCState old_pc = thread.pcState();
1016        ExecContext context(cpu, thread, execute, request->inst);
1017
1018        /* Handle LLSC requests and tests */
1019        if (is_load) {
1020            TheISA::handleLockedRead(&context, &request->request);
1021        } else {
1022            do_access = TheISA::handleLockedWrite(&context,
1023                &request->request, cacheBlockMask);
1024
1025            if (!do_access) {
1026                DPRINTF(MinorMem, "Not perfoming a memory "
1027                    "access for store conditional\n");
1028            }
1029        }
1030        thread.pcState(old_pc);
1031    }
1032
1033    /* See the do_access comment above */
1034    if (do_access) {
1035        if (!canSendToMemorySystem()) {
1036            DPRINTF(MinorMem, "Can't send request to memory system yet\n");
1037            return;
1038        }
1039
1040        /* Remember if this is an access which can't be idly
1041         *  discarded by an interrupt */
1042        if (!bufferable && !request->issuedToMemory) {
1043            numAccessesIssuedToMemory++;
1044            request->issuedToMemory = true;
1045        }
1046
1047        if (tryToSend(request)) {
1048            moveFromRequestsToTransfers(request);
1049        }
1050    } else {
1051        request->setState(LSQRequest::Complete);
1052        moveFromRequestsToTransfers(request);
1053    }
1054}
1055
1056bool
1057LSQ::tryToSend(LSQRequestPtr request)
1058{
1059    bool ret = false;
1060
1061    if (!canSendToMemorySystem()) {
1062        DPRINTF(MinorMem, "Can't send request: %s yet, no space in memory\n",
1063            *(request->inst));
1064    } else {
1065        PacketPtr packet = request->getHeadPacket();
1066
1067        DPRINTF(MinorMem, "Trying to send request: %s addr: 0x%x\n",
1068            *(request->inst), packet->req->getVaddr());
1069
1070        /* The sender state of the packet *must* be an LSQRequest
1071         *  so the response can be correctly handled */
1072        assert(packet->findNextSenderState<LSQRequest>());
1073
1074        if (request->request.isMmappedIpr()) {
1075            ThreadContext *thread =
1076                cpu.getContext(cpu.contextToThread(
1077                                request->request.contextId()));
1078
1079            if (request->isLoad) {
1080                DPRINTF(MinorMem, "IPR read inst: %s\n", *(request->inst));
1081                TheISA::handleIprRead(thread, packet);
1082            } else {
1083                DPRINTF(MinorMem, "IPR write inst: %s\n", *(request->inst));
1084                TheISA::handleIprWrite(thread, packet);
1085            }
1086
1087            request->stepToNextPacket();
1088            ret = request->sentAllPackets();
1089
1090            if (!ret) {
1091                DPRINTF(MinorMem, "IPR access has another packet: %s\n",
1092                    *(request->inst));
1093            }
1094
1095            if (ret)
1096                request->setState(LSQRequest::Complete);
1097            else
1098                request->setState(LSQRequest::RequestIssuing);
1099        } else if (dcachePort.sendTimingReq(packet)) {
1100            DPRINTF(MinorMem, "Sent data memory request\n");
1101
1102            numAccessesInMemorySystem++;
1103
1104            request->stepToNextPacket();
1105
1106            ret = request->sentAllPackets();
1107
1108            switch (request->state) {
1109              case LSQRequest::Translated:
1110              case LSQRequest::RequestIssuing:
1111                /* Fully or partially issued a request in the transfers
1112                 *  queue */
1113                request->setState(LSQRequest::RequestIssuing);
1114                break;
1115              case LSQRequest::StoreInStoreBuffer:
1116              case LSQRequest::StoreBufferIssuing:
1117                /* Fully or partially issued a request in the store
1118                 *  buffer */
1119                request->setState(LSQRequest::StoreBufferIssuing);
1120                break;
1121              default:
1122                assert(false);
1123                break;
1124            }
1125
1126            state = MemoryRunning;
1127        } else {
1128            DPRINTF(MinorMem,
1129                "Sending data memory request - needs retry\n");
1130
1131            /* Needs to be resent, wait for that */
1132            state = MemoryNeedsRetry;
1133            retryRequest = request;
1134
1135            switch (request->state) {
1136              case LSQRequest::Translated:
1137              case LSQRequest::RequestIssuing:
1138                request->setState(LSQRequest::RequestNeedsRetry);
1139                break;
1140              case LSQRequest::StoreInStoreBuffer:
1141              case LSQRequest::StoreBufferIssuing:
1142                request->setState(LSQRequest::StoreBufferNeedsRetry);
1143                break;
1144              default:
1145                assert(false);
1146                break;
1147            }
1148        }
1149    }
1150
1151    if (ret)
1152        threadSnoop(request);
1153
1154    return ret;
1155}
1156
1157void
1158LSQ::moveFromRequestsToTransfers(LSQRequestPtr request)
1159{
1160    assert(!requests.empty() && requests.front() == request);
1161    assert(transfers.unreservedRemainingSpace() != 0);
1162
1163    /* Need to count the number of stores in the transfers
1164     *  queue so that loads know when their store buffer forwarding
1165     *  results will be correct (only when all those stores
1166     *  have reached the store buffer) */
1167    if (!request->isLoad)
1168        numStoresInTransfers++;
1169
1170    requests.pop();
1171    transfers.push(request);
1172}
1173
1174bool
1175LSQ::canSendToMemorySystem()
1176{
1177    return state == MemoryRunning &&
1178        numAccessesInMemorySystem < inMemorySystemLimit;
1179}
1180
1181bool
1182LSQ::recvTimingResp(PacketPtr response)
1183{
1184    LSQRequestPtr request =
1185        safe_cast<LSQRequestPtr>(response->popSenderState());
1186
1187    DPRINTF(MinorMem, "Received response packet inst: %s"
1188        " addr: 0x%x cmd: %s\n",
1189        *(request->inst), response->getAddr(),
1190        response->cmd.toString());
1191
1192    numAccessesInMemorySystem--;
1193
1194    if (response->isError()) {
1195        DPRINTF(MinorMem, "Received error response packet: %s\n",
1196            *request->inst);
1197    }
1198
1199    switch (request->state) {
1200      case LSQRequest::RequestIssuing:
1201      case LSQRequest::RequestNeedsRetry:
1202        /* Response to a request from the transfers queue */
1203        request->retireResponse(response);
1204
1205        DPRINTF(MinorMem, "Has outstanding packets?: %d %d\n",
1206            request->hasPacketsInMemSystem(), request->isComplete());
1207
1208        break;
1209      case LSQRequest::StoreBufferIssuing:
1210      case LSQRequest::StoreBufferNeedsRetry:
1211        /* Response to a request from the store buffer */
1212        request->retireResponse(response);
1213
1214        /* Remove completed requests unless they are barriers (which will
1215         *  need to be removed in order */
1216        if (request->isComplete()) {
1217            if (!request->isBarrier()) {
1218                storeBuffer.deleteRequest(request);
1219            } else {
1220                DPRINTF(MinorMem, "Completed transfer for barrier: %s"
1221                    " leaving the request as it is also a barrier\n",
1222                    *(request->inst));
1223            }
1224        }
1225        break;
1226      default:
1227        /* Shouldn't be allowed to receive a response from another
1228         *  state */
1229        assert(false);
1230        break;
1231    }
1232
1233    /* We go to idle even if there are more things in the requests queue
1234     * as it's the job of step to actually step us on to the next
1235     * transaction */
1236
1237    /* Let's try and wake up the processor for the next cycle */
1238    cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1239
1240    /* Never busy */
1241    return true;
1242}
1243
1244void
1245LSQ::recvReqRetry()
1246{
1247    DPRINTF(MinorMem, "Received retry request\n");
1248
1249    assert(state == MemoryNeedsRetry);
1250
1251    switch (retryRequest->state) {
1252      case LSQRequest::RequestNeedsRetry:
1253        /* Retry in the requests queue */
1254        retryRequest->setState(LSQRequest::Translated);
1255        break;
1256      case LSQRequest::StoreBufferNeedsRetry:
1257        /* Retry in the store buffer */
1258        retryRequest->setState(LSQRequest::StoreInStoreBuffer);
1259        break;
1260      default:
1261        assert(false);
1262    }
1263
1264    /* Set state back to MemoryRunning so that the following
1265     *  tryToSend can actually send.  Note that this won't
1266     *  allow another transfer in as tryToSend should
1267     *  issue a memory request and either succeed for this
1268     *  request or return the LSQ back to MemoryNeedsRetry */
1269    state = MemoryRunning;
1270
1271    /* Try to resend the request */
1272    if (tryToSend(retryRequest)) {
1273        /* Successfully sent, need to move the request */
1274        switch (retryRequest->state) {
1275          case LSQRequest::RequestIssuing:
1276            /* In the requests queue */
1277            moveFromRequestsToTransfers(retryRequest);
1278            break;
1279          case LSQRequest::StoreBufferIssuing:
1280            /* In the store buffer */
1281            storeBuffer.countIssuedStore(retryRequest);
1282            break;
1283          default:
1284            assert(false);
1285            break;
1286        }
1287
1288        retryRequest = NULL;
1289    }
1290}
1291
1292LSQ::LSQ(std::string name_, std::string dcache_port_name_,
1293    MinorCPU &cpu_, Execute &execute_,
1294    unsigned int in_memory_system_limit, unsigned int line_width,
1295    unsigned int requests_queue_size, unsigned int transfers_queue_size,
1296    unsigned int store_buffer_size,
1297    unsigned int store_buffer_cycle_store_limit) :
1298    Named(name_),
1299    cpu(cpu_),
1300    execute(execute_),
1301    dcachePort(dcache_port_name_, *this, cpu_),
1302    lastMemBarrier(cpu.numThreads, 0),
1303    state(MemoryRunning),
1304    inMemorySystemLimit(in_memory_system_limit),
1305    lineWidth((line_width == 0 ? cpu.cacheLineSize() : line_width)),
1306    requests(name_ + ".requests", "addr", requests_queue_size),
1307    transfers(name_ + ".transfers", "addr", transfers_queue_size),
1308    storeBuffer(name_ + ".storeBuffer",
1309        *this, store_buffer_size, store_buffer_cycle_store_limit),
1310    numAccessesInMemorySystem(0),
1311    numAccessesInDTLB(0),
1312    numStoresInTransfers(0),
1313    numAccessesIssuedToMemory(0),
1314    retryRequest(NULL),
1315    cacheBlockMask(~(cpu_.cacheLineSize() - 1))
1316{
1317    if (in_memory_system_limit < 1) {
1318        fatal("%s: executeMaxAccessesInMemory must be >= 1 (%d)\n", name_,
1319            in_memory_system_limit);
1320    }
1321
1322    if (store_buffer_cycle_store_limit < 1) {
1323        fatal("%s: executeLSQMaxStoreBufferStoresPerCycle must be"
1324            " >= 1 (%d)\n", name_, store_buffer_cycle_store_limit);
1325    }
1326
1327    if (requests_queue_size < 1) {
1328        fatal("%s: executeLSQRequestsQueueSize must be"
1329            " >= 1 (%d)\n", name_, requests_queue_size);
1330    }
1331
1332    if (transfers_queue_size < 1) {
1333        fatal("%s: executeLSQTransfersQueueSize must be"
1334            " >= 1 (%d)\n", name_, transfers_queue_size);
1335    }
1336
1337    if (store_buffer_size < 1) {
1338        fatal("%s: executeLSQStoreBufferSize must be"
1339            " >= 1 (%d)\n", name_, store_buffer_size);
1340    }
1341
1342    if ((lineWidth & (lineWidth - 1)) != 0) {
1343        fatal("%s: lineWidth: %d must be a power of 2\n", name(), lineWidth);
1344    }
1345}
1346
1347LSQ::~LSQ()
1348{ }
1349
1350LSQ::LSQRequest::~LSQRequest()
1351{
1352    if (packet)
1353        delete packet;
1354    if (data)
1355        delete [] data;
1356}
1357
1358/**
1359 *  Step the memory access mechanism on to its next state.  In reality, most
1360 *  of the stepping is done by the callbacks on the LSQ but this
1361 *  function is responsible for issuing memory requests lodged in the
1362 *  requests queue.
1363 */
1364void
1365LSQ::step()
1366{
1367    /* Try to move address-translated requests between queues and issue
1368     *  them */
1369    if (!requests.empty())
1370        tryToSendToTransfers(requests.front());
1371
1372    storeBuffer.step();
1373}
1374
1375LSQ::LSQRequestPtr
1376LSQ::findResponse(MinorDynInstPtr inst)
1377{
1378    LSQ::LSQRequestPtr ret = NULL;
1379
1380    if (!transfers.empty()) {
1381        LSQRequestPtr request = transfers.front();
1382
1383        /* Same instruction and complete access or a store that's
1384         *  capable of being moved to the store buffer */
1385        if (request->inst->id == inst->id) {
1386            bool complete = request->isComplete();
1387            bool can_store = storeBuffer.canInsert();
1388            bool to_store_buffer = request->state ==
1389                LSQRequest::StoreToStoreBuffer;
1390
1391            if ((complete && !(request->isBarrier() && !can_store)) ||
1392                (to_store_buffer && can_store))
1393            {
1394                ret = request;
1395            }
1396        }
1397    }
1398
1399    if (ret) {
1400        DPRINTF(MinorMem, "Found matching memory response for inst: %s\n",
1401            *inst);
1402    } else {
1403        DPRINTF(MinorMem, "No matching memory response for inst: %s\n",
1404            *inst);
1405    }
1406
1407    return ret;
1408}
1409
1410void
1411LSQ::popResponse(LSQ::LSQRequestPtr response)
1412{
1413    assert(!transfers.empty() && transfers.front() == response);
1414
1415    transfers.pop();
1416
1417    if (!response->isLoad)
1418        numStoresInTransfers--;
1419
1420    if (response->issuedToMemory)
1421        numAccessesIssuedToMemory--;
1422
1423    if (response->state != LSQRequest::StoreInStoreBuffer) {
1424        DPRINTF(MinorMem, "Deleting %s request: %s\n",
1425            (response->isLoad ? "load" : "store"),
1426            *(response->inst));
1427
1428        delete response;
1429    }
1430}
1431
1432void
1433LSQ::sendStoreToStoreBuffer(LSQRequestPtr request)
1434{
1435    assert(request->state == LSQRequest::StoreToStoreBuffer);
1436
1437    DPRINTF(MinorMem, "Sending store: %s to store buffer\n",
1438        *(request->inst));
1439
1440    request->inst->inStoreBuffer = true;
1441
1442    storeBuffer.insert(request);
1443}
1444
1445bool
1446LSQ::isDrained()
1447{
1448    return requests.empty() && transfers.empty() &&
1449        storeBuffer.isDrained();
1450}
1451
1452bool
1453LSQ::needsToTick()
1454{
1455    bool ret = false;
1456
1457    if (canSendToMemorySystem()) {
1458        bool have_translated_requests = !requests.empty() &&
1459            requests.front()->state != LSQRequest::InTranslation &&
1460            transfers.unreservedRemainingSpace() != 0;
1461
1462        ret = have_translated_requests ||
1463            storeBuffer.numUnissuedStores() != 0;
1464    }
1465
1466    if (ret)
1467        DPRINTF(Activity, "Need to tick\n");
1468
1469    return ret;
1470}
1471
1472void
1473LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
1474    unsigned int size, Addr addr, unsigned int flags, uint64_t *res)
1475{
1476    bool needs_burst = transferNeedsBurst(addr, size, lineWidth);
1477    LSQRequestPtr request;
1478
1479    /* Copy given data into the request.  The request will pass this to the
1480     *  packet and then it will own the data */
1481    uint8_t *request_data = NULL;
1482
1483    DPRINTF(MinorMem, "Pushing request (%s) addr: 0x%x size: %d flags:"
1484        " 0x%x%s lineWidth : 0x%x\n",
1485        (isLoad ? "load" : "store"), addr, size, flags,
1486            (needs_burst ? " (needs burst)" : ""), lineWidth);
1487
1488    if (!isLoad) {
1489        /* request_data becomes the property of a ...DataRequest (see below)
1490         *  and destroyed by its destructor */
1491        request_data = new uint8_t[size];
1492        if (flags & Request::CACHE_BLOCK_ZERO) {
1493            /* For cache zeroing, just use zeroed data */
1494            std::memset(request_data, 0, size);
1495        } else {
1496            std::memcpy(request_data, data, size);
1497        }
1498    }
1499
1500    if (needs_burst) {
1501        request = new SplitDataRequest(
1502            *this, inst, isLoad, request_data, res);
1503    } else {
1504        request = new SingleDataRequest(
1505            *this, inst, isLoad, request_data, res);
1506    }
1507
1508    if (inst->traceData)
1509        inst->traceData->setMem(addr, size, flags);
1510
1511    int cid = cpu.threads[inst->id.threadId]->getTC()->contextId();
1512    request->request.setContext(cid);
1513    request->request.setVirt(0 /* asid */,
1514        addr, size, flags, cpu.dataMasterId(),
1515        /* I've no idea why we need the PC, but give it */
1516        inst->pc.instAddr());
1517
1518    requests.push(request);
1519    request->startAddrTranslation();
1520}
1521
1522void
1523LSQ::pushFailedRequest(MinorDynInstPtr inst)
1524{
1525    LSQRequestPtr request = new FailedDataRequest(*this, inst);
1526    requests.push(request);
1527}
1528
1529void
1530LSQ::minorTrace() const
1531{
1532    MINORTRACE("state=%s in_tlb_mem=%d/%d stores_in_transfers=%d"
1533        " lastMemBarrier=%d\n",
1534        state, numAccessesInDTLB, numAccessesInMemorySystem,
1535        numStoresInTransfers, lastMemBarrier[0]);
1536    requests.minorTrace();
1537    transfers.minorTrace();
1538    storeBuffer.minorTrace();
1539}
1540
1541LSQ::StoreBuffer::StoreBuffer(std::string name_, LSQ &lsq_,
1542    unsigned int store_buffer_size,
1543    unsigned int store_limit_per_cycle) :
1544    Named(name_), lsq(lsq_),
1545    numSlots(store_buffer_size),
1546    storeLimitPerCycle(store_limit_per_cycle),
1547    slots(),
1548    numUnissuedAccesses(0)
1549{
1550}
1551
1552PacketPtr
1553makePacketForRequest(Request &request, bool isLoad,
1554    Packet::SenderState *sender_state, PacketDataPtr data)
1555{
1556    PacketPtr ret = isLoad ? Packet::createRead(&request)
1557                           : Packet::createWrite(&request);
1558
1559    if (sender_state)
1560        ret->pushSenderState(sender_state);
1561
1562    if (isLoad)
1563        ret->allocate();
1564    else
1565        ret->dataDynamic(data);
1566
1567    return ret;
1568}
1569
1570void
1571LSQ::issuedMemBarrierInst(MinorDynInstPtr inst)
1572{
1573    assert(inst->isInst() && inst->staticInst->isMemBarrier());
1574    assert(inst->id.execSeqNum > lastMemBarrier[inst->id.threadId]);
1575
1576    /* Remember the barrier.  We only have a notion of one
1577     *  barrier so this may result in some mem refs being
1578     *  delayed if they are between barriers */
1579    lastMemBarrier[inst->id.threadId] = inst->id.execSeqNum;
1580}
1581
1582void
1583LSQ::LSQRequest::makePacket()
1584{
1585    /* Make the function idempotent */
1586    if (packet)
1587        return;
1588
1589    // if the translation faulted, do not create a packet
1590    if (fault != NoFault) {
1591        assert(packet == NULL);
1592        return;
1593    }
1594
1595    packet = makePacketForRequest(request, isLoad, this, data);
1596    /* Null the ret data so we know not to deallocate it when the
1597     * ret is destroyed.  The data now belongs to the ret and
1598     * the ret is responsible for its destruction */
1599    data = NULL;
1600}
1601
1602std::ostream &
1603operator <<(std::ostream &os, LSQ::MemoryState state)
1604{
1605    switch (state) {
1606      case LSQ::MemoryRunning:
1607        os << "MemoryRunning";
1608        break;
1609      case LSQ::MemoryNeedsRetry:
1610        os << "MemoryNeedsRetry";
1611        break;
1612      default:
1613        os << "MemoryState-" << static_cast<int>(state);
1614        break;
1615    }
1616    return os;
1617}
1618
1619void
1620LSQ::recvTimingSnoopReq(PacketPtr pkt)
1621{
1622    /* LLSC operations in Minor can't be speculative and are executed from
1623     * the head of the requests queue.  We shouldn't need to do more than
1624     * this action on snoops. */
1625    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1626        if (cpu.getCpuAddrMonitor(tid)->doMonitor(pkt)) {
1627            cpu.wakeup(tid);
1628        }
1629    }
1630
1631    if (pkt->isInvalidate() || pkt->isWrite()) {
1632        for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1633            TheISA::handleLockedSnoop(cpu.getContext(tid), pkt,
1634                                      cacheBlockMask);
1635        }
1636    }
1637}
1638
1639void
1640LSQ::threadSnoop(LSQRequestPtr request)
1641{
1642    /* LLSC operations in Minor can't be speculative and are executed from
1643     * the head of the requests queue.  We shouldn't need to do more than
1644     * this action on snoops. */
1645    ThreadID req_tid = request->inst->id.threadId;
1646    PacketPtr pkt = request->packet;
1647
1648    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1649        if (tid != req_tid) {
1650            if (cpu.getCpuAddrMonitor(tid)->doMonitor(pkt)) {
1651                cpu.wakeup(tid);
1652            }
1653
1654            if (pkt->isInvalidate() || pkt->isWrite()) {
1655                TheISA::handleLockedSnoop(cpu.getContext(tid), pkt,
1656                                          cacheBlockMask);
1657            }
1658        }
1659    }
1660}
1661
1662}
1663