X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Frequest.hh;h=f6406e2c5ee42f679465e0b1fbd8ef5a866b2b45;hb=6721b3e325139fb4ace99d858f0bdec44ec6af1b;hp=de0512e1c7d72a690cccf5c3e3df624d1db4fb45;hpb=0fa30e579edace72b923bd0dde4e687d43c5fbad;p=gem5.git diff --git a/src/mem/request.hh b/src/mem/request.hh index de0512e1c..f6406e2c5 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -39,227 +39,459 @@ #ifndef __MEM_REQUEST_HH__ #define __MEM_REQUEST_HH__ -#include "sim/host.hh" -#include "sim/root.hh" - #include +#include + +#include "base/flags.hh" +#include "base/misc.hh" +#include "base/types.hh" +#include "sim/core.hh" 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; +typedef uint16_t MasterID; class Request { + public: + typedef uint32_t FlagsType; + typedef ::Flags Flags; + + /** ASI information for this request if it exists. */ + static const FlagsType ASI_BITS = 0x000000FF; + /** The request was an instruction fetch. */ + static const FlagsType INST_FETCH = 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; + /** This request is to a memory mapped register. */ + static const FlagsType MMAPPED_IPR = 0x00002000; + /** This request is a clear exclusive. */ + static const FlagsType CLEAR_LL = 0x00004000; + + /** The request should not cause a memory access. */ + static const FlagsType NO_ACCESS = 0x00080000; + /** This request will lock or unlock the accessed memory. When used with + * a load, the access locks the particular chunk of memory. When used + * with a store, it unlocks. The rule is that locked accesses have to be + * made up of a locked load, some operation on the data, and then a locked + * store. + */ + static const FlagsType LOCKED = 0x00100000; + /** The request is a Load locked/store conditional. */ + static const FlagsType LLSC = 0x00200000; + /** This request is for a memory swap. */ + static const FlagsType MEM_SWAP = 0x00400000; + static const FlagsType MEM_SWAP_COND = 0x00800000; + + /** The request is a prefetch. */ + static const FlagsType PREFETCH = 0x01000000; + /** The request should be prefetched into the exclusive state. */ + static const FlagsType PF_EXCLUSIVE = 0x02000000; + /** The request should be marked as LRU. */ + static const FlagsType EVICT_NEXT = 0x04000000; + + /** These flags are *not* cleared when a Request object is reused + (assigned a new address). */ + static const FlagsType STICKY_FLAGS = INST_FETCH; + + /** Request Ids that are statically allocated + * @{*/ + /** This request id is used for writeback requests by the caches */ + static const MasterID wbMasterId = 0; + /** This request id is used for functional requests that don't come from a + * particular device + */ + static const MasterID funcMasterId = 1; + /** This request id is used for message signaled interrupts */ + static const MasterID intMasterId = 2; + /** Invalid request id for assertion checking only. It is invalid behavior + * to ever send this id as part of a request. + * @todo C++1x replace with numeric_limits when constexpr is added */ + static const MasterID invldMasterId = USHRT_MAX; + /** @} */ + + private: + typedef uint8_t PrivateFlagsType; + typedef ::Flags PrivateFlags; + + /** Whether or not the size is valid. */ + static const PrivateFlagsType VALID_SIZE = 0x00000001; + /** Whether or not paddr is valid (has been written yet). */ + static const PrivateFlagsType VALID_PADDR = 0x00000002; + /** Whether or not the vaddr & asid are valid. */ + static const PrivateFlagsType VALID_VADDR = 0x00000004; + /** Whether or not the pc is valid. */ + static const PrivateFlagsType VALID_PC = 0x00000010; + /** Whether or not the context ID is valid. */ + static const PrivateFlagsType VALID_CONTEXT_ID = 0x00000020; + static const PrivateFlagsType VALID_THREAD_ID = 0x00000040; + /** Whether or not the sc result is valid. */ + static const PrivateFlagsType VALID_EXTRA_DATA = 0x00000080; + + /** These flags are *not* cleared when a Request object is reused + (assigned a new address). */ + static const PrivateFlagsType STICKY_PRIVATE_FLAGS = + VALID_CONTEXT_ID | VALID_THREAD_ID; + private: /** * The physical address of the request. Valid only if validPaddr - * is set. */ - Addr paddr; + * 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. */ - int size; + * valid as long as one of the address fields is valid. + */ + int _size; + + /** The requestor ID which is unique in the system for all ports + * that are capable of issuing a transaction + */ + MasterID _masterId; /** Flag structure for the request. */ - uint32_t flags; + Flags _flags; + + /** Private flags for field validity checking. */ + PrivateFlags privateFlags; /** * 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; + * latencies. This field is set to curTick() any time paddr or vaddr + * is written. + */ + Tick _time; /** The address space ID. */ - int asid; - - /** This request is to a memory mapped register. */ - bool mmapedIpr; + int _asid; /** The virtual address of the request. */ - Addr vaddr; + Addr _vaddr; - /** The return value of store conditional. */ - uint64_t scResult; + /** + * Extra data for the request, such as the return value of + * store conditional or the compare value for a CAS. */ + uint64_t _extraData; - /** The cpu number (for statistics, typically). */ - int cpuNum; - /** The requesting thread id (for statistics, typically). */ - int threadNum; + /** The context ID (for statistics, typically). */ + int _contextId; + /** The thread ID (id within this CPU) */ + int _threadId; /** 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 validScResult; - /** Whether or not the cpu number & thread ID are valid. */ - bool validCpuAndThreadNums; - /** Whether or not the pc is valid. */ - bool validPC; + Addr _pc; public: - /** Minimal constructor. No fields are initialized. */ + /** Minimal constructor. No fields are initialized. + * (Note that _flags and privateFlags are cleared by Flags + * default constructor.) + */ 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); } - - Request(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc, - int _cpuNum, int _threadNum) + * just physical address, size, flags, and timestamp (to curTick()). + * These fields are adequate to perform a request. + */ + Request(Addr paddr, int size, Flags flags, MasterID mid) + { + setPhys(paddr, size, flags, mid); + } + + Request(Addr paddr, int size, Flags flags, MasterID mid, Tick time) + { + setPhys(paddr, size, flags, mid, time); + } + + Request(Addr paddr, int size, Flags flags, MasterID mid, Tick time, Addr pc) { - setThreadContext(_cpuNum, _threadNum); - setVirt(_asid, _vaddr, _size, _flags, _pc); + setPhys(paddr, size, flags, mid, time); + privateFlags.set(VALID_PC); + _pc = pc; } + Request(int asid, Addr vaddr, int size, Flags flags, MasterID mid, Addr pc, + int cid, ThreadID tid) + { + setVirt(asid, vaddr, size, flags, mid, pc); + setThreadContext(cid, tid); + } + + ~Request() {} + /** - * Set up CPU and thread numbers. */ - void setThreadContext(int _cpuNum, int _threadNum) + * Set up CPU and thread numbers. + */ + void + setThreadContext(int context_id, ThreadID tid) { - cpuNum = _cpuNum; - threadNum = _threadNum; - validCpuAndThreadNums = true; + _contextId = context_id; + _threadId = tid; + privateFlags.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, MasterID mid, Tick time) { - paddr = _paddr; - size = _size; - flags = _flags; - time = curTick; - validPaddr = true; - validAsidVaddr = false; - validPC = false; - validScResult = false; - mmapedIpr = false; + assert(size >= 0); + _paddr = paddr; + _size = size; + _time = time; + _masterId = mid; + _flags.clear(~STICKY_FLAGS); + _flags.set(flags); + privateFlags.clear(~STICKY_PRIVATE_FLAGS); + privateFlags.set(VALID_PADDR|VALID_SIZE); + } + + void + setPhys(Addr paddr, int size, Flags flags, MasterID mid) + { + setPhys(paddr, size, flags, mid, curTick()); } /** * 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, MasterID mid, Addr pc) { - asid = _asid; - vaddr = _vaddr; - size = _size; - flags = _flags; - pc = _pc; - time = curTick; - validPaddr = false; - validAsidVaddr = true; - validPC = true; - validScResult = false; - mmapedIpr = false; + assert(size >= 0); + _asid = asid; + _vaddr = vaddr; + _size = size; + _masterId = mid; + _pc = pc; + _time = curTick(); + + _flags.clear(~STICKY_FLAGS); + _flags.set(flags); + privateFlags.clear(~STICKY_PRIVATE_FLAGS); + privateFlags.set(VALID_VADDR|VALID_SIZE|VALID_PC); } - /** 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(privateFlags.isSet(VALID_VADDR)); + _paddr = paddr; + privateFlags.set(VALID_PADDR); + } + + /** + * Generate two requests as if this request had been split into two + * pieces. The original request can't have been translated already. + */ + void splitOnVaddr(Addr split_addr, RequestPtr &req1, RequestPtr &req2) { - assert(validAsidVaddr); - paddr = _paddr; - validPaddr = true; + assert(privateFlags.isSet(VALID_VADDR)); + assert(privateFlags.noneSet(VALID_PADDR)); + assert(split_addr > _vaddr && split_addr < _vaddr + _size); + req1 = new Request; + *req1 = *this; + req2 = new Request; + *req2 = *this; + req1->_size = split_addr - _vaddr; + req2->_vaddr = split_addr; + req2->_size = _size - req1->_size; } - /** Accessor for paddr. */ - Addr getPaddr() { assert(validPaddr); return paddr; } + /** + * Accessor for paddr. + */ + bool + hasPaddr() + { + return privateFlags.isSet(VALID_PADDR); + } + + Addr + getPaddr() + { + assert(privateFlags.isSet(VALID_PADDR)); + return _paddr; + } + + /** + * Accessor for size. + */ + bool + hasSize() + { + return privateFlags.isSet(VALID_SIZE); + } + + int + getSize() + { + assert(privateFlags.isSet(VALID_SIZE)); + return _size; + } - /** Accessor for size. */ - int getSize() { assert(validPaddr || validAsidVaddr); return size; } /** Accessor for time. */ - Tick getTime() { assert(validPaddr || validAsidVaddr); return time; } + Tick + time() const + { + assert(privateFlags.isSet(VALID_PADDR|VALID_VADDR)); + return _time; + } + + void + time(Tick time) + { + assert(privateFlags.isSet(VALID_PADDR|VALID_VADDR)); + _time = 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; } + Flags + getFlags() + { + assert(privateFlags.isSet(VALID_PADDR|VALID_VADDR)); + return _flags; + } - /** Accessor function for vaddr.*/ - Addr getVaddr() { assert(validAsidVaddr); return vaddr; } + /** Note that unlike other accessors, this function sets *specific + flags* (ORs them in); it does not assign its argument to the + _flags field. Thus this method should rightly be called + setFlags() and not just flags(). */ + void + setFlags(Flags flags) + { + assert(privateFlags.isSet(VALID_PADDR|VALID_VADDR)); + _flags.set(flags); + } - /** Accessor function for asid.*/ - int getAsid() { assert(validAsidVaddr); return asid; } + /** Accessor function for vaddr.*/ + Addr + getVaddr() + { + assert(privateFlags.isSet(VALID_VADDR)); + return _vaddr; + } - /** Accessor function for asi.*/ - uint8_t getAsi() { assert(validAsidVaddr); return flags & ASI_BITS; } + /** Accesssor for the requestor id. */ + MasterID + masterId() + { + return _masterId; + } - /** Accessor function for asi.*/ - void setAsi(uint8_t a) - { assert(validAsidVaddr); flags = (flags & ~ASI_BITS) | a; } + /** Accessor function for asid.*/ + int + getAsid() + { + assert(privateFlags.isSet(VALID_VADDR)); + return _asid; + } - /** Accessor function for asi.*/ - bool isMmapedIpr() { assert(validPaddr); return mmapedIpr; } + /** Accessor function for asid.*/ + void + setAsid(int asid) + { + _asid = asid; + } /** Accessor function for asi.*/ - void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; } + uint8_t + getAsi() + { + assert(privateFlags.isSet(VALID_VADDR)); + return _flags & ASI_BITS; + } /** Accessor function to check if sc result is valid. */ - bool scResultValid() { return validScResult; } + bool + extraDataValid() + { + return privateFlags.isSet(VALID_EXTRA_DATA); + } + /** Accessor function for store conditional return value.*/ - uint64_t getScResult() { assert(validScResult); return scResult; } + uint64_t + getExtraData() const + { + assert(privateFlags.isSet(VALID_EXTRA_DATA)); + return _extraData; + } + /** Accessor function for store conditional return value.*/ - void setScResult(uint64_t _scResult) - { scResult = _scResult; validScResult = true; } + void + setExtraData(uint64_t extraData) + { + _extraData = extraData; + privateFlags.set(VALID_EXTRA_DATA); + } - /** Accessor function for cpu number.*/ - int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; } - /** Accessor function for thread number.*/ - int getThreadNum() { assert(validCpuAndThreadNums); return threadNum; } + bool + hasContextId() const + { + return privateFlags.isSet(VALID_CONTEXT_ID); + } - /** Accessor function for pc.*/ - Addr getPC() { assert(validPC); return pc; } + /** Accessor function for context ID.*/ + int + contextId() const + { + assert(privateFlags.isSet(VALID_CONTEXT_ID)); + return _contextId; + } - /** Accessor Function to Check Cacheability. */ - bool isUncacheable() { return (getFlags() & UNCACHEABLE) != 0; } + /** Accessor function for thread ID. */ + int + threadId() const + { + assert(privateFlags.isSet(VALID_THREAD_ID)); + return _threadId; + } - bool isInstRead() { return (getFlags() & INST_READ) != 0; } + bool + hasPC() const + { + return privateFlags.isSet(VALID_PC); + } - bool isLocked() { return (getFlags() & LOCKED) != 0; } + /** Accessor function for pc.*/ + Addr + getPC() const + { + assert(privateFlags.isSet(VALID_PC)); + return _pc; + } - friend class Packet; + /** Accessor functions for flags. Note that these are for testing + only; setting flags should be done via setFlags(). */ + bool isUncacheable() const { return _flags.isSet(UNCACHEABLE); } + bool isInstFetch() const { return _flags.isSet(INST_FETCH); } + bool isPrefetch() const { return _flags.isSet(PREFETCH); } + bool isLLSC() const { return _flags.isSet(LLSC); } + bool isLocked() const { return _flags.isSet(LOCKED); } + bool isSwap() const { return _flags.isSet(MEM_SWAP|MEM_SWAP_COND); } + bool isCondSwap() const { return _flags.isSet(MEM_SWAP_COND); } + bool isMmappedIpr() const { return _flags.isSet(MMAPPED_IPR); } + bool isClearLL() const { return _flags.isSet(CLEAR_LL); } }; #endif // __MEM_REQUEST_HH__