/*
- * Copyright (c) 2012-2018 ARM Limited
+ * Copyright (c) 2012-2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
#include <cassert>
#include <list>
+#include "base/addr_range.hh"
#include "base/cast.hh"
#include "base/compiler.hh"
#include "base/flags.hh"
WriteClean, // writes dirty data below without evicting
CleanEvict,
SoftPFReq,
+ SoftPFExReq,
HardPFReq,
SoftPFResp,
HardPFResp,
StoreCondResp,
SwapReq,
SwapResp,
- MessageReq,
- MessageResp,
- MemFenceReq,
+ // MessageReq and MessageResp are deprecated.
+ MemFenceReq = SwapResp + 3,
MemFenceResp,
CleanSharedReq,
CleanSharedResp,
// Flags to transfer across when copying a packet
COPY_FLAGS = 0x0000003F,
+ // Flags that are used to create reponse packets
+ RESPONDER_FLAGS = 0x00000009,
+
// Does this packet have sharers (which means it should not be
// considered writable) or not. See setHasSharers below.
HAS_SHARERS = 0x00000001,
/**
* A virtual base opaque structure used to hold state associated
- * with the packet (e.g., an MSHR), specific to a MemObject that
+ * with the packet (e.g., an MSHR), specific to a SimObject that
* sees the packet. A pointer to this state is returned in the
- * packet's response so that the MemObject in question can quickly
+ * packet's response so that the SimObject in question can quickly
* look up the state needed to process it. A specific subclass
* would be derived from this to carry state specific to a
* particular sending device.
*
- * As multiple MemObjects may add their SenderState throughout the
+ * As multiple SimObjects may add their SenderState throughout the
* memory system, the SenderStates create a stack, where a
- * MemObject can add a new Senderstate, as long as the
+ * SimObject can add a new Senderstate, as long as the
* predecessing SenderState is restored when the response comes
* back. For this reason, the predecessor should always be
* populated with the current SenderState of a packet before
bool isPrint() const { return cmd.isPrint(); }
bool isFlush() const { return cmd.isFlush(); }
+ bool isWholeLineWrite(unsigned blk_size)
+ {
+ return (cmd == MemCmd::WriteReq || cmd == MemCmd::WriteLineReq) &&
+ getOffset(blk_size) == 0 && getSize() == blk_size;
+ }
+
//@{
/// Snoop flags
/**
bool responderHadWritable() const
{ return flags.isSet(RESPONDER_HAD_WRITABLE); }
+ /**
+ * Copy the reponse flags from an input packet to this packet. The
+ * reponse flags determine whether a responder has been found and
+ * the state at which the block will be at the destination.
+ *
+ * @pkt The packet that we will copy flags from
+ */
+ void copyResponderFlags(const PacketPtr pkt);
+
/**
* A writeback/writeclean cmd gets propagated further downstream
* by the receiver when the flag is set.
unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; }
+ /**
+ * Get address range to which this packet belongs.
+ *
+ * @return Address range of this packet.
+ */
+ AddrRange getAddrRange() const;
+
Addr getOffset(unsigned int blk_size) const
{
return getAddr() & Addr(blk_size - 1);
{
if (req->isLLSC())
return MemCmd::LoadLockedReq;
+ else if (req->isPrefetchEx())
+ return MemCmd::SoftPFExReq;
else if (req->isPrefetch())
return MemCmd::SoftPFReq;
else
flags.set(VALID_SIZE);
}
+ /**
+ * Check if packet corresponds to a given block-aligned address and
+ * address space.
+ *
+ * @param addr The address to compare against.
+ * @param is_secure Whether addr belongs to the secure address space.
+ * @param blk_size Block size in bytes.
+ * @return Whether packet matches description.
+ */
+ bool matchBlockAddr(const Addr addr, const bool is_secure,
+ const int blk_size) const;
+
+ /**
+ * Check if this packet refers to the same block-aligned address and
+ * address space as another packet.
+ *
+ * @param pkt The packet to compare against.
+ * @param blk_size Block size in bytes.
+ * @return Whether packet matches description.
+ */
+ bool matchBlockAddr(const PacketPtr pkt, const int blk_size) const;
+
+ /**
+ * Check if packet corresponds to a given address and address space.
+ *
+ * @param addr The address to compare against.
+ * @param is_secure Whether addr belongs to the secure address space.
+ * @return Whether packet matches description.
+ */
+ bool matchAddr(const Addr addr, const bool is_secure) const;
+
+ /**
+ * Check if this packet refers to the same address and address space as
+ * another packet.
+ *
+ * @param pkt The packet to compare against.
+ * @return Whether packet matches description.
+ */
+ bool matchAddr(const PacketPtr pkt) const;
public:
/**
getPtr()
{
assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
+ assert(!isMaskedWrite());
return (T*)data;
}
// same pointer from source to destination and back
assert(p != getPtr<uint8_t>() || flags.isSet(STATIC_DATA));
- if (p != getPtr<uint8_t>())
+ if (p != getPtr<uint8_t>()) {
// for packet with allocated dynamic data, we copy data from
// one to the other, e.g. a forwarded response to a response
std::memcpy(getPtr<uint8_t>(), p, getSize());
+ }
}
/**
void
writeData(uint8_t *p) const
{
- std::memcpy(p, getConstPtr<uint8_t>(), getSize());
+ if (!isMaskedWrite()) {
+ std::memcpy(p, getConstPtr<uint8_t>(), getSize());
+ } else {
+ assert(req->getByteEnable().size() == getSize());
+ // Write only the enabled bytes
+ const uint8_t *base = getConstPtr<uint8_t>();
+ for (int i = 0; i < getSize(); i++) {
+ if (req->getByteEnable()[i]) {
+ p[i] = *(base + i);
+ }
+ // Disabled bytes stay untouched
+ }
+ }
}
/**
bool
trySatisfyFunctional(PacketPtr other)
{
+ if (other->isMaskedWrite()) {
+ // Do not forward data if overlapping with a masked write
+ if (_isSecure == other->isSecure() &&
+ getAddr() <= (other->getAddr() + other->getSize() - 1) &&
+ other->getAddr() <= (getAddr() + getSize() - 1)) {
+ warn("Trying to check against a masked write, skipping."
+ " (addr: 0x%x, other addr: 0x%x)", getAddr(),
+ other->getAddr());
+ }
+ return false;
+ }
// all packets that are carrying a payload should have a valid
// data pointer
return trySatisfyFunctional(other, other->getAddr(), other->isSecure(),
return cmd == MemCmd::CleanEvict || cmd == MemCmd::WritebackClean;
}
+ bool
+ isMaskedWrite() const
+ {
+ return (cmd == MemCmd::WriteReq && !req->getByteEnable().empty());
+ }
+
/**
* Check a functional request against a memory value represented
* by a base/size pair and an associated data array. If the