diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/cache/cache_blk.hh | 2 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 4 | ||||
-rw-r--r-- | src/mem/packet.cc | 14 | ||||
-rw-r--r-- | src/mem/packet.hh | 5 | ||||
-rw-r--r-- | src/mem/packet_access.hh | 14 | ||||
-rw-r--r-- | src/mem/physical.cc | 91 | ||||
-rw-r--r-- | src/mem/physical.hh | 3 | ||||
-rw-r--r-- | src/mem/request.hh | 31 |
8 files changed, 133 insertions, 31 deletions
diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index 7b999e4b1..a4df1b03f 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -249,7 +249,7 @@ class CacheBlk } } - req->setScResult(success ? 1 : 0); + req->setExtraData(success ? 1 : 0); clearLoadLocks(); return success; } else { diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index ff35a0749..dac2b93a4 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -206,7 +206,7 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat, // complete miss (no matching block) if (pkt->req->isLocked() && pkt->isWrite()) { // miss on store conditional... just give up now - pkt->req->setScResult(0); + pkt->req->setExtraData(0); pkt->flags |= SATISFIED; } } @@ -1147,7 +1147,7 @@ Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt) } if (pkt->isWrite() && (pkt->req->isLocked())) { - pkt->req->setScResult(1); + pkt->req->setExtraData(1); } myCache()->access(pkt); return true; diff --git a/src/mem/packet.cc b/src/mem/packet.cc index dde6c00d5..14d08db1b 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -94,7 +94,13 @@ MemCmd::commandInfo[] = ReadExResp, "ReadExReq" }, /* ReadExResp */ { SET4(IsRead, IsInvalidate, IsResponse, HasData), - InvalidCmd, "ReadExResp" } + InvalidCmd, "ReadExResp" }, + /* SwapReq -- for Swap ldstub type operations */ + { SET4(IsReadWrite, IsRequest, HasData, NeedsResponse), + SwapResp, "SwapReq" }, + /* SwapResp -- for Swap ldstub type operations */ + { SET3(IsReadWrite, IsResponse, HasData), + InvalidCmd, "SwapResp" } }; @@ -238,9 +244,11 @@ operator<<(std::ostream &o, const Packet &p) if (p.isRead()) o << "Read "; if (p.isWrite()) - o << "Read "; + o << "Write "; + if (p.isReadWrite()) + o << "Read/Write "; if (p.isInvalidate()) - o << "Read "; + o << "Invalidate "; if (p.isRequest()) o << "Request "; if (p.isResponse()) diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 65d2207db..16410594a 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -88,6 +88,8 @@ class MemCmd UpgradeReq, ReadExReq, ReadExResp, + SwapReq, + SwapResp, NUM_MEM_CMDS }; @@ -106,6 +108,7 @@ class MemCmd IsHWPrefetch, IsUpgrade, HasData, + IsReadWrite, NUM_COMMAND_ATTRIBUTES }; @@ -141,6 +144,7 @@ class MemCmd bool needsResponse() const { return testCmdAttrib(NeedsResponse); } bool isInvalidate() const { return testCmdAttrib(IsInvalidate); } bool hasData() const { return testCmdAttrib(HasData); } + bool isReadWrite() const { return testCmdAttrib(IsReadWrite); } const Command responseCommand() const { return commandInfo[cmd].response; @@ -300,6 +304,7 @@ class Packet bool needsResponse() const { return cmd.needsResponse(); } bool isInvalidate() const { return cmd.isInvalidate(); } bool hasData() const { return cmd.hasData(); } + bool isReadWrite() const { return cmd.isReadWrite(); } bool isCacheFill() const { return (flags & CACHE_LINE_FILL) != 0; } bool isNoAllocate() const { return (flags & NO_ALLOCATE) != 0; } diff --git a/src/mem/packet_access.hh b/src/mem/packet_access.hh index aac0c3ae5..882aa98d0 100644 --- a/src/mem/packet_access.hh +++ b/src/mem/packet_access.hh @@ -30,6 +30,7 @@ */ #include "arch/isa_traits.hh" +#include "base/bigint.hh" #include "mem/packet.hh" #include "sim/byteswap.hh" @@ -40,6 +41,19 @@ // these functions and make the users do their own byte swapping since // the memory system does not in fact have an endianness. +template<> +inline Twin64_t +Packet::get() +{ + Twin64_t d; + assert(staticData || dynamicData); + assert(sizeof(Twin64_t) <= size); + d.a = TheISA::gtoh(*(uint64_t*)data); + d.b = TheISA::gtoh(*((uint64_t*)data + 1)); + return d; +} + + /** return the value of what is pointed to in the packet. */ template <typename T> inline T diff --git a/src/mem/physical.cc b/src/mem/physical.cc index eccd42bec..381669d4d 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -92,7 +92,7 @@ Addr PhysicalMemory::new_page() { Addr return_addr = pagePtr << LogVMPageSize; - return_addr += params()->addrRange.start; + return_addr += start(); ++pagePtr; return return_addr; @@ -187,7 +187,7 @@ PhysicalMemory::checkLockedAddrList(Request *req) } if (isLocked) { - req->setScResult(success ? 1 : 0); + req->setExtraData(success ? 1 : 0); } return success; @@ -196,16 +196,14 @@ PhysicalMemory::checkLockedAddrList(Request *req) void PhysicalMemory::doFunctionalAccess(PacketPtr pkt) { - assert(pkt->getAddr() >= params()->addrRange.start && - pkt->getAddr() + pkt->getSize() <= params()->addrRange.start + - params()->addrRange.size()); + assert(pkt->getAddr() >= start() && + pkt->getAddr() + pkt->getSize() <= start() + size()); if (pkt->isRead()) { if (pkt->req->isLocked()) { trackLoadLocked(pkt->req); } - memcpy(pkt->getPtr<uint8_t>(), - pmemAddr + pkt->getAddr() - params()->addrRange.start, + memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(), pkt->getSize()); #if TRACING_ON switch (pkt->getSize()) { @@ -233,8 +231,8 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt) } else if (pkt->isWrite()) { if (writeOK(pkt->req)) { - memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, - pkt->getPtr<uint8_t>(), pkt->getSize()); + memcpy(pmemAddr + pkt->getAddr() - start(), pkt->getPtr<uint8_t>(), + pkt->getSize()); #if TRACING_ON switch (pkt->getSize()) { case sizeof(uint64_t): @@ -259,12 +257,77 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt) } #endif } - } - else if (pkt->isInvalidate()) { + } else if (pkt->isInvalidate()) { //upgrade or invalidate pkt->flags |= SATISFIED; - } - else { + } else if (pkt->isReadWrite()) { + IntReg overwrite_val; + bool overwrite_mem; + uint64_t condition_val64; + uint32_t condition_val32; + uint64_t test_val64; + uint32_t test_val32; + + assert(sizeof(IntReg) >= pkt->getSize()); + + overwrite_mem = true; + // keep a copy of our possible write value, and copy what is at the + // memory address into the packet + memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); + memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(), + pkt->getSize()); + + if (pkt->req->isCondSwap()) { + if (pkt->getSize() == sizeof(uint64_t)) { + condition_val64 = htog(pkt->req->getExtraData()); + memcpy(&test_val64, pmemAddr + pkt->getAddr() - start(), sizeof(uint64_t)); + overwrite_mem = test_val64 == condition_val64; + } else if (pkt->getSize() == sizeof(uint32_t)) { + condition_val32 = htog((uint32_t)pkt->req->getExtraData()); + memcpy(&test_val32, pmemAddr + pkt->getAddr() - start(), sizeof(uint32_t)); + overwrite_mem = test_val32 == condition_val32; + } else + panic("Invalid size for conditional read/write\n"); + } + + if (overwrite_mem) + memcpy(pmemAddr + pkt->getAddr() - start(), + &overwrite_val, pkt->getSize()); + +#if TRACING_ON + switch (pkt->getSize()) { + case sizeof(uint64_t): + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", + pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); + DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n", + overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't", + condition_val64, overwrite_mem ? "happened" : "didn't happen"); + break; + case sizeof(uint32_t): + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", + pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); + DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n", + overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't", + condition_val32, overwrite_mem ? "happened" : "didn't happen"); + break; + case sizeof(uint16_t): + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", + pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); + DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n", + overwrite_mem); + break; + case sizeof(uint8_t): + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", + pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); + DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n", + overwrite_mem); + break; + default: + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x\n", + pkt->getSize(), pkt->getAddr()); + } +#endif + } else { panic("unimplemented"); } @@ -315,7 +378,7 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) { snoop.clear(); resp.clear(); - resp.push_back(RangeSize(params()->addrRange.start, + resp.push_back(RangeSize(start(), params()->addrRange.size())); } diff --git a/src/mem/physical.hh b/src/mem/physical.hh index af88bcaa0..f7200b502 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -131,7 +131,7 @@ class PhysicalMemory : public MemObject // no locked addrs: nothing to check, store_conditional fails bool isLocked = req->isLocked(); if (isLocked) { - req->setScResult(0); + req->setExtraData(0); } return !isLocked; // only do write if not an sc } else { @@ -148,6 +148,7 @@ class PhysicalMemory : public MemObject public: Addr new_page(); uint64_t size() { return params()->addrRange.size(); } + uint64_t start() { return params()->addrRange.start; } struct Params { diff --git a/src/mem/request.hh b/src/mem/request.hh index de0512e1c..43d8ff1d5 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -71,6 +71,10 @@ const uint32_t EVICT_NEXT = 0x20000; const uint32_t NO_ALIGN_FAULT = 0x40000; /** The request was an instruction read. */ const uint32_t INST_READ = 0x80000; +/** This request is for a memory swap. */ +const uint32_t MEM_SWAP = 0x100000; +const uint32_t MEM_SWAP_COND = 0x200000; + class Request { @@ -104,8 +108,9 @@ class Request /** The virtual address of the request. */ Addr vaddr; - /** The return value of store conditional. */ - uint64_t scResult; + /** Extra data for the request, such as the return value of + * store conditional or the compare value for a CAS. */ + uint64_t extraData; /** The cpu number (for statistics, typically). */ int cpuNum; @@ -120,7 +125,7 @@ class Request /** Whether or not the asid & vaddr are valid. */ bool validAsidVaddr; /** Whether or not the sc result is valid. */ - bool validScResult; + bool validExData; /** Whether or not the cpu number & thread ID are valid. */ bool validCpuAndThreadNums; /** Whether or not the pc is valid. */ @@ -130,7 +135,7 @@ class Request /** Minimal constructor. No fields are initialized. */ Request() : validPaddr(false), validAsidVaddr(false), - validScResult(false), validCpuAndThreadNums(false), validPC(false) + validExData(false), validCpuAndThreadNums(false), validPC(false) {} /** @@ -169,7 +174,7 @@ class Request validPaddr = true; validAsidVaddr = false; validPC = false; - validScResult = false; + validExData = false; mmapedIpr = false; } @@ -187,7 +192,7 @@ class Request validPaddr = false; validAsidVaddr = true; validPC = true; - validScResult = false; + validExData = false; mmapedIpr = false; } @@ -237,12 +242,12 @@ class Request void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; } /** Accessor function to check if sc result is valid. */ - bool scResultValid() { return validScResult; } + bool extraDataValid() { return validExData; } /** Accessor function for store conditional return value.*/ - uint64_t getScResult() { assert(validScResult); return scResult; } + uint64_t getExtraData() { assert(validExData); return extraData; } /** Accessor function for store conditional return value.*/ - void setScResult(uint64_t _scResult) - { scResult = _scResult; validScResult = true; } + void setExtraData(uint64_t _extraData) + { extraData = _extraData; validExData = true; } /** Accessor function for cpu number.*/ int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; } @@ -259,6 +264,12 @@ class Request bool isLocked() { return (getFlags() & LOCKED) != 0; } + bool isSwap() { return (getFlags() & MEM_SWAP || + getFlags() & MEM_SWAP_COND); } + + bool isCondSwap() { return (getFlags() & MEM_SWAP_COND) != 0; } + + friend class Packet; }; |