110259SAndrew.Bardsley@arm.com/*
210259SAndrew.Bardsley@arm.com * Copyright (c) 2013-2014 ARM Limited
310259SAndrew.Bardsley@arm.com * All rights reserved
410259SAndrew.Bardsley@arm.com *
510259SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall
610259SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual
710259SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating
810259SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software
910259SAndrew.Bardsley@arm.com * licensed hereunder.  You may use the software subject to the license
1010259SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated
1110259SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software,
1210259SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form.
1310259SAndrew.Bardsley@arm.com *
1410259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without
1510259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are
1610259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright
1710259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer;
1810259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright
1910259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the
2010259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution;
2110259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its
2210259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from
2310259SAndrew.Bardsley@arm.com * this software without specific prior written permission.
2410259SAndrew.Bardsley@arm.com *
2510259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610259SAndrew.Bardsley@arm.com *
3710259SAndrew.Bardsley@arm.com * Authors: Andrew Bardsley
3810259SAndrew.Bardsley@arm.com */
3910259SAndrew.Bardsley@arm.com
4011793Sbrandon.potter@amd.com#include "cpu/minor/fetch1.hh"
4111793Sbrandon.potter@amd.com
4210259SAndrew.Bardsley@arm.com#include <cstring>
4310259SAndrew.Bardsley@arm.com#include <iomanip>
4410259SAndrew.Bardsley@arm.com#include <sstream>
4510259SAndrew.Bardsley@arm.com
4610259SAndrew.Bardsley@arm.com#include "base/cast.hh"
4710259SAndrew.Bardsley@arm.com#include "cpu/minor/pipeline.hh"
4810259SAndrew.Bardsley@arm.com#include "debug/Drain.hh"
4910259SAndrew.Bardsley@arm.com#include "debug/Fetch.hh"
5010259SAndrew.Bardsley@arm.com#include "debug/MinorTrace.hh"
5110259SAndrew.Bardsley@arm.com
5210259SAndrew.Bardsley@arm.comnamespace Minor
5310259SAndrew.Bardsley@arm.com{
5410259SAndrew.Bardsley@arm.com
5510259SAndrew.Bardsley@arm.comFetch1::Fetch1(const std::string &name_,
5610259SAndrew.Bardsley@arm.com    MinorCPU &cpu_,
5710259SAndrew.Bardsley@arm.com    MinorCPUParams &params,
5810259SAndrew.Bardsley@arm.com    Latch<BranchData>::Output inp_,
5910259SAndrew.Bardsley@arm.com    Latch<ForwardLineData>::Input out_,
6010259SAndrew.Bardsley@arm.com    Latch<BranchData>::Output prediction_,
6111567Smitch.hayenga@arm.com    std::vector<InputBuffer<ForwardLineData>> &next_stage_input_buffer) :
6210259SAndrew.Bardsley@arm.com    Named(name_),
6310259SAndrew.Bardsley@arm.com    cpu(cpu_),
6410259SAndrew.Bardsley@arm.com    inp(inp_),
6510259SAndrew.Bardsley@arm.com    out(out_),
6610259SAndrew.Bardsley@arm.com    prediction(prediction_),
6710259SAndrew.Bardsley@arm.com    nextStageReserve(next_stage_input_buffer),
6810259SAndrew.Bardsley@arm.com    icachePort(name_ + ".icache_port", *this, cpu_),
6910259SAndrew.Bardsley@arm.com    lineSnap(params.fetch1LineSnapWidth),
7010259SAndrew.Bardsley@arm.com    maxLineWidth(params.fetch1LineWidth),
7110259SAndrew.Bardsley@arm.com    fetchLimit(params.fetch1FetchLimit),
7211567Smitch.hayenga@arm.com    fetchInfo(params.numThreads),
7311567Smitch.hayenga@arm.com    threadPriority(0),
7410259SAndrew.Bardsley@arm.com    requests(name_ + ".requests", "lines", params.fetch1FetchLimit),
7510259SAndrew.Bardsley@arm.com    transfers(name_ + ".transfers", "lines", params.fetch1FetchLimit),
7610259SAndrew.Bardsley@arm.com    icacheState(IcacheRunning),
7710259SAndrew.Bardsley@arm.com    lineSeqNum(InstId::firstLineSeqNum),
7810259SAndrew.Bardsley@arm.com    numFetchesInMemorySystem(0),
7910259SAndrew.Bardsley@arm.com    numFetchesInITLB(0)
8010259SAndrew.Bardsley@arm.com{
8110259SAndrew.Bardsley@arm.com    if (lineSnap == 0) {
8210259SAndrew.Bardsley@arm.com        lineSnap = cpu.cacheLineSize();
8310259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "lineSnap set to cache line size of: %d\n",
8410259SAndrew.Bardsley@arm.com            lineSnap);
8510259SAndrew.Bardsley@arm.com    }
8610259SAndrew.Bardsley@arm.com
8710259SAndrew.Bardsley@arm.com    if (maxLineWidth == 0) {
8810259SAndrew.Bardsley@arm.com        maxLineWidth = cpu.cacheLineSize();
8910259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "maxLineWidth set to cache line size of: %d\n",
9010259SAndrew.Bardsley@arm.com            maxLineWidth);
9110259SAndrew.Bardsley@arm.com    }
9210259SAndrew.Bardsley@arm.com
9310259SAndrew.Bardsley@arm.com    /* These assertions should be copied to the Python config. as well */
9410259SAndrew.Bardsley@arm.com    if ((lineSnap % sizeof(TheISA::MachInst)) != 0) {
9510259SAndrew.Bardsley@arm.com        fatal("%s: fetch1LineSnapWidth must be a multiple "
9610259SAndrew.Bardsley@arm.com            "of sizeof(TheISA::MachInst) (%d)\n", name_,
9710259SAndrew.Bardsley@arm.com            sizeof(TheISA::MachInst));
9810259SAndrew.Bardsley@arm.com    }
9910259SAndrew.Bardsley@arm.com
10010259SAndrew.Bardsley@arm.com    if (!(maxLineWidth >= lineSnap &&
10110259SAndrew.Bardsley@arm.com        (maxLineWidth % sizeof(TheISA::MachInst)) == 0))
10210259SAndrew.Bardsley@arm.com    {
10310259SAndrew.Bardsley@arm.com        fatal("%s: fetch1LineWidth must be a multiple of"
10410259SAndrew.Bardsley@arm.com            " sizeof(TheISA::MachInst)"
10510259SAndrew.Bardsley@arm.com            " (%d), and >= fetch1LineSnapWidth (%d)\n",
10610259SAndrew.Bardsley@arm.com            name_, sizeof(TheISA::MachInst), lineSnap);
10710259SAndrew.Bardsley@arm.com    }
10810259SAndrew.Bardsley@arm.com
10910259SAndrew.Bardsley@arm.com    if (fetchLimit < 1) {
11010259SAndrew.Bardsley@arm.com        fatal("%s: fetch1FetchLimit must be >= 1 (%d)\n", name_,
11110259SAndrew.Bardsley@arm.com            fetchLimit);
11210259SAndrew.Bardsley@arm.com    }
11310259SAndrew.Bardsley@arm.com}
11410259SAndrew.Bardsley@arm.com
11511567Smitch.hayenga@arm.cominline ThreadID
11611567Smitch.hayenga@arm.comFetch1::getScheduledThread()
11711567Smitch.hayenga@arm.com{
11811567Smitch.hayenga@arm.com    /* Select thread via policy. */
11911567Smitch.hayenga@arm.com    std::vector<ThreadID> priority_list;
12011567Smitch.hayenga@arm.com
12111567Smitch.hayenga@arm.com    switch (cpu.threadPolicy) {
12211567Smitch.hayenga@arm.com      case Enums::SingleThreaded:
12311567Smitch.hayenga@arm.com        priority_list.push_back(0);
12411567Smitch.hayenga@arm.com        break;
12511567Smitch.hayenga@arm.com      case Enums::RoundRobin:
12611567Smitch.hayenga@arm.com        priority_list = cpu.roundRobinPriority(threadPriority);
12711567Smitch.hayenga@arm.com        break;
12811567Smitch.hayenga@arm.com      case Enums::Random:
12911567Smitch.hayenga@arm.com        priority_list = cpu.randomPriority();
13011567Smitch.hayenga@arm.com        break;
13111567Smitch.hayenga@arm.com      default:
13211567Smitch.hayenga@arm.com        panic("Unknown fetch policy");
13311567Smitch.hayenga@arm.com    }
13411567Smitch.hayenga@arm.com
13511567Smitch.hayenga@arm.com    for (auto tid : priority_list) {
13611567Smitch.hayenga@arm.com        if (cpu.getContext(tid)->status() == ThreadContext::Active &&
13711567Smitch.hayenga@arm.com            !fetchInfo[tid].blocked &&
13811567Smitch.hayenga@arm.com            fetchInfo[tid].state == FetchRunning) {
13911567Smitch.hayenga@arm.com            threadPriority = tid;
14011567Smitch.hayenga@arm.com            return tid;
14111567Smitch.hayenga@arm.com        }
14211567Smitch.hayenga@arm.com    }
14311567Smitch.hayenga@arm.com
14411567Smitch.hayenga@arm.com   return InvalidThreadID;
14511567Smitch.hayenga@arm.com}
14611567Smitch.hayenga@arm.com
14710259SAndrew.Bardsley@arm.comvoid
14811567Smitch.hayenga@arm.comFetch1::fetchLine(ThreadID tid)
14910259SAndrew.Bardsley@arm.com{
15011567Smitch.hayenga@arm.com    /* Reference the currently used thread state. */
15111567Smitch.hayenga@arm.com    Fetch1ThreadInfo &thread = fetchInfo[tid];
15211567Smitch.hayenga@arm.com
15310259SAndrew.Bardsley@arm.com    /* If line_offset != 0, a request is pushed for the remainder of the
15410259SAndrew.Bardsley@arm.com     * line. */
15510259SAndrew.Bardsley@arm.com    /* Use a lower, sizeof(MachInst) aligned address for the fetch */
15611567Smitch.hayenga@arm.com    Addr aligned_pc = thread.pc.instAddr() & ~((Addr) lineSnap - 1);
15710259SAndrew.Bardsley@arm.com    unsigned int line_offset = aligned_pc % lineSnap;
15810259SAndrew.Bardsley@arm.com    unsigned int request_size = maxLineWidth - line_offset;
15910259SAndrew.Bardsley@arm.com
16010259SAndrew.Bardsley@arm.com    /* Fill in the line's id */
16111567Smitch.hayenga@arm.com    InstId request_id(tid,
16211567Smitch.hayenga@arm.com        thread.streamSeqNum, thread.predictionSeqNum,
16310259SAndrew.Bardsley@arm.com        lineSeqNum);
16410259SAndrew.Bardsley@arm.com
16511567Smitch.hayenga@arm.com    FetchRequestPtr request = new FetchRequest(*this, request_id, thread.pc);
16610259SAndrew.Bardsley@arm.com
16710259SAndrew.Bardsley@arm.com    DPRINTF(Fetch, "Inserting fetch into the fetch queue "
16810259SAndrew.Bardsley@arm.com        "%s addr: 0x%x pc: %s line_offset: %d request_size: %d\n",
16911567Smitch.hayenga@arm.com        request_id, aligned_pc, thread.pc, line_offset, request_size);
17010259SAndrew.Bardsley@arm.com
17112749Sgiacomo.travaglini@arm.com    request->request->setContext(cpu.threads[tid]->getTC()->contextId());
17212749Sgiacomo.travaglini@arm.com    request->request->setVirt(0 /* asid */,
17310259SAndrew.Bardsley@arm.com        aligned_pc, request_size, Request::INST_FETCH, cpu.instMasterId(),
17410259SAndrew.Bardsley@arm.com        /* I've no idea why we need the PC, but give it */
17511567Smitch.hayenga@arm.com        thread.pc.instAddr());
17610259SAndrew.Bardsley@arm.com
17710259SAndrew.Bardsley@arm.com    DPRINTF(Fetch, "Submitting ITLB request\n");
17810259SAndrew.Bardsley@arm.com    numFetchesInITLB++;
17910259SAndrew.Bardsley@arm.com
18010259SAndrew.Bardsley@arm.com    request->state = FetchRequest::InTranslation;
18110259SAndrew.Bardsley@arm.com
18210259SAndrew.Bardsley@arm.com    /* Reserve space in the queues upstream of requests for results */
18310259SAndrew.Bardsley@arm.com    transfers.reserve();
18410259SAndrew.Bardsley@arm.com    requests.push(request);
18510259SAndrew.Bardsley@arm.com
18610259SAndrew.Bardsley@arm.com    /* Submit the translation request.  The response will come
18710259SAndrew.Bardsley@arm.com     *  through finish/markDelayed on this request as it bears
18810259SAndrew.Bardsley@arm.com     *  the Translation interface */
18910259SAndrew.Bardsley@arm.com    cpu.threads[request->id.threadId]->itb->translateTiming(
19012749Sgiacomo.travaglini@arm.com        request->request,
19110259SAndrew.Bardsley@arm.com        cpu.getContext(request->id.threadId),
19210259SAndrew.Bardsley@arm.com        request, BaseTLB::Execute);
19310259SAndrew.Bardsley@arm.com
19410259SAndrew.Bardsley@arm.com    lineSeqNum++;
19510259SAndrew.Bardsley@arm.com
19610259SAndrew.Bardsley@arm.com    /* Step the PC for the next line onto the line aligned next address.
19710259SAndrew.Bardsley@arm.com     * Note that as instructions can span lines, this PC is only a
19810259SAndrew.Bardsley@arm.com     * reliable 'new' PC if the next line has a new stream sequence number. */
19910259SAndrew.Bardsley@arm.com#if THE_ISA == ALPHA_ISA
20010259SAndrew.Bardsley@arm.com    /* Restore the low bits of the PC used as address space flags */
20111567Smitch.hayenga@arm.com    Addr pc_low_bits = thread.pc.instAddr() &
20210259SAndrew.Bardsley@arm.com        ((Addr) (1 << sizeof(TheISA::MachInst)) - 1);
20310259SAndrew.Bardsley@arm.com
20411567Smitch.hayenga@arm.com    thread.pc.set(aligned_pc + request_size + pc_low_bits);
20510259SAndrew.Bardsley@arm.com#else
20611567Smitch.hayenga@arm.com    thread.pc.set(aligned_pc + request_size);
20710259SAndrew.Bardsley@arm.com#endif
20810259SAndrew.Bardsley@arm.com}
20910259SAndrew.Bardsley@arm.com
21010259SAndrew.Bardsley@arm.comstd::ostream &
21110259SAndrew.Bardsley@arm.comoperator <<(std::ostream &os, Fetch1::IcacheState state)
21210259SAndrew.Bardsley@arm.com{
21310259SAndrew.Bardsley@arm.com    switch (state) {
21410259SAndrew.Bardsley@arm.com      case Fetch1::IcacheRunning:
21510259SAndrew.Bardsley@arm.com        os << "IcacheRunning";
21610259SAndrew.Bardsley@arm.com        break;
21710259SAndrew.Bardsley@arm.com      case Fetch1::IcacheNeedsRetry:
21810259SAndrew.Bardsley@arm.com        os << "IcacheNeedsRetry";
21910259SAndrew.Bardsley@arm.com        break;
22010259SAndrew.Bardsley@arm.com      default:
22110259SAndrew.Bardsley@arm.com        os << "IcacheState-" << static_cast<int>(state);
22210259SAndrew.Bardsley@arm.com        break;
22310259SAndrew.Bardsley@arm.com    }
22410259SAndrew.Bardsley@arm.com    return os;
22510259SAndrew.Bardsley@arm.com}
22610259SAndrew.Bardsley@arm.com
22710259SAndrew.Bardsley@arm.comvoid
22810259SAndrew.Bardsley@arm.comFetch1::FetchRequest::makePacket()
22910259SAndrew.Bardsley@arm.com{
23010259SAndrew.Bardsley@arm.com    /* Make the necessary packet for a memory transaction */
23112749Sgiacomo.travaglini@arm.com    packet = new Packet(request, MemCmd::ReadReq);
23210259SAndrew.Bardsley@arm.com    packet->allocate();
23310259SAndrew.Bardsley@arm.com
23410259SAndrew.Bardsley@arm.com    /* This FetchRequest becomes SenderState to allow the response to be
23510259SAndrew.Bardsley@arm.com     *  identified */
23610259SAndrew.Bardsley@arm.com    packet->pushSenderState(this);
23710259SAndrew.Bardsley@arm.com}
23810259SAndrew.Bardsley@arm.com
23910259SAndrew.Bardsley@arm.comvoid
24012749Sgiacomo.travaglini@arm.comFetch1::FetchRequest::finish(const Fault &fault_, const RequestPtr &request_,
24110379Sandreas.hansson@arm.com                             ThreadContext *tc, BaseTLB::Mode mode)
24210259SAndrew.Bardsley@arm.com{
24310259SAndrew.Bardsley@arm.com    fault = fault_;
24410259SAndrew.Bardsley@arm.com
24510259SAndrew.Bardsley@arm.com    state = Translated;
24610259SAndrew.Bardsley@arm.com    fetch.handleTLBResponse(this);
24710259SAndrew.Bardsley@arm.com
24810259SAndrew.Bardsley@arm.com    /* Let's try and wake up the processor for the next cycle */
24910259SAndrew.Bardsley@arm.com    fetch.cpu.wakeupOnEvent(Pipeline::Fetch1StageId);
25010259SAndrew.Bardsley@arm.com}
25110259SAndrew.Bardsley@arm.com
25210259SAndrew.Bardsley@arm.comvoid
25310259SAndrew.Bardsley@arm.comFetch1::handleTLBResponse(FetchRequestPtr response)
25410259SAndrew.Bardsley@arm.com{
25510259SAndrew.Bardsley@arm.com    numFetchesInITLB--;
25610259SAndrew.Bardsley@arm.com
25710259SAndrew.Bardsley@arm.com    if (response->fault != NoFault) {
25810259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Fault in address ITLB translation: %s, "
25910259SAndrew.Bardsley@arm.com            "paddr: 0x%x, vaddr: 0x%x\n",
26010259SAndrew.Bardsley@arm.com            response->fault->name(),
26112749Sgiacomo.travaglini@arm.com            (response->request->hasPaddr() ?
26212749Sgiacomo.travaglini@arm.com                response->request->getPaddr() : 0),
26312749Sgiacomo.travaglini@arm.com            response->request->getVaddr());
26410259SAndrew.Bardsley@arm.com
26510259SAndrew.Bardsley@arm.com        if (DTRACE(MinorTrace))
26610259SAndrew.Bardsley@arm.com            minorTraceResponseLine(name(), response);
26710259SAndrew.Bardsley@arm.com    } else {
26810259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Got ITLB response\n");
26910259SAndrew.Bardsley@arm.com    }
27010259SAndrew.Bardsley@arm.com
27110259SAndrew.Bardsley@arm.com    response->state = FetchRequest::Translated;
27210259SAndrew.Bardsley@arm.com
27310259SAndrew.Bardsley@arm.com    tryToSendToTransfers(response);
27410259SAndrew.Bardsley@arm.com}
27510259SAndrew.Bardsley@arm.com
27610259SAndrew.Bardsley@arm.comFetch1::FetchRequest::~FetchRequest()
27710259SAndrew.Bardsley@arm.com{
27810259SAndrew.Bardsley@arm.com    if (packet)
27910259SAndrew.Bardsley@arm.com        delete packet;
28010259SAndrew.Bardsley@arm.com}
28110259SAndrew.Bardsley@arm.com
28210259SAndrew.Bardsley@arm.comvoid
28310259SAndrew.Bardsley@arm.comFetch1::tryToSendToTransfers(FetchRequestPtr request)
28410259SAndrew.Bardsley@arm.com{
28510259SAndrew.Bardsley@arm.com    if (!requests.empty() && requests.front() != request) {
28610259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Fetch not at front of requests queue, can't"
28710259SAndrew.Bardsley@arm.com            " issue to memory\n");
28810259SAndrew.Bardsley@arm.com        return;
28910259SAndrew.Bardsley@arm.com    }
29010259SAndrew.Bardsley@arm.com
29110259SAndrew.Bardsley@arm.com    if (request->state == FetchRequest::InTranslation) {
29210259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Fetch still in translation, not issuing to"
29310259SAndrew.Bardsley@arm.com            " memory\n");
29410259SAndrew.Bardsley@arm.com        return;
29510259SAndrew.Bardsley@arm.com    }
29610259SAndrew.Bardsley@arm.com
29710259SAndrew.Bardsley@arm.com    if (request->isDiscardable() || request->fault != NoFault) {
29810259SAndrew.Bardsley@arm.com        /* Discarded and faulting requests carry on through transfers
29910259SAndrew.Bardsley@arm.com         *  as Complete/packet == NULL */
30010259SAndrew.Bardsley@arm.com
30110259SAndrew.Bardsley@arm.com        request->state = FetchRequest::Complete;
30210259SAndrew.Bardsley@arm.com        moveFromRequestsToTransfers(request);
30310259SAndrew.Bardsley@arm.com
30410259SAndrew.Bardsley@arm.com        /* Wake up the pipeline next cycle as there will be no event
30510259SAndrew.Bardsley@arm.com         *  for this queue->queue transfer */
30610259SAndrew.Bardsley@arm.com        cpu.wakeupOnEvent(Pipeline::Fetch1StageId);
30710259SAndrew.Bardsley@arm.com    } else if (request->state == FetchRequest::Translated) {
30810259SAndrew.Bardsley@arm.com        if (!request->packet)
30910259SAndrew.Bardsley@arm.com            request->makePacket();
31010259SAndrew.Bardsley@arm.com
31110259SAndrew.Bardsley@arm.com        /* Ensure that the packet won't delete the request */
31210259SAndrew.Bardsley@arm.com        assert(request->packet->needsResponse());
31310259SAndrew.Bardsley@arm.com
31410259SAndrew.Bardsley@arm.com        if (tryToSend(request))
31510259SAndrew.Bardsley@arm.com            moveFromRequestsToTransfers(request);
31610259SAndrew.Bardsley@arm.com    } else {
31710259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Not advancing line fetch\n");
31810259SAndrew.Bardsley@arm.com    }
31910259SAndrew.Bardsley@arm.com}
32010259SAndrew.Bardsley@arm.com
32110259SAndrew.Bardsley@arm.comvoid
32210259SAndrew.Bardsley@arm.comFetch1::moveFromRequestsToTransfers(FetchRequestPtr request)
32310259SAndrew.Bardsley@arm.com{
32410259SAndrew.Bardsley@arm.com    assert(!requests.empty() && requests.front() == request);
32510259SAndrew.Bardsley@arm.com
32610259SAndrew.Bardsley@arm.com    requests.pop();
32710259SAndrew.Bardsley@arm.com    transfers.push(request);
32810259SAndrew.Bardsley@arm.com}
32910259SAndrew.Bardsley@arm.com
33010259SAndrew.Bardsley@arm.combool
33110259SAndrew.Bardsley@arm.comFetch1::tryToSend(FetchRequestPtr request)
33210259SAndrew.Bardsley@arm.com{
33310259SAndrew.Bardsley@arm.com    bool ret = false;
33410259SAndrew.Bardsley@arm.com
33510259SAndrew.Bardsley@arm.com    if (icachePort.sendTimingReq(request->packet)) {
33610259SAndrew.Bardsley@arm.com        /* Invalidate the fetch_requests packet so we don't
33710259SAndrew.Bardsley@arm.com         *  accidentally fail to deallocate it (or use it!)
33810259SAndrew.Bardsley@arm.com         *  later by overwriting it */
33910259SAndrew.Bardsley@arm.com        request->packet = NULL;
34010259SAndrew.Bardsley@arm.com        request->state = FetchRequest::RequestIssuing;
34110259SAndrew.Bardsley@arm.com        numFetchesInMemorySystem++;
34210259SAndrew.Bardsley@arm.com
34310259SAndrew.Bardsley@arm.com        ret = true;
34410259SAndrew.Bardsley@arm.com
34510259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Issued fetch request to memory: %s\n",
34610259SAndrew.Bardsley@arm.com            request->id);
34710259SAndrew.Bardsley@arm.com    } else {
34810259SAndrew.Bardsley@arm.com        /* Needs to be resent, wait for that */
34910259SAndrew.Bardsley@arm.com        icacheState = IcacheNeedsRetry;
35010259SAndrew.Bardsley@arm.com
35110259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Line fetch needs to retry: %s\n",
35210259SAndrew.Bardsley@arm.com            request->id);
35310259SAndrew.Bardsley@arm.com    }
35410259SAndrew.Bardsley@arm.com
35510259SAndrew.Bardsley@arm.com    return ret;
35610259SAndrew.Bardsley@arm.com}
35710259SAndrew.Bardsley@arm.com
35810259SAndrew.Bardsley@arm.comvoid
35910259SAndrew.Bardsley@arm.comFetch1::stepQueues()
36010259SAndrew.Bardsley@arm.com{
36110259SAndrew.Bardsley@arm.com    IcacheState old_icache_state = icacheState;
36210259SAndrew.Bardsley@arm.com
36310259SAndrew.Bardsley@arm.com    switch (icacheState) {
36410259SAndrew.Bardsley@arm.com      case IcacheRunning:
36510259SAndrew.Bardsley@arm.com        /* Move ITLB results on to the memory system */
36610259SAndrew.Bardsley@arm.com        if (!requests.empty()) {
36710259SAndrew.Bardsley@arm.com            tryToSendToTransfers(requests.front());
36810259SAndrew.Bardsley@arm.com        }
36910259SAndrew.Bardsley@arm.com        break;
37010259SAndrew.Bardsley@arm.com      case IcacheNeedsRetry:
37110259SAndrew.Bardsley@arm.com        break;
37210259SAndrew.Bardsley@arm.com    }
37310259SAndrew.Bardsley@arm.com
37410259SAndrew.Bardsley@arm.com    if (icacheState != old_icache_state) {
37510259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Step in state %s moving to state %s\n",
37610259SAndrew.Bardsley@arm.com            old_icache_state, icacheState);
37710259SAndrew.Bardsley@arm.com    }
37810259SAndrew.Bardsley@arm.com}
37910259SAndrew.Bardsley@arm.com
38010259SAndrew.Bardsley@arm.comvoid
38110259SAndrew.Bardsley@arm.comFetch1::popAndDiscard(FetchQueue &queue)
38210259SAndrew.Bardsley@arm.com{
38310259SAndrew.Bardsley@arm.com    if (!queue.empty()) {
38410259SAndrew.Bardsley@arm.com        delete queue.front();
38510259SAndrew.Bardsley@arm.com        queue.pop();
38610259SAndrew.Bardsley@arm.com    }
38710259SAndrew.Bardsley@arm.com}
38810259SAndrew.Bardsley@arm.com
38910259SAndrew.Bardsley@arm.comunsigned int
39010259SAndrew.Bardsley@arm.comFetch1::numInFlightFetches()
39110259SAndrew.Bardsley@arm.com{
39210259SAndrew.Bardsley@arm.com    return requests.occupiedSpace() +
39310259SAndrew.Bardsley@arm.com        transfers.occupiedSpace();
39410259SAndrew.Bardsley@arm.com}
39510259SAndrew.Bardsley@arm.com
39610259SAndrew.Bardsley@arm.com/** Print the appropriate MinorLine line for a fetch response */
39710259SAndrew.Bardsley@arm.comvoid
39810259SAndrew.Bardsley@arm.comFetch1::minorTraceResponseLine(const std::string &name,
39910259SAndrew.Bardsley@arm.com    Fetch1::FetchRequestPtr response) const
40010259SAndrew.Bardsley@arm.com{
40112749Sgiacomo.travaglini@arm.com    const RequestPtr &request M5_VAR_USED = response->request;
40210259SAndrew.Bardsley@arm.com
40310259SAndrew.Bardsley@arm.com    if (response->packet && response->packet->isError()) {
40410259SAndrew.Bardsley@arm.com        MINORLINE(this, "id=F;%s vaddr=0x%x fault=\"error packet\"\n",
40512749Sgiacomo.travaglini@arm.com            response->id, request->getVaddr());
40610259SAndrew.Bardsley@arm.com    } else if (response->fault != NoFault) {
40710259SAndrew.Bardsley@arm.com        MINORLINE(this, "id=F;%s vaddr=0x%x fault=\"%s\"\n",
40812749Sgiacomo.travaglini@arm.com            response->id, request->getVaddr(), response->fault->name());
40910259SAndrew.Bardsley@arm.com    } else {
41010259SAndrew.Bardsley@arm.com        MINORLINE(this, "id=%s size=%d vaddr=0x%x paddr=0x%x\n",
41112749Sgiacomo.travaglini@arm.com            response->id, request->getSize(),
41212749Sgiacomo.travaglini@arm.com            request->getVaddr(), request->getPaddr());
41310259SAndrew.Bardsley@arm.com    }
41410259SAndrew.Bardsley@arm.com}
41510259SAndrew.Bardsley@arm.com
41610259SAndrew.Bardsley@arm.combool
41710259SAndrew.Bardsley@arm.comFetch1::recvTimingResp(PacketPtr response)
41810259SAndrew.Bardsley@arm.com{
41910259SAndrew.Bardsley@arm.com    DPRINTF(Fetch, "recvTimingResp %d\n", numFetchesInMemorySystem);
42010259SAndrew.Bardsley@arm.com
42110259SAndrew.Bardsley@arm.com    /* Only push the response if we didn't change stream?  No,  all responses
42210259SAndrew.Bardsley@arm.com     *  should hit the responses queue.  It's the job of 'step' to throw them
42310259SAndrew.Bardsley@arm.com     *  away. */
42410259SAndrew.Bardsley@arm.com    FetchRequestPtr fetch_request = safe_cast<FetchRequestPtr>
42510259SAndrew.Bardsley@arm.com        (response->popSenderState());
42610259SAndrew.Bardsley@arm.com
42710259SAndrew.Bardsley@arm.com    /* Fixup packet in fetch_request as this may have changed */
42810259SAndrew.Bardsley@arm.com    assert(!fetch_request->packet);
42910259SAndrew.Bardsley@arm.com    fetch_request->packet = response;
43010259SAndrew.Bardsley@arm.com
43110259SAndrew.Bardsley@arm.com    numFetchesInMemorySystem--;
43210259SAndrew.Bardsley@arm.com    fetch_request->state = FetchRequest::Complete;
43310259SAndrew.Bardsley@arm.com
43410259SAndrew.Bardsley@arm.com    if (DTRACE(MinorTrace))
43510259SAndrew.Bardsley@arm.com        minorTraceResponseLine(name(), fetch_request);
43610259SAndrew.Bardsley@arm.com
43710259SAndrew.Bardsley@arm.com    if (response->isError()) {
43810259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Received error response packet: %s\n",
43910259SAndrew.Bardsley@arm.com            fetch_request->id);
44010259SAndrew.Bardsley@arm.com    }
44110259SAndrew.Bardsley@arm.com
44210259SAndrew.Bardsley@arm.com    /* We go to idle even if there are more things to do on the queues as
44310259SAndrew.Bardsley@arm.com     *  it's the job of step to actually step us on to the next transaction */
44410259SAndrew.Bardsley@arm.com
44510259SAndrew.Bardsley@arm.com    /* Let's try and wake up the processor for the next cycle to move on
44610259SAndrew.Bardsley@arm.com     *  queues */
44710259SAndrew.Bardsley@arm.com    cpu.wakeupOnEvent(Pipeline::Fetch1StageId);
44810259SAndrew.Bardsley@arm.com
44910259SAndrew.Bardsley@arm.com    /* Never busy */
45010259SAndrew.Bardsley@arm.com    return true;
45110259SAndrew.Bardsley@arm.com}
45210259SAndrew.Bardsley@arm.com
45310259SAndrew.Bardsley@arm.comvoid
45410713Sandreas.hansson@arm.comFetch1::recvReqRetry()
45510259SAndrew.Bardsley@arm.com{
45610259SAndrew.Bardsley@arm.com    DPRINTF(Fetch, "recvRetry\n");
45710259SAndrew.Bardsley@arm.com    assert(icacheState == IcacheNeedsRetry);
45810259SAndrew.Bardsley@arm.com    assert(!requests.empty());
45910259SAndrew.Bardsley@arm.com
46010259SAndrew.Bardsley@arm.com    FetchRequestPtr retryRequest = requests.front();
46110259SAndrew.Bardsley@arm.com
46210259SAndrew.Bardsley@arm.com    icacheState = IcacheRunning;
46310259SAndrew.Bardsley@arm.com
46410259SAndrew.Bardsley@arm.com    if (tryToSend(retryRequest))
46510259SAndrew.Bardsley@arm.com        moveFromRequestsToTransfers(retryRequest);
46610259SAndrew.Bardsley@arm.com}
46710259SAndrew.Bardsley@arm.com
46810259SAndrew.Bardsley@arm.comstd::ostream &
46910259SAndrew.Bardsley@arm.comoperator <<(std::ostream &os, Fetch1::FetchState state)
47010259SAndrew.Bardsley@arm.com{
47110259SAndrew.Bardsley@arm.com    switch (state) {
47210259SAndrew.Bardsley@arm.com      case Fetch1::FetchHalted:
47310259SAndrew.Bardsley@arm.com        os << "FetchHalted";
47410259SAndrew.Bardsley@arm.com        break;
47510259SAndrew.Bardsley@arm.com      case Fetch1::FetchWaitingForPC:
47610259SAndrew.Bardsley@arm.com        os << "FetchWaitingForPC";
47710259SAndrew.Bardsley@arm.com        break;
47810259SAndrew.Bardsley@arm.com      case Fetch1::FetchRunning:
47910259SAndrew.Bardsley@arm.com        os << "FetchRunning";
48010259SAndrew.Bardsley@arm.com        break;
48110259SAndrew.Bardsley@arm.com      default:
48210259SAndrew.Bardsley@arm.com        os << "FetchState-" << static_cast<int>(state);
48310259SAndrew.Bardsley@arm.com        break;
48410259SAndrew.Bardsley@arm.com    }
48510259SAndrew.Bardsley@arm.com    return os;
48610259SAndrew.Bardsley@arm.com}
48710259SAndrew.Bardsley@arm.com
48810259SAndrew.Bardsley@arm.comvoid
48910259SAndrew.Bardsley@arm.comFetch1::changeStream(const BranchData &branch)
49010259SAndrew.Bardsley@arm.com{
49111567Smitch.hayenga@arm.com    Fetch1ThreadInfo &thread = fetchInfo[branch.threadId];
49211567Smitch.hayenga@arm.com
49310259SAndrew.Bardsley@arm.com    updateExpectedSeqNums(branch);
49410259SAndrew.Bardsley@arm.com
49510259SAndrew.Bardsley@arm.com    /* Start fetching again if we were stopped */
49610259SAndrew.Bardsley@arm.com    switch (branch.reason) {
49710259SAndrew.Bardsley@arm.com      case BranchData::SuspendThread:
49811567Smitch.hayenga@arm.com        {
49911567Smitch.hayenga@arm.com            if (thread.wakeupGuard) {
50011567Smitch.hayenga@arm.com                DPRINTF(Fetch, "Not suspending fetch due to guard: %s\n",
50111567Smitch.hayenga@arm.com                                branch);
50211567Smitch.hayenga@arm.com            } else {
50311567Smitch.hayenga@arm.com                DPRINTF(Fetch, "Suspending fetch: %s\n", branch);
50411567Smitch.hayenga@arm.com                thread.state = FetchWaitingForPC;
50511567Smitch.hayenga@arm.com            }
50611567Smitch.hayenga@arm.com        }
50710259SAndrew.Bardsley@arm.com        break;
50810259SAndrew.Bardsley@arm.com      case BranchData::HaltFetch:
50910259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Halting fetch\n");
51011567Smitch.hayenga@arm.com        thread.state = FetchHalted;
51110259SAndrew.Bardsley@arm.com        break;
51210259SAndrew.Bardsley@arm.com      default:
51310259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Changing stream on branch: %s\n", branch);
51411567Smitch.hayenga@arm.com        thread.state = FetchRunning;
51510259SAndrew.Bardsley@arm.com        break;
51610259SAndrew.Bardsley@arm.com    }
51711567Smitch.hayenga@arm.com    thread.pc = branch.target;
51810259SAndrew.Bardsley@arm.com}
51910259SAndrew.Bardsley@arm.com
52010259SAndrew.Bardsley@arm.comvoid
52110259SAndrew.Bardsley@arm.comFetch1::updateExpectedSeqNums(const BranchData &branch)
52210259SAndrew.Bardsley@arm.com{
52311567Smitch.hayenga@arm.com    Fetch1ThreadInfo &thread = fetchInfo[branch.threadId];
52411567Smitch.hayenga@arm.com
52510259SAndrew.Bardsley@arm.com    DPRINTF(Fetch, "Updating streamSeqNum from: %d to %d,"
52610259SAndrew.Bardsley@arm.com        " predictionSeqNum from: %d to %d\n",
52711567Smitch.hayenga@arm.com        thread.streamSeqNum, branch.newStreamSeqNum,
52811567Smitch.hayenga@arm.com        thread.predictionSeqNum, branch.newPredictionSeqNum);
52910259SAndrew.Bardsley@arm.com
53010259SAndrew.Bardsley@arm.com    /* Change the stream */
53111567Smitch.hayenga@arm.com    thread.streamSeqNum = branch.newStreamSeqNum;
53210259SAndrew.Bardsley@arm.com    /* Update the prediction.  Note that it's possible for this to
53310259SAndrew.Bardsley@arm.com     *  actually set the prediction to an *older* value if new
53410259SAndrew.Bardsley@arm.com     *  predictions have been discarded by execute */
53511567Smitch.hayenga@arm.com    thread.predictionSeqNum = branch.newPredictionSeqNum;
53610259SAndrew.Bardsley@arm.com}
53710259SAndrew.Bardsley@arm.com
53810259SAndrew.Bardsley@arm.comvoid
53910259SAndrew.Bardsley@arm.comFetch1::processResponse(Fetch1::FetchRequestPtr response,
54010259SAndrew.Bardsley@arm.com    ForwardLineData &line)
54110259SAndrew.Bardsley@arm.com{
54211567Smitch.hayenga@arm.com    Fetch1ThreadInfo &thread = fetchInfo[response->id.threadId];
54310259SAndrew.Bardsley@arm.com    PacketPtr packet = response->packet;
54410259SAndrew.Bardsley@arm.com
54510259SAndrew.Bardsley@arm.com    /* Pass the prefetch abort (if any) on to Fetch2 in a ForwardLineData
54610259SAndrew.Bardsley@arm.com     * structure */
54710259SAndrew.Bardsley@arm.com    line.setFault(response->fault);
54810259SAndrew.Bardsley@arm.com    /* Make sequence numbers valid in return */
54910259SAndrew.Bardsley@arm.com    line.id = response->id;
55010259SAndrew.Bardsley@arm.com    /* Set PC to virtual address */
55110259SAndrew.Bardsley@arm.com    line.pc = response->pc;
55210259SAndrew.Bardsley@arm.com    /* Set the lineBase, which is a sizeof(MachInst) aligned address <=
55310259SAndrew.Bardsley@arm.com     *  pc.instAddr() */
55412749Sgiacomo.travaglini@arm.com    line.lineBaseAddr = response->request->getVaddr();
55510259SAndrew.Bardsley@arm.com
55610259SAndrew.Bardsley@arm.com    if (response->fault != NoFault) {
55710259SAndrew.Bardsley@arm.com        /* Stop fetching if there was a fault */
55810259SAndrew.Bardsley@arm.com        /* Should probably try to flush the queues as well, but we
55910259SAndrew.Bardsley@arm.com         * can't be sure that this fault will actually reach Execute, and we
56010259SAndrew.Bardsley@arm.com         * can't (currently) selectively remove this stream from the queues */
56110259SAndrew.Bardsley@arm.com        DPRINTF(Fetch, "Stopping line fetch because of fault: %s\n",
56210259SAndrew.Bardsley@arm.com            response->fault->name());
56311567Smitch.hayenga@arm.com        thread.state = Fetch1::FetchWaitingForPC;
56410259SAndrew.Bardsley@arm.com    } else {
56510259SAndrew.Bardsley@arm.com        line.adoptPacketData(packet);
56610259SAndrew.Bardsley@arm.com        /* Null the response's packet to prevent the response from trying to
56710259SAndrew.Bardsley@arm.com         *  deallocate the packet */
56810259SAndrew.Bardsley@arm.com        response->packet = NULL;
56910259SAndrew.Bardsley@arm.com    }
57010259SAndrew.Bardsley@arm.com}
57110259SAndrew.Bardsley@arm.com
57210259SAndrew.Bardsley@arm.comvoid
57310259SAndrew.Bardsley@arm.comFetch1::evaluate()
57410259SAndrew.Bardsley@arm.com{
57510259SAndrew.Bardsley@arm.com    const BranchData &execute_branch = *inp.outputWire;
57610259SAndrew.Bardsley@arm.com    const BranchData &fetch2_branch = *prediction.outputWire;
57710259SAndrew.Bardsley@arm.com    ForwardLineData &line_out = *out.inputWire;
57810259SAndrew.Bardsley@arm.com
57910259SAndrew.Bardsley@arm.com    assert(line_out.isBubble());
58010259SAndrew.Bardsley@arm.com
58111567Smitch.hayenga@arm.com    for (ThreadID tid = 0; tid < cpu.numThreads; tid++)
58211567Smitch.hayenga@arm.com        fetchInfo[tid].blocked = !nextStageReserve[tid].canReserve();
58310259SAndrew.Bardsley@arm.com
58411567Smitch.hayenga@arm.com    /** Are both branches from later stages valid and for the same thread? */
58511567Smitch.hayenga@arm.com    if (execute_branch.threadId != InvalidThreadID &&
58611567Smitch.hayenga@arm.com        execute_branch.threadId == fetch2_branch.threadId) {
58711567Smitch.hayenga@arm.com
58811567Smitch.hayenga@arm.com        Fetch1ThreadInfo &thread = fetchInfo[execute_branch.threadId];
58911567Smitch.hayenga@arm.com
59011567Smitch.hayenga@arm.com        /* Are we changing stream?  Look to the Execute branches first, then
59111567Smitch.hayenga@arm.com         * to predicted changes of stream from Fetch2 */
59211567Smitch.hayenga@arm.com        if (execute_branch.isStreamChange()) {
59311567Smitch.hayenga@arm.com            if (thread.state == FetchHalted) {
59411567Smitch.hayenga@arm.com                DPRINTF(Fetch, "Halted, ignoring branch: %s\n", execute_branch);
59511567Smitch.hayenga@arm.com            } else {
59610259SAndrew.Bardsley@arm.com                changeStream(execute_branch);
59711567Smitch.hayenga@arm.com            }
59811567Smitch.hayenga@arm.com
59911567Smitch.hayenga@arm.com            if (!fetch2_branch.isBubble()) {
60011567Smitch.hayenga@arm.com                DPRINTF(Fetch, "Ignoring simultaneous prediction: %s\n",
60111567Smitch.hayenga@arm.com                    fetch2_branch);
60211567Smitch.hayenga@arm.com            }
60311567Smitch.hayenga@arm.com
60411567Smitch.hayenga@arm.com            /* The streamSeqNum tagging in request/response ->req should handle
60511567Smitch.hayenga@arm.com             *  discarding those requests when we get to them. */
60611567Smitch.hayenga@arm.com        } else if (thread.state != FetchHalted && fetch2_branch.isStreamChange()) {
60711567Smitch.hayenga@arm.com            /* Handle branch predictions by changing the instruction source
60811567Smitch.hayenga@arm.com             * if we're still processing the same stream (as set by streamSeqNum)
60911567Smitch.hayenga@arm.com             * as the one of the prediction.
61011567Smitch.hayenga@arm.com             */
61111567Smitch.hayenga@arm.com            if (fetch2_branch.newStreamSeqNum != thread.streamSeqNum) {
61211567Smitch.hayenga@arm.com                DPRINTF(Fetch, "Not changing stream on prediction: %s,"
61311567Smitch.hayenga@arm.com                    " streamSeqNum mismatch\n",
61411567Smitch.hayenga@arm.com                    fetch2_branch);
61510259SAndrew.Bardsley@arm.com            } else {
61611567Smitch.hayenga@arm.com                changeStream(fetch2_branch);
61710259SAndrew.Bardsley@arm.com            }
61811567Smitch.hayenga@arm.com        }
61911567Smitch.hayenga@arm.com    } else {
62011567Smitch.hayenga@arm.com        /* Fetch2 and Execute branches are for different threads */
62111567Smitch.hayenga@arm.com        if (execute_branch.threadId != InvalidThreadID &&
62211567Smitch.hayenga@arm.com            execute_branch.isStreamChange()) {
62311567Smitch.hayenga@arm.com
62411567Smitch.hayenga@arm.com            if (fetchInfo[execute_branch.threadId].state == FetchHalted) {
62511567Smitch.hayenga@arm.com                DPRINTF(Fetch, "Halted, ignoring branch: %s\n", execute_branch);
62611567Smitch.hayenga@arm.com            } else {
62711567Smitch.hayenga@arm.com                changeStream(execute_branch);
62811567Smitch.hayenga@arm.com            }
62910259SAndrew.Bardsley@arm.com        }
63010259SAndrew.Bardsley@arm.com
63111567Smitch.hayenga@arm.com        if (fetch2_branch.threadId != InvalidThreadID &&
63211567Smitch.hayenga@arm.com            fetch2_branch.isStreamChange()) {
63310259SAndrew.Bardsley@arm.com
63411567Smitch.hayenga@arm.com            if (fetchInfo[fetch2_branch.threadId].state == FetchHalted) {
63511567Smitch.hayenga@arm.com                DPRINTF(Fetch, "Halted, ignoring branch: %s\n", fetch2_branch);
63611567Smitch.hayenga@arm.com            } else if (fetch2_branch.newStreamSeqNum != fetchInfo[fetch2_branch.threadId].streamSeqNum) {
63711567Smitch.hayenga@arm.com                DPRINTF(Fetch, "Not changing stream on prediction: %s,"
63811567Smitch.hayenga@arm.com                    " streamSeqNum mismatch\n", fetch2_branch);
63911567Smitch.hayenga@arm.com            } else {
64011567Smitch.hayenga@arm.com                changeStream(fetch2_branch);
64111567Smitch.hayenga@arm.com            }
64210259SAndrew.Bardsley@arm.com        }
64310259SAndrew.Bardsley@arm.com    }
64410259SAndrew.Bardsley@arm.com
64511567Smitch.hayenga@arm.com    if (numInFlightFetches() < fetchLimit) {
64611567Smitch.hayenga@arm.com        ThreadID fetch_tid = getScheduledThread();
64711567Smitch.hayenga@arm.com
64811567Smitch.hayenga@arm.com        if (fetch_tid != InvalidThreadID) {
64911567Smitch.hayenga@arm.com            DPRINTF(Fetch, "Fetching from thread %d\n", fetch_tid);
65011567Smitch.hayenga@arm.com
65111567Smitch.hayenga@arm.com            /* Generate fetch to selected thread */
65211567Smitch.hayenga@arm.com            fetchLine(fetch_tid);
65311567Smitch.hayenga@arm.com            /* Take up a slot in the fetch queue */
65411567Smitch.hayenga@arm.com            nextStageReserve[fetch_tid].reserve();
65511567Smitch.hayenga@arm.com        } else {
65611567Smitch.hayenga@arm.com            DPRINTF(Fetch, "No active threads available to fetch from\n");
65711567Smitch.hayenga@arm.com        }
65810259SAndrew.Bardsley@arm.com    }
65910259SAndrew.Bardsley@arm.com
66011567Smitch.hayenga@arm.com
66110259SAndrew.Bardsley@arm.com    /* Halting shouldn't prevent fetches in flight from being processed */
66210259SAndrew.Bardsley@arm.com    /* Step fetches through the icachePort queues and memory system */
66310259SAndrew.Bardsley@arm.com    stepQueues();
66410259SAndrew.Bardsley@arm.com
66510259SAndrew.Bardsley@arm.com    /* As we've thrown away early lines, if there is a line, it must
66610259SAndrew.Bardsley@arm.com     *  be from the right stream */
66710259SAndrew.Bardsley@arm.com    if (!transfers.empty() &&
66810259SAndrew.Bardsley@arm.com        transfers.front()->isComplete())
66910259SAndrew.Bardsley@arm.com    {
67010259SAndrew.Bardsley@arm.com        Fetch1::FetchRequestPtr response = transfers.front();
67110259SAndrew.Bardsley@arm.com
67210259SAndrew.Bardsley@arm.com        if (response->isDiscardable()) {
67311567Smitch.hayenga@arm.com            nextStageReserve[response->id.threadId].freeReservation();
67410259SAndrew.Bardsley@arm.com
67511567Smitch.hayenga@arm.com            DPRINTF(Fetch, "Discarding translated fetch as it's for"
67610259SAndrew.Bardsley@arm.com                " an old stream\n");
67710259SAndrew.Bardsley@arm.com
67810259SAndrew.Bardsley@arm.com            /* Wake up next cycle just in case there was some other
67910259SAndrew.Bardsley@arm.com             *  action to do */
68010259SAndrew.Bardsley@arm.com            cpu.wakeupOnEvent(Pipeline::Fetch1StageId);
68110259SAndrew.Bardsley@arm.com        } else {
68210259SAndrew.Bardsley@arm.com            DPRINTF(Fetch, "Processing fetched line: %s\n",
68310259SAndrew.Bardsley@arm.com                response->id);
68410259SAndrew.Bardsley@arm.com
68510259SAndrew.Bardsley@arm.com            processResponse(response, line_out);
68610259SAndrew.Bardsley@arm.com        }
68710259SAndrew.Bardsley@arm.com
68810259SAndrew.Bardsley@arm.com        popAndDiscard(transfers);
68910259SAndrew.Bardsley@arm.com    }
69010259SAndrew.Bardsley@arm.com
69110259SAndrew.Bardsley@arm.com    /* If we generated output, and mark the stage as being active
69210259SAndrew.Bardsley@arm.com     *  to encourage that output on to the next stage */
69310259SAndrew.Bardsley@arm.com    if (!line_out.isBubble())
69410259SAndrew.Bardsley@arm.com        cpu.activityRecorder->activity();
69510259SAndrew.Bardsley@arm.com
69610259SAndrew.Bardsley@arm.com    /* Fetch1 has no inputBuffer so the only activity we can have is to
69710259SAndrew.Bardsley@arm.com     *  generate a line output (tested just above) or to initiate a memory
69810259SAndrew.Bardsley@arm.com     *  fetch which will signal activity when it returns/needs stepping
69910259SAndrew.Bardsley@arm.com     *  between queues */
70011567Smitch.hayenga@arm.com
70111567Smitch.hayenga@arm.com
70211567Smitch.hayenga@arm.com    /* This looks hackish.  And it is, but there doesn't seem to be a better
70311567Smitch.hayenga@arm.com     * way to do this.  The signal from commit to suspend fetch takes 1
70411567Smitch.hayenga@arm.com     * clock cycle to propagate to fetch.  However, a legitimate wakeup
70511567Smitch.hayenga@arm.com     * may occur between cycles from the memory system.  Thus wakeup guard
70611567Smitch.hayenga@arm.com     * prevents us from suspending in that case. */
70711567Smitch.hayenga@arm.com
70811567Smitch.hayenga@arm.com    for (auto& thread : fetchInfo) {
70911567Smitch.hayenga@arm.com        thread.wakeupGuard = false;
71011567Smitch.hayenga@arm.com    }
71111567Smitch.hayenga@arm.com}
71211567Smitch.hayenga@arm.com
71311567Smitch.hayenga@arm.comvoid
71411567Smitch.hayenga@arm.comFetch1::wakeupFetch(ThreadID tid)
71511567Smitch.hayenga@arm.com{
71611567Smitch.hayenga@arm.com    ThreadContext *thread_ctx = cpu.getContext(tid);
71711567Smitch.hayenga@arm.com    Fetch1ThreadInfo &thread = fetchInfo[tid];
71811567Smitch.hayenga@arm.com    thread.pc = thread_ctx->pcState();
71911567Smitch.hayenga@arm.com    thread.state = FetchRunning;
72011567Smitch.hayenga@arm.com    thread.wakeupGuard = true;
72111567Smitch.hayenga@arm.com    DPRINTF(Fetch, "[tid:%d]: Changing stream wakeup %s\n",
72211567Smitch.hayenga@arm.com            tid, thread_ctx->pcState());
72311567Smitch.hayenga@arm.com
72411567Smitch.hayenga@arm.com    cpu.wakeupOnEvent(Pipeline::Fetch1StageId);
72510259SAndrew.Bardsley@arm.com}
72610259SAndrew.Bardsley@arm.com
72710259SAndrew.Bardsley@arm.combool
72810259SAndrew.Bardsley@arm.comFetch1::isDrained()
72910259SAndrew.Bardsley@arm.com{
73011567Smitch.hayenga@arm.com    bool drained = numInFlightFetches() == 0 && (*out.inputWire).isBubble();
73111567Smitch.hayenga@arm.com    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
73211567Smitch.hayenga@arm.com        Fetch1ThreadInfo &thread = fetchInfo[tid];
73311567Smitch.hayenga@arm.com        DPRINTF(Drain, "isDrained[tid:%d]: %s %s%s\n",
73411567Smitch.hayenga@arm.com                tid,
73511567Smitch.hayenga@arm.com                thread.state == FetchHalted,
73611567Smitch.hayenga@arm.com                (numInFlightFetches() == 0 ? "" : "inFlightFetches "),
73711567Smitch.hayenga@arm.com                ((*out.inputWire).isBubble() ? "" : "outputtingLine"));
73810259SAndrew.Bardsley@arm.com
73911568Smitch.hayenga@arm.com        drained = drained && (thread.state != FetchRunning);
74011567Smitch.hayenga@arm.com    }
74111567Smitch.hayenga@arm.com
74211567Smitch.hayenga@arm.com    return drained;
74310259SAndrew.Bardsley@arm.com}
74410259SAndrew.Bardsley@arm.com
74510259SAndrew.Bardsley@arm.comvoid
74610259SAndrew.Bardsley@arm.comFetch1::FetchRequest::reportData(std::ostream &os) const
74710259SAndrew.Bardsley@arm.com{
74810259SAndrew.Bardsley@arm.com    os << id;
74910259SAndrew.Bardsley@arm.com}
75010259SAndrew.Bardsley@arm.com
75110259SAndrew.Bardsley@arm.combool Fetch1::FetchRequest::isDiscardable() const
75210259SAndrew.Bardsley@arm.com{
75311567Smitch.hayenga@arm.com    Fetch1ThreadInfo &thread = fetch.fetchInfo[id.threadId];
75411567Smitch.hayenga@arm.com
75510259SAndrew.Bardsley@arm.com    /* Can't discard lines in TLB/memory */
75610259SAndrew.Bardsley@arm.com    return state != InTranslation && state != RequestIssuing &&
75711567Smitch.hayenga@arm.com        (id.streamSeqNum != thread.streamSeqNum ||
75811567Smitch.hayenga@arm.com        id.predictionSeqNum != thread.predictionSeqNum);
75910259SAndrew.Bardsley@arm.com}
76010259SAndrew.Bardsley@arm.com
76110259SAndrew.Bardsley@arm.comvoid
76210259SAndrew.Bardsley@arm.comFetch1::minorTrace() const
76310259SAndrew.Bardsley@arm.com{
76411567Smitch.hayenga@arm.com    // TODO: Un-bork minorTrace for THREADS
76511567Smitch.hayenga@arm.com    // bork bork bork
76611567Smitch.hayenga@arm.com    const Fetch1ThreadInfo &thread = fetchInfo[0];
76711567Smitch.hayenga@arm.com
76810259SAndrew.Bardsley@arm.com    std::ostringstream data;
76910259SAndrew.Bardsley@arm.com
77011567Smitch.hayenga@arm.com    if (thread.blocked)
77110259SAndrew.Bardsley@arm.com        data << 'B';
77210259SAndrew.Bardsley@arm.com    else
77310259SAndrew.Bardsley@arm.com        (*out.inputWire).reportData(data);
77410259SAndrew.Bardsley@arm.com
77510259SAndrew.Bardsley@arm.com    MINORTRACE("state=%s icacheState=%s in_tlb_mem=%s/%s"
77611567Smitch.hayenga@arm.com        " streamSeqNum=%d lines=%s\n", thread.state, icacheState,
77710259SAndrew.Bardsley@arm.com        numFetchesInITLB, numFetchesInMemorySystem,
77811567Smitch.hayenga@arm.com        thread.streamSeqNum, data.str());
77910259SAndrew.Bardsley@arm.com    requests.minorTrace();
78010259SAndrew.Bardsley@arm.com    transfers.minorTrace();
78110259SAndrew.Bardsley@arm.com}
78210259SAndrew.Bardsley@arm.com
78310259SAndrew.Bardsley@arm.com}
784