* 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: Ron Dreslinski
+ * Steve Reinhardt
+ * Ali Saidi
*/
/**
#define __MEM_PACKET_HH__
#include "mem/request.hh"
-#include "arch/isa_traits.hh"
+#include "sim/host.hh"
#include "sim/root.hh"
+#include <list>
+#include <cassert>
struct Packet;
typedef Packet* PacketPtr;
typedef uint8_t* PacketDataPtr;
-
+typedef std::list<PacketPtr> PacketList;
+
+//Coherence Flags
+#define NACKED_LINE 1 << 0
+#define SATISFIED 1 << 1
+#define SHARED_LINE 1 << 2
+#define CACHE_LINE_FILL 1 << 3
+#define COMPRESSED 1 << 4
+#define NO_ALLOCATE 1 << 5
+#define SNOOP_COMMIT 1 << 6
+
+//for now. @todo fix later
+#define NUM_MEM_CMDS 1 << 11
/**
* A Packet is used to encapsulate a transfer between two objects in
* the memory system (e.g., the L1 and L2 cache). (In contrast, a
*/
class Packet
{
+ public:
+ /** Temporary FLAGS field until cache gets working, this should be in coherence/sender state. */
+ uint64_t flags;
+
private:
/** A pointer to the data being transfered. It can be differnt
* sizes at each level of the heirarchy so it belongs in the
* be called on it rather than simply delete.*/
bool arrayData;
-
/** The address of the request. This address could be virtual or
* physical, depending on the system configuration. */
Addr addr;
/** Is the 'src' field valid? */
bool srcValid;
+
public:
+ /** Used to calculate latencies for each packet.*/
+ Tick time;
+
+ /** The time at which the packet will be fully transmitted */
+ Tick finishTime;
+
+ /** The time at which the first chunk of the packet will be transmitted */
+ Tick firstWordTime;
+
/** The special destination address indicating that the packet
* should be routed based on its address. */
static const short Broadcast = -1;
private:
/** List of command attributes. */
+ // If you add a new CommandAttribute, make sure to increase NUM_MEM_CMDS
+ // as well.
enum CommandAttribute
{
IsRead = 1 << 0,
IsRequest = 1 << 4,
IsResponse = 1 << 5,
NeedsResponse = 1 << 6,
+ IsSWPrefetch = 1 << 7,
+ IsHWPrefetch = 1 << 8,
+ IsUpgrade = 1 << 9,
+ HasData = 1 << 10
};
public:
/** List of all commands associated with a packet. */
enum Command
{
+ InvalidCmd = 0,
ReadReq = IsRead | IsRequest | NeedsResponse,
- WriteReq = IsWrite | IsRequest | NeedsResponse,
- WriteReqNoAck = IsWrite | IsRequest,
- ReadResp = IsRead | IsResponse,
- WriteResp = IsWrite | IsResponse
+ WriteReq = IsWrite | IsRequest | NeedsResponse | HasData,
+ WriteReqNoAck = IsWrite | IsRequest | HasData,
+ ReadResp = IsRead | IsResponse | NeedsResponse | HasData,
+ WriteResp = IsWrite | IsResponse | NeedsResponse,
+ Writeback = IsWrite | IsRequest | HasData,
+ SoftPFReq = IsRead | IsRequest | IsSWPrefetch | NeedsResponse,
+ HardPFReq = IsRead | IsRequest | IsHWPrefetch | NeedsResponse,
+ SoftPFResp = IsRead | IsResponse | IsSWPrefetch
+ | NeedsResponse | HasData,
+ HardPFResp = IsRead | IsResponse | IsHWPrefetch
+ | NeedsResponse | HasData,
+ InvalidateReq = IsInvalidate | IsRequest,
+ WriteInvalidateReq = IsWrite | IsInvalidate | IsRequest | HasData,
+ UpgradeReq = IsInvalidate | IsRequest | IsUpgrade,
+ ReadExReq = IsRead | IsInvalidate | IsRequest | NeedsResponse,
+ ReadExResp = IsRead | IsInvalidate | IsResponse
+ | NeedsResponse | HasData
};
/** Return the string name of the cmd field (for debugging and
* tracing). */
const std::string &cmdString() const;
+ /** Reutrn the string to a cmd given by idx. */
+ const std::string &cmdIdxToString(Command idx);
+
+ /** Return the index of this command. */
+ inline int cmdToIndex() const { return (int) cmd; }
+
/** The command field of the packet. */
Command cmd;
bool isRead() { return (cmd & IsRead) != 0; }
+ bool isWrite() { return (cmd & IsWrite) != 0; }
bool isRequest() { return (cmd & IsRequest) != 0; }
bool isResponse() { return (cmd & IsResponse) != 0; }
bool needsResponse() { return (cmd & NeedsResponse) != 0; }
+ bool isInvalidate() { return (cmd & IsInvalidate) != 0; }
+ bool hasData() { return (cmd & HasData) != 0; }
+
+ bool isCacheFill() { return (flags & CACHE_LINE_FILL) != 0; }
+ bool isNoAllocate() { return (flags & NO_ALLOCATE) != 0; }
+ bool isCompressed() { return (flags & COMPRESSED) != 0; }
+
+ bool nic_pkt() { assert("Unimplemented\n" && 0); return false; }
/** Possible results of a packet's request. */
enum Result
{
Success,
BadAddress,
+ Nacked,
Unknown
};
Addr getAddr() const { assert(addrSizeValid); return addr; }
int getSize() const { assert(addrSizeValid); return size; }
+ Addr getOffset(int blkSize) const { return addr & (Addr)(blkSize - 1); }
+
+ void addrOverride(Addr newAddr) { assert(addrSizeValid); addr = newAddr; }
+ void cmdOverride(Command newCmd) { cmd = newCmd; }
/** Constructor. Note that a Request object must be constructed
* first, but the Requests's physical address and size fields
req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
result(Unknown)
{
+ flags = 0;
+ time = curTick;
+ }
+
+ /** Alternate constructor if you are trying to create a packet with
+ * a request that is for a whole block, not the address from the req.
+ * this allows for overriding the size/addr of the req.*/
+ Packet(Request *_req, Command _cmd, short _dest, int _blkSize)
+ : data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize),
+ dest(_dest),
+ addrSizeValid(_req->validPaddr), srcValid(false),
+ req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
+ result(Unknown)
+ {
+ flags = 0;
+ time = curTick;
}
/** Destructor. */
assert(req->validPaddr);
addr = req->paddr;
size = req->size;
+ time = req->time;
addrSizeValid = true;
result = Unknown;
if (dynamicData) {
* for returning as a response to that request. Used for timing
* accesses only. For atomic and functional accesses, the
* request packet is always implicitly passed back *without*
- * modifying the command or destination fields, so this function
+ * modifying the destination fields, so this function
* should not be called. */
void makeTimingResponse() {
assert(needsResponse());
+ assert(isRequest());
int icmd = (int)cmd;
- icmd &= ~(IsRequest | NeedsResponse);
+ icmd &= ~(IsRequest);
icmd |= IsResponse;
+ if (isRead())
+ icmd |= HasData;
+ if (isWrite())
+ icmd &= ~HasData;
cmd = (Command)icmd;
dest = src;
srcValid = false;
}
+ /** Take a request packet and modify it in place to be suitable
+ * for returning as a response to that request.
+ */
+ void makeAtomicResponse() {
+ assert(needsResponse());
+ assert(isRequest());
+ int icmd = (int)cmd;
+ icmd &= ~(IsRequest);
+ icmd |= IsResponse;
+ cmd = (Command)icmd;
+ }
+
+ /** Take a request packet that has been returned as NACKED and modify it so
+ * that it can be sent out again. Only packets that need a response can be
+ * NACKED, so verify that that is true. */
+ void reinitNacked() {
+ assert(needsResponse() && result == Nacked);
+ dest = Broadcast;
+ result = Unknown;
+ }
+
+
/** Set the data pointer to the following value that should not be freed. */
template <typename T>
void dataStatic(T *p);