From d658b6e1cc22de852fef611e28f448257acc298a Mon Sep 17 00:00:00 2001 From: Tony Gutierrez Date: Tue, 19 Jan 2016 13:57:50 -0500 Subject: * * * mem: support for gpu-style RMWs in ruby This patch adds support for GPU-style read-modify-write (RMW) operations in ruby. Such atomic operations are traditionally executed at the memory controller (instead of through an L1 cache using cache-line locking). Currently, this patch works by propogating operation functors through the memory system. --- src/mem/abstract_mem.cc | 69 +++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 31 deletions(-) (limited to 'src/mem/abstract_mem.cc') diff --git a/src/mem/abstract_mem.cc b/src/mem/abstract_mem.cc index 0835d3fdf..cbe360779 100644 --- a/src/mem/abstract_mem.cc +++ b/src/mem/abstract_mem.cc @@ -341,39 +341,46 @@ AbstractMemory::access(PacketPtr pkt) uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start(); if (pkt->cmd == MemCmd::SwapReq) { - std::vector 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(), - pkt->getSize()); - std::memcpy(pkt->getPtr(), 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(), hostAddr, pkt->getSize()); + (*(pkt->getAtomicOp()))(hostAddr); + } + } else { + std::vector 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(), + pkt->getSize()); + std::memcpy(pkt->getPtr(), 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()) { -- cgit v1.2.3