summaryrefslogtreecommitdiff
path: root/src/mem/physical.cc
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2006-10-09 22:59:56 -0400
committerKevin Lim <ktlim@umich.edu>2006-10-09 22:59:56 -0400
commitbdde892d668e17fb5a67de0e560a85b9092adf9e (patch)
tree3876a98dcd7f80aca7bf7e2153dbaa32c83a15b5 /src/mem/physical.cc
parenta9ae6c8656dc233996c81cdeb6f5c8539442af95 (diff)
parent5448517da4cd13e3c8438850f04367d9614d686b (diff)
downloadgem5-bdde892d668e17fb5a67de0e560a85b9092adf9e.tar.xz
Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/o3-merge/newmem src/cpu/memtest/memtest.cc: src/cpu/memtest/memtest.hh: src/cpu/simple/timing.hh: tests/configs/o3-timing-mp.py: Hand merge. --HG-- extra : convert_revision : a58cc439eb5e8f900d175ed8b5a85b6c8723e558
Diffstat (limited to 'src/mem/physical.cc')
-rw-r--r--src/mem/physical.cc112
1 files changed, 98 insertions, 14 deletions
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index 0580954de..7303f278e 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -110,28 +110,112 @@ PhysicalMemory::calculateLatency(Packet *pkt)
return lat;
}
+
+
+// Add load-locked to tracking list. Should only be called if the
+// operation is a load and the LOCKED flag is set.
+void
+PhysicalMemory::trackLoadLocked(Request *req)
+{
+ Addr paddr = LockedAddr::mask(req->getPaddr());
+
+ // first we check if we already have a locked addr for this
+ // xc. Since each xc only gets one, we just update the
+ // existing record with the new address.
+ list<LockedAddr>::iterator i;
+
+ for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
+ if (i->matchesContext(req)) {
+ DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n",
+ req->getCpuNum(), req->getThreadNum(), paddr);
+ i->addr = paddr;
+ return;
+ }
+ }
+
+ // no record for this xc: need to allocate a new one
+ DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n",
+ req->getCpuNum(), req->getThreadNum(), paddr);
+ lockedAddrList.push_front(LockedAddr(req));
+}
+
+
+// Called on *writes* only... both regular stores and
+// store-conditional operations. Check for conventional stores which
+// conflict with locked addresses, and for success/failure of store
+// conditionals.
+bool
+PhysicalMemory::checkLockedAddrList(Request *req)
+{
+ Addr paddr = LockedAddr::mask(req->getPaddr());
+ bool isLocked = req->isLocked();
+
+ // Initialize return value. Non-conditional stores always
+ // succeed. Assume conditional stores will fail until proven
+ // otherwise.
+ bool success = !isLocked;
+
+ // Iterate over list. Note that there could be multiple matching
+ // records, as more than one context could have done a load locked
+ // to this location.
+ list<LockedAddr>::iterator i = lockedAddrList.begin();
+
+ while (i != lockedAddrList.end()) {
+
+ if (i->addr == paddr) {
+ // we have a matching address
+
+ if (isLocked && i->matchesContext(req)) {
+ // it's a store conditional, and as far as the memory
+ // system can tell, the requesting context's lock is
+ // still valid.
+ DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n",
+ req->getCpuNum(), req->getThreadNum(), paddr);
+ success = true;
+ }
+
+ // Get rid of our record of this lock and advance to next
+ DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n",
+ i->cpuNum, i->threadNum, paddr);
+ i = lockedAddrList.erase(i);
+ }
+ else {
+ // no match: advance to next record
+ ++i;
+ }
+ }
+
+ if (isLocked) {
+ req->setScResult(success ? 1 : 0);
+ }
+
+ return success;
+}
+
void
PhysicalMemory::doFunctionalAccess(Packet *pkt)
{
assert(pkt->getAddr() + pkt->getSize() <= params()->addrRange.size());
- switch (pkt->cmd) {
- case Packet::ReadReq:
+ if (pkt->isRead()) {
+ if (pkt->req->isLocked()) {
+ trackLoadLocked(pkt->req);
+ }
memcpy(pkt->getPtr<uint8_t>(),
pmemAddr + pkt->getAddr() - params()->addrRange.start,
pkt->getSize());
- break;
- case Packet::WriteReq:
- memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
- pkt->getPtr<uint8_t>(),
- pkt->getSize());
- // temporary hack: will need to add real LL/SC implementation
- // for cacheless systems later.
- if (pkt->req->getFlags() & LOCKED) {
- pkt->req->setScResult(1);
+ }
+ else if (pkt->isWrite()) {
+ if (writeOK(pkt->req)) {
+ memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
+ pkt->getPtr<uint8_t>(), pkt->getSize());
}
- break;
- default:
+ }
+ else if (pkt->isInvalidate()) {
+ //upgrade or invalidate
+ pkt->flags |= SATISFIED;
+ }
+ else {
panic("unimplemented");
}
@@ -147,7 +231,7 @@ PhysicalMemory::getPort(const std::string &if_name, int idx)
port = new MemoryPort(name() + "-port", this);
return port;
} else if (if_name == "functional") {
- /* special port for functional writes at startup. */
+ /* special port for functional writes at startup. And for memtester */
return new MemoryPort(name() + "-funcport", this);
} else {
panic("PhysicalMemory::getPort: unknown port %s requested", if_name);