uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start();
if (pkt->cmd == MemCmd::SwapReq) {
- std::vector<uint8_t> overwrite_val(pkt->getSize());
- uint64_t condition_val64;
- uint32_t condition_val32;
-
- if (!pmemAddr)
- panic("Swap only works if there is real memory (i.e. null=False)");
-
- bool overwrite_mem = true;
- // keep a copy of our possible write value, and copy what is at the
- // memory address into the packet
- std::memcpy(&overwrite_val[0], pkt->getConstPtr<uint8_t>(),
- pkt->getSize());
- std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
-
- if (pkt->req->isCondSwap()) {
- if (pkt->getSize() == sizeof(uint64_t)) {
- condition_val64 = pkt->req->getExtraData();
- overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
- sizeof(uint64_t));
- } else if (pkt->getSize() == sizeof(uint32_t)) {
- condition_val32 = (uint32_t)pkt->req->getExtraData();
- overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
- sizeof(uint32_t));
- } else
- panic("Invalid size for conditional read/write\n");
- }
+ if (pkt->isAtomicOp()) {
+ if (pmemAddr) {
+ memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+ (*(pkt->getAtomicOp()))(hostAddr);
+ }
+ } else {
+ std::vector<uint8_t> overwrite_val(pkt->getSize());
+ uint64_t condition_val64;
+ uint32_t condition_val32;
+
+ if (!pmemAddr)
+ panic("Swap only works if there is real memory (i.e. null=False)");
+
+ bool overwrite_mem = true;
+ // keep a copy of our possible write value, and copy what is at the
+ // memory address into the packet
+ std::memcpy(&overwrite_val[0], pkt->getConstPtr<uint8_t>(),
+ pkt->getSize());
+ std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+
+ if (pkt->req->isCondSwap()) {
+ if (pkt->getSize() == sizeof(uint64_t)) {
+ condition_val64 = pkt->req->getExtraData();
+ overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
+ sizeof(uint64_t));
+ } else if (pkt->getSize() == sizeof(uint32_t)) {
+ condition_val32 = (uint32_t)pkt->req->getExtraData();
+ overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
+ sizeof(uint32_t));
+ } else
+ panic("Invalid size for conditional read/write\n");
+ }
- if (overwrite_mem)
- std::memcpy(hostAddr, &overwrite_val[0], pkt->getSize());
+ if (overwrite_mem)
+ std::memcpy(hostAddr, &overwrite_val[0], pkt->getSize());
- assert(!pkt->req->isInstFetch());
- TRACE_PACKET("Read/Write");
- numOther[pkt->req->masterId()]++;
+ assert(!pkt->req->isInstFetch());
+ TRACE_PACKET("Read/Write");
+ numOther[pkt->req->masterId()]++;
+ }
} else if (pkt->isRead()) {
assert(!pkt->isWrite());
if (pkt->isLLSC()) {
/** The request should be marked with RELEASE. */
RELEASE = 0x00040000,
+ /** The request is an atomic that returns data. */
+ ATOMIC_RETURN_OP = 0x40000000,
+ /** The request is an atomic that does not return data. */
+ ATOMIC_NO_RETURN_OP = 0x80000000,
+
/** The request should be marked with KERNEL.
* Used to indicate the synchronization associated with a GPU kernel
* launch or completion.
/** Sequence number of the instruction that creates the request */
InstSeqNum _reqInstSeqNum;
+ /** A pointer to an atomic operation */
+ AtomicOpFunctor *atomicOpFunctor;
+
public:
/**
: _paddr(0), _size(0), _masterId(invldMasterId), _time(0),
_taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0),
_extraData(0), _contextId(0), _threadId(0), _pc(0),
- _reqInstSeqNum(0), translateDelta(0), accessDelta(0), depth(0)
+ _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0),
+ accessDelta(0), depth(0)
{}
Request(Addr paddr, unsigned size, Flags flags, MasterID mid,
: _paddr(0), _size(0), _masterId(invldMasterId), _time(0),
_taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0),
_extraData(0), _contextId(0), _threadId(0), _pc(0),
- _reqInstSeqNum(seq_num), translateDelta(0), accessDelta(0), depth(0)
+ _reqInstSeqNum(seq_num), atomicOpFunctor(nullptr), translateDelta(0),
+ accessDelta(0), depth(0)
{
setPhys(paddr, size, flags, mid, curTick());
setThreadContext(cid, tid);
: _paddr(0), _size(0), _masterId(invldMasterId), _time(0),
_taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0),
_extraData(0), _contextId(0), _threadId(0), _pc(0),
- _reqInstSeqNum(0), translateDelta(0), accessDelta(0), depth(0)
+ _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0),
+ accessDelta(0), depth(0)
{
setPhys(paddr, size, flags, mid, curTick());
}
: _paddr(0), _size(0), _masterId(invldMasterId), _time(0),
_taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0),
_extraData(0), _contextId(0), _threadId(0), _pc(0),
- _reqInstSeqNum(0), translateDelta(0), accessDelta(0), depth(0)
+ _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0),
+ accessDelta(0), depth(0)
{
setPhys(paddr, size, flags, mid, time);
}
Addr pc)
: _paddr(0), _size(0), _masterId(invldMasterId), _time(0),
_taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0),
- _extraData(0), _contextId(0), _threadId(0), _pc(0),
- _reqInstSeqNum(0), translateDelta(0), accessDelta(0), depth(0)
+ _extraData(0), _contextId(0), _threadId(0), _pc(pc),
+ _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0),
+ accessDelta(0), depth(0)
{
setPhys(paddr, size, flags, mid, time);
privateFlags.set(VALID_PC);
- _pc = pc;
}
Request(int asid, Addr vaddr, unsigned size, Flags flags, MasterID mid,
: _paddr(0), _size(0), _masterId(invldMasterId), _time(0),
_taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0),
_extraData(0), _contextId(0), _threadId(0), _pc(0),
- _reqInstSeqNum(0), translateDelta(0), accessDelta(0), depth(0)
+ _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0),
+ accessDelta(0), depth(0)
+ {
+ setVirt(asid, vaddr, size, flags, mid, pc);
+ setThreadContext(cid, tid);
+ }
+
+ Request(int asid, Addr vaddr, int size, Flags flags, MasterID mid, Addr pc,
+ int cid, ThreadID tid, AtomicOpFunctor *atomic_op)
+ : atomicOpFunctor(atomic_op)
{
setVirt(asid, vaddr, size, flags, mid, pc);
setThreadContext(cid, tid);
}
- ~Request() {}
+ ~Request()
+ {
+ if (hasAtomicOpFunctor()) {
+ delete atomicOpFunctor;
+ }
+ }
/**
* Set up CPU and thread numbers.
return _time;
}
+ /**
+ * Accessor for atomic-op functor.
+ */
+ bool
+ hasAtomicOpFunctor()
+ {
+ return atomicOpFunctor != NULL;
+ }
+
+ AtomicOpFunctor *
+ getAtomicOpFunctor()
+ {
+ assert(atomicOpFunctor != NULL);
+ return atomicOpFunctor;
+ }
+
/** Accessor for flags. */
Flags
getFlags()
bool isAcquire() const { return _flags.isSet(ACQUIRE); }
bool isRelease() const { return _flags.isSet(RELEASE); }
bool isKernel() const { return _flags.isSet(KERNEL); }
+ bool isAtomicReturn() const { return _flags.isSet(ATOMIC_RETURN_OP); }
+ bool isAtomicNoReturn() const { return _flags.isSet(ATOMIC_NO_RETURN_OP); }
+
+ bool
+ isAtomic() const
+ {
+ return _flags.isSet(ATOMIC_RETURN_OP) ||
+ _flags.isSet(ATOMIC_NO_RETURN_OP);
+ }
/**
* Accessor functions for the memory space configuration flags and used by