X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fphysical.cc;h=0302f7351f9b31655a439aa62d51509ceac8eb09;hb=06482e6eeda9ba092c2fdc87217e391e64ff36a0;hp=8fea733ec37ef443cdf146aa701baa38478f04e6;hpb=8abab05c833bcba09ef0093a5fbfb77398c10bf3;p=gem5.git diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 8fea733ec..0302f7351 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -39,21 +39,17 @@ #include #include - +#include "arch/isa_traits.hh" #include "base/misc.hh" #include "config/full_system.hh" -#include "mem/packet_impl.hh" #include "mem/physical.hh" -#include "sim/host.hh" #include "sim/builder.hh" #include "sim/eventq.hh" -#include "arch/isa_traits.hh" - +#include "sim/host.hh" using namespace std; using namespace TheISA; - PhysicalMemory::PhysicalMemory(Params *p) : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p) { @@ -105,33 +101,121 @@ PhysicalMemory::deviceBlockSize() } Tick -PhysicalMemory::calculateLatency(Packet *pkt) +PhysicalMemory::calculateLatency(PacketPtr 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::doFunctionalAccess(Packet *pkt) +PhysicalMemory::trackLoadLocked(Request *req) { - assert(pkt->getAddr() + pkt->getSize() < params()->addrRange.size()); + 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::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)); +} + - switch (pkt->cmd) { - case Packet::ReadReq: +// 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::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(PacketPtr pkt) +{ + assert(pkt->getAddr() + pkt->getSize() <= params()->addrRange.size()); + + if (pkt->isRead()) { + if (pkt->req->isLocked()) { + trackLoadLocked(pkt->req); + } + DPRINTF(MemoryAccess, "Performing Read of size %i on address 0x%x\n", + pkt->getSize(), pkt->getAddr()); memcpy(pkt->getPtr(), pmemAddr + pkt->getAddr() - params()->addrRange.start, pkt->getSize()); - break; - case Packet::WriteReq: - memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, - pkt->getPtr(), - 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)) { + DPRINTF(MemoryAccess, "Performing Write of size %i on address 0x%x\n", + pkt->getSize(), pkt->getAddr()); + memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, + pkt->getPtr(), 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); @@ -193,14 +277,14 @@ PhysicalMemory::MemoryPort::deviceBlockSize() } Tick -PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt) +PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) { memory->doFunctionalAccess(pkt); return memory->calculateLatency(pkt); } void -PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt) +PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) { // Default implementation of SimpleTimingPort::recvFunctional() // calls recvAtomic() and throws away the latency; we can save a