Modified to work with do_events
authorRon Dreslinski <rdreslin@umich.edu>
Tue, 14 Dec 2004 18:15:54 +0000 (13:15 -0500)
committerRon Dreslinski <rdreslin@umich.edu>
Tue, 14 Dec 2004 18:15:54 +0000 (13:15 -0500)
No multiple requests to the same block outstanding from the same tester
Using false sharing, each tester only access a single byte within the block based on which tester it is
Allow more cycles before signalling deadlock, with do_events it may take some time with NACK/retry and many proccessors

--HG--
extra : convert_revision : 4c8eab99082c53840a5ad2a926457dfc27f23b77

cpu/memtest/memtest.cc
cpu/memtest/memtest.hh

index 6584a62baf926828d5ae3c3b4c19ca450a3b76d6..e967c79da930ebcb3a99d0a971c46e183e39ebeb 100644 (file)
 
 // FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
 
-#include <string>
-#include <sstream>
 #include <iomanip>
+#include <set>
+#include <sstream>
+#include <string>
 #include <vector>
 
 #include "base/misc.hh"
@@ -44,6 +45,8 @@
 
 using namespace std;
 
+int TESTER_ALLOCATOR=0;
+
 MemTest::MemTest(const string &name,
                  MemInterface *_cache_interface,
                  FunctionalMemory *main_mem,
@@ -111,6 +114,8 @@ MemTest::MemTest(const string &name,
     noResponseCycles = 0;
     numReads = 0;
     tickEvent.schedule(0);
+
+    id = TESTER_ALLOCATOR++;
 }
 
 static void
@@ -127,6 +132,11 @@ printData(ostream &os, uint8_t *data, int nbytes)
 void
 MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
 {
+    //Remove the address from the list of outstanding
+    std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
+    assert(removeAddr != outstandingAddrs.end());
+    outstandingAddrs.erase(removeAddr);
+
     switch (req->cmd) {
       case Read:
         if (memcmp(req->data, data, req->size) != 0) {
@@ -158,6 +168,10 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
         break;
 
       case Copy:
+        //Also remove dest from outstanding list
+        removeAddr = outstandingAddrs.find(req->dest);
+        assert(removeAddr != outstandingAddrs.end());
+        outstandingAddrs.erase(removeAddr);
         numCopiesStat++;
         break;
 
@@ -212,7 +226,7 @@ MemTest::tick()
     if (!tickEvent.scheduled())
         tickEvent.schedule(curTick + 1);
 
-    if (++noResponseCycles >= 5000) {
+    if (++noResponseCycles >= 500000) {
         cerr << name() << ": deadlocked at cycle " << curTick << endl;
         fatal("");
     }
@@ -232,6 +246,16 @@ MemTest::tick()
     unsigned source_align = rand() % 100;
     unsigned dest_align = rand() % 100;
 
+    //If we aren't doing copies, use id as offset, and do a false sharing
+    //mem tester
+    if (percentCopies == 0) {
+        //We can eliminate the lower bits of the offset, and then use the id
+        //to offset within the blks
+        offset1 &= ~63; //Not the low order bits
+        offset1 += id;
+        access_size = 0;
+    }
+
     MemReqPtr req = new MemReq();
 
     if (cacheable < percentUncacheable) {
@@ -251,6 +275,13 @@ MemTest::tick()
 
     if (cmd < percentReads) {
         // read
+
+        //For now we only allow one outstanding request per addreess per tester
+        //This means we assume CPU does write forwarding to reads that alias something
+        //in the cpu store buffer.
+        if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
+        else outstandingAddrs.insert(req->paddr);
+
         req->cmd = Read;
         uint8_t *result = new uint8_t[8];
         checkMem->access(Read, req->paddr, result, req->size);
@@ -273,6 +304,13 @@ MemTest::tick()
         }
     } else if (cmd < (100 - percentCopies)){
         // write
+
+        //For now we only allow one outstanding request per addreess per tester
+        //This means we assume CPU does write forwarding to reads that alias something
+        //in the cpu store buffer.
+        if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
+        else outstandingAddrs.insert(req->paddr);
+
         req->cmd = Write;
         memcpy(req->data, &data, req->size);
         checkMem->access(Write, req->paddr, req->data, req->size);
@@ -298,6 +336,11 @@ MemTest::tick()
         // copy
         Addr source = ((base) ? baseAddr1 : baseAddr2) + offset1;
         Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
+        if (outstandingAddrs.find(source) != outstandingAddrs.end()) return;
+        else outstandingAddrs.insert(source);
+        if (outstandingAddrs.find(dest) != outstandingAddrs.end()) return;
+        else outstandingAddrs.insert(dest);
+
         if (source_align >= percentSourceUnaligned) {
             source = blockAddr(source);
         }
index 72e0709d978549acdf8cfffcd5cba0e10439ea6e..43b17a713960b161f632c157c7013d3afcc2869e 100644 (file)
 #ifndef __MEMTEST_HH__
 #define __MEMTEST_HH__
 
-#include "sim/sim_object.hh"
-#include "mem/mem_interface.hh"
-#include "mem/functional_mem/functional_memory.hh"
-#include "cpu/base_cpu.hh"
-#include "cpu/exec_context.hh"
+#include <set>
 
 #include "base/statistics.hh"
+#include "cpu/base_cpu.hh"
+#include "cpu/exec_context.hh"
+#include "mem/functional_mem/functional_memory.hh"
+#include "mem/mem_interface.hh"
+#include "sim/sim_object.hh"
 #include "sim/stats.hh"
 
 class MemTest : public BaseCPU
@@ -87,6 +88,10 @@ class MemTest : public BaseCPU
     unsigned percentCopies;    // target percentage of copy accesses
     unsigned percentUncacheable;
 
+    int id;
+
+    std::set<unsigned> outstandingAddrs;
+
     unsigned blockSize;
 
     Addr blockAddrMask;