diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/packet.cc | 14 | ||||
-rw-r--r-- | src/mem/packet.hh | 167 | ||||
-rw-r--r-- | src/mem/physical.cc | 3 | ||||
-rw-r--r-- | src/mem/port.cc | 5 | ||||
-rw-r--r-- | src/mem/port.hh | 25 | ||||
-rw-r--r-- | src/mem/request.hh | 236 |
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; }; |