2014-07-23 23:09:04 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013-2014 ARM Limited
|
|
|
|
* All rights reserved
|
|
|
|
*
|
|
|
|
* The license below extends only to copyright in the software and shall
|
|
|
|
* not be construed as granting a license to any other intellectual
|
|
|
|
* property including but not limited to intellectual property relating
|
|
|
|
* to a hardware implementation of the functionality of the software
|
|
|
|
* licensed hereunder. You may use the software subject to the license
|
|
|
|
* terms below provided that you ensure that this notice is replicated
|
|
|
|
* unmodified and in its entirety in all distributions of the software,
|
|
|
|
* modified or unmodified, in source code or in binary form.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met: redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer;
|
|
|
|
* redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution;
|
|
|
|
* neither the name of the copyright holders nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* Authors: Andrew Bardsley
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
*
|
|
|
|
* Fetch1 is responsible for fetching "lines" from memory and passing
|
|
|
|
* them to Fetch2
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __CPU_MINOR_FETCH1_HH__
|
|
|
|
#define __CPU_MINOR_FETCH1_HH__
|
|
|
|
|
|
|
|
#include "cpu/minor/buffers.hh"
|
|
|
|
#include "cpu/minor/cpu.hh"
|
|
|
|
#include "cpu/minor/pipe_data.hh"
|
|
|
|
#include "cpu/base.hh"
|
|
|
|
#include "mem/packet.hh"
|
|
|
|
|
|
|
|
namespace Minor
|
|
|
|
{
|
|
|
|
|
|
|
|
/** A stage responsible for fetching "lines" from memory and passing
|
|
|
|
* them to Fetch2 */
|
|
|
|
class Fetch1 : public Named
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
/** Exposable fetch port */
|
|
|
|
class IcachePort : public MinorCPU::MinorCPUPort
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
/** My owner */
|
|
|
|
Fetch1 &fetch;
|
|
|
|
|
|
|
|
public:
|
|
|
|
IcachePort(std::string name, Fetch1 &fetch_, MinorCPU &cpu) :
|
|
|
|
MinorCPU::MinorCPUPort(name, cpu), fetch(fetch_)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool recvTimingResp(PacketPtr pkt)
|
|
|
|
{ return fetch.recvTimingResp(pkt); }
|
|
|
|
|
2015-03-02 10:00:35 +01:00
|
|
|
void recvReqRetry() { fetch.recvReqRetry(); }
|
2014-07-23 23:09:04 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/** Memory access queuing.
|
|
|
|
*
|
|
|
|
* A request can be submitted by pushing it onto the requests queue after
|
|
|
|
* issuing an ITLB lookup (state becomes InTranslation) with a
|
|
|
|
* FetchSenderState senderState containing the current lineSeqNum and
|
|
|
|
* stream/predictionSeqNum.
|
|
|
|
*
|
|
|
|
* Translated packets (state becomes Translation) are then passed to the
|
|
|
|
* memory system and the transfers queue (state becomes RequestIssuing).
|
|
|
|
* Retries are handled by leaving the packet on the requests queue and
|
|
|
|
* changing the state to IcacheNeedsRetry).
|
|
|
|
*
|
|
|
|
* Responses from the memory system alter the request object (state
|
|
|
|
* become Complete). Responses can be picked up from the head of the
|
|
|
|
* transfers queue to pass on to Fetch2. */
|
|
|
|
|
|
|
|
/** Structure to hold SenderState info through
|
|
|
|
* translation and memory accesses. */
|
|
|
|
class FetchRequest :
|
|
|
|
public BaseTLB::Translation, /* For TLB lookups */
|
|
|
|
public Packet::SenderState /* For packing into a Packet */
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
/** Owning fetch unit */
|
|
|
|
Fetch1 &fetch;
|
|
|
|
|
|
|
|
public:
|
|
|
|
/** Progress of this request through address translation and
|
|
|
|
* memory */
|
|
|
|
enum FetchRequestState
|
|
|
|
{
|
|
|
|
NotIssued, /* Just been made */
|
|
|
|
InTranslation, /* Issued to ITLB, must wait for reqply */
|
|
|
|
Translated, /* Translation complete */
|
|
|
|
RequestIssuing, /* Issued to memory, must wait for response */
|
|
|
|
Complete /* Complete. Either a fault, or a fetched line */
|
|
|
|
};
|
|
|
|
|
|
|
|
FetchRequestState state;
|
|
|
|
|
|
|
|
/** Identity of the line that this request will generate */
|
|
|
|
InstId id;
|
|
|
|
|
|
|
|
/** FetchRequests carry packets while they're in the requests and
|
|
|
|
* transfers responses queues. When a Packet returns from the memory
|
|
|
|
* system, its request needs to have its packet updated as this may
|
|
|
|
* have changed in flight */
|
|
|
|
PacketPtr packet;
|
|
|
|
|
|
|
|
/** The underlying request that this fetch represents */
|
|
|
|
Request request;
|
|
|
|
|
|
|
|
/** PC to fixup with line address */
|
|
|
|
TheISA::PCState pc;
|
|
|
|
|
|
|
|
/** Fill in a fault if one happens during fetch, check this by
|
|
|
|
* picking apart the response packet */
|
|
|
|
Fault fault;
|
|
|
|
|
|
|
|
/** Make a packet to use with the memory transaction */
|
|
|
|
void makePacket();
|
|
|
|
|
|
|
|
/** Report interface */
|
|
|
|
void reportData(std::ostream &os) const;
|
|
|
|
|
|
|
|
/** Is this line out of date with the current stream/prediction
|
|
|
|
* sequence and can it be discarded without orphaning in flight
|
|
|
|
* TLB lookups/memory accesses? */
|
|
|
|
bool isDiscardable() const;
|
|
|
|
|
|
|
|
/** Is this a complete read line or fault */
|
|
|
|
bool isComplete() const { return state == Complete; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** BaseTLB::Translation interface */
|
|
|
|
|
|
|
|
/** Interface for ITLB responses. We can handle delay, so don't
|
|
|
|
* do anything */
|
|
|
|
void markDelayed() { }
|
|
|
|
|
|
|
|
/** Interface for ITLB responses. Populates self and then passes
|
|
|
|
* the request on to the ports' handleTLBResponse member
|
|
|
|
* function */
|
2014-09-19 16:35:18 +02:00
|
|
|
void finish(const Fault &fault_, RequestPtr request_,
|
|
|
|
ThreadContext *tc, BaseTLB::Mode mode);
|
2014-07-23 23:09:04 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
FetchRequest(Fetch1 &fetch_, InstId id_, TheISA::PCState pc_) :
|
|
|
|
SenderState(),
|
|
|
|
fetch(fetch_),
|
|
|
|
state(NotIssued),
|
|
|
|
id(id_),
|
|
|
|
packet(NULL),
|
|
|
|
request(),
|
|
|
|
pc(pc_),
|
|
|
|
fault(NoFault)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
~FetchRequest();
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef FetchRequest *FetchRequestPtr;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Construction-assigned data members */
|
|
|
|
|
|
|
|
/** Pointer back to the containing CPU */
|
|
|
|
MinorCPU &cpu;
|
|
|
|
|
|
|
|
/** Input port carrying branch requests from Execute */
|
|
|
|
Latch<BranchData>::Output inp;
|
|
|
|
/** Output port carrying read lines to Fetch2 */
|
|
|
|
Latch<ForwardLineData>::Input out;
|
|
|
|
/** Input port carrying branch predictions from Fetch2 */
|
|
|
|
Latch<BranchData>::Output prediction;
|
|
|
|
|
|
|
|
/** Interface to reserve space in the next stage */
|
|
|
|
Reservable &nextStageReserve;
|
|
|
|
|
|
|
|
/** IcachePort to pass to the CPU. Fetch1 is the only module that uses
|
|
|
|
* it. */
|
|
|
|
IcachePort icachePort;
|
|
|
|
|
|
|
|
/** Line snap size in bytes. All fetches clip to make their ends not
|
|
|
|
* extend beyond this limit. Setting this to the machine L1 cache line
|
|
|
|
* length will result in fetches never crossing line boundaries. */
|
|
|
|
unsigned int lineSnap;
|
|
|
|
|
|
|
|
/** Maximum fetch width in bytes. Setting this (and lineSnap) to the
|
|
|
|
* machine L1 cache line length will result in fetches of whole cache
|
|
|
|
* lines. Setting this to sizeof(MachInst) will result it fetches of
|
|
|
|
* single instructions (except near the end of lineSnap lines) */
|
|
|
|
unsigned int maxLineWidth;
|
|
|
|
|
|
|
|
/** Maximum number of fetches allowed in flight (in queues or memory) */
|
|
|
|
unsigned int fetchLimit;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Cycle-by-cycle state */
|
|
|
|
|
|
|
|
/** State of memory access for head instruction fetch */
|
|
|
|
enum FetchState
|
|
|
|
{
|
|
|
|
FetchHalted, /* Not fetching, waiting to be woken by transition
|
|
|
|
to FetchWaitingForPC. The PC is not valid in this state */
|
|
|
|
FetchWaitingForPC, /* Not fetching, waiting for stream change.
|
|
|
|
This doesn't stop issued fetches from being returned and
|
|
|
|
processed or for branches to change the state to Running. */
|
|
|
|
FetchRunning /* Try to fetch, when possible */
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Stage cycle-by-cycle state */
|
|
|
|
|
|
|
|
FetchState state;
|
|
|
|
|
|
|
|
/** Fetch PC value. This is updated by branches from Execute, branch
|
|
|
|
* prediction targets from Fetch2 and by incrementing it as we fetch
|
|
|
|
* lines subsequent to those two sources. */
|
|
|
|
TheISA::PCState pc;
|
|
|
|
|
|
|
|
/** Stream sequence number. This changes on request from Execute and is
|
|
|
|
* used to tag instructions by the fetch stream to which they belong.
|
|
|
|
* Execute originates new prediction sequence numbers. */
|
|
|
|
InstSeqNum streamSeqNum;
|
|
|
|
|
|
|
|
/** Prediction sequence number. This changes when requests from Execute
|
|
|
|
* or Fetch2 ask for a change of fetch address and is used to tag lines
|
|
|
|
* by the prediction to which they belong. Fetch2 originates
|
|
|
|
* prediction sequence numbers. */
|
|
|
|
InstSeqNum predictionSeqNum;
|
|
|
|
|
|
|
|
/** Blocked indication for report */
|
|
|
|
bool blocked;
|
|
|
|
|
|
|
|
/** State of memory access for head instruction fetch */
|
|
|
|
enum IcacheState
|
|
|
|
{
|
|
|
|
IcacheRunning, /* Default. Step icache queues when possible */
|
|
|
|
IcacheNeedsRetry /* Request rejected, will be asked to retry */
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Queue<FetchRequestPtr,
|
|
|
|
ReportTraitsPtrAdaptor<FetchRequestPtr>,
|
|
|
|
NoBubbleTraits<FetchRequestPtr> >
|
|
|
|
FetchQueue;
|
|
|
|
|
|
|
|
/** Queue of address translated requests from Fetch1 */
|
|
|
|
FetchQueue requests;
|
|
|
|
|
|
|
|
/** Queue of in-memory system requests and responses */
|
|
|
|
FetchQueue transfers;
|
|
|
|
|
|
|
|
/** Retry state of icache_port */
|
|
|
|
IcacheState icacheState;
|
|
|
|
|
|
|
|
/** Sequence number for line fetch used for ordering lines to flush */
|
|
|
|
InstSeqNum lineSeqNum;
|
|
|
|
|
|
|
|
/** Count of the number fetches which have left the transfers queue
|
|
|
|
* and are in the 'wild' in the memory system. Try not to rely on
|
|
|
|
* this value, it's better to code without knowledge of the number
|
|
|
|
* of outstanding accesses */
|
|
|
|
unsigned int numFetchesInMemorySystem;
|
|
|
|
/** Number of requests inside the ITLB rather than in the queues.
|
|
|
|
* All requests so located *must* have reserved space in the
|
|
|
|
* transfers queue */
|
|
|
|
unsigned int numFetchesInITLB;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
friend std::ostream &operator <<(std::ostream &os,
|
|
|
|
Fetch1::FetchState state);
|
|
|
|
|
|
|
|
/** Start fetching from a new address. */
|
|
|
|
void changeStream(const BranchData &branch);
|
|
|
|
|
|
|
|
/** Update streamSeqNum and predictionSeqNum from the given branch (and
|
|
|
|
* assume these have changed and discard (on delivery) all lines in
|
|
|
|
* flight) */
|
|
|
|
void updateExpectedSeqNums(const BranchData &branch);
|
|
|
|
|
|
|
|
/** Convert a response to a ForwardLineData */
|
|
|
|
void processResponse(FetchRequestPtr response,
|
|
|
|
ForwardLineData &line);
|
|
|
|
|
|
|
|
friend std::ostream &operator <<(std::ostream &os,
|
|
|
|
IcacheState state);
|
|
|
|
|
|
|
|
/** Insert a line fetch into the requests. This can be a partial
|
|
|
|
* line request where the given address has a non-0 offset into a
|
|
|
|
* line. */
|
|
|
|
void fetchLine();
|
|
|
|
|
|
|
|
/** Try and issue a fetch for a translated request at the
|
|
|
|
* head of the requests queue. Also tries to move the request
|
|
|
|
* between queues */
|
|
|
|
void tryToSendToTransfers(FetchRequestPtr request);
|
|
|
|
|
|
|
|
/** Try to send (or resend) a memory request's next/only packet to
|
|
|
|
* the memory system. Returns true if the fetch was successfully
|
|
|
|
* sent to memory */
|
|
|
|
bool tryToSend(FetchRequestPtr request);
|
|
|
|
|
|
|
|
/** Move a request between queues */
|
|
|
|
void moveFromRequestsToTransfers(FetchRequestPtr request);
|
|
|
|
|
|
|
|
/** Step requests along between requests and transfers queues */
|
|
|
|
void stepQueues();
|
|
|
|
|
|
|
|
/** Pop a request from the given queue and correctly deallocate and
|
|
|
|
* discard it. */
|
|
|
|
void popAndDiscard(FetchQueue &queue);
|
|
|
|
|
|
|
|
/** Handle pushing a TLB response onto the right queue */
|
|
|
|
void handleTLBResponse(FetchRequestPtr response);
|
|
|
|
|
|
|
|
/** Returns the total number of queue occupancy, in-ITLB and
|
|
|
|
* in-memory system fetches */
|
|
|
|
unsigned int numInFlightFetches();
|
|
|
|
|
|
|
|
/** Print the appropriate MinorLine line for a fetch response */
|
|
|
|
void minorTraceResponseLine(const std::string &name,
|
|
|
|
FetchRequestPtr response) const;
|
|
|
|
|
|
|
|
/** Memory interface */
|
|
|
|
virtual bool recvTimingResp(PacketPtr pkt);
|
2015-03-02 10:00:35 +01:00
|
|
|
virtual void recvReqRetry();
|
2014-07-23 23:09:04 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
Fetch1(const std::string &name_,
|
|
|
|
MinorCPU &cpu_,
|
|
|
|
MinorCPUParams ¶ms,
|
|
|
|
Latch<BranchData>::Output inp_,
|
|
|
|
Latch<ForwardLineData>::Input out_,
|
|
|
|
Latch<BranchData>::Output prediction_,
|
|
|
|
Reservable &next_stage_input_buffer);
|
|
|
|
|
|
|
|
public:
|
|
|
|
/** Returns the IcachePort owned by this Fetch1 */
|
|
|
|
MinorCPU::MinorCPUPort &getIcachePort() { return icachePort; }
|
|
|
|
|
|
|
|
/** Pass on input/buffer data to the output if you can */
|
|
|
|
void evaluate();
|
|
|
|
|
|
|
|
void minorTrace() const;
|
|
|
|
|
|
|
|
/** Is this stage drained? For Fetch1, draining is initiated by
|
|
|
|
* Execute signalling a branch with the reason HaltFetch */
|
|
|
|
bool isDrained();
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __CPU_MINOR_FETCH1_HH__ */
|