#include "base/compiler.hh"
#include "base/fast_alloc.hh"
#include "base/misc.hh"
+#include "base/printable.hh"
#include "mem/request.hh"
#include "sim/host.hh"
#include "sim/core.hh"
InvalidCmd,
ReadReq,
ReadResp,
+ ReadRespWithInvalidate,
WriteReq,
WriteResp,
Writeback,
NetworkNackError, // nacked at network layer (not by protocol)
InvalidDestError, // packet dest field invalid
BadAddressError, // memory address invalid
+ // Fake simulator-only commands
+ PrintReq, // Print state matching address
NUM_MEM_CMDS
};
IsLocked, //!< Alpha/MIPS LL or SC access
HasData, //!< There is an associated payload
IsError, //!< Error response
+ IsPrint, //!< Print state matching address (for debugging)
NUM_COMMAND_ATTRIBUTES
};
bool isReadWrite() const { return isRead() && isWrite(); }
bool isLocked() const { return testCmdAttrib(IsLocked); }
bool isError() const { return testCmdAttrib(IsError); }
+ bool isPrint() const { return testCmdAttrib(IsPrint); }
const Command responseCommand() const {
return commandInfo[cmd].response;
* ultimate destination and back, possibly being conveyed by several
* different Packets along the way.)
*/
-class Packet : public FastAlloc
+class Packet : public FastAlloc, public Printable
{
public:
MemInhibit,
Shared,
// Special control flags
+ /// Special timing-mode atomic snoop for multi-level coherence.
ExpressSnoop,
+ /// Does supplier have exclusive copy?
+ /// Useful for multi-level coherence.
+ SupplyExclusive,
NUM_PACKET_FLAGS
};
virtual ~SenderState() {}
};
+ /**
+ * Object used to maintain state of a PrintReq. The senderState
+ * field of a PrintReq should always be of this type.
+ */
+ class PrintReqState : public SenderState {
+ /** An entry in the label stack. */
+ class LabelStackEntry {
+ public:
+ const std::string label;
+ std::string *prefix;
+ bool labelPrinted;
+ LabelStackEntry(const std::string &_label,
+ std::string *_prefix);
+ };
+
+ typedef std::list<LabelStackEntry> LabelStack;
+ LabelStack labelStack;
+
+ std::string *curPrefixPtr;
+
+ public:
+ std::ostream &os;
+ const int verbosity;
+
+ PrintReqState(std::ostream &os, int verbosity = 0);
+ ~PrintReqState();
+
+ /** Returns the current line prefix. */
+ const std::string &curPrefix() { return *curPrefixPtr; }
+
+ /** Push a label onto the label stack, and prepend the given
+ * prefix string onto the current prefix. Labels will only be
+ * printed if an object within the label's scope is
+ * printed. */
+ void pushLabel(const std::string &lbl,
+ const std::string &prefix = " ");
+ /** Pop a label off the label stack. */
+ void popLabel();
+ /** Print all of the pending unprinted labels on the
+ * stack. Called by printObj(), so normally not called by
+ * users unless bypassing printObj(). */
+ void printLabels();
+ /** Print a Printable object to os, because it matched the
+ * address on a PrintReq. */
+ void printObj(Printable *obj);
+ };
+
/** This packet's sender state. Devices should use dynamic_cast<>
* to cast to the state appropriate to the sender. */
SenderState *senderState;
bool isReadWrite() const { return cmd.isReadWrite(); }
bool isLocked() const { return cmd.isLocked(); }
bool isError() const { return cmd.isError(); }
+ bool isPrint() const { return cmd.isPrint(); }
// Snoop flags
void assertMemInhibit() { flags[MemInhibit] = true; }
- void assertShared() { flags[Shared] = true; }
bool memInhibitAsserted() { return flags[MemInhibit]; }
+ void assertShared() { flags[Shared] = true; }
bool sharedAsserted() { return flags[Shared]; }
// Special control flags
void setExpressSnoop() { flags[ExpressSnoop] = true; }
bool isExpressSnoop() { return flags[ExpressSnoop]; }
+ void setSupplyExclusive() { flags[SupplyExclusive] = true; }
+ bool isSupplyExclusive() { return flags[SupplyExclusive]; }
// Network error conditions... encapsulate them as methods since
// their encoding keeps changing (from result field to command
// field, etc.)
- void setNacked() { origCmd = cmd; cmd = MemCmd::NetworkNackError; }
- void setBadAddress() { origCmd = cmd; cmd = MemCmd::BadAddressError; }
+ void setNacked() { assert(isResponse()); cmd = MemCmd::NetworkNackError; }
+ void setBadAddress() { assert(isResponse()); cmd = MemCmd::BadAddressError; }
bool wasNacked() { return cmd == MemCmd::NetworkNackError; }
bool hadBadAddress() { return cmd == MemCmd::BadAddressError; }
+ void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
bool nic_pkt() { panic("Unimplemented"); M5_DUMMY_RETURN }
{
assert(needsResponse());
assert(isRequest());
+ origCmd = cmd;
cmd = cmd.responseCommand();
dest = src;
destValid = srcValid;
/** If there isn't data in the packet, allocate some. */
void allocate();
- /** Do the packet modify the same addresses. */
- bool intersect(PacketPtr p);
-
/**
* Check a functional request against a memory value represented
* by a base/size pair and an associated data array. If the
* value. If the functional request is a write, it may update the
* memory value.
*/
- bool checkFunctional(Addr base, int size, uint8_t *data);
+ bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data);
/**
* Check a functional request against a memory value stored in
* another packet (i.e. an in-transit request or response).
*/
bool checkFunctional(PacketPtr otherPkt) {
- return (otherPkt->hasData() &&
- checkFunctional(otherPkt->getAddr(), otherPkt->getSize(),
- otherPkt->getPtr<uint8_t>()));
+ return checkFunctional(otherPkt,
+ otherPkt->getAddr(), otherPkt->getSize(),
+ otherPkt->hasData() ?
+ otherPkt->getPtr<uint8_t>() : NULL);
}
-};
-std::ostream & operator<<(std::ostream &o, const Packet &p);
+ /**
+ * Push label for PrintReq (safe to call unconditionally).
+ */
+ void pushLabel(const std::string &lbl) {
+ if (isPrint()) {
+ dynamic_cast<PrintReqState*>(senderState)->pushLabel(lbl);
+ }
+ }
+
+ /**
+ * Pop label for PrintReq (safe to call unconditionally).
+ */
+ void popLabel() {
+ if (isPrint()) {
+ dynamic_cast<PrintReqState*>(senderState)->popLabel();
+ }
+ }
+
+ void print(std::ostream &o, int verbosity = 0,
+ const std::string &prefix = "") const;
+};
#endif //__MEM_PACKET_HH