blob: 97651b4b46a1b6a0dc3e7bdbed9fb7a9826bad08 [file] [log] [blame]
/*
* 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.
*/
/**
* @file
*
* Contains class definitions for data flowing between pipeline stages in
* the top-level structure portion of this model. Latch types are also
* defined which pair forward/backward flowing data specific to each stage
* pair.
*
* No post-configuration inter-stage communication should *ever* take place
* outside these classes (except for reservation!)
*/
#ifndef __CPU_MINOR_PIPE_DATA_HH__
#define __CPU_MINOR_PIPE_DATA_HH__
#include "cpu/minor/buffers.hh"
#include "cpu/minor/dyn_inst.hh"
#include "cpu/base.hh"
namespace gem5
{
GEM5_DEPRECATED_NAMESPACE(Minor, minor);
namespace minor
{
/** Forward data betwen Execute and Fetch1 carrying change-of-address/stream
* information. */
class BranchData /* : public ReportIF, public BubbleIF */
{
public:
enum Reason
{
/* *** No change of stream (information to branch prediction) */
/* Don't branch at all (bubble) */
NoBranch,
/* Don't branch, but here's the details of a correct prediction
* that was executed */
CorrectlyPredictedBranch,
/* *** Change of stream */
/* Take an unpredicted branch */
UnpredictedBranch,
/* Take a branch on branch prediction data (from Fetch2) */
BranchPrediction,
/* Prediction of wrong target PC */
BadlyPredictedBranchTarget,
/* Bad branch prediction (didn't actually branch). Need to branch
* back to correct stream. If the target is wrong, use
* BadlyPredictedBranchTarget */
BadlyPredictedBranch,
/* Suspend fetching for this thread (inst->id.threadId).
* This will be woken up by another stream changing branch so
* count it as stream changing itself and expect pc to be the PC
* of the next instruction */
SuspendThread,
/* Branch from an interrupt (no instruction) */
Interrupt,
/* Stop fetching in anticipation of of draining */
HaltFetch
};
/** Is a request with this reason actually a request to change the
* PC rather than a bubble or branch prediction information */
static bool isStreamChange(const BranchData::Reason reason);
/** Is a request with this reason actually a 'real' branch, that is,
* a stream change that's not just an instruction to Fetch1 to halt
* or wake up */
static bool isBranch(const BranchData::Reason reason);
public:
/** Explanation for this branch */
Reason reason = NoBranch;
/** ThreadID associated with branch */
ThreadID threadId = InvalidThreadID;
/** Sequence number of new stream/prediction to be adopted */
InstSeqNum newStreamSeqNum = 0;
InstSeqNum newPredictionSeqNum = 0;
/** Starting PC of that stream */
std::unique_ptr<PCStateBase> target;
/** Instruction which caused this branch */
MinorDynInstPtr inst = MinorDynInst::bubble();
public:
BranchData() {}
BranchData(Reason reason_, ThreadID thread_id,
InstSeqNum new_stream_seq_num, InstSeqNum new_prediction_seq_num,
const PCStateBase &_target, MinorDynInstPtr inst_) :
reason(reason_), threadId(thread_id),
newStreamSeqNum(new_stream_seq_num),
newPredictionSeqNum(new_prediction_seq_num),
inst(inst_)
{
set(target, _target);
}
BranchData(const BranchData &other) :
reason(other.reason), threadId(other.threadId),
newStreamSeqNum(other.newStreamSeqNum),
newPredictionSeqNum(other.newPredictionSeqNum),
inst(other.inst)
{
set(target, other.target);
}
BranchData &
operator=(const BranchData &other)
{
reason = other.reason;
threadId = other.threadId;
newStreamSeqNum = other.newStreamSeqNum;
newPredictionSeqNum = other.newPredictionSeqNum;
set(target, other.target);
inst = other.inst;
return *this;
}
/** BubbleIF interface */
static BranchData bubble() { return BranchData(); }
bool isBubble() const { return reason == NoBranch; }
/** As static isStreamChange but on this branch data */
bool isStreamChange() const { return isStreamChange(reason); }
/** As static isBranch but on this branch data */
bool isBranch() const { return isBranch(reason); }
/** ReportIF interface */
void reportData(std::ostream &os) const;
};
/** Print a branch reason enum */
std::ostream &operator <<(std::ostream &os, BranchData::Reason reason);
/** Print BranchData contents in a format suitable for DPRINTF comments, not
* for MinorTrace */
std::ostream &operator <<(std::ostream &os, const BranchData &branch);
/** Line fetch data in the forward direction. Contains a single cache line
* (or fragment of a line), its address, a sequence number assigned when
* that line was fetched and a bubbleFlag that can allow ForwardLineData to
* be used to represent the absence of line data in a pipeline. */
class ForwardLineData /* : public ReportIF, public BubbleIF */
{
private:
/** This line is a bubble. No other data member is required to be valid
* if this is true
* Make lines bubbles by default */
bool bubbleFlag = true;
public:
/** First byte address in the line. This is allowed to be
* <= pc.instAddr() */
Addr lineBaseAddr = 0;
/** PC of the first inst within this sequence */
std::unique_ptr<PCStateBase> pc;
/** Address of this line of data */
Addr fetchAddr;
/** Explicit line width, don't rely on data.size */
unsigned int lineWidth = 0;
public:
/** This line has a fault. The bubble flag will be false and seqNums
* will be valid but no data will */
Fault fault = NoFault;
/** Thread, stream, prediction ... id of this line */
InstId id;
/** Line data. line[0] is the byte at address pc.instAddr(). Data is
* only valid upto lineWidth - 1. */
uint8_t *line = nullptr;
/** Packet from which the line is taken */
Packet *packet = nullptr;
public:
ForwardLineData() {}
ForwardLineData(const ForwardLineData &other) :
bubbleFlag(other.bubbleFlag), lineBaseAddr(other.lineBaseAddr),
pc(other.pc->clone()), fetchAddr(other.fetchAddr),
lineWidth(other.lineWidth), fault(other.fault), id(other.id),
line(other.line), packet(other.packet)
{}
ForwardLineData &
operator=(const ForwardLineData &other)
{
bubbleFlag = other.bubbleFlag;
lineBaseAddr = other.lineBaseAddr;
set(pc, other.pc);
fetchAddr = other.fetchAddr;
lineWidth = other.lineWidth;
fault = other.fault;
id = other.id;
line = other.line;
packet = other.packet;
return *this;
}
~ForwardLineData() { line = NULL; }
public:
/** This is a fault, not a line */
bool isFault() const { return fault != NoFault; }
/** Set fault and possible clear the bubble flag */
void setFault(Fault fault_);
/** In-place initialise a ForwardLineData, freeing and overridding the
* line */
void allocateLine(unsigned int width_);
/** Use the data from a packet as line instead of allocating new
* space. On destruction of this object, the packet will be destroyed */
void adoptPacketData(Packet *packet);
/** Free this ForwardLineData line. Note that these are shared between
* line objects and so you must be careful when deallocating them.
* Copying of ForwardLineData can, therefore, be done by default copy
* constructors/assignment */
void freeLine();
/** BubbleIF interface */
static ForwardLineData bubble() { return ForwardLineData(); }
bool isBubble() const { return bubbleFlag; }
/** ReportIF interface */
void reportData(std::ostream &os) const;
};
/** Maximum number of instructions that can be carried by the pipeline. */
const unsigned int MAX_FORWARD_INSTS = 16;
/** Forward flowing data between Fetch2,Decode,Execute carrying a packet of
* instructions of a width appropriate to the configured stage widths.
* Also carries exception information where instructions are not valid */
class ForwardInstData /* : public ReportIF, public BubbleIF */
{
public:
/** Array of carried insts, ref counted */
MinorDynInstPtr insts[MAX_FORWARD_INSTS];
/** The number of insts slots that can be expected to be valid insts */
unsigned int numInsts;
/** Thread associated with these instructions */
ThreadID threadId;
public:
explicit ForwardInstData(unsigned int width = 0,
ThreadID tid = InvalidThreadID);
ForwardInstData(const ForwardInstData &src);
public:
/** Number of instructions carried by this object */
unsigned int width() const { return numInsts; }
/** Copy the inst array only as far as numInsts */
ForwardInstData &operator =(const ForwardInstData &src);
/** Resize a bubble/empty ForwardInstData and fill with bubbles */
void resize(unsigned int width);
/** Fill with bubbles from 0 to width() - 1 */
void bubbleFill();
/** BubbleIF interface */
bool isBubble() const;
/** ReportIF interface */
void reportData(std::ostream &os) const;
};
} // namespace minor
} // namespace gem5
#endif /* __CPU_MINOR_PIPE_DATA_HH__ */