mem-cache: Add multiple eviction stats
[gem5.git] / src / arch / x86 / memhelpers.hh
index 64032732582e475bbd870366b079022510793e9f..424b729b63420500a91057bedab205311b864ec3 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2011 Google
+ * Copyright (c) 2015 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #ifndef __ARCH_X86_MEMHELPERS_HH__
 #define __ARCH_X86_MEMHELPERS_HH__
 
+#include <array>
+
 #include "base/types.hh"
+#include "cpu/exec_context.hh"
 #include "sim/byteswap.hh"
 #include "sim/insttracer.hh"
 
 namespace X86ISA
 {
 
-template <class XC>
-Fault
-readMemTiming(XC *xc, Trace::InstRecord *traceData, Addr addr,
-        uint64_t &mem, unsigned dataSize, unsigned flags)
+/// Initiate a read from memory in timing mode.
+static Fault
+initiateMemRead(ExecContext *xc, Trace::InstRecord *traceData, Addr addr,
+                unsigned dataSize, Request::Flags flags)
 {
-    return xc->readMem(addr, (uint8_t *)&mem, dataSize, flags);
+    return xc->initiateMemRead(addr, dataSize, flags);
 }
 
-static inline uint64_t
-getMem(PacketPtr pkt, unsigned dataSize, Trace::InstRecord *traceData)
+static void
+getMem(PacketPtr pkt, uint64_t &mem, unsigned dataSize,
+       Trace::InstRecord *traceData)
 {
-    uint64_t mem;
     switch (dataSize) {
       case 1:
-        mem = pkt->get<uint8_t>();
+        mem = pkt->getLE<uint8_t>();
         break;
       case 2:
-        mem = pkt->get<uint16_t>();
+        mem = pkt->getLE<uint16_t>();
         break;
       case 4:
-        mem = pkt->get<uint32_t>();
+        mem = pkt->getLE<uint32_t>();
         break;
       case 8:
-        mem = pkt->get<uint64_t>();
+        mem = pkt->getLE<uint64_t>();
         break;
       default:
         panic("Unhandled size in getMem.\n");
     }
     if (traceData)
         traceData->setData(mem);
-    return mem;
 }
 
-template <class XC>
-Fault
-readMemAtomic(XC *xc, Trace::InstRecord *traceData, Addr addr, uint64_t &mem,
-        unsigned dataSize, unsigned flags)
+template <typename T, size_t N>
+static void
+getPackedMem(PacketPtr pkt, std::array<uint64_t, N> &mem, unsigned dataSize)
+{
+    std::array<T, N> real_mem = pkt->getLE<std::array<T, N> >();
+    for (int i = 0; i < N; i++)
+        mem[i] = real_mem[i];
+}
+
+template <size_t N>
+static void
+getMem(PacketPtr pkt, std::array<uint64_t, N> &mem, unsigned dataSize,
+       Trace::InstRecord *traceData)
+{
+    switch (dataSize) {
+      case 4:
+        getPackedMem<uint32_t, N>(pkt, mem, dataSize);
+        break;
+      case 8:
+        getPackedMem<uint64_t, N>(pkt, mem, dataSize);
+        break;
+      default:
+        panic("Unhandled element size in getMem.\n");
+    }
+    if (traceData)
+        traceData->setData(mem[0]);
+}
+
+
+static Fault
+readMemAtomic(ExecContext *xc, Trace::InstRecord *traceData, Addr addr,
+              uint64_t &mem, unsigned dataSize, Request::Flags flags)
 {
     memset(&mem, 0, sizeof(mem));
     Fault fault = xc->readMem(addr, (uint8_t *)&mem, dataSize, flags);
@@ -82,39 +113,134 @@ readMemAtomic(XC *xc, Trace::InstRecord *traceData, Addr addr, uint64_t &mem,
         // If LE to LE, this is a nop, if LE to BE, the actual data ends up
         // in the right place because the LSBs where at the low addresses on
         // access. This doesn't work for BE guests.
-        mem = gtoh(mem);
+        mem = letoh(mem);
         if (traceData)
             traceData->setData(mem);
     }
     return fault;
 }
 
-template <class XC>
-Fault
-writeMemTiming(XC *xc, Trace::InstRecord *traceData, uint64_t mem,
-        unsigned dataSize, Addr addr, unsigned flags, uint64_t *res)
+template <typename T, size_t N>
+static Fault
+readPackedMemAtomic(ExecContext *xc, Addr addr, std::array<uint64_t, N> &mem,
+                    unsigned flags)
 {
-    if (traceData) {
-        traceData->setData(mem);
+    std::array<T, N> real_mem;
+    Fault fault = xc->readMem(addr, (uint8_t *)&real_mem,
+                              sizeof(T) * N, flags);
+    if (fault == NoFault) {
+        real_mem = letoh(real_mem);
+        for (int i = 0; i < N; i++)
+            mem[i] = real_mem[i];
     }
-    mem = TheISA::htog(mem);
-    return xc->writeMem((uint8_t *)&mem, dataSize, addr, flags, res);
+    return fault;
+}
+
+template <size_t N>
+static Fault
+readMemAtomic(ExecContext *xc, Trace::InstRecord *traceData, Addr addr,
+              std::array<uint64_t, N> &mem, unsigned dataSize,
+              unsigned flags)
+{
+    Fault fault = NoFault;
+
+    switch (dataSize) {
+      case 4:
+        fault = readPackedMemAtomic<uint32_t, N>(xc, addr, mem, flags);
+        break;
+      case 8:
+        fault = readPackedMemAtomic<uint64_t, N>(xc, addr, mem, flags);
+        break;
+      default:
+        panic("Unhandled element size in readMemAtomic\n");
+    }
+    if (fault == NoFault && traceData)
+        traceData->setData(mem[0]);
+    return fault;
 }
 
-template <class XC>
-Fault
-writeMemAtomic(XC *xc, Trace::InstRecord *traceData, uint64_t mem,
-        unsigned dataSize, Addr addr, unsigned flags, uint64_t *res)
+template <typename T, size_t N>
+static Fault
+writePackedMem(ExecContext *xc, std::array<uint64_t, N> &mem, Addr addr,
+               unsigned flags, uint64_t *res)
 {
-    if (traceData) {
+    std::array<T, N> real_mem;
+    for (int i = 0; i < N; i++)
+        real_mem[i] = mem[i];
+    real_mem = htole(real_mem);
+    return xc->writeMem((uint8_t *)&real_mem, sizeof(T) * N,
+                        addr, flags, res);
+}
+
+static Fault
+writeMemTiming(ExecContext *xc, Trace::InstRecord *traceData, uint64_t mem,
+               unsigned dataSize, Addr addr, Request::Flags flags,
+               uint64_t *res)
+{
+    if (traceData)
         traceData->setData(mem);
+    mem = htole(mem);
+    return xc->writeMem((uint8_t *)&mem, dataSize, addr, flags, res);
+}
+
+template <size_t N>
+static Fault
+writeMemTiming(ExecContext *xc, Trace::InstRecord *traceData,
+               std::array<uint64_t, N> &mem, unsigned dataSize,
+               Addr addr, unsigned flags, uint64_t *res)
+{
+    if (traceData)
+        traceData->setData(mem[0]);
+
+    switch (dataSize) {
+      case 4:
+        return writePackedMem<uint32_t, N>(xc, mem, addr, flags, res);
+      case 8:
+        return writePackedMem<uint64_t, N>(xc, mem, addr, flags, res);
+      default:
+        panic("Unhandled element size in writeMemTiming.\n");
     }
-    uint64_t host_mem = TheISA::htog(mem);
+}
+
+static Fault
+writeMemAtomic(ExecContext *xc, Trace::InstRecord *traceData, uint64_t mem,
+               unsigned dataSize, Addr addr, Request::Flags flags,
+               uint64_t *res)
+{
+    if (traceData)
+        traceData->setData(mem);
+    uint64_t host_mem = htole(mem);
     Fault fault =
           xc->writeMem((uint8_t *)&host_mem, dataSize, addr, flags, res);
-    if (fault == NoFault && res != NULL) {
-        *res = gtoh(*res);
+    if (fault == NoFault && res)
+        *res = letoh(*res);
+    return fault;
+}
+
+template <size_t N>
+static Fault
+writeMemAtomic(ExecContext *xc, Trace::InstRecord *traceData,
+               std::array<uint64_t, N> &mem, unsigned dataSize,
+               Addr addr, unsigned flags, uint64_t *res)
+{
+    if (traceData)
+        traceData->setData(mem[0]);
+
+    Fault fault;
+    switch (dataSize) {
+      case 4:
+        fault = writePackedMem<uint32_t, N>(xc, mem, addr, flags, res);
+        break;
+      case 8:
+        fault = writePackedMem<uint64_t, N>(xc, mem, addr, flags, res);
+        break;
+      default:
+        panic("Unhandled element size in writeMemAtomic.\n");
     }
+
+    if (fault == NoFault && res)
+        *res = letoh(*res);
+
     return fault;
 }