* Andreas Hansson
*/
-#include "arch/registers.hh"
-#include "config/the_isa.hh"
+#include <vector>
+
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
#include "debug/LLSC.hh"
#include "debug/MemoryAccess.hh"
#include "mem/abstract_mem.hh"
confTableReported(p->conf_table_reported), inAddrMap(p->in_addr_map),
_system(NULL)
{
- if (size() % TheISA::PageBytes != 0)
+}
+
+void
+AbstractMemory::init()
+{
+ assert(system());
+
+ if (size() % _system->getPageBytes() != 0)
panic("Memory Size not divisible by page size\n");
}
if (i->addr == paddr) {
DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
i->contextId, paddr);
+ // For ARM, a spinlock would typically include a Wait
+ // For Event (WFE) to conserve energy. The ARMv8
+ // architecture specifies that an event is
+ // automatically generated when clearing the exclusive
+ // monitor to wake up the processor in WFE.
+ system()->getThreadContext(i->contextId)->getCpuPtr()->wakeup();
i = lockedAddrList.erase(i);
} else {
i++;
#if TRACING_ON
-#define CASE(A, T) \
- case sizeof(T): \
- DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \
- A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \
+#define CASE(A, T) \
+ case sizeof(T): \
+ DPRINTF(MemoryAccess,"%s from %s of size %i on address 0x%x data " \
+ "0x%x %c\n", A, system()->getMasterName(pkt->req->masterId()),\
+ pkt->getSize(), pkt->getAddr(), pkt->get<T>(), \
+ pkt->req->isUncacheable() ? 'U' : 'C'); \
break
CASE(A, uint16_t); \
CASE(A, uint8_t); \
default: \
- DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \
- A, pkt->getSize(), pkt->getAddr()); \
- DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
- } \
+ DPRINTF(MemoryAccess, "%s from %s of size %i on address 0x%x %c\n",\
+ A, system()->getMasterName(pkt->req->masterId()), \
+ pkt->getSize(), pkt->getAddr(), \
+ pkt->req->isUncacheable() ? 'U' : 'C'); \
+ DDUMP(MemoryAccess, pkt->getConstPtr<uint8_t>(), pkt->getSize()); \
+ } \
} while (0)
#else
void
AbstractMemory::access(PacketPtr pkt)
{
- assert(pkt->getAddr() >= range.start &&
- (pkt->getAddr() + pkt->getSize() - 1) <= range.end);
-
if (pkt->memInhibitAsserted()) {
DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
pkt->getAddr());
return;
}
- uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start;
+ if (pkt->cmd == MemCmd::CleanEvict) {
+ DPRINTF(MemoryAccess, "CleanEvict on 0x%x: not responding\n",
+ pkt->getAddr());
+ return;
+ }
+
+ assert(AddrRange(pkt->getAddr(),
+ pkt->getAddr() + (pkt->getSize() - 1)).isSubset(range));
+
+ uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start();
if (pkt->cmd == MemCmd::SwapReq) {
- TheISA::IntReg overwrite_val;
- bool overwrite_mem;
+ std::vector<uint8_t> 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)");
- assert(sizeof(TheISA::IntReg) >= pkt->getSize());
- overwrite_mem = true;
+ 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, pkt->getPtr<uint8_t>(), pkt->getSize());
+ std::memcpy(&overwrite_val[0], pkt->getConstPtr<uint8_t>(),
+ pkt->getSize());
std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
if (pkt->req->isCondSwap()) {
}
if (overwrite_mem)
- std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
+ std::memcpy(hostAddr, &overwrite_val[0], pkt->getSize());
assert(!pkt->req->isInstFetch());
TRACE_PACKET("Read/Write");
bytesRead[pkt->req->masterId()] += pkt->getSize();
if (pkt->req->isInstFetch())
bytesInstRead[pkt->req->masterId()] += pkt->getSize();
+ } else if (pkt->isInvalidate()) {
+ // no need to do anything
+ // this clause is intentionally before the write clause: the only
+ // transaction that is both a write and an invalidate is
+ // WriteInvalidate, and for the sake of consistency, it does not
+ // write to memory. in a cacheless system, there are no WriteInv's
+ // because the Write -> WriteInvalidate rewrite happens in the cache.
} else if (pkt->isWrite()) {
if (writeOK(pkt)) {
- if (pmemAddr)
- memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+ if (pmemAddr) {
+ memcpy(hostAddr, pkt->getConstPtr<uint8_t>(), pkt->getSize());
+ DPRINTF(MemoryAccess, "%s wrote %x bytes to address %x\n",
+ __func__, pkt->getSize(), pkt->getAddr());
+ }
assert(!pkt->req->isInstFetch());
TRACE_PACKET("Write");
numWrites[pkt->req->masterId()]++;
bytesWritten[pkt->req->masterId()] += pkt->getSize();
}
- } else if (pkt->isInvalidate()) {
- // no need to do anything
} else {
panic("unimplemented");
}
void
AbstractMemory::functionalAccess(PacketPtr pkt)
{
- assert(pkt->getAddr() >= range.start &&
- (pkt->getAddr() + pkt->getSize() - 1) <= range.end);
+ assert(AddrRange(pkt->getAddr(),
+ pkt->getAddr() + pkt->getSize() - 1).isSubset(range));
- uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start;
+ uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start();
if (pkt->isRead()) {
if (pmemAddr)
pkt->makeResponse();
} else if (pkt->isWrite()) {
if (pmemAddr)
- memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+ memcpy(hostAddr, pkt->getConstPtr<uint8_t>(), pkt->getSize());
TRACE_PACKET("Write");
pkt->makeResponse();
} else if (pkt->isPrint()) {