#include "arch/isa_traits.hh"
#include "base/misc.hh"
+#include "base/random.hh"
#include "config/full_system.hh"
#include "mem/packet_access.hh"
#include "mem/physical.hh"
-#include "sim/builder.hh"
#include "sim/eventq.hh"
#include "sim/host.hh"
using namespace std;
using namespace TheISA;
-PhysicalMemory::PhysicalMemory(Params *p)
- : MemObject(p->name), pmemAddr(NULL), lat(p->latency), _params(p)
+PhysicalMemory::PhysicalMemory(const Params *p)
+ : MemObject(p), pmemAddr(NULL), pagePtr(0),
+ lat(p->latency), lat_var(p->latency_var),
+ cachedSize(params()->range.size()), cachedStart(params()->range.start)
{
- if (params()->addrRange.size() % TheISA::PageBytes != 0)
+ if (params()->range.size() % TheISA::PageBytes != 0)
panic("Memory Size not divisible by page size\n");
+ if (params()->null)
+ return;
+
int map_flags = MAP_ANON | MAP_PRIVATE;
- pmemAddr =
- (uint8_t *)mmap(NULL, params()->addrRange.size(),
- PROT_READ | PROT_WRITE, map_flags, -1, 0);
+ pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(),
+ PROT_READ | PROT_WRITE, map_flags, -1, 0);
if (pmemAddr == (void *)MAP_FAILED) {
perror("mmap");
}
//If requested, initialize all the memory to 0
- if(params()->zero)
- memset(pmemAddr, 0, params()->addrRange.size());
-
- pagePtr = 0;
+ if (p->zero)
+ memset(pmemAddr, 0, p->range.size());
}
void
PhysicalMemory::~PhysicalMemory()
{
if (pmemAddr)
- munmap((char*)pmemAddr, params()->addrRange.size());
+ munmap((char*)pmemAddr, params()->range.size());
//Remove memPorts?
}
Tick
PhysicalMemory::calculateLatency(PacketPtr pkt)
{
- return lat;
+ Tick latency = lat;
+ if (lat_var != 0)
+ latency += random_mt.random<Tick>(0, lat_var);
+ return latency;
}
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);
+ DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n",
+ req->contextId(), 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);
+ DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n",
+ req->contextId(), paddr);
lockedAddrList.push_front(LockedAddr(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);
+ DPRINTF(LLSC, "StCond success: context %d addr %#x\n",
+ req->contextId(), 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);
+ DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
+ i->contextId, paddr);
i = lockedAddrList.erase(i);
}
else {
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(IntReg) >= pkt->getSize());
overwrite_mem = true;
if (pkt->isLocked()) {
trackLoadLocked(pkt);
}
- memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+ if (pmemAddr)
+ memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
TRACE_PACKET("Read");
} else if (pkt->isWrite()) {
if (writeOK(pkt)) {
- memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+ if (pmemAddr)
+ memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
TRACE_PACKET("Write");
}
} else if (pkt->isInvalidate()) {
assert(pkt->getAddr() >= start() &&
pkt->getAddr() + pkt->getSize() <= start() + size());
+
uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
- if (pkt->cmd == MemCmd::ReadReq) {
- memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+ if (pkt->isRead()) {
+ if (pmemAddr)
+ memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
TRACE_PACKET("Read");
- } else if (pkt->cmd == MemCmd::WriteReq) {
- memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+ pkt->makeAtomicResponse();
+ } else if (pkt->isWrite()) {
+ if (pmemAddr)
+ memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
TRACE_PACKET("Write");
+ pkt->makeAtomicResponse();
+ } else if (pkt->isPrint()) {
+ Packet::PrintReqState *prs =
+ dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
+ // Need to call printLabels() explicitly since we're not going
+ // through printObj().
+ prs->printLabels();
+ // Right now we just print the single byte at the specified address.
+ ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
} else {
panic("PhysicalMemory: unimplemented functional command %s",
pkt->cmdString());
}
-
- pkt->result = Packet::Success;
}
PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
PhysicalMemory *_memory)
- : SimpleTimingPort(_name), memory(_memory)
+ : SimpleTimingPort(_name, _memory), memory(_memory)
{ }
void
{
snoop = false;
resp.clear();
- resp.push_back(RangeSize(start(), params()->addrRange.size()));
+ resp.push_back(RangeSize(start(), params()->range.size()));
}
int
void
PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
{
- checkFunctional(pkt);
+ pkt->pushLabel(memory->name());
+
+ if (!checkFunctional(pkt)) {
+ // Default implementation of SimpleTimingPort::recvFunctional()
+ // calls recvAtomic() and throws away the latency; we can save a
+ // little here by just not calculating the latency.
+ memory->doFunctionalAccess(pkt);
+ }
- // Default implementation of SimpleTimingPort::recvFunctional()
- // calls recvAtomic() and throws away the latency; we can save a
- // little here by just not calculating the latency.
- memory->doFunctionalAccess(pkt);
+ pkt->popLabel();
}
unsigned int
void
PhysicalMemory::serialize(ostream &os)
{
+ if (!pmemAddr)
+ return;
+
gzFile compressedMem;
string filename = name() + ".physmem";
fatal("Insufficient memory to allocate compression state for %s\n",
filename);
- if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) {
+ if (gzwrite(compressedMem, pmemAddr, params()->range.size()) !=
+ params()->range.size()) {
fatal("Write failed on physical memory checkpoint file '%s'\n",
filename);
}
void
PhysicalMemory::unserialize(Checkpoint *cp, const string §ion)
{
+ if (!pmemAddr)
+ return;
+
gzFile compressedMem;
long *tempPage;
long *pmem_current;
uint32_t bytesRead;
const int chunkSize = 16384;
-
string filename;
UNSERIALIZE_SCALAR(filename);
// unmap file that was mmaped in the constructor
// This is done here to make sure that gzip and open don't muck with our
// nice large space of memory before we reallocate it
- munmap((char*)pmemAddr, params()->addrRange.size());
+ munmap((char*)pmemAddr, params()->range.size());
- pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
+ pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(),
+ PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
if (pmemAddr == (void *)MAP_FAILED) {
perror("mmap");
fatal("Unable to malloc memory to read file %s\n", filename);
/* Only copy bytes that are non-zero, so we don't give the VM system hell */
- while (curSize < params()->addrRange.size()) {
+ while (curSize < params()->range.size()) {
bytesRead = gzread(compressedMem, tempPage, chunkSize);
- if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize)
+ if (bytesRead != chunkSize &&
+ bytesRead != params()->range.size() - curSize)
fatal("Read failed on physical memory checkpoint file '%s'"
" got %d bytes, expected %d or %d bytes\n",
- filename, bytesRead, chunkSize, params()->addrRange.size()-curSize);
+ filename, bytesRead, chunkSize,
+ params()->range.size() - curSize);
assert(bytesRead % sizeof(long) == 0);
}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
-
- Param<string> file;
- Param<Range<Addr> > range;
- Param<Tick> latency;
- Param<bool> zero;
-
-END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
-
- INIT_PARAM_DFLT(file, "memory mapped file", ""),
- INIT_PARAM(range, "Device Address Range"),
- INIT_PARAM(latency, "Memory access latency"),
- INIT_PARAM(zero, "Zero initialize memory")
-
-END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
-
-CREATE_SIM_OBJECT(PhysicalMemory)
+PhysicalMemory *
+PhysicalMemoryParams::create()
{
- PhysicalMemory::Params *p = new PhysicalMemory::Params;
- p->name = getInstanceName();
- p->addrRange = range;
- p->latency = latency;
- p->zero = zero;
- return new PhysicalMemory(p);
+ return new PhysicalMemory(this);
}
-
-REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)