/*
+ * Copyright (c) 2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
#define __MEM_REQUEST_HH__
#include <cassert>
+#include <climits>
-#include "base/fast_alloc.hh"
#include "base/flags.hh"
#include "base/misc.hh"
-#include "sim/host.hh"
+#include "base/types.hh"
#include "sim/core.hh"
+/**
+ * Special TaskIds that are used for per-context-switch stats dumps
+ * and Cache Occupancy. Having too many tasks seems to be a problem
+ * with vector stats. 1024 seems to be a reasonable number that
+ * doesn't cause a problem with stats and is large enough to realistic
+ * benchmarks (Linux/Android boot, BBench, etc.)
+ */
+
+namespace ContextSwitchTaskId {
+ enum TaskId {
+ MaxNormalTaskId = 1021, /* Maximum number of normal tasks */
+ Prefetcher = 1022, /* For cache lines brought in by prefetcher */
+ DMA = 1023, /* Mostly Table Walker */
+ Unknown = 1024,
+ NumTaskId
+ };
+}
+
class Request;
typedef Request* RequestPtr;
+typedef uint16_t MasterID;
-class Request : public FastAlloc
+class Request
{
public:
typedef uint32_t FlagsType;
/** The request is to an uncacheable address. */
static const FlagsType UNCACHEABLE = 0x00001000;
/** This request is to a memory mapped register. */
- static const FlagsType MMAPED_IPR = 0x00002000;
-
- /** The request should not cause a page fault. */
- static const FlagsType NO_FAULT = 0x00010000;
- /** The request should ignore unaligned access faults */
- static const FlagsType NO_ALIGN_FAULT = 0x00020000;
- /** The request should ignore unaligned access faults */
- static const FlagsType NO_HALF_WORD_ALIGN_FAULT = 0x00040000;
+ 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
(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;
+ /** @} */
+
+ /** Invalid or unknown Pid. Possible when operating system is not present
+ * or has not assigned a pid yet */
+ static const uint32_t invldPid = UINT_MAX;
+
private:
typedef uint8_t PrivateFlagsType;
typedef ::Flags<PrivateFlagsType> PrivateFlags;
* The physical address of the request. Valid only if validPaddr
* is set.
*/
- Addr paddr;
+ 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;
+ 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. */
- Flags 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
+ * latencies. This field is set to curTick() any time paddr or vaddr
* is written.
*/
- Tick time;
+ Tick _time;
/** The address space ID. */
- int asid;
+ int _asid;
/** The virtual address of the request. */
- Addr vaddr;
+ Addr _vaddr;
/**
* Extra data for the request, such as the return value of
* store conditional or the compare value for a CAS. */
- uint64_t extraData;
+ uint64_t _extraData;
/** The context ID (for statistics, typically). */
int _contextId;
int _threadId;
/** program counter of initiating access; for tracing/debugging */
- Addr pc;
+ 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()
{}
/**
* Constructor for physical (e.g. device) requests. Initializes
- * just physical address, size, flags, and timestamp (to curTick).
+ * just physical address, size, flags, and timestamp (to curTick()).
* These fields are adequate to perform a request.
*/
- Request(Addr paddr, int size, Flags flags)
+ Request(Addr paddr, int size, Flags flags, MasterID mid)
{
- setPhys(paddr, size, flags);
+ setPhys(paddr, size, flags, mid);
}
- Request(int asid, Addr vaddr, int size, Flags flags, Addr pc,
- int cid, int tid)
+ Request(Addr paddr, int size, Flags flags, MasterID mid, Tick time)
{
- setVirt(asid, vaddr, size, flags, pc);
+ 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, Flags flags, MasterID mid, Addr pc,
+ int cid, ThreadID tid)
+ {
+ setVirt(asid, vaddr, size, flags, mid, pc);
setThreadContext(cid, tid);
}
- ~Request() {} // for FastAlloc
+ ~Request() {}
/**
* Set up CPU and thread numbers.
*/
void
- setThreadContext(int context_id, int thread_id)
+ setThreadContext(int context_id, ThreadID tid)
{
_contextId = context_id;
- _threadId = thread_id;
+ _threadId = tid;
privateFlags.set(VALID_CONTEXT_ID|VALID_THREAD_ID);
}
* allocated Request object.
*/
void
- setPhys(Addr _paddr, int _size, Flags _flags)
+ setPhys(Addr paddr, int size, Flags flags, MasterID mid, Tick time)
{
- assert(_size >= 0);
- paddr = _paddr;
- size = _size;
- time = curTick;
-
- flags.clear(~STICKY_FLAGS);
- flags.set(_flags);
+ 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, Flags _flags, Addr _pc)
+ setVirt(int asid, Addr vaddr, int size, Flags flags, MasterID mid, Addr pc)
{
- assert(_size >= 0);
- asid = _asid;
- vaddr = _vaddr;
- size = _size;
- flags = _flags;
- pc = _pc;
- time = curTick;
-
- flags.clear(~STICKY_FLAGS);
- flags.set(_flags);
+ 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);
}
* to guarantee that the size and flags are also set.
*/
void
- setPaddr(Addr _paddr)
+ setPaddr(Addr paddr)
{
assert(privateFlags.isSet(VALID_VADDR));
- paddr = _paddr;
+ _paddr = paddr;
privateFlags.set(VALID_PADDR);
}
{
assert(privateFlags.isSet(VALID_VADDR));
assert(privateFlags.noneSet(VALID_PADDR));
- assert(split_addr > vaddr && split_addr < vaddr + size);
+ 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;
+ req1->_size = split_addr - _vaddr;
+ req2->_vaddr = split_addr;
+ req2->_size = _size - req1->_size;
}
/**
getPaddr()
{
assert(privateFlags.isSet(VALID_PADDR));
- return paddr;
+ return _paddr;
}
/**
getSize()
{
assert(privateFlags.isSet(VALID_SIZE));
- return size;
+ return _size;
}
/** Accessor for time. */
Tick
- getTime()
+ time() const
{
assert(privateFlags.isSet(VALID_PADDR|VALID_VADDR));
- return time;
+ return _time;
+ }
+
+ void
+ time(Tick time)
+ {
+ assert(privateFlags.isSet(VALID_PADDR|VALID_VADDR));
+ _time = time;
}
/** Accessor for flags. */
getFlags()
{
assert(privateFlags.isSet(VALID_PADDR|VALID_VADDR));
- return flags;
+ 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)
+ setFlags(Flags flags)
{
assert(privateFlags.isSet(VALID_PADDR|VALID_VADDR));
- flags.set(_flags);
+ _flags.set(flags);
}
/** Accessor function for vaddr.*/
getVaddr()
{
assert(privateFlags.isSet(VALID_VADDR));
- return vaddr;
+ return _vaddr;
+ }
+
+ /** Accesssor for the requestor id. */
+ MasterID
+ masterId()
+ {
+ return _masterId;
}
/** Accessor function for asid.*/
getAsid()
{
assert(privateFlags.isSet(VALID_VADDR));
- return asid;
+ return _asid;
+ }
+
+ /** Accessor function for asid.*/
+ void
+ setAsid(int asid)
+ {
+ _asid = asid;
}
/** Accessor function for asi.*/
getAsi()
{
assert(privateFlags.isSet(VALID_VADDR));
- return flags & ASI_BITS;
- }
-
- /** Accessor function for MMAPED_IPR flag. */
- bool
- isMmapedIpr()
- {
- assert(privateFlags.isSet(VALID_PADDR));
- return flags.isSet(MMAPED_IPR);
- }
-
- void
- setMmapedIpr(bool r)
- {
- assert(VALID_VADDR);
- flags.set(MMAPED_IPR);
+ return _flags & ASI_BITS;
}
/** Accessor function to check if sc result is valid. */
getExtraData() const
{
assert(privateFlags.isSet(VALID_EXTRA_DATA));
- return extraData;
+ return _extraData;
}
/** Accessor function for store conditional return value.*/
void
- setExtraData(uint64_t _extraData)
+ setExtraData(uint64_t extraData)
{
- extraData = _extraData;
+ _extraData = extraData;
privateFlags.set(VALID_EXTRA_DATA);
}
getPC() const
{
assert(privateFlags.isSet(VALID_PC));
- return pc;
+ return _pc;
}
- /** Accessor Function to Check Cacheability. */
- 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
- isMisaligned() const
- {
- if (flags.isSet(NO_ALIGN_FAULT))
- return false;
-
- if ((vaddr & 0x1))
- return true;
-
- if (flags.isSet(NO_HALF_WORD_ALIGN_FAULT))
- return false;
-
- if ((vaddr & 0x2))
- return true;
-
- return false;
- }
+ /** 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__