Ruby NetDest: add assert for bad element in netdest
[gem5.git] / src / mem / request.hh
index 457310298ffa0ef7a84c3097f6adcc13f212d8e5..f6406e2c5ee42f679465e0b1fbd8ef5a866b2b45 100644 (file)
 #ifndef __MEM_REQUEST_HH__
 #define __MEM_REQUEST_HH__
 
-#include "sim/host.hh"
-#include "sim/root.hh"
+#include <cassert>
+#include <climits>
+
+#include "base/flags.hh"
+#include "base/misc.hh"
+#include "base/types.hh"
+#include "sim/core.hh"
 
 class Request;
 
 typedef Request* RequestPtr;
-
-
-/** The request is a Load locked/store conditional. */
-const unsigned LOCKED          = 0x001;
-/** The virtual address is also the physical address. */
-const unsigned PHYSICAL                = 0x002;
-/** The request is an ALPHA VPTE pal access (hw_ld). */
-const unsigned VPTE            = 0x004;
-/** Use the alternate mode bits in ALPHA. */
-const unsigned ALTMODE         = 0x008;
-/** The request is to an uncacheable address. */
-const unsigned UNCACHEABLE     = 0x010;
-/** The request should not cause a page fault. */
-const unsigned NO_FAULT         = 0x020;
-/** The request should be prefetched into the exclusive state. */
-const unsigned PF_EXCLUSIVE    = 0x100;
-/** The request should be marked as LRU. */
-const unsigned EVICT_NEXT      = 0x200;
-/** The request should ignore unaligned access faults */
-const unsigned NO_ALIGN_FAULT   = 0x400;
-/** The request was an instruction read. */
-const unsigned INST_READ        = 0x800;
+typedef uint16_t MasterID;
 
 class Request
 {
+  public:
+    typedef uint32_t FlagsType;
+    typedef ::Flags<FlagsType> 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<PrivateFlagsType> 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;
+    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); }
+     * 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)
+    {
+        setPhys(paddr, size, flags, mid, time);
+        privateFlags.set(VALID_PC);
+        _pc = pc;
+    }
 
-    Request(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc,
-            int _cpuNum, int _threadNum)
+    Request(int asid, Addr vaddr, int size, Flags flags, MasterID mid, Addr pc,
+            int cid, ThreadID tid)
     {
-        setThreadContext(_cpuNum, _threadNum);
-        setVirt(_asid, _vaddr, _size, _flags, _pc);
+        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)
+    {
+        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)
     {
-        paddr = _paddr;
-        size = _size;
-        flags = _flags;
-        time = curTick;
-        validPaddr = true;
-        validAsidVaddr = false;
-        validPC = false;
-        validScResult = false;
+        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)
-    {
-        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
+     * allocated Request object.
+     */
+    void
+    setVirt(int asid, Addr vaddr, int size, Flags flags, MasterID mid, Addr pc)
+    {
+        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
      * 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(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.
+     */
+    bool
+    hasPaddr()
+    {
+        return privateFlags.isSet(VALID_PADDR);
+    }
+
+    Addr
+    getPaddr()
+    {
+        assert(privateFlags.isSet(VALID_PADDR));
+        return _paddr;
+    }
+
+    /**
+     *  Accessor for size.
+     */
+    bool
+    hasSize()
     {
-        assert(validAsidVaddr);
-        paddr = _paddr;
-        validPaddr = true;
+        return privateFlags.isSet(VALID_SIZE);
     }
 
-    /** Accessor for paddr. */
-    Addr getPaddr() { assert(validPaddr); return paddr; }
+    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;
+    }
+
+    /** 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 vaddr.*/
-    Addr getVaddr() { assert(validAsidVaddr); return vaddr; }
+    Addr
+    getVaddr()
+    {
+        assert(privateFlags.isSet(VALID_VADDR));
+        return _vaddr;
+    }
+
+    /** Accesssor for the requestor id. */
+    MasterID
+    masterId()
+    {
+        return _masterId;
+    }
+
+    /** Accessor function for asid.*/
+    int
+    getAsid()
+    {
+        assert(privateFlags.isSet(VALID_VADDR));
+        return _asid;
+    }
 
     /** Accessor function for asid.*/
-    int getAsid() { assert(validAsidVaddr); return asid; }
+    void
+    setAsid(int asid)
+    {
+        _asid = asid;
+    }
+
+    /** Accessor function for asi.*/
+    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 for thread ID. */
+    int
+    threadId() const
+    {
+        assert(privateFlags.isSet(VALID_THREAD_ID));
+        return _threadId;
+    }
 
-    /** Accessor Function to Check Cacheability. */
-    bool isUncacheable() { return getFlags() & UNCACHEABLE; }
+    bool
+    hasPC() const
+    {
+        return privateFlags.isSet(VALID_PC);
+    }
 
-    bool isInstRead() { return getFlags() & INST_READ; }
+    /** 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__