summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/cache/cache_blk.hh2
-rw-r--r--src/mem/cache/cache_impl.hh4
-rw-r--r--src/mem/packet.cc14
-rw-r--r--src/mem/packet.hh5
-rw-r--r--src/mem/packet_access.hh14
-rw-r--r--src/mem/physical.cc91
-rw-r--r--src/mem/physical.hh3
-rw-r--r--src/mem/request.hh31
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;
};