289 lines
9.8 KiB
C++
289 lines
9.8 KiB
C++
|
/*
|
||
|
* 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
|
||
|
*
|
||
|
* 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 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,
|
||
|
/* Wakeup fetching from Halted */
|
||
|
WakeupFetch,
|
||
|
/* 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;
|
||
|
|
||
|
/** Sequence number of new stream/prediction to be adopted */
|
||
|
InstSeqNum newStreamSeqNum;
|
||
|
InstSeqNum newPredictionSeqNum;
|
||
|
|
||
|
/** Starting PC of that stream */
|
||
|
TheISA::PCState target;
|
||
|
|
||
|
/** Instruction which caused this branch */
|
||
|
MinorDynInstPtr inst;
|
||
|
|
||
|
public:
|
||
|
BranchData() :
|
||
|
reason(NoBranch), newStreamSeqNum(0),
|
||
|
newPredictionSeqNum(0), target(TheISA::PCState(0)),
|
||
|
inst(MinorDynInst::bubble())
|
||
|
{ }
|
||
|
|
||
|
BranchData(
|
||
|
Reason reason_,
|
||
|
InstSeqNum new_stream_seq_num,
|
||
|
InstSeqNum new_prediction_seq_num,
|
||
|
TheISA::PCState target,
|
||
|
MinorDynInstPtr inst_) :
|
||
|
reason(reason_),
|
||
|
newStreamSeqNum(new_stream_seq_num),
|
||
|
newPredictionSeqNum(new_prediction_seq_num),
|
||
|
target(target),
|
||
|
inst(inst_)
|
||
|
{ }
|
||
|
|
||
|
/** 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 */
|
||
|
bool bubbleFlag;
|
||
|
|
||
|
public:
|
||
|
/** First byte address in the line. This is allowed to be
|
||
|
* <= pc.instAddr() */
|
||
|
Addr lineBaseAddr;
|
||
|
|
||
|
/** PC of the first requested inst within this line */
|
||
|
TheISA::PCState pc;
|
||
|
|
||
|
/** Explicit line width, don't rely on data.size */
|
||
|
unsigned int lineWidth;
|
||
|
|
||
|
public:
|
||
|
/** This line has a fault. The bubble flag will be false and seqNums
|
||
|
* will be valid but no data will */
|
||
|
Fault fault;
|
||
|
|
||
|
/** 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;
|
||
|
|
||
|
/** Packet from which the line is taken */
|
||
|
Packet *packet;
|
||
|
|
||
|
public:
|
||
|
ForwardLineData() :
|
||
|
bubbleFlag(true),
|
||
|
lineBaseAddr(0),
|
||
|
lineWidth(0),
|
||
|
fault(NoFault),
|
||
|
line(NULL),
|
||
|
packet(NULL)
|
||
|
{
|
||
|
/* Make lines bubbles by default */
|
||
|
}
|
||
|
|
||
|
~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;
|
||
|
|
||
|
public:
|
||
|
explicit ForwardInstData(unsigned int width = 0);
|
||
|
|
||
|
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;
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif /* __CPU_MINOR_PIPE_DATA_HH__ */
|