Configs: Add support for the InOrder CPU model
[gem5.git] / src / mem / physical.cc
index 2742eca51a5c54b4c726dcae4c6d35ea90e73f9f..16ff3de6ddb49520dabe4e734950b662b891bc0c 100644 (file)
 
 #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");
@@ -68,10 +72,8 @@ PhysicalMemory::PhysicalMemory(Params *p)
     }
 
     //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
@@ -90,7 +92,7 @@ PhysicalMemory::init()
 PhysicalMemory::~PhysicalMemory()
 {
     if (pmemAddr)
-        munmap((char*)pmemAddr, params()->addrRange.size());
+        munmap((char*)pmemAddr, params()->range.size());
     //Remove memPorts?
 }
 
@@ -114,7 +116,10 @@ PhysicalMemory::deviceBlockSize()
 Tick
 PhysicalMemory::calculateLatency(PacketPtr pkt)
 {
-    return lat;
+    Tick latency = lat;
+    if (lat_var != 0)
+        latency += random_mt.random<Tick>(0, lat_var);
+    return latency;
 }
 
 
@@ -134,16 +139,16 @@ PhysicalMemory::trackLoadLocked(PacketPtr pkt)
 
     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));
 }
 
@@ -178,14 +183,14 @@ PhysicalMemory::checkLockedAddrList(PacketPtr pkt)
                 // 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 {
@@ -250,6 +255,8 @@ PhysicalMemory::doAtomicAccess(PacketPtr pkt)
         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;
@@ -280,11 +287,13 @@ PhysicalMemory::doAtomicAccess(PacketPtr pkt)
         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()) {
@@ -309,20 +318,31 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
     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->makeAtomicResponse();
 }
 
 
@@ -363,7 +383,7 @@ PhysicalMemory::recvStatusChange(Port::Status status)
 
 PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
                                        PhysicalMemory *_memory)
-    : SimpleTimingPort(_name), memory(_memory)
+    : SimpleTimingPort(_name, _memory), memory(_memory)
 { }
 
 void
@@ -384,7 +404,7 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop)
 {
     snoop = false;
     resp.clear();
-    resp.push_back(RangeSize(start(), params()->addrRange.size()));
+    resp.push_back(RangeSize(start(), params()->range.size()));
 }
 
 int
@@ -402,12 +422,16 @@ PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
 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
@@ -428,6 +452,9 @@ PhysicalMemory::drain(Event *de)
 void
 PhysicalMemory::serialize(ostream &os)
 {
+    if (!pmemAddr)
+        return;
+
     gzFile compressedMem;
     string filename = name() + ".physmem";
 
@@ -446,7 +473,8 @@ PhysicalMemory::serialize(ostream &os)
         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);
     }
@@ -459,6 +487,9 @@ PhysicalMemory::serialize(ostream &os)
 void
 PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
 {
+    if (!pmemAddr)
+        return;
+
     gzFile compressedMem;
     long *tempPage;
     long *pmem_current;
@@ -466,7 +497,6 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
     uint32_t bytesRead;
     const int chunkSize = 16384;
 
-
     string filename;
 
     UNSERIALIZE_SCALAR(filename);
@@ -488,10 +518,10 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
     // 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");
@@ -504,12 +534,14 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
         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);
 
@@ -531,33 +563,8 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
 
 }
 
-
-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)