struct AtomicOpFunctor
{
virtual void operator()(uint8_t *p) = 0;
+ virtual AtomicOpFunctor* clone() = 0;
virtual ~AtomicOpFunctor() {}
};
struct TypedAtomicOpFunctor : public AtomicOpFunctor
{
void operator()(uint8_t *p) { execute((T *)p); }
+ virtual AtomicOpFunctor* clone() = 0;
virtual void execute(T * p) = 0;
};
// 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
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()) {
*/
void
setVirt(int asid, Addr vaddr, unsigned size, Flags flags, MasterID mid,
- Addr pc)
+ Addr pc, AtomicOpFunctor *amo_op = nullptr)
{
_asid = asid;
_vaddr = vaddr;
depth = 0;
accessDelta = 0;
translateDelta = 0;
+ atomicOpFunctor = amo_op;
}
/**