diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/bridge.cc | 93 | ||||
-rw-r--r-- | src/mem/bridge.hh | 6 | ||||
-rw-r--r-- | src/mem/bus.cc | 28 | ||||
-rw-r--r-- | src/mem/bus.hh | 13 | ||||
-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 | 37 | ||||
-rw-r--r-- | src/mem/request.hh | 236 |
10 files changed, 330 insertions, 272 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index 736e8dc81..5b8b9164b 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -90,7 +90,17 @@ Bridge::BridgePort::recvTiming(Packet *pkt) DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", pkt->getSrc(), pkt->getDest(), pkt->getAddr()); - if (pkt->isResponse()) { + return otherPort->queueForSendTiming(pkt); +} + + +bool +Bridge::BridgePort::queueForSendTiming(Packet *pkt) +{ + if (queueFull()) + return false; + + if (pkt->isResponse()) { // This is a response for a request we forwarded earlier. The // corresponding PacketBuffer should be stored in the packet's // senderState field. @@ -99,22 +109,16 @@ Bridge::BridgePort::recvTiming(Packet *pkt) // set up new packet dest & senderState based on values saved // from original request buf->fixResponse(pkt); + DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n", + pkt->senderState, buf); DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest()); delete buf; } - return otherPort->queueForSendTiming(pkt); -} - - -bool -Bridge::BridgePort::queueForSendTiming(Packet *pkt) -{ - if (queueFull()) - return false; - Tick readyTime = curTick + delay; PacketBuffer *buf = new PacketBuffer(pkt, readyTime); + DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n", + buf->origSenderState, buf); // If we're about to put this packet at the head of the queue, we // need to schedule an event to do the transmit. Otherwise there @@ -126,43 +130,16 @@ Bridge::BridgePort::queueForSendTiming(Packet *pkt) sendQueue.push_back(buf); - // Did we just become blocked? If yes, let other side know. - if (queueFull()) - otherPort->sendStatusChange(Port::Blocked); - return true; } - -void -Bridge::BridgePort::finishSend(PacketBuffer *buf) -{ - if (buf->expectResponse) { - // Must wait for response. We just need to count outstanding - // responses (in case we want to cap them); PacketBuffer - // pointer will be recovered on response. - ++outstandingResponses; - DPRINTF(BusBridge, " successful: awaiting response (%d)\n", - outstandingResponses); - } else { - // no response expected... deallocate packet buffer now. - DPRINTF(BusBridge, " successful: no response expected\n"); - delete buf; - } - - // If there are more packets to send, schedule event to try again. - if (!sendQueue.empty()) { - buf = sendQueue.front(); - sendEvent.schedule(std::max(buf->ready, curTick + 1)); - } -} - - void Bridge::BridgePort::trySend() { assert(!sendQueue.empty()); + bool was_full = queueFull(); + PacketBuffer *buf = sendQueue.front(); assert(buf->ready <= curTick); @@ -176,20 +153,41 @@ Bridge::BridgePort::trySend() // send successful sendQueue.pop_front(); buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it - finishSend(buf); + + if (buf->expectResponse) { + // Must wait for response. We just need to count outstanding + // responses (in case we want to cap them); PacketBuffer + // pointer will be recovered on response. + ++outstandingResponses; + DPRINTF(BusBridge, " successful: awaiting response (%d)\n", + outstandingResponses); + } else { + // no response expected... deallocate packet buffer now. + DPRINTF(BusBridge, " successful: no response expected\n"); + delete buf; + } + + // If there are more packets to send, schedule event to try again. + if (!sendQueue.empty()) { + buf = sendQueue.front(); + sendEvent.schedule(std::max(buf->ready, curTick + 1)); + } + // Let things start sending again + if (was_full) { + DPRINTF(BusBridge, "Queue was full, sending retry\n"); + otherPort->sendRetry(); + } + } else { DPRINTF(BusBridge, " unsuccessful\n"); } } -Packet * +void Bridge::BridgePort::recvRetry() { - PacketBuffer *buf = sendQueue.front(); - Packet *pkt = buf->pkt; - finishSend(buf); - return pkt; + trySend(); } /** Function called by the port when the bus is receiving a Atomic @@ -223,9 +221,6 @@ Bridge::BridgePort::recvFunctional(Packet *pkt) void Bridge::BridgePort::recvStatusChange(Port::Status status) { - if (status == Port::Blocked || status == Port::Unblocked) - return; - otherPort->sendStatusChange(status); } diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index 8a5cbf92a..8c7af562c 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -38,7 +38,6 @@ #include <inttypes.h> #include <queue> - #include "mem/mem_object.hh" #include "mem/packet.hh" #include "mem/port.hh" @@ -77,7 +76,8 @@ class Bridge : public MemObject origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()), expectResponse(_pkt->needsResponse()) { - pkt->senderState = this; + if (!pkt->isResponse()) + pkt->senderState = this; } void fixResponse(Packet *pkt) @@ -146,7 +146,7 @@ class Bridge : public MemObject /** When receiving a retry request from the peer port, pass it to the bridge. */ - virtual Packet* recvRetry(); + virtual void recvRetry(); /** When receiving a Atomic requestfrom the peer port, pass it to the bridge. */ diff --git a/src/mem/bus.cc b/src/mem/bus.cc index cfc99a64f..aec3ef2f6 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -72,9 +72,35 @@ Bus::recvTiming(Packet *pkt) assert(dest != pkt->getSrc()); // catch infinite loops port = interfaces[dest]; } - return port->sendTiming(pkt); + if (port->sendTiming(pkt)) { + // packet was successfully sent, just return true. + return true; + } + + // packet not successfully sent + retryList.push_back(interfaces[pkt->getSrc()]); + return false; +} + +void +Bus::recvRetry(int id) +{ + // Go through all the elements on the list calling sendRetry on each + // This is not very efficient at all but it works. Ultimately we should end + // up with something that is more intelligent. + int initialSize = retryList.size(); + int i; + Port *p; + + for (i = 0; i < initialSize; i++) { + assert(retryList.size() > 0); + p = retryList.front(); + retryList.pop_front(); + p->sendRetry(); + } } + Port * Bus::findPort(Addr addr, int id) { diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 5eeb07904..774f9f3a4 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -67,6 +67,10 @@ class Bus : public MemObject transaction.*/ void recvFunctional(Packet *pkt); + /** Timing function called by port when it is once again able to process + * requests. */ + void recvRetry(int id); + /** Function called by the port when the bus is recieving a status change.*/ void recvStatusChange(Port::Status status, int id); @@ -126,6 +130,11 @@ class Bus : public MemObject virtual void recvStatusChange(Status status) { bus->recvStatusChange(status, id); } + /** When reciving a retry from the peer port (at id), + pass it to the bus. */ + virtual void recvRetry() + { bus->recvRetry(id); } + // This should return all the 'owned' addresses that are // downstream from this bus, yes? That is, the union of all // the 'owned' address ranges of all the other interfaces on @@ -143,6 +152,10 @@ class Bus : public MemObject connected to this bus.*/ std::vector<Port*> interfaces; + /** An array of pointers to ports that retry should be called on because the + * original send failed for whatever reason.*/ + std::list<Port*> retryList; + public: /** A function used to return the port associated with this bus object. */ 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 f9103865e..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). */ @@ -92,23 +97,12 @@ class Port virtual ~Port() {}; // mey be better to use subclasses & RTTI? - /** Holds the ports status. Keeps track if it is blocked, or has - calculated a range change. */ + /** Holds the ports status. Currently just that a range recomputation needs + * to be done. */ enum Status { - Blocked, - Unblocked, 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). */ @@ -140,7 +134,7 @@ class Port wait. This shouldn't be valid for response paths (IO Devices). so it is set to panic if it isn't already defined. */ - virtual Packet *recvRetry() { panic("??"); } + virtual void recvRetry() { panic("??"); } /** Called by a peer port in order to determine the block size of the device connected to this port. It sometimes doesn't make sense for @@ -165,16 +159,17 @@ class Port port receive function. @return This function returns if the send was succesful in it's recieve. If it was a failure, then the port will wait for a recvRetry - at which point it can issue a successful sendTiming. This is used in + at which point it can possibly issue a successful sendTiming. This is used in case a cache has a higher priority request come in while waiting for the bus to arbitrate. */ 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); } @@ -194,7 +189,7 @@ class Port /** When a timing access doesn't return a success, some time later the Retry will be sent. */ - Packet *sendRetry() { return peer->recvRetry(); } + void sendRetry() { return peer->recvRetry(); } /** Called by the associated device if it wishes to find out the blocksize of the device on attached to the peer port. 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; }; |