/*
* Copyright (c) 2006 The Regents of The University of Michigan
+ * Copyright (c) 2010 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "base/flags.hh"
#include "base/misc.hh"
#include "base/printable.hh"
+#include "base/types.hh"
#include "mem/request.hh"
-#include "sim/host.hh"
#include "sim/core.hh"
-
struct Packet;
typedef Packet *PacketPtr;
typedef uint8_t* PacketDataPtr;
WriteInvalidateReq,
WriteInvalidateResp,
UpgradeReq,
+ SCUpgradeReq, // Special "weak" upgrade for StoreCond
UpgradeResp,
+ SCUpgradeFailReq, // Failed SCUpgradeReq in MSHR (never sent)
+ UpgradeFailResp, // Valid for SCUpgradeReq only
ReadExReq,
ReadExResp,
LoadLockedReq,
StoreCondReq,
+ StoreCondFailReq, // Failed StoreCondReq in MSHR (never sent)
StoreCondResp,
SwapReq,
SwapResp,
BadAddressError, // memory address invalid
// Fake simulator-only commands
PrintReq, // Print state matching address
+ FlushReq, //request for a cache flush
NUM_MEM_CMDS
};
{
IsRead, //!< Data flows from responder to requester
IsWrite, //!< Data flows from requester to responder
+ IsUpgrade,
IsPrefetch, //!< Not a demand access
IsInvalidate,
NeedsExclusive, //!< Requires exclusive copy to complete in-cache
NeedsResponse, //!< Requester needs response from target
IsSWPrefetch,
IsHWPrefetch,
- IsLocked, //!< Alpha/MIPS LL or SC access
+ IsLlsc, //!< Alpha/MIPS LL or SC access
HasData, //!< There is an associated payload
IsError, //!< Error response
IsPrint, //!< Print state matching address (for debugging)
+ IsFlush, //!< Flush the address from caches
NUM_COMMAND_ATTRIBUTES
};
public:
bool isRead() const { return testCmdAttrib(IsRead); }
- bool isWrite() const { return testCmdAttrib(IsWrite); }
+ bool isWrite() const { return testCmdAttrib(IsWrite); }
+ bool isUpgrade() const { return testCmdAttrib(IsUpgrade); }
bool isRequest() const { return testCmdAttrib(IsRequest); }
bool isResponse() const { return testCmdAttrib(IsResponse); }
bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
bool hasData() const { return testCmdAttrib(HasData); }
bool isReadWrite() const { return isRead() && isWrite(); }
- bool isLocked() const { return testCmdAttrib(IsLocked); }
+ bool isLLSC() const { return testCmdAttrib(IsLlsc); }
bool isError() const { return testCmdAttrib(IsError); }
bool isPrint() const { return testCmdAttrib(IsPrint); }
+ bool isFlush() const { return testCmdAttrib(IsFlush); }
const Command
responseCommand() const
Addr addr;
/// The size of the request or transfer.
- int size;
+ unsigned size;
/**
* Device address (e.g., bus ID) of the source of the
inline int cmdToIndex() const { return cmd.toInt(); }
bool isRead() const { return cmd.isRead(); }
- bool isWrite() const { return cmd.isWrite(); }
+ bool isWrite() const { return cmd.isWrite(); }
+ bool isUpgrade() const { return cmd.isUpgrade(); }
bool isRequest() const { return cmd.isRequest(); }
bool isResponse() const { return cmd.isResponse(); }
bool needsExclusive() const { return cmd.needsExclusive(); }
bool isInvalidate() const { return cmd.isInvalidate(); }
bool hasData() const { return cmd.hasData(); }
bool isReadWrite() const { return cmd.isReadWrite(); }
- bool isLocked() const { return cmd.isLocked(); }
+ bool isLLSC() const { return cmd.isLLSC(); }
bool isError() const { return cmd.isError(); }
bool isPrint() const { return cmd.isPrint(); }
+ bool isFlush() const { return cmd.isFlush(); }
// Snoop flags
void assertMemInhibit() { flags.set(MEM_INHIBIT); }
- bool memInhibitAsserted() { return flags.any(MEM_INHIBIT); }
+ bool memInhibitAsserted() { return flags.isSet(MEM_INHIBIT); }
void assertShared() { flags.set(SHARED); }
- bool sharedAsserted() { return flags.any(SHARED); }
+ bool sharedAsserted() { return flags.isSet(SHARED); }
// Special control flags
void setExpressSnoop() { flags.set(EXPRESS_SNOOP); }
- bool isExpressSnoop() { return flags.any(EXPRESS_SNOOP); }
+ bool isExpressSnoop() { return flags.isSet(EXPRESS_SNOOP); }
void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); }
- bool isSupplyExclusive() { return flags.any(SUPPLY_EXCLUSIVE); }
+ void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); }
+ bool isSupplyExclusive() { return flags.isSet(SUPPLY_EXCLUSIVE); }
// Network error conditions... encapsulate them as methods since
// their encoding keeps changing (from result field to command
bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; }
void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
+ bool isSrcValid() { return flags.isSet(VALID_SRC); }
/// Accessor function to get the source index of the packet.
- NodeID getSrc() const { assert(flags.any(VALID_SRC)); return src; }
+ NodeID getSrc() const { assert(flags.isSet(VALID_SRC)); return src; }
/// Accessor function to set the source index of the packet.
void setSrc(NodeID _src) { src = _src; flags.set(VALID_SRC); }
/// Reset source field, e.g. to retransmit packet on different bus.
void clearSrc() { flags.clear(VALID_SRC); }
+ bool isDestValid() { return flags.isSet(VALID_DST); }
/// Accessor function for the destination index of the packet.
- NodeID getDest() const { assert(flags.any(VALID_DST)); return dest; }
+ NodeID getDest() const { assert(flags.isSet(VALID_DST)); return dest; }
/// Accessor function to set the destination index of the packet.
void setDest(NodeID _dest) { dest = _dest; flags.set(VALID_DST); }
- Addr getAddr() const { assert(flags.all(VALID_ADDR)); return addr; }
- int getSize() const { assert(flags.all(VALID_SIZE)); return size; }
+ Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
+ unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; }
Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
+ /**
+ * It has been determined that the SC packet should successfully update
+ * memory. Therefore, convert this SC packet to a normal write.
+ */
+ void
+ convertScToWrite()
+ {
+ assert(isLLSC());
+ assert(isWrite());
+ cmd = MemCmd::WriteReq;
+ }
+
+ /**
+ * When ruby is in use, Ruby will monitor the cache line and thus M5
+ * phys memory should treat LL ops as normal reads.
+ */
+ void
+ convertLlToRead()
+ {
+ assert(isLLSC());
+ assert(isRead());
+ cmd = MemCmd::ReadReq;
+ }
+
/**
* Constructor. Note that a Request object must be constructed
* first, but the Requests's physical address and size fields need
* supplied.
*/
Packet(Request *_req, MemCmd _cmd, NodeID _dest)
- : cmd(_cmd), req(_req), data(NULL), addr(_req->paddr),
- size(_req->size), dest(_dest), time(curTick), senderState(NULL)
+ : flags(VALID_DST), cmd(_cmd), req(_req), data(NULL),
+ dest(_dest), time(curTick()), senderState(NULL)
{
+ if (req->hasPaddr()) {
+ addr = req->getPaddr();
+ flags.set(VALID_ADDR);
+ }
+ if (req->hasSize()) {
+ size = req->getSize();
+ flags.set(VALID_SIZE);
+ }
}
/**
* req. this allows for overriding the size/addr of the req.
*/
Packet(Request *_req, MemCmd _cmd, NodeID _dest, int _blkSize)
- : cmd(_cmd), req(_req), data(NULL),
- addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest),
- time(curTick), senderState(NULL)
+ : flags(VALID_DST), cmd(_cmd), req(_req), data(NULL),
+ dest(_dest), time(curTick()), senderState(NULL)
{
+ if (req->hasPaddr()) {
+ addr = req->getPaddr() & ~(_blkSize - 1);
+ flags.set(VALID_ADDR);
+ }
+ size = _blkSize;
+ flags.set(VALID_SIZE);
}
/**
*/
Packet(Packet *pkt, bool clearFlags = false)
: cmd(pkt->cmd), req(pkt->req),
- data(pkt->flags.any(STATIC_DATA) ? pkt->data : NULL),
+ data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest),
- time(curTick), senderState(pkt->senderState)
+ time(curTick()), senderState(pkt->senderState)
{
if (!clearFlags)
flags.set(pkt->flags & COPY_FLAGS);
void
reinitFromRequest()
{
- assert(req->flags.any(Request::VALID_PADDR));
+ assert(req->hasPaddr());
flags = 0;
- addr = req->paddr;
- size = req->size;
- time = req->time;
+ addr = req->getPaddr();
+ size = req->getSize();
+ time = req->time();
flags.set(VALID_ADDR|VALID_SIZE);
deleteData();
assert(isRequest());
origCmd = cmd;
cmd = cmd.responseCommand();
- if (flags.any(VALID_SRC)) {
- dest = src;
- flags.set(VALID_DST);
- flags.clear(VALID_SRC);
- } else {
- flags.clear(VALID_DST);
- }
+
+ // responses are never express, even if the snoop that
+ // triggered them was
+ flags.clear(EXPRESS_SNOOP);
+
+ dest = src;
+ flags.set(VALID_DST, flags.isSet(VALID_SRC));
+ flags.clear(VALID_SRC);
}
void
setDest(Broadcast);
}
+ void
+ setSize(unsigned size)
+ {
+ assert(!flags.isSet(VALID_SIZE));
+
+ this->size = size;
+ flags.set(VALID_SIZE);
+ }
+
/**
* Set the data pointer to the following value that should not be
void
dataStatic(T *p)
{
- assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
+ assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
data = (PacketDataPtr)p;
flags.set(STATIC_DATA);
}
void
dataDynamicArray(T *p)
{
- assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
+ assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
data = (PacketDataPtr)p;
flags.set(DYNAMIC_DATA|ARRAY_DATA);
}
void
dataDynamic(T *p)
{
- assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
+ assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
data = (PacketDataPtr)p;
flags.set(DYNAMIC_DATA);
}
*/
template <typename T>
T*
- getPtr()
+ getPtr(bool null_ok = false)
{
- assert(flags.any(STATIC_DATA|DYNAMIC_DATA));
+ assert(null_ok || flags.isSet(STATIC_DATA|DYNAMIC_DATA));
return (T*)data;
}
void
setData(uint8_t *p)
{
- std::memcpy(getPtr<uint8_t>(), p, getSize());
+ if (p != getPtr<uint8_t>())
+ std::memcpy(getPtr<uint8_t>(), p, getSize());
}
/**
void
deleteData()
{
- if (flags.any(ARRAY_DATA))
+ if (flags.isSet(ARRAY_DATA))
delete [] data;
- else if (flags.any(DYNAMIC_DATA))
-
+ else if (flags.isSet(DYNAMIC_DATA))
delete data;
flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA);
allocate()
{
if (data) {
- assert(flags.none(STATIC_DATA|DYNAMIC_DATA));
- } else {
- flags.set(DYNAMIC_DATA|ARRAY_DATA);
- data = new uint8_t[getSize()];
+ assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
+ return;
}
- }
+ assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
+ flags.set(DYNAMIC_DATA|ARRAY_DATA);
+ data = new uint8_t[getSize()];
+ }
/**
* Check a functional request against a memory value represented