From 3535d746ab2adaef4c13fbf869ccc3a2e98279cd Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:17 -0800 Subject: [PATCH] style: clean up the Packet stuff --- src/mem/packet.cc | 64 ++--- src/mem/packet.hh | 552 ++++++++++++++++++++++----------------- src/mem/packet_access.hh | 3 +- src/mem/request.hh | 393 +++++++++++++++++++--------- 4 files changed, 606 insertions(+), 406 deletions(-) diff --git a/src/mem/packet.cc b/src/mem/packet.cc index f27bd9dbf..17e58859a 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -42,6 +42,8 @@ #include "base/trace.hh" #include "mem/packet.hh" +using namespace std; + // The one downside to bitsets is that static initializers can get ugly. #define SET1(a1) (1 << (a1)) #define SET2(a1, a2) (SET1(a1) | SET1(a2)) @@ -133,35 +135,6 @@ MemCmd::commandInfo[] = { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" } }; - -/** delete the data pointed to in the data pointer. Ok to call to matter how - * data was allocted. */ -void -Packet::deleteData() -{ - assert(staticData || dynamicData); - if (staticData) - return; - - if (arrayData) - delete [] data; - else - delete data; -} - -/** If there isn't data in the packet, allocate some. */ -void -Packet::allocate() -{ - if (data) - return; - assert(!staticData); - dynamicData = true; - arrayData = true; - data = new uint8_t[getSize()]; -} - - bool Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) { @@ -193,7 +166,7 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) if (isRead()) { if (func_start >= val_start && func_end <= val_end) { allocate(); - std::memcpy(getPtr(), data + offset, getSize()); + memcpy(getPtr(), data + offset, getSize()); makeResponse(); return true; } else { @@ -208,11 +181,12 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) } } else if (isWrite()) { if (offset >= 0) { - std::memcpy(data + offset, getPtr(), - (std::min(func_end, val_end) - func_start) + 1); - } else { // val_start > func_start - std::memcpy(data, getPtr() - offset, - (std::min(func_end, val_end) - val_start) + 1); + memcpy(data + offset, getPtr(), + (min(func_end, val_end) - func_start) + 1); + } else { + // val_start > func_start + memcpy(data, getPtr() - offset, + (min(func_end, val_end) - val_start) + 1); } } else { panic("Don't know how to handle command %s\n", cmdString()); @@ -222,23 +196,19 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) return false; } - void -Packet::print(std::ostream &o, const int verbosity, - const std::string &prefix) const +Packet::print(ostream &o, const int verbosity, const string &prefix) const { ccprintf(o, "%s[%x:%x] %s\n", prefix, getAddr(), getAddr() + getSize() - 1, cmdString()); } - -Packet::PrintReqState::PrintReqState(std::ostream &_os, int _verbosity) - : curPrefixPtr(new std::string("")), os(_os), verbosity(_verbosity) +Packet::PrintReqState::PrintReqState(ostream &_os, int _verbosity) + : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity) { labelStack.push_back(LabelStackEntry("", curPrefixPtr)); } - Packet::PrintReqState::~PrintReqState() { labelStack.pop_back(); @@ -246,21 +216,17 @@ Packet::PrintReqState::~PrintReqState() delete curPrefixPtr; } - Packet::PrintReqState:: -LabelStackEntry::LabelStackEntry(const std::string &_label, - std::string *_prefix) +LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix) : label(_label), prefix(_prefix), labelPrinted(false) { } - void -Packet::PrintReqState::pushLabel(const std::string &lbl, - const std::string &prefix) +Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix) { labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); - curPrefixPtr = new std::string(*curPrefixPtr); + curPrefixPtr = new string(*curPrefixPtr); *curPrefixPtr += prefix; } diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 1227cec89..38eb2e92b 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -42,8 +42,10 @@ #include #include +#include "base/cast.hh" #include "base/compiler.hh" #include "base/fast_alloc.hh" +#include "base/flags.hh" #include "base/misc.hh" #include "base/printable.hh" #include "mem/request.hh" @@ -58,9 +60,12 @@ typedef std::list PacketList; class MemCmd { - public: + friend class Packet; - /** List of all commands associated with a packet. */ + public: + /** + * List of all commands associated with a packet. + */ enum Command { InvalidCmd, @@ -100,7 +105,9 @@ class MemCmd }; private: - /** List of command attributes. */ + /** + * List of command attributes. + */ enum Attribute { IsRead, //!< Data flows from responder to requester @@ -120,26 +127,31 @@ class MemCmd NUM_COMMAND_ATTRIBUTES }; - /** Structure that defines attributes and other data associated - * with a Command. */ - struct CommandInfo { - /** Set of attribute flags. */ + /** + * Structure that defines attributes and other data associated + * with a Command. + */ + struct CommandInfo + { + /// Set of attribute flags. const std::bitset attributes; - /** Corresponding response for requests; InvalidCmd if no - * response is applicable. */ + /// Corresponding response for requests; InvalidCmd if no + /// response is applicable. const Command response; - /** String representation (for printing) */ + /// String representation (for printing) const std::string str; }; - /** Array to map Command enum to associated info. */ + /// Array to map Command enum to associated info. static const CommandInfo commandInfo[]; private: Command cmd; - bool testCmdAttrib(MemCmd::Attribute attrib) const { + bool + testCmdAttrib(MemCmd::Attribute attrib) const + { return commandInfo[cmd].attributes[attrib] != 0; } @@ -158,33 +170,22 @@ class MemCmd bool isError() const { return testCmdAttrib(IsError); } bool isPrint() const { return testCmdAttrib(IsPrint); } - const Command responseCommand() const { + const Command + responseCommand() const + { return commandInfo[cmd].response; } - /** Return the string to a cmd given by idx. */ - const std::string &toString() const { - return commandInfo[cmd].str; - } - + /// Return the string to a cmd given by idx. + const std::string &toString() const { return commandInfo[cmd].str; } int toInt() const { return (int)cmd; } - MemCmd(Command _cmd) - : cmd(_cmd) - { } + MemCmd(Command _cmd) : cmd(_cmd) { } + MemCmd(int _cmd) : cmd((Command)_cmd) { } + MemCmd() : cmd(InvalidCmd) { } - MemCmd(int _cmd) - : cmd((Command)_cmd) - { } - - MemCmd() - : cmd(InvalidCmd) - { } - - bool operator==(MemCmd c2) { return (cmd == c2.cmd); } - bool operator!=(MemCmd c2) { return (cmd != c2.cmd); } - - friend class Packet; + bool operator==(MemCmd c2) const { return (cmd == c2.cmd); } + bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); } }; /** @@ -197,107 +198,118 @@ class MemCmd class Packet : public FastAlloc, public Printable { public: + typedef uint32_t FlagsType; + typedef ::Flags Flags; + typedef short NodeID; + private: + static const FlagsType PUBLIC_FLAGS = 0x00000000; + static const FlagsType PRIVATE_FLAGS = 0x00007F0F; + static const FlagsType COPY_FLAGS = 0x0000000F; + + static const FlagsType SHARED = 0x00000001; + // Special control flags + /// Special timing-mode atomic snoop for multi-level coherence. + static const FlagsType EXPRESS_SNOOP = 0x00000002; + /// Does supplier have exclusive copy? + /// Useful for multi-level coherence. + static const FlagsType SUPPLY_EXCLUSIVE = 0x00000004; + // Snoop response flags + static const FlagsType MEM_INHIBIT = 0x00000008; + /// Are the 'addr' and 'size' fields valid? + static const FlagsType VALID_ADDR = 0x00000100; + static const FlagsType VALID_SIZE = 0x00000200; + /// Is the 'src' field valid? + static const FlagsType VALID_SRC = 0x00000400; + static const FlagsType VALID_DST = 0x00000800; + /// Is the data pointer set to a value that shouldn't be freed + /// when the packet is destroyed? + static const FlagsType STATIC_DATA = 0x00001000; + /// The data pointer points to a value that should be freed when + /// the packet is destroyed. + static const FlagsType DYNAMIC_DATA = 0x00002000; + /// the data pointer points to an array (thus delete []) needs to + /// be called on it rather than simply delete. + static const FlagsType ARRAY_DATA = 0x00004000; + + Flags flags; + + public: typedef MemCmd::Command Command; - /** The command field of the packet. */ + /// The command field of the packet. MemCmd cmd; - /** A pointer to the original request. */ + /// A pointer to the original request. RequestPtr req; private: - /** A pointer to the data being transfered. It can be differnt - * sizes at each level of the heirarchy so it belongs in the - * packet, not request. This may or may not be populated when a - * responder recieves the packet. If not populated it memory - * should be allocated. + /** + * A pointer to the data being transfered. It can be differnt + * sizes at each level of the heirarchy so it belongs in the + * packet, not request. This may or may not be populated when a + * responder recieves the packet. If not populated it memory should + * be allocated. */ PacketDataPtr data; - /** Is the data pointer set to a value that shouldn't be freed - * when the packet is destroyed? */ - bool staticData; - /** The data pointer points to a value that should be freed when - * the packet is destroyed. */ - bool dynamicData; - /** the data pointer points to an array (thus delete [] ) needs to - * 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. */ + /// The address of the request. This address could be virtual or + /// physical, depending on the system configuration. Addr addr; - /** The size of the request or transfer. */ + /// The size of the request or transfer. int size; - /** Device address (e.g., bus ID) of the source of the - * transaction. The source is not responsible for setting this - * field; it is set implicitly by the interconnect when the - * packet is first sent. */ - short src; + /** + * Device address (e.g., bus ID) of the source of the + * transaction. The source is not responsible for setting this + * field; it is set implicitly by the interconnect when the packet + * is first sent. + */ + NodeID src; - /** Device address (e.g., bus ID) of the destination of the - * transaction. The special value Broadcast indicates that the - * packet should be routed based on its address. This field is - * initialized in the constructor and is thus always valid - * (unlike * addr, size, and src). */ - short dest; + /** + * Device address (e.g., bus ID) of the destination of the + * transaction. The special value Broadcast indicates that the + * packet should be routed based on its address. This field is + * initialized in the constructor and is thus always valid (unlike + * addr, size, and src). + */ + NodeID dest; - /** The original value of the command field. Only valid when the + /** + * The original value of the command field. Only valid when the * current command field is an error condition; in that case, the * previous contents of the command field are copied here. This * field is *not* set on non-error responses. */ MemCmd origCmd; - /** Are the 'addr' and 'size' fields valid? */ - bool addrSizeValid; - /** Is the 'src' field valid? */ - bool srcValid; - bool destValid; - - enum Flag { - // Snoop response flags - 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 - }; - - /** Status flags */ - std::bitset flags; - public: - - /** Used to calculate latencies for each packet.*/ + /// Used to calculate latencies for each packet. Tick time; - /** The time at which the packet will be fully transmitted */ + /// 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 */ + /// 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; + /// The special destination address indicating that the packet + /// should be routed based on its address. + static const NodeID Broadcast = -1; - /** A virtual base opaque structure used to hold state associated - * with the packet but specific to the sending device (e.g., an - * MSHR). A pointer to this state is returned in the packet's - * response so that the sender 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. */ - class SenderState { - public: + /** + * A virtual base opaque structure used to hold state associated + * with the packet but specific to the sending device (e.g., an + * MSHR). A pointer to this state is returned in the packet's + * response so that the sender 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. + */ + struct SenderState + { virtual ~SenderState() {} }; @@ -305,15 +317,18 @@ class Packet : public FastAlloc, public Printable * Object used to maintain state of a PrintReq. The senderState * field of a PrintReq should always be of this type. */ - class PrintReqState : public SenderState, public FastAlloc { - /** An entry in the label stack. */ - class LabelStackEntry { - public: + class PrintReqState : public SenderState, public FastAlloc + { + private: + /** + * An entry in the label stack. + */ + struct LabelStackEntry + { const std::string label; std::string *prefix; bool labelPrinted; - LabelStackEntry(const std::string &_label, - std::string *_prefix); + LabelStackEntry(const std::string &_label, std::string *_prefix); }; typedef std::list LabelStack; @@ -328,35 +343,53 @@ class Packet : public FastAlloc, public Printable PrintReqState(std::ostream &os, int verbosity = 0); ~PrintReqState(); - /** Returns the current line prefix. */ + /** + * Returns the current line prefix. + */ const std::string &curPrefix() { return *curPrefixPtr; } - /** Push a label onto the label stack, and prepend the given + /** + * 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. */ + * 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. */ + + /** + * Pop a label off the label stack. + */ void popLabel(); - /** Print all of the pending unprinted labels on the + + /** + * Print all of the pending unprinted labels on the * stack. Called by printObj(), so normally not called by - * users unless bypassing printObj(). */ + * users unless bypassing printObj(). + */ void printLabels(); - /** Print a Printable object to os, because it matched the - * address on a PrintReq. */ + + /** + * 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. */ + /** + * This packet's sender state. Devices should use dynamic_cast<> + * to cast to the state appropriate to the sender. The intent of + * this variable is to allow a device to attach extra information + * to a request. A response packet must return the sender state + * that was attached to the original request (even if a new packet + * is created). + */ SenderState *senderState; - /** Return the string name of the cmd field (for debugging and - * tracing). */ + /// Return the string name of the cmd field (for debugging and + /// tracing). const std::string &cmdString() const { return cmd.toString(); } - /** Return the index of this command. */ + /// Return the index of this command. inline int cmdToIndex() const { return cmd.toInt(); } bool isRead() const { return cmd.isRead(); } @@ -373,88 +406,101 @@ class Packet : public FastAlloc, public Printable bool isPrint() const { return cmd.isPrint(); } // Snoop flags - void assertMemInhibit() { flags[MemInhibit] = true; } - bool memInhibitAsserted() { return flags[MemInhibit]; } - void assertShared() { flags[Shared] = true; } - bool sharedAsserted() { return flags[Shared]; } + void assertMemInhibit() { flags.set(MEM_INHIBIT); } + bool memInhibitAsserted() { return flags.any(MEM_INHIBIT); } + void assertShared() { flags.set(SHARED); } + bool sharedAsserted() { return flags.any(SHARED); } // Special control flags - void setExpressSnoop() { flags[ExpressSnoop] = true; } - bool isExpressSnoop() { return flags[ExpressSnoop]; } - void setSupplyExclusive() { flags[SupplyExclusive] = true; } - bool isSupplyExclusive() { return flags[SupplyExclusive]; } + void setExpressSnoop() { flags.set(EXPRESS_SNOOP); } + bool isExpressSnoop() { return flags.any(EXPRESS_SNOOP); } + void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); } + bool isSupplyExclusive() { return flags.any(SUPPLY_EXCLUSIVE); } // Network error conditions... encapsulate them as methods since // their encoding keeps changing (from result field to command // field, etc.) - 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 + setNacked() + { + assert(isResponse()); + cmd = MemCmd::NetworkNackError; + } + + void + setBadAddress() + { + assert(isResponse()); + cmd = MemCmd::BadAddressError; + } + + bool wasNacked() const { return cmd == MemCmd::NetworkNackError; } + bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; } void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; } - bool nic_pkt() { panic("Unimplemented"); M5_DUMMY_RETURN } + /// Accessor function to get the source index of the packet. + NodeID getSrc() const { assert(flags.any(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); } - /** Accessor function that returns the source index of the packet. */ - short getSrc() const { assert(srcValid); return src; } - void setSrc(short _src) { src = _src; srcValid = true; } - /** Reset source field, e.g. to retransmit packet on different bus. */ - void clearSrc() { srcValid = false; } + /// Accessor function for the destination index of the packet. + NodeID getDest() const { assert(flags.any(VALID_DST)); return dest; } + /// Accessor function to set the destination index of the packet. + void setDest(NodeID _dest) { dest = _dest; flags.set(VALID_DST); } - /** Accessor function that returns the destination index of - the packet. */ - short getDest() const { assert(destValid); return dest; } - void setDest(short _dest) { dest = _dest; destValid = true; } + Addr getAddr() const { assert(flags.all(VALID_ADDR)); return addr; } + int getSize() const { assert(flags.all(VALID_SIZE)); return size; } + Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); } - Addr getAddr() const { assert(addrSizeValid); return addr; } - int getSize() const { assert(addrSizeValid); return size; } - Addr getOffset(int blkSize) const { return addr & (Addr)(blkSize - 1); } - - /** Constructor. Note that a Request object must be constructed - * first, but the Requests's physical address and size fields - * need not be valid. The command and destination addresses - * must be supplied. */ - Packet(Request *_req, MemCmd _cmd, short _dest) - : cmd(_cmd), req(_req), - data(NULL), staticData(false), dynamicData(false), arrayData(false), - addr(_req->paddr), size(_req->size), dest(_dest), - addrSizeValid(_req->validPaddr), srcValid(false), destValid(true), - flags(0), time(curTick), senderState(NULL) + /** + * Constructor. Note that a Request object must be constructed + * first, but the Requests's physical address and size fields need + * not be valid. The command and destination addresses must be + * 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) { } - /** 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, MemCmd _cmd, short _dest, int _blkSize) - : cmd(_cmd), req(_req), - data(NULL), staticData(false), dynamicData(false), arrayData(false), + /** + * 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, MemCmd _cmd, NodeID _dest, int _blkSize) + : cmd(_cmd), req(_req), data(NULL), addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest), - addrSizeValid(_req->validPaddr), srcValid(false), destValid(true), - flags(0), time(curTick), senderState(NULL) + time(curTick), senderState(NULL) { } - /** Alternate constructor for copying a packet. Copy all fields + /** + * Alternate constructor for copying a packet. Copy all fields * *except* if the original packet's data was dynamic, don't copy * that, as we can't guarantee that the new packet's lifetime is * less than that of the original packet. In this case the new - * packet should allocate its own data. */ - Packet(Packet *origPkt, bool clearFlags = false) - : cmd(origPkt->cmd), req(origPkt->req), - data(origPkt->staticData ? origPkt->data : NULL), - staticData(origPkt->staticData), - dynamicData(false), arrayData(false), - addr(origPkt->addr), size(origPkt->size), - src(origPkt->src), dest(origPkt->dest), - addrSizeValid(origPkt->addrSizeValid), - srcValid(origPkt->srcValid), destValid(origPkt->destValid), - flags(clearFlags ? 0 : origPkt->flags), - time(curTick), senderState(origPkt->senderState) + * packet should allocate its own data. + */ + Packet(Packet *pkt, bool clearFlags = false) + : cmd(pkt->cmd), req(pkt->req), + data(pkt->flags.any(STATIC_DATA) ? pkt->data : NULL), + addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest), + time(curTick), senderState(pkt->senderState) { + if (!clearFlags) + flags.set(pkt->flags & COPY_FLAGS); + + flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE|VALID_SRC|VALID_DST)); + flags.set(pkt->flags & STATIC_DATA); } - /** Destructor. */ + /** + * clean up packet variables + */ ~Packet() { // If this is a request packet for which there's no response, @@ -462,27 +508,27 @@ class Packet : public FastAlloc, public Printable // never get the chance. if (req && isRequest() && !needsResponse()) delete req; - if (staticData || dynamicData) - deleteData(); + deleteData(); } - /** Reinitialize packet address and size from the associated - * Request object, and reset other fields that may have been - * modified by a previous transaction. Typically called when a - * statically allocated Request/Packet pair is reused for - * multiple transactions. */ - void reinitFromRequest() { - assert(req->validPaddr); + /** + * Reinitialize packet address and size from the associated + * Request object, and reset other fields that may have been + * modified by a previous transaction. Typically called when a + * statically allocated Request/Packet pair is reused for multiple + * transactions. + */ + void + reinitFromRequest() + { + assert(req->flags.any(Request::VALID_PADDR)); flags = 0; addr = req->paddr; size = req->size; time = req->time; - addrSizeValid = true; - if (dynamicData) { - deleteData(); - dynamicData = false; - arrayData = false; - } + + flags.set(VALID_ADDR|VALID_SIZE); + deleteData(); } /** @@ -491,23 +537,30 @@ class Packet : public FastAlloc, public Printable * destination fields are *not* modified, as is appropriate for * atomic accesses. */ - void makeResponse() + void + makeResponse() { assert(needsResponse()); assert(isRequest()); origCmd = cmd; cmd = cmd.responseCommand(); - dest = src; - destValid = srcValid; - srcValid = false; + if (flags.any(VALID_SRC)) { + dest = src; + flags.set(VALID_DST); + flags.clear(VALID_SRC); + } else { + flags.clear(VALID_DST); + } } - void makeAtomicResponse() + void + makeAtomicResponse() { makeResponse(); } - void makeTimingResponse() + void + makeTimingResponse() { makeResponse(); } @@ -535,10 +588,9 @@ class Packet : public FastAlloc, public Printable void dataStatic(T *p) { - if(dynamicData) - dynamicData = false; + assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; - staticData = true; + flags.set(STATIC_DATA); } /** @@ -549,10 +601,9 @@ class Packet : public FastAlloc, public Printable void dataDynamicArray(T *p) { - assert(!staticData && !dynamicData); + assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; - dynamicData = true; - arrayData = true; + flags.set(DYNAMIC_DATA|ARRAY_DATA); } /** @@ -563,33 +614,39 @@ class Packet : public FastAlloc, public Printable void dataDynamic(T *p) { - assert(!staticData && !dynamicData); + assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; - dynamicData = true; - arrayData = false; + flags.set(DYNAMIC_DATA); } - /** get a pointer to the data ptr. */ + /** + * get a pointer to the data ptr. + */ template T* getPtr() { - assert(staticData || dynamicData); + assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); return (T*)data; } - /** return the value of what is pointed to in the packet. */ + /** + * return the value of what is pointed to in the packet. + */ template T get(); - /** set the value in the data pointer to v. */ + /** + * set the value in the data pointer to v. + */ template void set(T v); /** * Copy data into the packet from the provided pointer. */ - void setData(uint8_t *p) + void + setData(uint8_t *p) { std::memcpy(getPtr(), p, getSize()); } @@ -598,7 +655,8 @@ class Packet : public FastAlloc, public Printable * Copy data into the packet from the provided block pointer, * which is aligned to the given block size. */ - void setDataFromBlock(uint8_t *blk_data, int blkSize) + void + setDataFromBlock(uint8_t *blk_data, int blkSize) { setData(blk_data + getOffset(blkSize)); } @@ -607,7 +665,8 @@ class Packet : public FastAlloc, public Printable * Copy data from the packet to the provided block pointer, which * is aligned to the given block size. */ - void writeData(uint8_t *p) + void + writeData(uint8_t *p) { std::memcpy(p, getPtr(), getSize()); } @@ -615,7 +674,8 @@ class Packet : public FastAlloc, public Printable /** * Copy data from the packet to the memory at the provided pointer. */ - void writeDataToBlock(uint8_t *blk_data, int blkSize) + void + writeDataToBlock(uint8_t *blk_data, int blkSize) { writeData(blk_data + getOffset(blkSize)); } @@ -624,10 +684,31 @@ class Packet : public FastAlloc, public Printable * delete the data pointed to in the data pointer. Ok to call to * matter how data was allocted. */ - void deleteData(); + void + deleteData() + { + if (flags.any(ARRAY_DATA)) + delete [] data; + else if (flags.any(DYNAMIC_DATA)) + + delete data; + + flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA); + data = NULL; + } /** If there isn't data in the packet, allocate some. */ - void allocate(); + void + allocate() + { + if (data) { + assert(flags.none(STATIC_DATA|DYNAMIC_DATA)); + } else { + flags.set(DYNAMIC_DATA|ARRAY_DATA); + data = new uint8_t[getSize()]; + } + } + /** * Check a functional request against a memory value represented @@ -642,29 +723,32 @@ class Packet : public FastAlloc, public Printable * 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 checkFunctional(otherPkt, - otherPkt->getAddr(), otherPkt->getSize(), - otherPkt->hasData() ? - otherPkt->getPtr() : NULL); + bool + checkFunctional(PacketPtr other) + { + uint8_t *data = other->hasData() ? other->getPtr() : NULL; + return checkFunctional(other, other->getAddr(), other->getSize(), + data); } /** * Push label for PrintReq (safe to call unconditionally). */ - void pushLabel(const std::string &lbl) { - if (isPrint()) { - dynamic_cast(senderState)->pushLabel(lbl); - } + void + pushLabel(const std::string &lbl) + { + if (isPrint()) + safe_cast(senderState)->pushLabel(lbl); } /** * Pop label for PrintReq (safe to call unconditionally). */ - void popLabel() { - if (isPrint()) { - dynamic_cast(senderState)->popLabel(); - } + void + popLabel() + { + if (isPrint()) + safe_cast(senderState)->popLabel(); } void print(std::ostream &o, int verbosity = 0, diff --git a/src/mem/packet_access.hh b/src/mem/packet_access.hh index d1edd00aa..1e233ee57 100644 --- a/src/mem/packet_access.hh +++ b/src/mem/packet_access.hh @@ -46,7 +46,7 @@ template inline T Packet::get() { - assert(staticData || dynamicData); + assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); assert(sizeof(T) <= size); return TheISA::gtoh(*(T*)data); } @@ -56,6 +56,7 @@ template inline void Packet::set(T v) { + assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); assert(sizeof(T) <= size); *(T*)data = TheISA::htog(v); } diff --git a/src/mem/request.hh b/src/mem/request.hh index d1e011c7d..c3a523d9b 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -39,79 +39,103 @@ #ifndef __MEM_REQUEST_HH__ #define __MEM_REQUEST_HH__ +#include + #include "base/fast_alloc.hh" +#include "base/flags.hh" #include "sim/host.hh" #include "sim/core.hh" -#include - class Request; typedef Request* RequestPtr; - -/** ASI information for this request if it exsits. */ -const uint32_t ASI_BITS = 0x000FF; -/** The request is a Load locked/store conditional. */ -const uint32_t LOCKED = 0x00100; -/** The virtual address is also the physical address. */ -const uint32_t PHYSICAL = 0x00200; -/** The request is an ALPHA VPTE pal access (hw_ld). */ -const uint32_t VPTE = 0x00400; -/** Use the alternate mode bits in ALPHA. */ -const uint32_t ALTMODE = 0x00800; -/** The request is to an uncacheable address. */ -const uint32_t UNCACHEABLE = 0x01000; -/** The request should not cause a page fault. */ -const uint32_t NO_FAULT = 0x02000; -/** The request should be prefetched into the exclusive state. */ -const uint32_t PF_EXCLUSIVE = 0x10000; -/** The request should be marked as LRU. */ -const uint32_t EVICT_NEXT = 0x20000; -/** The request should ignore unaligned access faults */ -const uint32_t NO_ALIGN_FAULT = 0x40000; -/** The request was an instruction read. */ -const uint32_t INST_READ = 0x80000; -/** This request is for a memory swap. */ -const uint32_t MEM_SWAP = 0x100000; -const uint32_t MEM_SWAP_COND = 0x200000; -/** The request should ignore unaligned access faults */ -const uint32_t NO_HALF_WORD_ALIGN_FAULT = 0x400000; - - class Request : public FastAlloc { + public: + typedef uint32_t FlagsType; + typedef ::Flags Flags; + + /** ASI information for this request if it exists. */ + static const FlagsType ASI_BITS = 0x000000FF; + /** The request is a Load locked/store conditional. */ + static const FlagsType LOCKED = 0x00000100; + /** The virtual address is also the physical address. */ + static const FlagsType PHYSICAL = 0x00000200; + /** The request is an ALPHA VPTE pal access (hw_ld). */ + static const FlagsType VPTE = 0x00000400; + /** Use the alternate mode bits in ALPHA. */ + static const FlagsType ALTMODE = 0x00000800; + /** The request is to an uncacheable address. */ + static const FlagsType UNCACHEABLE = 0x00001000; + /** The request should not cause a page fault. */ + static const FlagsType NO_FAULT = 0x00002000; + /** The request should be prefetched into the exclusive state. */ + static const FlagsType PF_EXCLUSIVE = 0x00010000; + /** The request should be marked as LRU. */ + static const FlagsType EVICT_NEXT = 0x00020000; + /** The request should ignore unaligned access faults */ + static const FlagsType NO_ALIGN_FAULT = 0x00040000; + /** The request was an instruction read. */ + static const FlagsType INST_READ = 0x00080000; + /** This request is for a memory swap. */ + static const FlagsType MEM_SWAP = 0x00100000; + static const FlagsType MEM_SWAP_COND = 0x00200000; + /** The request should ignore unaligned access faults */ + static const FlagsType NO_HALF_WORD_ALIGN_FAULT = 0x00400000; + /** This request is to a memory mapped register. */ + static const FlagsType MMAPED_IPR = 0x00800000; + + private: + static const FlagsType PUBLIC_FLAGS = 0x00FF3FFF; + static const FlagsType PRIVATE_FLAGS = 0xFF000000; + + /** Whether or not the size is valid. */ + static const FlagsType VALID_SIZE = 0x01000000; + /** Whether or not paddr is valid (has been written yet). */ + static const FlagsType VALID_PADDR = 0x02000000; + /** Whether or not the vaddr & asid are valid. */ + static const FlagsType VALID_VADDR = 0x04000000; + /** Whether or not the pc is valid. */ + static const FlagsType VALID_PC = 0x10000000; + /** Whether or not the context ID is valid. */ + static const FlagsType VALID_CONTEXT_ID = 0x20000000; + static const FlagsType VALID_THREAD_ID = 0x40000000; + /** Whether or not the sc result is valid. */ + static const FlagsType VALID_EXTRA_DATA = 0x80000000; + private: /** * The physical address of the request. Valid only if validPaddr - * is set. */ + * is set. + */ Addr paddr; /** * The size of the request. This field must be set when vaddr or * paddr is written via setVirt() or setPhys(), so it is always - * valid as long as one of the address fields is valid. */ + * valid as long as one of the address fields is valid. + */ int size; /** Flag structure for the request. */ - uint32_t flags; + Flags flags; /** * The time this request was started. Used to calculate * latencies. This field is set to curTick any time paddr or vaddr - * is written. */ + * is written. + */ Tick time; /** The address space ID. */ int asid; - /** This request is to a memory mapped register. */ - bool mmapedIpr; - /** The virtual address of the request. */ Addr vaddr; - /** Extra data for the request, such as the return value of + /** + * Extra data for the request, such as the return value of * store conditional or the compare value for a CAS. */ uint64_t extraData; @@ -123,170 +147,295 @@ class Request : public FastAlloc /** program counter of initiating access; for tracing/debugging */ Addr pc; - /** Whether or not paddr is valid (has been written yet). */ - bool validPaddr; - /** Whether or not the asid & vaddr are valid. */ - bool validAsidVaddr; - /** Whether or not the sc result is valid. */ - bool validExData; - /** Whether or not the context ID is valid. */ - bool validContextAndThreadIds; - /** Whether or not the pc is valid. */ - bool validPC; - public: /** Minimal constructor. No fields are initialized. */ Request() - : validPaddr(false), validAsidVaddr(false), - validExData(false), validContextAndThreadIds(false), validPC(false) {} /** * Constructor for physical (e.g. device) requests. Initializes * just physical address, size, flags, and timestamp (to curTick). - * These fields are adequate to perform a request. */ - Request(Addr _paddr, int _size, int _flags) - : validContextAndThreadIds(false) - { setPhys(_paddr, _size, _flags); } - - Request(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc, - int _context_id, int _thread_id) + * These fields are adequate to perform a request. + */ + Request(Addr paddr, int size, Flags flags) { - setThreadContext(_context_id, _thread_id); - setVirt(_asid, _vaddr, _size, _flags, _pc); + setPhys(paddr, size, flags); + } + + Request(int asid, Addr vaddr, int size, Flags flags, Addr pc, + int cid, int tid) + { + setThreadContext(cid, tid); + setVirt(asid, vaddr, size, flags, pc); } ~Request() {} // for FastAlloc /** - * Set up CPU and thread numbers. */ - void setThreadContext(int _context_id, int _thread_id) + * Set up CPU and thread numbers. + */ + void + setThreadContext(int context_id, int thread_id) { - _contextId = _context_id; - _threadId = _thread_id; - validContextAndThreadIds = true; + _contextId = context_id; + _threadId = thread_id; + flags.set(VALID_CONTEXT_ID|VALID_THREAD_ID); } /** * Set up a physical (e.g. device) request in a previously - * allocated Request object. */ - void setPhys(Addr _paddr, int _size, int _flags) + * allocated Request object. + */ + void + setPhys(Addr _paddr, int _size, Flags _flags) { assert(_size >= 0); paddr = _paddr; size = _size; - flags = _flags; time = curTick; - validPaddr = true; - validAsidVaddr = false; - validPC = false; - validExData = false; - mmapedIpr = false; + + flags.set(VALID_PADDR|VALID_SIZE); + flags.clear(VALID_VADDR|VALID_PC|VALID_EXTRA_DATA|MMAPED_IPR); + flags.update(_flags, PUBLIC_FLAGS); } /** * Set up a virtual (e.g., CPU) request in a previously - * allocated Request object. */ - void setVirt(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc) + * allocated Request object. + */ + void + setVirt(int _asid, Addr _vaddr, int _size, Flags _flags, Addr _pc) { assert(_size >= 0); asid = _asid; vaddr = _vaddr; size = _size; - flags = _flags; pc = _pc; time = curTick; - validPaddr = false; - validAsidVaddr = true; - validPC = true; - validExData = false; - mmapedIpr = false; + + flags.set(VALID_VADDR|VALID_SIZE|VALID_PC); + flags.clear(VALID_PADDR|VALID_EXTRA_DATA|MMAPED_IPR); + flags.update(_flags, PUBLIC_FLAGS); } - /** Set just the physical address. This should only be used to + /** + * Set just the physical address. This should only be used to * record the result of a translation, and thus the vaddr must be * valid before this method is called. Otherwise, use setPhys() * to guarantee that the size and flags are also set. */ - void setPaddr(Addr _paddr) + void + setPaddr(Addr _paddr) { - assert(validAsidVaddr); + assert(flags.any(VALID_VADDR)); paddr = _paddr; - validPaddr = true; + flags.set(VALID_PADDR); } - /** Accessor for paddr. */ - Addr getPaddr() { assert(validPaddr); return paddr; } + /** + * Accessor for paddr. + */ + Addr + getPaddr() + { + assert(flags.any(VALID_PADDR)); + return paddr; + } + + /** + * Accessor for size. + */ + int + getSize() + { + assert(flags.any(VALID_SIZE)); + return size; + } - /** Accessor for size. */ - int getSize() { assert(validPaddr || validAsidVaddr); return size; } /** Accessor for time. */ - Tick getTime() { assert(validPaddr || validAsidVaddr); return time; } - void resetTime() { assert(validPaddr || validAsidVaddr); time = curTick; } + Tick + getTime() + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + return time; + } + void setTime(Tick when) { - assert(validPaddr || validAsidVaddr); + assert(flags.any(VALID_PADDR|VALID_VADDR)); time = when; } + void resetTime() { setTime(curTick); } + /** Accessor for flags. */ - uint32_t getFlags() { assert(validPaddr || validAsidVaddr); return flags; } - /** Accessor for paddr. */ - void setFlags(uint32_t _flags) - { assert(validPaddr || validAsidVaddr); flags = _flags; } + Flags + getFlags() + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + return flags & PUBLIC_FLAGS; + } + + Flags + anyFlags(Flags _flags) + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(_flags.none(~PUBLIC_FLAGS)); + return flags.any(_flags); + } + + Flags + allFlags(Flags _flags) + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(_flags.none(~PUBLIC_FLAGS)); + return flags.all(_flags); + } + + /** Accessor for flags. */ + void + setFlags(Flags _flags) + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(_flags.none(~PUBLIC_FLAGS)); + flags.set(_flags); + } + + void + clearFlags(Flags _flags) + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(_flags.none(~PUBLIC_FLAGS)); + flags.clear(_flags); + } + + void + clearFlags() + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + flags.clear(PUBLIC_FLAGS); + } /** Accessor function for vaddr.*/ - Addr getVaddr() { assert(validAsidVaddr); return vaddr; } + Addr + getVaddr() + { + assert(flags.any(VALID_VADDR)); + return vaddr; + } /** Accessor function for asid.*/ - int getAsid() { assert(validAsidVaddr); return asid; } + int + getAsid() + { + assert(flags.any(VALID_VADDR)); + return asid; + } /** Accessor function for asi.*/ - uint8_t getAsi() { assert(validAsidVaddr); return flags & ASI_BITS; } + uint8_t + getAsi() + { + assert(flags.any(VALID_VADDR)); + return flags & ASI_BITS; + } /** Accessor function for asi.*/ - void setAsi(uint8_t a) - { assert(validAsidVaddr); flags = (flags & ~ASI_BITS) | a; } + void + setAsi(uint8_t a) + { + assert(flags.any(VALID_VADDR)); + flags.update(a, ASI_BITS); + } /** Accessor function for asi.*/ - bool isMmapedIpr() { assert(validPaddr); return mmapedIpr; } + bool + isMmapedIpr() + { + assert(flags.any(VALID_PADDR)); + return flags.any(MMAPED_IPR); + } /** Accessor function for asi.*/ - void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; } + void + setMmapedIpr(bool r) + { + assert(VALID_VADDR); + flags.set(MMAPED_IPR); + } /** Accessor function to check if sc result is valid. */ - bool extraDataValid() { return validExData; } + bool + extraDataValid() + { + return flags.any(VALID_EXTRA_DATA); + } + /** Accessor function for store conditional return value.*/ - uint64_t getExtraData() { assert(validExData); return extraData; } + uint64_t + getExtraData() const + { + assert(flags.any(VALID_EXTRA_DATA)); + return extraData; + } + /** Accessor function for store conditional return value.*/ - void setExtraData(uint64_t _extraData) - { extraData = _extraData; validExData = true; } + void + setExtraData(uint64_t _extraData) + { + extraData = _extraData; + flags.set(VALID_EXTRA_DATA); + } /** Accessor function for context ID.*/ - int contextId() { assert(validContextAndThreadIds); return _contextId; } + int + contextId() const + { + assert(flags.any(VALID_CONTEXT_ID)); + return _contextId; + } + /** Accessor function for thread ID. */ - int threadId() { assert(validContextAndThreadIds); return _threadId; } + int + threadId() const + { + assert(flags.any(VALID_THREAD_ID)); + return _threadId; + } /** Accessor function for pc.*/ - Addr getPC() { assert(validPC); return pc; } + Addr + getPC() const + { + assert(flags.any(VALID_PC)); + return pc; + } /** Accessor Function to Check Cacheability. */ - bool isUncacheable() { return (getFlags() & UNCACHEABLE) != 0; } + bool isUncacheable() const { return flags.any(UNCACHEABLE); } + bool isInstRead() const { return flags.any(INST_READ); } + bool isLocked() const { return flags.any(LOCKED); } + bool isSwap() const { return flags.any(MEM_SWAP|MEM_SWAP_COND); } + bool isCondSwap() const { return flags.any(MEM_SWAP_COND); } - bool isInstRead() { return (getFlags() & INST_READ) != 0; } + bool + isMisaligned() const + { + if (flags.any(NO_ALIGN_FAULT)) + return false; - bool isLocked() { return (getFlags() & LOCKED) != 0; } + if ((vaddr & 0x1)) + return true; - bool isSwap() { return (getFlags() & MEM_SWAP || - getFlags() & MEM_SWAP_COND); } + if (flags.any(NO_HALF_WORD_ALIGN_FAULT)) + return false; - bool isCondSwap() { return (getFlags() & MEM_SWAP_COND) != 0; } + if ((vaddr & 0x2)) + return true; - bool inline isMisaligned() {return (!(getFlags() & NO_ALIGN_FAULT) && - ((vaddr & 1) || - (!(getFlags() & NO_HALF_WORD_ALIGN_FAULT) - && (vaddr & 0x2))));} + return false; + } friend class Packet; };