/*
- * Copyright (c) 2012-2013 ARM Limited
+ * Copyright (c) 2012-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
HardPFReq,
SoftPFResp,
HardPFResp,
- // WriteInvalidateReq transactions used to be generated by the
- // DMA ports when writing full blocks to memory, however, it
- // is not used anymore since we put the I/O cache in place to
- // deal with partial block writes. Hence, WriteInvalidateReq
- // and WriteInvalidateResp are currently unused. The
- // implication is that the I/O cache does read-exclusive
- // operations on every full-cache-block DMA, and ultimately
- // this needs to be fixed.
WriteInvalidateReq,
WriteInvalidateResp,
UpgradeReq,
bool hasData() const { return testCmdAttrib(HasData); }
bool isReadWrite() const { return isRead() && isWrite(); }
bool isLLSC() const { return testCmdAttrib(IsLlsc); }
+ bool isSWPrefetch() const { return testCmdAttrib(IsSWPrefetch); }
+ bool isHWPrefetch() const { return testCmdAttrib(IsHWPrefetch); }
+ bool isPrefetch() const { return testCmdAttrib(IsSWPrefetch) ||
+ testCmdAttrib(IsHWPrefetch); }
bool isError() const { return testCmdAttrib(IsError); }
bool isPrint() const { return testCmdAttrib(IsPrint); }
bool isFlush() const { return testCmdAttrib(IsFlush); }
/// suppress the error if this packet encounters a functional
/// access failure.
static const FlagsType SUPPRESS_FUNC_ERROR = 0x00008000;
+ // Signal prefetch squash through express snoop flag
+ static const FlagsType PREFETCH_SNOOP_SQUASH = 0x00010000;
Flags flags;
/// physical, depending on the system configuration.
Addr addr;
+ /// True if the request targets the secure memory space.
+ bool _isSecure;
+
/// The size of the request or transfer.
unsigned size;
/**
* Source port identifier set on a request packet to enable
* appropriate routing of the responses. The source port
- * identifier is set by any multiplexing component, e.g. a bus, as
- * the timing responses need this information to be routed back to
- * the appropriate port at a later point in time. The field can be
- * updated (over-written) as the request packet passes through
- * additional multiplexing components, and it is their
- * responsibility to remember the original source port identifier,
- * for example by using an appropriate sender state. The latter is
- * done in the cache and bridge.
+ * identifier is set by any multiplexing component, e.g. a
+ * crossbar, as the timing responses need this information to be
+ * routed back to the appropriate port at a later point in
+ * time. The field can be updated (over-written) as the request
+ * packet passes through additional multiplexing components, and
+ * it is their responsibility to remember the original source port
+ * identifier, for example by using an appropriate sender
+ * state. The latter is done in the cache and bridge.
*/
PortID src;
* packets that passed through a multiplexing component as a
* request packet. The source port identifier is turned into a
* destination port identifier when the packet is turned into a
- * response, and the destination is used, e.g. by the bus, to
+ * response, and the destination is used, e.g. by the crossbar, to
* select the appropriate path through the interconnect.
*/
PortID dest;
uint16_t bytesValidEnd;
public:
- /// Used to calculate latencies for each packet.
- Tick time;
- /// The time at which the packet will be fully transmitted
- Tick finishTime;
+ /**
+ * The extra delay from seeing the packet until the first word is
+ * transmitted. This delay is used to communicate the crossbar
+ * forwarding latency to the neighbouring object (e.g. a cache)
+ * that actually makes the packet wait. As the delay is relative,
+ * a 32-bit unsigned should be sufficient.
+ */
+ uint32_t firstWordDelay;
- /// The time at which the first chunk of the packet will be transmitted
- Tick firstWordTime;
+ /**
+ * The extra pipelining delay from seeing the packet until the
+ * last word is transmitted by the component that provided it (if
+ * any). This includes the first word delay. Similar to the first
+ * word delay, this is used to make up for the fact that the
+ * crossbar does not make the packet wait. As the delay is
+ * relative, a 32-bit unsigned should be sufficient.
+ */
+ uint32_t lastWordDelay;
/**
* A virtual base opaque structure used to hold state associated
*/
SenderState *popSenderState();
+ /**
+ * Go through the sender state stack and return the first instance
+ * that is of type T (as determined by a dynamic_cast). If there
+ * is no sender state of type T, NULL is returned.
+ *
+ * @return The topmost state of type T
+ */
+ template <typename T>
+ T * findNextSenderState() const
+ {
+ T *t = NULL;
+ SenderState* sender_state = senderState;
+ while (t == NULL && sender_state != NULL) {
+ t = dynamic_cast<T*>(sender_state);
+ sender_state = sender_state->predecessor;
+ }
+ return t;
+ }
+
/// Return the string name of the cmd field (for debugging and
/// tracing).
const std::string &cmdString() const { return cmd.toString(); }
bool isFlush() const { return cmd.isFlush(); }
// Snoop flags
- void assertMemInhibit() { flags.set(MEM_INHIBIT); }
- bool memInhibitAsserted() { return flags.isSet(MEM_INHIBIT); }
- void assertShared() { flags.set(SHARED); }
- bool sharedAsserted() { return flags.isSet(SHARED); }
+ void assertMemInhibit() { flags.set(MEM_INHIBIT); }
+ bool memInhibitAsserted() const { return flags.isSet(MEM_INHIBIT); }
+ void assertShared() { flags.set(SHARED); }
+ bool sharedAsserted() const { return flags.isSet(SHARED); }
// Special control flags
- void setExpressSnoop() { flags.set(EXPRESS_SNOOP); }
- bool isExpressSnoop() { return flags.isSet(EXPRESS_SNOOP); }
- void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); }
- void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); }
- bool isSupplyExclusive() { return flags.isSet(SUPPLY_EXCLUSIVE); }
- void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); }
- bool suppressFuncError() { return flags.isSet(SUPPRESS_FUNC_ERROR); }
+ void setExpressSnoop() { flags.set(EXPRESS_SNOOP); }
+ bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); }
+ void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); }
+ void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); }
+ bool isSupplyExclusive() const { return flags.isSet(SUPPLY_EXCLUSIVE); }
+ void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); }
+ bool suppressFuncError() const { return flags.isSet(SUPPRESS_FUNC_ERROR); }
+ void setPrefetchSquashed() { flags.set(PREFETCH_SNOOP_SQUASH); }
+ bool prefetchSquashed() const { return flags.isSet(PREFETCH_SNOOP_SQUASH); }
// Network error conditions... encapsulate them as methods since
// their encoding keeps changing (from result field to command
PortID getSrc() const { assert(isSrcValid()); return src; }
/// Accessor function to set the source index of the packet.
void setSrc(PortID _src) { src = _src; }
- /// Reset source field, e.g. to retransmit packet on different bus.
- void clearSrc() { src = InvalidPortID; }
bool isDestValid() const { return dest != InvalidPortID; }
/// Accessor function for the destination index of the packet.
unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; }
Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
+ bool isSecure() const
+ {
+ assert(flags.isSet(VALID_ADDR));
+ return _isSecure;
+ }
+
/**
* It has been determined that the SC packet should successfully update
* memory. Therefore, convert this SC packet to a normal write.
* not be valid. The command must be supplied.
*/
Packet(Request *_req, MemCmd _cmd)
- : cmd(_cmd), req(_req), data(NULL),
- src(InvalidPortID), dest(InvalidPortID),
+ : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
+ size(0), src(InvalidPortID), dest(InvalidPortID),
bytesValidStart(0), bytesValidEnd(0),
- time(curTick()), senderState(NULL)
+ firstWordDelay(0), lastWordDelay(0),
+ senderState(NULL)
{
if (req->hasPaddr()) {
addr = req->getPaddr();
flags.set(VALID_ADDR);
+ _isSecure = req->isSecure();
}
if (req->hasSize()) {
size = req->getSize();
* req. this allows for overriding the size/addr of the req.
*/
Packet(Request *_req, MemCmd _cmd, int _blkSize)
- : cmd(_cmd), req(_req), data(NULL),
+ : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
src(InvalidPortID), dest(InvalidPortID),
bytesValidStart(0), bytesValidEnd(0),
- time(curTick()), senderState(NULL)
+ firstWordDelay(0), lastWordDelay(0),
+ senderState(NULL)
{
if (req->hasPaddr()) {
addr = req->getPaddr() & ~(_blkSize - 1);
flags.set(VALID_ADDR);
+ _isSecure = req->isSecure();
}
size = _blkSize;
flags.set(VALID_SIZE);
Packet(Packet *pkt, bool clearFlags = false)
: cmd(pkt->cmd), req(pkt->req),
data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
- addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest),
- bytesValidStart(pkt->bytesValidStart), bytesValidEnd(pkt->bytesValidEnd),
- time(curTick()), senderState(pkt->senderState)
+ addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
+ src(pkt->src), dest(pkt->dest),
+ bytesValidStart(pkt->bytesValidStart),
+ bytesValidEnd(pkt->bytesValidEnd),
+ firstWordDelay(pkt->firstWordDelay),
+ lastWordDelay(pkt->lastWordDelay),
+ senderState(pkt->senderState)
{
if (!clearFlags)
flags.set(pkt->flags & COPY_FLAGS);
flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
flags.set(pkt->flags & STATIC_DATA);
+ }
+ /**
+ * Change the packet type based on request type.
+ */
+ void
+ refineCommand()
+ {
+ if (cmd == MemCmd::ReadReq) {
+ if (req->isLLSC()) {
+ cmd = MemCmd::LoadLockedReq;
+ } else if (req->isPrefetch()) {
+ cmd = MemCmd::SoftPFReq;
+ }
+ } else if (cmd == MemCmd::WriteReq) {
+ if (req->isLLSC()) {
+ cmd = MemCmd::StoreCondReq;
+ } else if (req->isSwap()) {
+ cmd = MemCmd::SwapReq;
+ }
+ }
+ }
+
+ /**
+ * Constructor-like methods that return Packets based on Request objects.
+ * Will call refineCommand() to fine-tune the Packet type if it's not a
+ * vanilla read or write.
+ */
+ static PacketPtr
+ createRead(Request *req)
+ {
+ PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
+ pkt->refineCommand();
+ return pkt;
+ }
+
+ static PacketPtr
+ createWrite(Request *req)
+ {
+ PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
+ pkt->refineCommand();
+ return pkt;
}
/**
assert(req->hasPaddr());
flags = 0;
addr = req->getPaddr();
+ _isSecure = req->isSecure();
size = req->getSize();
- time = req->time();
+
+ src = InvalidPortID;
+ dest = InvalidPortID;
+ bytesValidStart = 0;
+ bytesValidEnd = 0;
+ firstWordDelay = 0;
+ lastWordDelay = 0;
flags.set(VALID_ADDR|VALID_SIZE);
deleteData();
flags.clear(EXPRESS_SNOOP);
dest = src;
- clearSrc();
+ src = InvalidPortID;
}
void
* value. If the functional request is a write, it may update the
* memory value.
*/
- bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data);
+ bool checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
+ uint8_t *data);
/**
* Check a functional request against a memory value stored in
checkFunctional(PacketPtr other)
{
uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL;
- return checkFunctional(other, other->getAddr(), other->getSize(),
- data);
+ return checkFunctional(other, other->getAddr(), other->isSecure(),
+ other->getSize(), data);
}
/**
void print(std::ostream &o, int verbosity = 0,
const std::string &prefix = "") const;
+
+ /**
+ * A no-args wrapper of print(std::ostream...)
+ * meant to be invoked from DPRINTFs
+ * avoiding string overheads in fast mode
+ * @return string with the request's type and start<->end addresses
+ */
+ std::string print() const;
};
#endif //__MEM_PACKET_HH