memtest.cc revision 4203
16167SN/A/*
26167SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
310526Snilay@cs.wisc.edu * All rights reserved.
410892Sandreas.hansson@arm.com *
510892Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68673SN/A * modification, are permitted provided that the following conditions are
710892Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
810892Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
910892Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
1010892Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
1110628Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
129150SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
139583Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from
1410036SAli.Saidi@ARM.com * this software without specific prior written permission.
1510036SAli.Saidi@ARM.com *
1610526Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710526Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810526Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910526Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010526Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110526Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210526Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310526Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410892Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510892Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610892Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710892Sandreas.hansson@arm.com *
2810892Sandreas.hansson@arm.com * Authors: Erik Hallnor
2910892Sandreas.hansson@arm.com *          Steve Reinhardt
3010526Snilay@cs.wisc.edu */
3110526Snilay@cs.wisc.edu
3210526Snilay@cs.wisc.edu// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
3310526Snilay@cs.wisc.edu
3410892Sandreas.hansson@arm.com#include <iomanip>
3510892Sandreas.hansson@arm.com#include <set>
3610892Sandreas.hansson@arm.com#include <string>
3710526Snilay@cs.wisc.edu#include <vector>
3810526Snilay@cs.wisc.edu
3910892Sandreas.hansson@arm.com#include "base/misc.hh"
4010892Sandreas.hansson@arm.com#include "base/statistics.hh"
4110526Snilay@cs.wisc.edu#include "cpu/memtest/memtest.hh"
4210892Sandreas.hansson@arm.com//#include "cpu/simple_thread.hh"
4310526Snilay@cs.wisc.edu//#include "mem/cache/base_cache.hh"
4410526Snilay@cs.wisc.edu#include "mem/mem_object.hh"
4510892Sandreas.hansson@arm.com#include "mem/port.hh"
4610892Sandreas.hansson@arm.com#include "mem/packet.hh"
4710892Sandreas.hansson@arm.com//#include "mem/physical.hh"
4810892Sandreas.hansson@arm.com#include "mem/request.hh"
4910892Sandreas.hansson@arm.com#include "sim/builder.hh"
5010892Sandreas.hansson@arm.com#include "sim/sim_events.hh"
5110892Sandreas.hansson@arm.com#include "sim/stats.hh"
5210892Sandreas.hansson@arm.com
5310892Sandreas.hansson@arm.comusing namespace std;
5410526Snilay@cs.wisc.edu
5510892Sandreas.hansson@arm.comint TESTER_ALLOCATOR=0;
5610892Sandreas.hansson@arm.com
5710892Sandreas.hansson@arm.combool
5810526Snilay@cs.wisc.eduMemTest::CpuPort::recvTiming(PacketPtr pkt)
5910526Snilay@cs.wisc.edu{
6010526Snilay@cs.wisc.edu    memtest->completeRequest(pkt);
6110892Sandreas.hansson@arm.com    return true;
6210892Sandreas.hansson@arm.com}
6310892Sandreas.hansson@arm.com
6410892Sandreas.hansson@arm.comTick
6510892Sandreas.hansson@arm.comMemTest::CpuPort::recvAtomic(PacketPtr pkt)
6610892Sandreas.hansson@arm.com{
6710892Sandreas.hansson@arm.com    panic("MemTest doesn't expect recvAtomic callback!");
6810526Snilay@cs.wisc.edu    return curTick;
6910892Sandreas.hansson@arm.com}
7010526Snilay@cs.wisc.edu
7110892Sandreas.hansson@arm.comvoid
7210892Sandreas.hansson@arm.comMemTest::CpuPort::recvFunctional(PacketPtr pkt)
7310892Sandreas.hansson@arm.com{
7410526Snilay@cs.wisc.edu    //Do nothing if we see one come through
7510526Snilay@cs.wisc.edu//    if (curTick != 0)//Supress warning durring initialization
7610892Sandreas.hansson@arm.com//        warn("Functional Writes not implemented in MemTester\n");
7710526Snilay@cs.wisc.edu    //Need to find any response values that intersect and update
7810526Snilay@cs.wisc.edu    return;
7910526Snilay@cs.wisc.edu}
8010526Snilay@cs.wisc.edu
8110526Snilay@cs.wisc.eduvoid
8210526Snilay@cs.wisc.eduMemTest::CpuPort::recvStatusChange(Status status)
8310526Snilay@cs.wisc.edu{
8410526Snilay@cs.wisc.edu    if (status == RangeChange) {
8510526Snilay@cs.wisc.edu        if (!snoopRangeSent) {
8610526Snilay@cs.wisc.edu            snoopRangeSent = true;
8710526Snilay@cs.wisc.edu            sendStatusChange(Port::RangeChange);
8810526Snilay@cs.wisc.edu        }
8910526Snilay@cs.wisc.edu        return;
9010526Snilay@cs.wisc.edu    }
9110892Sandreas.hansson@arm.com
9210526Snilay@cs.wisc.edu    panic("MemTest doesn't expect recvStatusChange callback!");
9310526Snilay@cs.wisc.edu}
9410526Snilay@cs.wisc.edu
9510526Snilay@cs.wisc.eduvoid
9610526Snilay@cs.wisc.eduMemTest::CpuPort::recvRetry()
9710526Snilay@cs.wisc.edu{
9810526Snilay@cs.wisc.edu    memtest->doRetry();
9910526Snilay@cs.wisc.edu}
10010526Snilay@cs.wisc.edu
10110526Snilay@cs.wisc.eduvoid
10210526Snilay@cs.wisc.eduMemTest::sendPkt(PacketPtr pkt) {
10310526Snilay@cs.wisc.edu    if (atomic) {
10410526Snilay@cs.wisc.edu        cachePort.sendAtomic(pkt);
10510526Snilay@cs.wisc.edu        pkt->makeAtomicResponse();
10610526Snilay@cs.wisc.edu        completeRequest(pkt);
10710526Snilay@cs.wisc.edu    }
10810526Snilay@cs.wisc.edu    else if (!cachePort.sendTiming(pkt)) {
10910526Snilay@cs.wisc.edu        accessRetry = true;
11010526Snilay@cs.wisc.edu        retryPkt = pkt;
11110526Snilay@cs.wisc.edu    }
11210526Snilay@cs.wisc.edu
11310526Snilay@cs.wisc.edu}
11410526Snilay@cs.wisc.edu
11510526Snilay@cs.wisc.eduMemTest::MemTest(const string &name,
11610526Snilay@cs.wisc.edu//		 MemInterface *_cache_interface,
11710526Snilay@cs.wisc.edu//		 PhysicalMemory *main_mem,
11810526Snilay@cs.wisc.edu//		 PhysicalMemory *check_mem,
11910526Snilay@cs.wisc.edu                 unsigned _memorySize,
12010526Snilay@cs.wisc.edu                 unsigned _percentReads,
12110526Snilay@cs.wisc.edu                 unsigned _percentFunctional,
12210526Snilay@cs.wisc.edu                 unsigned _percentUncacheable,
12310526Snilay@cs.wisc.edu                 unsigned _progressInterval,
12410526Snilay@cs.wisc.edu                 unsigned _percentSourceUnaligned,
12510526Snilay@cs.wisc.edu                 unsigned _percentDestUnaligned,
12610526Snilay@cs.wisc.edu                 Addr _traceAddr,
12710526Snilay@cs.wisc.edu                 Counter _max_loads,
12810526Snilay@cs.wisc.edu                 bool _atomic)
12910526Snilay@cs.wisc.edu    : MemObject(name),
13010526Snilay@cs.wisc.edu      tickEvent(this),
13110526Snilay@cs.wisc.edu      cachePort("test", this),
13210526Snilay@cs.wisc.edu      funcPort("functional", this),
13310526Snilay@cs.wisc.edu      retryPkt(NULL),
13410526Snilay@cs.wisc.edu//      mainMem(main_mem),
13510526Snilay@cs.wisc.edu//      checkMem(check_mem),
13610526Snilay@cs.wisc.edu      size(_memorySize),
13710526Snilay@cs.wisc.edu      percentReads(_percentReads),
13810892Sandreas.hansson@arm.com      percentFunctional(_percentFunctional),
13910892Sandreas.hansson@arm.com      percentUncacheable(_percentUncacheable),
14010892Sandreas.hansson@arm.com      progressInterval(_progressInterval),
14110892Sandreas.hansson@arm.com      nextProgressMessage(_progressInterval),
14210892Sandreas.hansson@arm.com      percentSourceUnaligned(_percentSourceUnaligned),
14310892Sandreas.hansson@arm.com      percentDestUnaligned(percentDestUnaligned),
14410892Sandreas.hansson@arm.com      maxLoads(_max_loads),
14510892Sandreas.hansson@arm.com      atomic(_atomic)
14610526Snilay@cs.wisc.edu{
14710526Snilay@cs.wisc.edu    vector<string> cmd;
14810526Snilay@cs.wisc.edu    cmd.push_back("/bin/ls");
14910526Snilay@cs.wisc.edu    vector<string> null_vec;
15010526Snilay@cs.wisc.edu    //  thread = new SimpleThread(NULL, 0, NULL, 0, mainMem);
15110526Snilay@cs.wisc.edu    curTick = 0;
15210526Snilay@cs.wisc.edu
15310526Snilay@cs.wisc.edu    cachePort.snoopRangeSent = false;
15410526Snilay@cs.wisc.edu    funcPort.snoopRangeSent = true;
15510526Snilay@cs.wisc.edu
15610526Snilay@cs.wisc.edu    // Needs to be masked off once we know the block size.
15710526Snilay@cs.wisc.edu    traceBlockAddr = _traceAddr;
15810526Snilay@cs.wisc.edu    baseAddr1 = 0x100000;
15910526Snilay@cs.wisc.edu    baseAddr2 = 0x400000;
16010526Snilay@cs.wisc.edu    uncacheAddr = 0x800000;
16110526Snilay@cs.wisc.edu
16210526Snilay@cs.wisc.edu    // set up counters
16310526Snilay@cs.wisc.edu    noResponseCycles = 0;
16410526Snilay@cs.wisc.edu    numReads = 0;
16510526Snilay@cs.wisc.edu    tickEvent.schedule(0);
16610526Snilay@cs.wisc.edu
16710526Snilay@cs.wisc.edu    id = TESTER_ALLOCATOR++;
16810526Snilay@cs.wisc.edu    if (TESTER_ALLOCATOR > 8)
16910526Snilay@cs.wisc.edu        panic("False sharing memtester only allows up to 8 testers");
17010526Snilay@cs.wisc.edu
17110526Snilay@cs.wisc.edu    accessRetry = false;
17210526Snilay@cs.wisc.edu}
17310526Snilay@cs.wisc.edu
17410526Snilay@cs.wisc.eduPort *
17510526Snilay@cs.wisc.eduMemTest::getPort(const std::string &if_name, int idx)
17610526Snilay@cs.wisc.edu{
17710526Snilay@cs.wisc.edu    if (if_name == "functional")
17810526Snilay@cs.wisc.edu        return &funcPort;
17910526Snilay@cs.wisc.edu    else if (if_name == "test")
18010526Snilay@cs.wisc.edu        return &cachePort;
18110526Snilay@cs.wisc.edu    else
18210526Snilay@cs.wisc.edu        panic("No Such Port\n");
18310526Snilay@cs.wisc.edu}
18410526Snilay@cs.wisc.edu
18510526Snilay@cs.wisc.eduvoid
18610526Snilay@cs.wisc.eduMemTest::init()
18710892Sandreas.hansson@arm.com{
18810892Sandreas.hansson@arm.com    // By the time init() is called, the ports should be hooked up.
18910892Sandreas.hansson@arm.com    blockSize = cachePort.peerBlockSize();
19010892Sandreas.hansson@arm.com    blockAddrMask = blockSize - 1;
19110892Sandreas.hansson@arm.com    traceBlockAddr = blockAddr(traceBlockAddr);
19210892Sandreas.hansson@arm.com
19310892Sandreas.hansson@arm.com    // set up intial memory contents here
19410892Sandreas.hansson@arm.com
19510892Sandreas.hansson@arm.com    cachePort.memsetBlob(baseAddr1, 1, size);
19610892Sandreas.hansson@arm.com    funcPort.memsetBlob(baseAddr1, 1, size);
19710892Sandreas.hansson@arm.com    cachePort.memsetBlob(baseAddr2, 2, size);
19810892Sandreas.hansson@arm.com    funcPort.memsetBlob(baseAddr2, 2, size);
19910892Sandreas.hansson@arm.com    cachePort.memsetBlob(uncacheAddr, 3, size);
20010892Sandreas.hansson@arm.com    funcPort.memsetBlob(uncacheAddr, 3, size);
20110526Snilay@cs.wisc.edu}
20210892Sandreas.hansson@arm.com
20310892Sandreas.hansson@arm.comstatic void
20410892Sandreas.hansson@arm.comprintData(ostream &os, uint8_t *data, int nbytes)
20510892Sandreas.hansson@arm.com{
20610892Sandreas.hansson@arm.com    os << hex << setfill('0');
20710892Sandreas.hansson@arm.com    // assume little-endian: print bytes from highest address to lowest
20810892Sandreas.hansson@arm.com    for (uint8_t *dp = data + nbytes - 1; dp >= data; --dp) {
20910526Snilay@cs.wisc.edu        os << setw(2) << (unsigned)*dp;
21010526Snilay@cs.wisc.edu    }
21110526Snilay@cs.wisc.edu    os << dec;
21210892Sandreas.hansson@arm.com}
21310892Sandreas.hansson@arm.com
21410892Sandreas.hansson@arm.comvoid
21510892Sandreas.hansson@arm.comMemTest::completeRequest(PacketPtr pkt)
21610892Sandreas.hansson@arm.com{
21710892Sandreas.hansson@arm.com    MemTestSenderState *state =
21810892Sandreas.hansson@arm.com        dynamic_cast<MemTestSenderState *>(pkt->senderState);
21910526Snilay@cs.wisc.edu
22010892Sandreas.hansson@arm.com    uint8_t *data = state->data;
22110892Sandreas.hansson@arm.com    uint8_t *pkt_data = pkt->getPtr<uint8_t>();
22210892Sandreas.hansson@arm.com    Request *req = pkt->req;
22310892Sandreas.hansson@arm.com
22410526Snilay@cs.wisc.edu    //Remove the address from the list of outstanding
22510892Sandreas.hansson@arm.com    std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->getPaddr());
22610892Sandreas.hansson@arm.com    assert(removeAddr != outstandingAddrs.end());
22710892Sandreas.hansson@arm.com    outstandingAddrs.erase(removeAddr);
22810892Sandreas.hansson@arm.com
22910892Sandreas.hansson@arm.com    switch (pkt->cmd.toInt()) {
23010526Snilay@cs.wisc.edu      case MemCmd::ReadResp:
23110892Sandreas.hansson@arm.com
23210892Sandreas.hansson@arm.com        if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
23310892Sandreas.hansson@arm.com            cerr << name() << ": on read of 0x" << hex << req->getPaddr()
23410526Snilay@cs.wisc.edu                 << " (0x" << hex << blockAddr(req->getPaddr()) << ")"
23510892Sandreas.hansson@arm.com                 << "@ cycle " << dec << curTick
23610892Sandreas.hansson@arm.com                 << ", cache returns 0x";
23710892Sandreas.hansson@arm.com            printData(cerr, pkt_data, pkt->getSize());
23810892Sandreas.hansson@arm.com            cerr << ", expected 0x";
23910892Sandreas.hansson@arm.com            printData(cerr, data, pkt->getSize());
24010526Snilay@cs.wisc.edu            cerr << endl;
24110892Sandreas.hansson@arm.com            fatal("");
24210892Sandreas.hansson@arm.com        }
24310892Sandreas.hansson@arm.com
24410892Sandreas.hansson@arm.com        numReads++;
24510892Sandreas.hansson@arm.com        numReadsStat++;
24610628Sandreas.hansson@arm.com
24710892Sandreas.hansson@arm.com        if (numReads == nextProgressMessage) {
24810892Sandreas.hansson@arm.com            ccprintf(cerr, "%s: completed %d read accesses @%d\n",
24910892Sandreas.hansson@arm.com                     name(), numReads, curTick);
25010892Sandreas.hansson@arm.com            nextProgressMessage += progressInterval;
25110892Sandreas.hansson@arm.com        }
25210628Sandreas.hansson@arm.com
25310628Sandreas.hansson@arm.com        if (numReads >= maxLoads)
25410892Sandreas.hansson@arm.com            exitSimLoop("Maximum number of loads reached!");
25510628Sandreas.hansson@arm.com        break;
25610892Sandreas.hansson@arm.com
25710892Sandreas.hansson@arm.com      case MemCmd::WriteResp:
25810892Sandreas.hansson@arm.com        numWritesStat++;
25910892Sandreas.hansson@arm.com        break;
26010628Sandreas.hansson@arm.com/*
26110892Sandreas.hansson@arm.com      case Copy:
26210892Sandreas.hansson@arm.com        //Also remove dest from outstanding list
26310892Sandreas.hansson@arm.com        removeAddr = outstandingAddrs.find(req->dest);
26410892Sandreas.hansson@arm.com        assert(removeAddr != outstandingAddrs.end());
26510892Sandreas.hansson@arm.com        outstandingAddrs.erase(removeAddr);
26610628Sandreas.hansson@arm.com        numCopiesStat++;
26710628Sandreas.hansson@arm.com        break;
26810892Sandreas.hansson@arm.com*/
26910628Sandreas.hansson@arm.com      default:
27010526Snilay@cs.wisc.edu        panic("invalid command");
27110036SAli.Saidi@ARM.com    }
2728673SN/A
27310892Sandreas.hansson@arm.com    if (blockAddr(req->getPaddr()) == traceBlockAddr) {
2748673SN/A        cerr << name() << ": completed "
2757935SN/A             << (pkt->isWrite() ? "write" : "read")
2769150SAli.Saidi@ARM.com             << " access of "
2779583Snilay@cs.wisc.edu             << dec << pkt->getSize() << " bytes at address 0x"
2789924Ssteve.reinhardt@amd.com             << hex << req->getPaddr()
2798673SN/A             << " (0x" << hex << blockAddr(req->getPaddr()) << ")"
2809702Snilay@cs.wisc.edu             << ", value = 0x";
2819150SAli.Saidi@ARM.com        printData(cerr, pkt_data, pkt->getSize());
2829924Ssteve.reinhardt@amd.com        cerr << " @ cycle " << dec << curTick;
2837935SN/A
2849924Ssteve.reinhardt@amd.com        cerr << endl;
2859924Ssteve.reinhardt@amd.com    }
2867935SN/A
2877935SN/A    noResponseCycles = 0;
2889924Ssteve.reinhardt@amd.com    delete state;
2899924Ssteve.reinhardt@amd.com    delete [] data;
2909583Snilay@cs.wisc.edu    delete pkt->req;
2919583Snilay@cs.wisc.edu    delete pkt;
2929373Snilay@cs.wisc.edu}
29310526Snilay@cs.wisc.edu
29410892Sandreas.hansson@arm.comvoid
29510526Snilay@cs.wisc.eduMemTest::regStats()
29610526Snilay@cs.wisc.edu{
29710063Snilay@cs.wisc.edu    using namespace Stats;
29810220Sandreas.hansson@arm.com
29910220Sandreas.hansson@arm.com    numReadsStat
30010220Sandreas.hansson@arm.com        .name(name() + ".num_reads")
30110220Sandreas.hansson@arm.com        .desc("number of read accesses completed")
30210220Sandreas.hansson@arm.com        ;
30310220Sandreas.hansson@arm.com
30410220Sandreas.hansson@arm.com    numWritesStat
30510220Sandreas.hansson@arm.com        .name(name() + ".num_writes")
30610220Sandreas.hansson@arm.com        .desc("number of write accesses completed")
30710220Sandreas.hansson@arm.com        ;
30810220Sandreas.hansson@arm.com
30910220Sandreas.hansson@arm.com    numCopiesStat
31010220Sandreas.hansson@arm.com        .name(name() + ".num_copies")
31110220Sandreas.hansson@arm.com        .desc("number of copy accesses completed")
31210220Sandreas.hansson@arm.com        ;
31310220Sandreas.hansson@arm.com}
31410220Sandreas.hansson@arm.com
31510220Sandreas.hansson@arm.comvoid
31610220Sandreas.hansson@arm.comMemTest::tick()
31710220Sandreas.hansson@arm.com{
31810220Sandreas.hansson@arm.com    if (!tickEvent.scheduled())
31910220Sandreas.hansson@arm.com        tickEvent.schedule(curTick + cycles(1));
32010220Sandreas.hansson@arm.com
32110220Sandreas.hansson@arm.com    if (++noResponseCycles >= 500000) {
32210220Sandreas.hansson@arm.com        cerr << name() << ": deadlocked at cycle " << curTick << endl;
32310220Sandreas.hansson@arm.com        fatal("");
32410220Sandreas.hansson@arm.com    }
32510220Sandreas.hansson@arm.com
32610220Sandreas.hansson@arm.com    if (accessRetry) {
32710220Sandreas.hansson@arm.com        return;
32810220Sandreas.hansson@arm.com    }
32910220Sandreas.hansson@arm.com
33010220Sandreas.hansson@arm.com    //make new request
33110220Sandreas.hansson@arm.com    unsigned cmd = random() % 100;
33210220Sandreas.hansson@arm.com    unsigned offset = random() % size;
33310628Sandreas.hansson@arm.com    unsigned base = random() % 2;
33410628Sandreas.hansson@arm.com    uint64_t data = random();
33510628Sandreas.hansson@arm.com    unsigned access_size = random() % 4;
33610628Sandreas.hansson@arm.com    unsigned cacheable = random() % 100;
33710628Sandreas.hansson@arm.com
33810628Sandreas.hansson@arm.com    //If we aren't doing copies, use id as offset, and do a false sharing
33910628Sandreas.hansson@arm.com    //mem tester
34010628Sandreas.hansson@arm.com    //We can eliminate the lower bits of the offset, and then use the id
34110628Sandreas.hansson@arm.com    //to offset within the blks
34210628Sandreas.hansson@arm.com    offset &= ~63; //Not the low order bits
34310628Sandreas.hansson@arm.com    offset += id;
34410628Sandreas.hansson@arm.com    access_size = 0;
34510628Sandreas.hansson@arm.com
34610628Sandreas.hansson@arm.com    Request *req = new Request();
34710628Sandreas.hansson@arm.com    uint32_t flags = 0;
34810628Sandreas.hansson@arm.com    Addr paddr;
34910892Sandreas.hansson@arm.com
35010892Sandreas.hansson@arm.com    if (cacheable < percentUncacheable) {
35110892Sandreas.hansson@arm.com        flags |= UNCACHEABLE;
35210892Sandreas.hansson@arm.com        paddr = uncacheAddr + offset;
35310628Sandreas.hansson@arm.com    } else {
35410628Sandreas.hansson@arm.com        paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
35510628Sandreas.hansson@arm.com    }
35610628Sandreas.hansson@arm.com    bool probe = (random() % 100 < percentFunctional) && !(flags & UNCACHEABLE);
35710628Sandreas.hansson@arm.com    //bool probe = false;
35810628Sandreas.hansson@arm.com
35910628Sandreas.hansson@arm.com    paddr &= ~((1 << access_size) - 1);
36010628Sandreas.hansson@arm.com    req->setPhys(paddr, 1 << access_size, flags);
36110628Sandreas.hansson@arm.com    req->setThreadContext(id,0);
36210628Sandreas.hansson@arm.com
36310628Sandreas.hansson@arm.com    uint8_t *result = new uint8_t[8];
36410892Sandreas.hansson@arm.com
36510892Sandreas.hansson@arm.com    if (cmd < percentReads) {
36610892Sandreas.hansson@arm.com        // read
36710892Sandreas.hansson@arm.com
36810628Sandreas.hansson@arm.com        //For now we only allow one outstanding request per addreess per tester
36910628Sandreas.hansson@arm.com        //This means we assume CPU does write forwarding to reads that alias something
37010628Sandreas.hansson@arm.com        //in the cpu store buffer.
37110628Sandreas.hansson@arm.com        if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) {
37210628Sandreas.hansson@arm.com            delete [] result;
37310628Sandreas.hansson@arm.com            delete req;
37410892Sandreas.hansson@arm.com            return;
37510628Sandreas.hansson@arm.com        }
37610628Sandreas.hansson@arm.com        else outstandingAddrs.insert(paddr);
37710628Sandreas.hansson@arm.com
37810628Sandreas.hansson@arm.com        // ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin
37910628Sandreas.hansson@arm.com        funcPort.readBlob(req->getPaddr(), result, req->getSize());
38010628Sandreas.hansson@arm.com
38110628Sandreas.hansson@arm.com        if (blockAddr(paddr) == traceBlockAddr) {
38210628Sandreas.hansson@arm.com            cerr << name()
38310892Sandreas.hansson@arm.com                 << ": initiating read "
38410628Sandreas.hansson@arm.com                 << ((probe) ? "probe of " : "access of ")
38510628Sandreas.hansson@arm.com                 << dec << req->getSize() << " bytes from addr 0x"
38610628Sandreas.hansson@arm.com                 << hex << paddr
38710628Sandreas.hansson@arm.com                 << " (0x" << hex << blockAddr(paddr) << ")"
38810628Sandreas.hansson@arm.com                 << " at cycle "
38910628Sandreas.hansson@arm.com                 << dec << curTick << endl;
39010628Sandreas.hansson@arm.com        }
39110628Sandreas.hansson@arm.com
39210892Sandreas.hansson@arm.com        PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
39310628Sandreas.hansson@arm.com        pkt->dataDynamicArray(new uint8_t[req->getSize()]);
39410628Sandreas.hansson@arm.com        MemTestSenderState *state = new MemTestSenderState(result);
39510628Sandreas.hansson@arm.com        pkt->senderState = state;
39610628Sandreas.hansson@arm.com
39710628Sandreas.hansson@arm.com        if (probe) {
39810628Sandreas.hansson@arm.com            cachePort.sendFunctional(pkt);
39910628Sandreas.hansson@arm.com            pkt->makeAtomicResponse();
40010628Sandreas.hansson@arm.com            completeRequest(pkt);
40110628Sandreas.hansson@arm.com        } else {
40210628Sandreas.hansson@arm.com//	    req->completionEvent = new MemCompleteEvent(req, result, this);
40310628Sandreas.hansson@arm.com            sendPkt(pkt);
40410628Sandreas.hansson@arm.com        }
40510628Sandreas.hansson@arm.com    } else {
40610628Sandreas.hansson@arm.com        // write
40710628Sandreas.hansson@arm.com
40810628Sandreas.hansson@arm.com        //For now we only allow one outstanding request per addreess per tester
40910892Sandreas.hansson@arm.com        //This means we assume CPU does write forwarding to reads that alias something
4109864Snilay@cs.wisc.edu        //in the cpu store buffer.
4119864Snilay@cs.wisc.edu        if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) {
4129864Snilay@cs.wisc.edu            delete [] result;
4139864Snilay@cs.wisc.edu            delete req;
41410892Sandreas.hansson@arm.com            return;
4159864Snilay@cs.wisc.edu        }
4169864Snilay@cs.wisc.edu
4179864Snilay@cs.wisc.edu        else outstandingAddrs.insert(paddr);
4189864Snilay@cs.wisc.edu
41910892Sandreas.hansson@arm.com/*
4209864Snilay@cs.wisc.edu        if (blockAddr(req->getPaddr()) == traceBlockAddr) {
4219864Snilay@cs.wisc.edu            cerr << name() << ": initiating write "
4229864Snilay@cs.wisc.edu                 << ((probe)?"probe of ":"access of ")
4239864Snilay@cs.wisc.edu                 << dec << req->getSize() << " bytes (value = 0x";
42410892Sandreas.hansson@arm.com            printData(cerr, data_pkt->getPtr(), req->getSize());
4259864Snilay@cs.wisc.edu            cerr << ") to addr 0x"
4269864Snilay@cs.wisc.edu                 << hex << req->getPaddr()
4279864Snilay@cs.wisc.edu                 << " (0x" << hex << blockAddr(req->getPaddr()) << ")"
4289864Snilay@cs.wisc.edu                 << " at cycle "
42910892Sandreas.hansson@arm.com                 << dec << curTick << endl;
4309864Snilay@cs.wisc.edu        }
4319864Snilay@cs.wisc.edu*/
4329864Snilay@cs.wisc.edu        PacketPtr pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast);
4339864Snilay@cs.wisc.edu        uint8_t *pkt_data = new uint8_t[req->getSize()];
43410892Sandreas.hansson@arm.com        pkt->dataDynamicArray(pkt_data);
4359864Snilay@cs.wisc.edu        memcpy(pkt_data, &data, req->getSize());
4369864Snilay@cs.wisc.edu        MemTestSenderState *state = new MemTestSenderState(result);
4379864Snilay@cs.wisc.edu        pkt->senderState = state;
4389864Snilay@cs.wisc.edu
43910013Snilay@cs.wisc.edu        funcPort.writeBlob(req->getPaddr(), pkt_data, req->getSize());
44010013Snilay@cs.wisc.edu
44110013Snilay@cs.wisc.edu        if (probe) {
44210013Snilay@cs.wisc.edu            cachePort.sendFunctional(pkt);
44310013Snilay@cs.wisc.edu            pkt->makeAtomicResponse();
44410013Snilay@cs.wisc.edu            completeRequest(pkt);
44510013Snilay@cs.wisc.edu        } else {
44610013Snilay@cs.wisc.edu//	    req->completionEvent = new MemCompleteEvent(req, NULL, this);
44710013Snilay@cs.wisc.edu            sendPkt(pkt);
44810013Snilay@cs.wisc.edu        }
44910892Sandreas.hansson@arm.com    }
45010892Sandreas.hansson@arm.com/*    else {
45110013Snilay@cs.wisc.edu        // copy
45210892Sandreas.hansson@arm.com        unsigned source_align = random() % 100;
45310892Sandreas.hansson@arm.com        unsigned dest_align = random() % 100;
45410892Sandreas.hansson@arm.com        unsigned offset2 = random() % size;
45510892Sandreas.hansson@arm.com
45610013Snilay@cs.wisc.edu        Addr source = ((base) ? baseAddr1 : baseAddr2) + offset;
45710013Snilay@cs.wisc.edu        Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
45810013Snilay@cs.wisc.edu        if (outstandingAddrs.find(source) != outstandingAddrs.end()) return;
45910013Snilay@cs.wisc.edu        else outstandingAddrs.insert(source);
46010013Snilay@cs.wisc.edu        if (outstandingAddrs.find(dest) != outstandingAddrs.end()) return;
46110013Snilay@cs.wisc.edu        else outstandingAddrs.insert(dest);
46210013Snilay@cs.wisc.edu
46310013Snilay@cs.wisc.edu        if (source_align >= percentSourceUnaligned) {
46410892Sandreas.hansson@arm.com            source = blockAddr(source);
46510892Sandreas.hansson@arm.com        }
46610013Snilay@cs.wisc.edu        if (dest_align >= percentDestUnaligned) {
46710892Sandreas.hansson@arm.com            dest = blockAddr(dest);
46810892Sandreas.hansson@arm.com        }
46910892Sandreas.hansson@arm.com        req->cmd = Copy;
47010892Sandreas.hansson@arm.com        req->flags &= ~UNCACHEABLE;
47110013Snilay@cs.wisc.edu        req->paddr = source;
47210526Snilay@cs.wisc.edu        req->dest = dest;
47310526Snilay@cs.wisc.edu        delete [] req->data;
47410013Snilay@cs.wisc.edu        req->data = new uint8_t[blockSize];
47510892Sandreas.hansson@arm.com        req->size = blockSize;
47610892Sandreas.hansson@arm.com        if (source == traceBlockAddr || dest == traceBlockAddr) {
47710892Sandreas.hansson@arm.com            cerr << name()
47810892Sandreas.hansson@arm.com                 << ": initiating copy of "
47910013Snilay@cs.wisc.edu                 << dec << req->size << " bytes from addr 0x"
48010013Snilay@cs.wisc.edu                 << hex << source
48110013Snilay@cs.wisc.edu                 << " (0x" << hex << blockAddr(source) << ")"
48210013Snilay@cs.wisc.edu                 << " to addr 0x"
48310013Snilay@cs.wisc.edu                 << hex << dest
48410013Snilay@cs.wisc.edu                 << " (0x" << hex << blockAddr(dest) << ")"
48510013Snilay@cs.wisc.edu                 << " at cycle "
48610013Snilay@cs.wisc.edu                 << dec << curTick << endl;
48710526Snilay@cs.wisc.edu        }*
48810526Snilay@cs.wisc.edu        cacheInterface->access(req);
48910013Snilay@cs.wisc.edu        uint8_t result[blockSize];
49010892Sandreas.hansson@arm.com        checkMem->access(Read, source, &result, blockSize);
49110892Sandreas.hansson@arm.com        checkMem->access(Write, dest, &result, blockSize);
49210892Sandreas.hansson@arm.com    }
49310892Sandreas.hansson@arm.com*/
49410013Snilay@cs.wisc.edu}
49510526Snilay@cs.wisc.edu
49610526Snilay@cs.wisc.eduvoid
49710013Snilay@cs.wisc.eduMemTest::doRetry()
49810892Sandreas.hansson@arm.com{
49910892Sandreas.hansson@arm.com    if (cachePort.sendTiming(retryPkt)) {
50010892Sandreas.hansson@arm.com        accessRetry = false;
50110892Sandreas.hansson@arm.com        retryPkt = NULL;
50210013Snilay@cs.wisc.edu    }
50310013Snilay@cs.wisc.edu}
50410013Snilay@cs.wisc.edu
50510013Snilay@cs.wisc.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
50610013Snilay@cs.wisc.edu
50710013Snilay@cs.wisc.edu//    SimObjectParam<BaseCache *> cache;
50810013Snilay@cs.wisc.edu//    SimObjectParam<PhysicalMemory *> main_mem;
50910013Snilay@cs.wisc.edu//    SimObjectParam<PhysicalMemory *> check_mem;
51010526Snilay@cs.wisc.edu    Param<unsigned> memory_size;
51110526Snilay@cs.wisc.edu    Param<unsigned> percent_reads;
51210013Snilay@cs.wisc.edu    Param<unsigned> percent_functional;
51310892Sandreas.hansson@arm.com    Param<unsigned> percent_uncacheable;
51410892Sandreas.hansson@arm.com    Param<unsigned> progress_interval;
51510892Sandreas.hansson@arm.com    Param<unsigned> percent_source_unaligned;
51610892Sandreas.hansson@arm.com    Param<unsigned> percent_dest_unaligned;
51710013Snilay@cs.wisc.edu    Param<Addr> trace_addr;
51810526Snilay@cs.wisc.edu    Param<Counter> max_loads;
51910526Snilay@cs.wisc.edu    Param<bool> atomic;
52010013Snilay@cs.wisc.edu
52110526Snilay@cs.wisc.eduEND_DECLARE_SIM_OBJECT_PARAMS(MemTest)
52210526Snilay@cs.wisc.edu
52310526Snilay@cs.wisc.edu
52410013Snilay@cs.wisc.eduBEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
52510013Snilay@cs.wisc.edu
52610013Snilay@cs.wisc.edu//    INIT_PARAM(cache, "L1 cache"),
52710013Snilay@cs.wisc.edu//    INIT_PARAM(main_mem, "hierarchical memory"),
52810013Snilay@cs.wisc.edu//    INIT_PARAM(check_mem, "check memory"),
52910013Snilay@cs.wisc.edu    INIT_PARAM(memory_size, "memory size"),
53010013Snilay@cs.wisc.edu    INIT_PARAM(percent_reads, "target read percentage"),
53110013Snilay@cs.wisc.edu    INIT_PARAM(percent_functional, "percentage of access that are functional"),
53210013Snilay@cs.wisc.edu    INIT_PARAM(percent_uncacheable, "target uncacheable percentage"),
53310526Snilay@cs.wisc.edu    INIT_PARAM(progress_interval, "progress report interval (in accesses)"),
53410526Snilay@cs.wisc.edu    INIT_PARAM(percent_source_unaligned,
53510013Snilay@cs.wisc.edu               "percent of copy source address that are unaligned"),
53610526Snilay@cs.wisc.edu    INIT_PARAM(percent_dest_unaligned,
53710526Snilay@cs.wisc.edu               "percent of copy dest address that are unaligned"),
53810013Snilay@cs.wisc.edu    INIT_PARAM(trace_addr, "address to trace"),
53910013Snilay@cs.wisc.edu                              INIT_PARAM(max_loads, "terminate when we have reached this load count"),
54010013Snilay@cs.wisc.edu    INIT_PARAM(atomic, "Is the tester testing atomic mode (or timing)")
54110526Snilay@cs.wisc.edu
54210526Snilay@cs.wisc.eduEND_INIT_SIM_OBJECT_PARAMS(MemTest)
54310013Snilay@cs.wisc.edu
54410892Sandreas.hansson@arm.com
54510892Sandreas.hansson@arm.comCREATE_SIM_OBJECT(MemTest)
54610892Sandreas.hansson@arm.com{
54710892Sandreas.hansson@arm.com    return new MemTest(getInstanceName(), /*cache->getInterface(),*/ /*main_mem,*/
54810013Snilay@cs.wisc.edu                       /*check_mem,*/ memory_size, percent_reads, percent_functional,
54910013Snilay@cs.wisc.edu                       percent_uncacheable, progress_interval,
55010013Snilay@cs.wisc.edu                       percent_source_unaligned, percent_dest_unaligned,
55110013Snilay@cs.wisc.edu                       trace_addr, max_loads, atomic);
55210013Snilay@cs.wisc.edu}
55310013Snilay@cs.wisc.edu
55410013Snilay@cs.wisc.eduREGISTER_SIM_OBJECT("MemTest", MemTest)
55510013Snilay@cs.wisc.edu