base,mem: Support AtomicOpFunctor in the classic memory system
AtomicOpFunctor can be used to implement atomic memory operations. AtomicOpFunctor is captured inside a memory request and executed directly in the memory hierarchy in a single step. This patch enables AtomicOpFunctor pointers to be included in a memory request and executed in a single step in the classic cache system. This patch also makes the copy constructor of Request class do a deep copy of AtomicOpFunctor object. This prevents a copy of a Request object from accessing a deleted AtomicOpFunctor object. Change-Id: I6649532b37f711e55f4552ad26893efeb300dd37 Reviewed-on: https://gem5-review.googlesource.com/8185 Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com> Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
This commit is contained in:
@@ -191,6 +191,7 @@ constexpr decltype(nullptr) NoFault = nullptr;
|
||||
struct AtomicOpFunctor
|
||||
{
|
||||
virtual void operator()(uint8_t *p) = 0;
|
||||
virtual AtomicOpFunctor* clone() = 0;
|
||||
virtual ~AtomicOpFunctor() {}
|
||||
};
|
||||
|
||||
@@ -198,6 +199,7 @@ template <class T>
|
||||
struct TypedAtomicOpFunctor : public AtomicOpFunctor
|
||||
{
|
||||
void operator()(uint8_t *p) { execute((T *)p); }
|
||||
virtual AtomicOpFunctor* clone() = 0;
|
||||
virtual void execute(T * p) = 0;
|
||||
};
|
||||
|
||||
|
||||
17
src/mem/cache/base.cc
vendored
17
src/mem/cache/base.cc
vendored
@@ -836,7 +836,22 @@ BaseCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool)
|
||||
// Check RMW operations first since both isRead() and
|
||||
// isWrite() will be true for them
|
||||
if (pkt->cmd == MemCmd::SwapReq) {
|
||||
cmpAndSwap(blk, pkt);
|
||||
if (pkt->isAtomicOp()) {
|
||||
// extract data from cache and save it into the data field in
|
||||
// the packet as a return value from this atomic op
|
||||
|
||||
int offset = tags->extractBlkOffset(pkt->getAddr());
|
||||
uint8_t *blk_data = blk->data + offset;
|
||||
std::memcpy(pkt->getPtr<uint8_t>(), blk_data, pkt->getSize());
|
||||
|
||||
// execute AMO operation
|
||||
(*(pkt->getAtomicOp()))(blk_data);
|
||||
|
||||
// set block status to dirty
|
||||
blk->status |= BlkDirty;
|
||||
} else {
|
||||
cmpAndSwap(blk, pkt);
|
||||
}
|
||||
} else if (pkt->isWrite()) {
|
||||
// we have the block in a writable state and can go ahead,
|
||||
// note that the line may be also be considered writable in
|
||||
|
||||
@@ -841,7 +841,7 @@ class Packet : public Printable
|
||||
{
|
||||
if (req->isLLSC())
|
||||
return MemCmd::StoreCondReq;
|
||||
else if (req->isSwap())
|
||||
else if (req->isSwap() || req->isAtomic())
|
||||
return MemCmd::SwapReq;
|
||||
else if (req->isCacheInvalidate()) {
|
||||
return req->isCacheClean() ? MemCmd::CleanInvalidReq :
|
||||
|
||||
@@ -445,12 +445,30 @@ class Request
|
||||
|
||||
Request(int asid, Addr vaddr, unsigned size, Flags flags, MasterID mid,
|
||||
Addr pc, ContextID cid, AtomicOpFunctor *atomic_op)
|
||||
: atomicOpFunctor(atomic_op)
|
||||
{
|
||||
setVirt(asid, vaddr, size, flags, mid, pc);
|
||||
setVirt(asid, vaddr, size, flags, mid, pc, atomic_op);
|
||||
setContext(cid);
|
||||
}
|
||||
|
||||
Request(const Request& other)
|
||||
: _paddr(other._paddr), _size(other._size),
|
||||
_masterId(other._masterId),
|
||||
_flags(other._flags),
|
||||
_memSpaceConfigFlags(other._memSpaceConfigFlags),
|
||||
privateFlags(other.privateFlags),
|
||||
_time(other._time),
|
||||
_taskId(other._taskId), _asid(other._asid), _vaddr(other._vaddr),
|
||||
_extraData(other._extraData), _contextId(other._contextId),
|
||||
_pc(other._pc), _reqInstSeqNum(other._reqInstSeqNum),
|
||||
translateDelta(other.translateDelta),
|
||||
accessDelta(other.accessDelta), depth(other.depth)
|
||||
{
|
||||
if (other.atomicOpFunctor)
|
||||
atomicOpFunctor = (other.atomicOpFunctor)->clone();
|
||||
else
|
||||
atomicOpFunctor = nullptr;
|
||||
}
|
||||
|
||||
~Request()
|
||||
{
|
||||
if (hasAtomicOpFunctor()) {
|
||||
@@ -474,7 +492,7 @@ class Request
|
||||
*/
|
||||
void
|
||||
setVirt(int asid, Addr vaddr, unsigned size, Flags flags, MasterID mid,
|
||||
Addr pc)
|
||||
Addr pc, AtomicOpFunctor *amo_op = nullptr)
|
||||
{
|
||||
_asid = asid;
|
||||
_vaddr = vaddr;
|
||||
@@ -490,6 +508,7 @@ class Request
|
||||
depth = 0;
|
||||
accessDelta = 0;
|
||||
translateDelta = 0;
|
||||
atomicOpFunctor = amo_op;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user