summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/packet.cc14
-rw-r--r--src/mem/packet.hh167
-rw-r--r--src/mem/physical.cc3
-rw-r--r--src/mem/port.cc5
-rw-r--r--src/mem/port.hh25
-rw-r--r--src/mem/request.hh236
6 files changed, 238 insertions, 212 deletions
diff --git a/src/mem/packet.cc b/src/mem/packet.cc
index 3b415d77f..4cda657f5 100644
--- a/src/mem/packet.cc
+++ b/src/mem/packet.cc
@@ -97,20 +97,6 @@ Packet::intersect(Packet *p)
return false;
}
-/** Minimally reset a packet so something like simple cpu can reuse it. */
-void
-Packet::reset()
-{
- result = Unknown;
- if (dynamicData) {
- deleteData();
- dynamicData = false;
- arrayData = false;
- time = curTick;
- }
-}
-
-
bool
fixPacket(Packet *func, Packet *timing)
{
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index 83f52ede5..4bcc05abd 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -28,8 +28,7 @@
/**
* @file
- * Declaration of the Packet Class, a packet is a transaction occuring
- * between a single level of the memory heirarchy (ie L1->L2).
+ * Declaration of the Packet class.
*/
#ifndef __MEM_PACKET_HH__
@@ -44,81 +43,96 @@ typedef Packet* PacketPtr;
typedef uint8_t* PacketDataPtr;
/**
- * A Packet is the structure to handle requests between two levels
- * of the memory system. The Request is a global object that trancends
- * all of the memory heirarchy, but at each levels interface a packet
- * is created to transfer data/requests. For example, a request would
- * be used to initiate a request to go to memory/IOdevices, as the request
- * passes through the memory system several packets will be created. One
- * will be created to go between the L1 and L2 caches and another to go to
- * the next level and so forth.
- *
- * Packets are assumed to be returned in the case of a single response. If
- * the transaction has no response, then the consumer will delete the packet.
+ * 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
+ * single Request travels all the way from the requester to the
+ * ultimate destination and back, possibly being conveyed by several
+ * different Packets along the way.)
*/
class Packet
{
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? */
+ /** 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. */
+ /** 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.*/
+ /** 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, could be virtual or physical (depending on
- cache configurations). */
+ /** The address of the request. This address could be virtual or
+ * physical, depending on the system configuration. */
Addr addr;
- /** Indicates the size of the request. */
+ /** The size of the request or transfer. */
int size;
- /** A index of the source of the transaction. */
+ /** 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;
- /** A index to the destination of the transaction. */
+ /** 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;
- bool addrValid;
- bool sizeValid;
+ /** Are the 'addr' and 'size' fields valid? */
+ bool addrSizeValid;
+ /** Is the 'src' field valid? */
bool srcValid;
public:
+ /** The special destination address indicating that the packet
+ * should be routed based on its address. */
static const short Broadcast = -1;
- /** A pointer to the overall request. */
+ /** A pointer to the original request. */
RequestPtr req;
+ /** A virtual base opaque structure used to hold coherence-related
+ * state. A specific subclass would be derived from this to
+ * carry state specific to a particular coherence protocol. */
class CoherenceState {
public:
virtual ~CoherenceState() {}
};
- /** A virtual base opaque structure used to hold
- coherence status messages. */
- CoherenceState *coherence; // virtual base opaque,
- // assert(dynamic_cast<Foo>) etc.
-
+ /** This packet's coherence state. Caches should use
+ * dynamic_cast<> to cast to the state appropriate for the
+ * system's coherence protocol. */
+ CoherenceState *coherence;
+
+ /** 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:
virtual ~SenderState() {}
};
- /** A virtual base opaque structure used to hold the senders state. */
- SenderState *senderState; // virtual base opaque,
- // assert(dynamic_cast<Foo>) etc.
+ /** This packet's sender state. Devices should use dynamic_cast<>
+ * to cast to the state appropriate to the sender. */
+ SenderState *senderState;
private:
/** List of command attributes. */
@@ -144,9 +158,11 @@ class Packet
WriteResp = IsWrite | IsResponse
};
+ /** Return the string name of the cmd field (for debugging and
+ * tracing). */
const std::string &cmdString() const;
- /** The command of the transaction. */
+ /** The command field of the packet. */
Command cmd;
bool isRead() { return (cmd & IsRead) != 0; }
@@ -154,20 +170,7 @@ class Packet
bool isResponse() { return (cmd & IsResponse) != 0; }
bool needsResponse() { return (cmd & NeedsResponse) != 0; }
- void makeTimingResponse() {
- assert(needsResponse());
- int icmd = (int)cmd;
- icmd &= ~(IsRequest | NeedsResponse);
- icmd |= IsResponse;
- cmd = (Command)icmd;
- dest = src;
- srcValid = false;
- }
-
- /** The time this request was responded to. Used to calculate latencies. */
- Tick time;
-
- /** The result of a particular packets request. */
+ /** Possible results of a packet's request. */
enum Result
{
Success,
@@ -175,7 +178,7 @@ class Packet
Unknown
};
- /** The result of the packet transaction. */
+ /** The result of this packet's request. */
Result result;
/** Accessor function that returns the source index of the packet. */
@@ -187,33 +190,59 @@ class Packet
short getDest() const { return dest; }
void setDest(short _dest) { dest = _dest; }
- Addr getAddr() const { assert(addrValid); return addr; }
- void setAddr(Addr _addr) { addr = _addr; addrValid = true; }
-
- int getSize() const { assert(sizeValid); return size; }
- void setSize(int _size) { size = _size; sizeValid = true; }
-
+ Addr getAddr() const { assert(addrSizeValid); return addr; }
+ int getSize() const { assert(addrSizeValid); return size; }
+ /** 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, Command _cmd, short _dest)
: data(NULL), staticData(false), dynamicData(false), arrayData(false),
addr(_req->paddr), size(_req->size), dest(_dest),
- addrValid(_req->validPaddr), sizeValid(_req->validSize),
+ addrSizeValid(_req->validPaddr),
srcValid(false),
req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
- time(curTick), result(Unknown)
+ result(Unknown)
{
}
+ /** Destructor. */
~Packet()
{ deleteData(); }
-
- /** Minimally reset a packet so something like simple cpu can reuse it. */
- void reset();
-
+ /** 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() {
- if (req->validPaddr) setAddr(req->paddr);
- if (req->validSize) setSize(req->size);
+ assert(req->validPaddr);
+ addr = req->paddr;
+ size = req->size;
+ addrSizeValid = true;
+ result = Unknown;
+ if (dynamicData) {
+ deleteData();
+ dynamicData = false;
+ arrayData = false;
+ }
+ }
+
+ /** Take a request packet and modify it in place to be suitable
+ * 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
+ * should not be called. */
+ void makeTimingResponse() {
+ assert(needsResponse());
+ int icmd = (int)cmd;
+ icmd &= ~(IsRequest | NeedsResponse);
+ icmd |= IsResponse;
+ cmd = (Command)icmd;
+ dest = src;
+ srcValid = false;
}
/** Set the data pointer to the following value that should not be freed. */
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index 26dbef0cd..fa7eb803e 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -139,8 +139,7 @@ Tick
PhysicalMemory::doAtomicAccess(Packet *pkt)
{
doFunctionalAccess(pkt);
- pkt->time = curTick + lat;
- return curTick + lat;
+ return lat;
}
void
diff --git a/src/mem/port.cc b/src/mem/port.cc
index 651cb739a..e216ffe71 100644
--- a/src/mem/port.cc
+++ b/src/mem/port.cc
@@ -45,13 +45,12 @@ Port::setPeer(Port *port)
void
Port::blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd)
{
- Request req(false);
+ Request req;
Packet pkt(&req, cmd, Packet::Broadcast);
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
- req.setPaddr(gen.addr());
- req.setSize(gen.size());
+ req.setPhys(gen.addr(), gen.size(), 0);
pkt.reinitFromRequest();
pkt.dataStatic(p);
sendFunctional(&pkt);
diff --git a/src/mem/port.hh b/src/mem/port.hh
index 79fbf1fdb..80ae035b1 100644
--- a/src/mem/port.hh
+++ b/src/mem/port.hh
@@ -74,6 +74,11 @@ class Port
/** Descriptive name (for DPRINTF output) */
const std::string portName;
+ /** A pointer to the peer port. Ports always come in pairs, that way they
+ can use a standardized interface to communicate between different
+ memory objects. */
+ Port *peer;
+
public:
/**
@@ -83,7 +88,7 @@ class Port
* of memory system object to which the port belongs.
*/
Port(const std::string &_name)
- : portName(_name)
+ : portName(_name), peer(NULL)
{ }
/** Return port name (for DPRINTF). */
@@ -98,15 +103,6 @@ class Port
RangeChange
};
- private:
-
- /** A pointer to the peer port. Ports always come in pairs, that way they
- can use a standardized interface to communicate between different
- memory objects. */
- Port *peer;
-
- public:
-
/** Function to set the pointer for the peer port.
@todo should be called by the configuration stuff (python).
*/
@@ -169,10 +165,11 @@ class Port
*/
bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); }
- /** Function called by the associated device to send an atomic access,
- an access in which the data is moved and the state is updated in one
- cycle, without interleaving with other memory accesses.
- */
+ /** Function called by the associated device to send an atomic
+ * access, an access in which the data is moved and the state is
+ * updated in one cycle, without interleaving with other memory
+ * accesses. Returns estimated latency of access.
+ */
Tick sendAtomic(Packet *pkt)
{ return peer->recvAtomic(pkt); }
diff --git a/src/mem/request.hh b/src/mem/request.hh
index 10550e859..c69b36c40 100644
--- a/src/mem/request.hh
+++ b/src/mem/request.hh
@@ -61,139 +61,155 @@ const unsigned NO_ALIGN_FAULT = 0x400;
class Request
{
- //@todo Make Accesor functions, make these private.
- public:
- /** Constructor, needs a bool to signify if it is/isn't Cpu Request. */
- Request(bool isCpu);
-
- /** reset the request to it's initial state so it can be reused.*/
- void resetAll(bool isCpu);
-
- /** reset the request's addrs times, etc, so but not everything to same
- * time. */
- void resetMin();
-
-//First non-cpu request fields
private:
- /** The physical address of the request. */
+ /**
+ * The physical address of the request. Valid only if validPaddr
+ * is set. */
Addr paddr;
- /** Wether or not paddr is valid (has been written yet). */
- bool validPaddr;
- /** The size of the request. */
+ /**
+ * 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. */
int size;
- /** Wether or not size is valid (has been written yet). */
- bool validSize;
-
- /** The time this request was started. Used to calculate latencies. */
- Tick time;
- /** Wether or not time is valid (has been written yet). */
- bool validTime;
-
- /** Destination address if this is a block copy. */
- Addr copyDest;
- /** Wether or not copyDest is valid (has been written yet). */
- bool validCopyDest;
/** Flag structure for the request. */
uint32_t flags;
-//Accsesors for non-cpu request fields
- public:
- /** Accesor for paddr. */
- Addr getPaddr();
- /** Accesor for paddr. */
- void setPaddr(Addr _paddr);
-
- /** Accesor for size. */
- int getSize();
- /** Accesor for size. */
- void setSize(int _size);
-
- /** Accesor for time. */
- Tick getTime();
- /** Accesor for time. */
- void setTime(Tick _time);
-
- /** Accesor for copy dest. */
- Addr getCopyDest();
- /** Accesor for copy dest. */
- void setCopyDest(Addr _copyDest);
-
- /** Accesor for flags. */
- uint32_t getFlags();
- /** Accesor for paddr. */
- void setFlags(uint32_t _flags);
-
-//Now cpu-request fields
- private:
- /** Bool to signify if this is a cpuRequest. */
- bool cpuReq;
-
- /** The virtual address of the request. */
- Addr vaddr;
- /** Wether or not the vaddr is valid. */
- bool validVaddr;
+ /**
+ * The time this request was started. Used to calculate
+ * latencies. This field is set to curTick any time paddr or vaddr
+ * is written. */
+ Tick time;
/** The address space ID. */
int asid;
- /** Wether or not the asid is valid. */
- bool validAsid;
+ /** The virtual address of the request. */
+ Addr vaddr;
/** The return value of store conditional. */
uint64_t scResult;
- /** Wether or not the sc result is valid. */
- bool validScResult;
- /** The cpu number for statistics. */
+ /** The cpu number (for statistics, typically). */
int cpuNum;
- /** Wether or not the cpu number is valid. */
- bool validCpuNum;
-
- /** The requesting thread id. */
+ /** The requesting thread id (for statistics, typically). */
int threadNum;
- /** Wether or not the thread id is valid. */
- bool validThreadNum;
/** program counter of initiating access; for tracing/debugging */
Addr pc;
- /** Wether or not the pc is valid. */
+
+ /** 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 validScResult;
+ /** Whether or not the cpu number & thread ID are valid. */
+ bool validCpuAndThreadNums;
+ /** Whether or not the pc is valid. */
bool validPC;
-//Accessor Functions for cpu request fields
public:
- /** Accesor function to determine if this is a cpu request or not.*/
- bool isCpuRequest();
-
- /** Accesor function for vaddr.*/
- Addr getVaddr();
- /** Accesor function for vaddr.*/
- void setVaddr(Addr _vaddr);
-
- /** Accesor function for asid.*/
- int getAsid();
- /** Accesor function for asid.*/
- void setAsid(int _asid);
-
- /** Accesor function for store conditional return value.*/
- uint64_t getScResult();
- /** Accesor function for store conditional return value.*/
- void setScResult(uint64_t _scResult);
-
- /** Accesor function for cpu number.*/
- int getCpuNum();
- /** Accesor function for cpu number.*/
- void setCpuNum(int _cpuNum);
-
- /** Accesor function for thread number.*/
- int getThreadNum();
- /** Accesor function for thread number.*/
- void setThreadNum(int _threadNum);
-
- /** Accesor function for pc.*/
- Addr getPC();
- /** Accesor function for pc.*/
- void setPC(Addr _pc);
+ /** Minimal constructor. No fields are initialized. */
+ Request()
+ : validPaddr(false), validAsidVaddr(false),
+ validScResult(false), validCpuAndThreadNums(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)
+ : validCpuAndThreadNums(false)
+ { setPhys(_paddr, _size, _flags); }
+
+ /**
+ * Set up CPU and thread numbers. */
+ void setThreadContext(int _cpuNum, int _threadNum)
+ {
+ cpuNum = _cpuNum;
+ threadNum = _threadNum;
+ validCpuAndThreadNums = true;
+ }
+
+ /**
+ * Set up a physical (e.g. device) request in a previously
+ * allocated Request object. */
+ void setPhys(Addr _paddr, int _size, int _flags)
+ {
+ paddr = _paddr;
+ size = _size;
+ flags = _flags;
+ time = curTick;
+ validPaddr = true;
+ validAsidVaddr = false;
+ validPC = false;
+ validScResult = false;
+ }
+
+ /**
+ * 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)
+ {
+ asid = _asid;
+ vaddr = _vaddr;
+ size = _size;
+ flags = _flags;
+ pc = _pc;
+ time = curTick;
+ validPaddr = false;
+ validAsidVaddr = true;
+ validPC = true;
+ validScResult = false;
+ }
+
+ /** 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)
+ {
+ assert(validAsidVaddr);
+ paddr = _paddr;
+ validPaddr = true;
+ }
+
+ /** Accessor for paddr. */
+ Addr getPaddr() { assert(validPaddr); return paddr; }
+
+ /** Accessor for size. */
+ int getSize() { assert(validPaddr || validAsidVaddr); return size; }
+ /** Accessor for time. */
+ Tick getTime() { assert(validPaddr || validAsidVaddr); return time; }
+
+ /** Accessor for flags. */
+ uint32_t getFlags() { assert(validPaddr || validAsidVaddr); return flags; }
+ /** Accessor for paddr. */
+ void setFlags(uint32_t _flags)
+ { assert(validPaddr || validAsidVaddr); flags = _flags; }
+
+ /** Accessor function for vaddr.*/
+ Addr getVaddr() { assert(validAsidVaddr); return vaddr; }
+
+ /** Accessor function for asid.*/
+ int getAsid() { assert(validAsidVaddr); return asid; }
+
+ /** Accessor function for store conditional return value.*/
+ uint64_t getScResult() { assert(validScResult); return scResult; }
+ /** Accessor function for store conditional return value.*/
+ void setScResult(uint64_t _scResult)
+ { scResult = _scResult; validScResult = true; }
+
+ /** Accessor function for cpu number.*/
+ int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; }
+ /** Accessor function for thread number.*/
+ int getThreadNum() { assert(validCpuAndThreadNums); return threadNum; }
+
+ /** Accessor function for pc.*/
+ Addr getPC() { assert(validPC); return pc; }
friend class Packet;
};