memtest.cc revision 8853
1955SN/A/*
2955SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
39812Sandreas.hansson@arm.com * All rights reserved.
49812Sandreas.hansson@arm.com *
59812Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
69812Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
79812Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
89812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
99812Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
109812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
119812Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
129812Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
139812Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
149812Sandreas.hansson@arm.com * this software without specific prior written permission.
157816Ssteve.reinhardt@amd.com *
165871Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171762SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27955SN/A *
28955SN/A * Authors: Erik Hallnor
29955SN/A *          Steve Reinhardt
30955SN/A */
31955SN/A
32955SN/A// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
33955SN/A
34955SN/A#include <iomanip>
35955SN/A#include <set>
36955SN/A#include <string>
37955SN/A#include <vector>
38955SN/A
39955SN/A#include "base/misc.hh"
40955SN/A#include "base/statistics.hh"
41955SN/A#include "cpu/testers/memtest/memtest.hh"
422665Ssaidi@eecs.umich.edu#include "debug/MemTest.hh"
432665Ssaidi@eecs.umich.edu#include "mem/mem_object.hh"
445863Snate@binkert.org#include "mem/packet.hh"
45955SN/A#include "mem/port.hh"
46955SN/A#include "mem/request.hh"
47955SN/A#include "sim/sim_events.hh"
48955SN/A#include "sim/stats.hh"
49955SN/A#include "sim/system.hh"
508878Ssteve.reinhardt@amd.com
512632Sstever@eecs.umich.eduusing namespace std;
528878Ssteve.reinhardt@amd.com
532632Sstever@eecs.umich.eduint TESTER_ALLOCATOR=0;
54955SN/A
558878Ssteve.reinhardt@amd.combool
562632Sstever@eecs.umich.eduMemTest::CpuPort::recvTiming(PacketPtr pkt)
572761Sstever@eecs.umich.edu{
582632Sstever@eecs.umich.edu    if (pkt->isResponse()) {
592632Sstever@eecs.umich.edu        memtest->completeRequest(pkt);
602632Sstever@eecs.umich.edu    } else {
612761Sstever@eecs.umich.edu        // must be snoop upcall
622761Sstever@eecs.umich.edu        assert(pkt->isRequest());
632761Sstever@eecs.umich.edu        assert(pkt->getDest() == Packet::Broadcast);
648878Ssteve.reinhardt@amd.com    }
658878Ssteve.reinhardt@amd.com    return true;
662761Sstever@eecs.umich.edu}
672761Sstever@eecs.umich.edu
682761Sstever@eecs.umich.eduTick
692761Sstever@eecs.umich.eduMemTest::CpuPort::recvAtomic(PacketPtr pkt)
702761Sstever@eecs.umich.edu{
718878Ssteve.reinhardt@amd.com    // must be snoop upcall
728878Ssteve.reinhardt@amd.com    assert(pkt->isRequest());
732632Sstever@eecs.umich.edu    assert(pkt->getDest() == Packet::Broadcast);
742632Sstever@eecs.umich.edu    return curTick();
758878Ssteve.reinhardt@amd.com}
768878Ssteve.reinhardt@amd.com
772632Sstever@eecs.umich.eduvoid
78955SN/AMemTest::CpuPort::recvFunctional(PacketPtr pkt)
79955SN/A{
80955SN/A    //Do nothing if we see one come through
815863Snate@binkert.org//    if (curTick() != 0)//Supress warning durring initialization
825863Snate@binkert.org//        warn("Functional Writes not implemented in MemTester\n");
835863Snate@binkert.org    //Need to find any response values that intersect and update
845863Snate@binkert.org    return;
855863Snate@binkert.org}
865863Snate@binkert.org
875863Snate@binkert.orgvoid
885863Snate@binkert.orgMemTest::CpuPort::recvRangeChange()
895863Snate@binkert.org{
905863Snate@binkert.org}
915863Snate@binkert.org
928878Ssteve.reinhardt@amd.comvoid
935863Snate@binkert.orgMemTest::CpuPort::recvRetry()
945863Snate@binkert.org{
955863Snate@binkert.org    memtest->doRetry();
969812Sandreas.hansson@arm.com}
979812Sandreas.hansson@arm.com
985863Snate@binkert.orgvoid
999812Sandreas.hansson@arm.comMemTest::sendPkt(PacketPtr pkt) {
1005863Snate@binkert.org    if (atomic) {
1015863Snate@binkert.org        cachePort.sendAtomic(pkt);
1025863Snate@binkert.org        completeRequest(pkt);
1039812Sandreas.hansson@arm.com    }
1049812Sandreas.hansson@arm.com    else if (!cachePort.sendTiming(pkt)) {
1055863Snate@binkert.org        DPRINTF(MemTest, "accessRetry setting to true\n");
1065863Snate@binkert.org
1078878Ssteve.reinhardt@amd.com        //
1085863Snate@binkert.org        // dma requests should never be retried
1095863Snate@binkert.org        //
1105863Snate@binkert.org        if (issueDmas) {
1116654Snate@binkert.org            panic("Nacked DMA requests are not supported\n");
11210196SCurtis.Dunham@arm.com        }
113955SN/A        accessRetry = true;
1145396Ssaidi@eecs.umich.edu        retryPkt = pkt;
1155863Snate@binkert.org    } else {
1165863Snate@binkert.org        if (issueDmas) {
1174202Sbinkertn@umich.edu            dmaOutstanding = true;
1185863Snate@binkert.org        }
1195863Snate@binkert.org    }
1205863Snate@binkert.org
1215863Snate@binkert.org}
122955SN/A
1236654Snate@binkert.orgMemTest::MemTest(const Params *p)
1245273Sstever@gmail.com    : MemObject(p),
1255871Snate@binkert.org      tickEvent(this),
1265273Sstever@gmail.com      cachePort("test", this),
1276655Snate@binkert.org      funcPort("functional", this),
1288878Ssteve.reinhardt@amd.com      funcProxy(funcPort),
1296655Snate@binkert.org      retryPkt(NULL),
1306655Snate@binkert.org//      mainMem(main_mem),
1319219Spower.jg@gmail.com//      checkMem(check_mem),
1326655Snate@binkert.org      size(p->memory_size),
1335871Snate@binkert.org      percentReads(p->percent_reads),
1346654Snate@binkert.org      percentFunctional(p->percent_functional),
1358947Sandreas.hansson@arm.com      percentUncacheable(p->percent_uncacheable),
1365396Ssaidi@eecs.umich.edu      issueDmas(p->issue_dmas),
1378120Sgblack@eecs.umich.edu      masterId(p->sys->getMasterId(name())),
1388120Sgblack@eecs.umich.edu      progressInterval(p->progress_interval),
1398120Sgblack@eecs.umich.edu      nextProgressMessage(p->progress_interval),
1408120Sgblack@eecs.umich.edu      percentSourceUnaligned(p->percent_source_unaligned),
1418120Sgblack@eecs.umich.edu      percentDestUnaligned(p->percent_dest_unaligned),
1428120Sgblack@eecs.umich.edu      maxLoads(p->max_loads),
1438120Sgblack@eecs.umich.edu      atomic(p->atomic),
1448120Sgblack@eecs.umich.edu      suppress_func_warnings(p->suppress_func_warnings)
1458879Ssteve.reinhardt@amd.com{
1468879Ssteve.reinhardt@amd.com    id = TESTER_ALLOCATOR++;
1478879Ssteve.reinhardt@amd.com
1488879Ssteve.reinhardt@amd.com    // Needs to be masked off once we know the block size.
1498879Ssteve.reinhardt@amd.com    traceBlockAddr = p->trace_addr;
1508879Ssteve.reinhardt@amd.com    baseAddr1 = 0x100000;
1518879Ssteve.reinhardt@amd.com    baseAddr2 = 0x400000;
1528879Ssteve.reinhardt@amd.com    uncacheAddr = 0x800000;
1538879Ssteve.reinhardt@amd.com
1548879Ssteve.reinhardt@amd.com    // set up counters
1558879Ssteve.reinhardt@amd.com    noResponseCycles = 0;
1568879Ssteve.reinhardt@amd.com    numReads = 0;
1578879Ssteve.reinhardt@amd.com    numWrites = 0;
1588120Sgblack@eecs.umich.edu    schedule(tickEvent, 0);
1598120Sgblack@eecs.umich.edu
1608120Sgblack@eecs.umich.edu    accessRetry = false;
1618120Sgblack@eecs.umich.edu    dmaOutstanding = false;
1628120Sgblack@eecs.umich.edu}
1638120Sgblack@eecs.umich.edu
1648120Sgblack@eecs.umich.eduPort *
1658120Sgblack@eecs.umich.eduMemTest::getPort(const std::string &if_name, int idx)
1668120Sgblack@eecs.umich.edu{
1678120Sgblack@eecs.umich.edu    if (if_name == "functional")
1688120Sgblack@eecs.umich.edu        return &funcPort;
1698120Sgblack@eecs.umich.edu    else if (if_name == "test")
1708120Sgblack@eecs.umich.edu        return &cachePort;
1718120Sgblack@eecs.umich.edu    else
1728879Ssteve.reinhardt@amd.com        panic("No Such Port\n");
1738879Ssteve.reinhardt@amd.com}
1748879Ssteve.reinhardt@amd.com
1758879Ssteve.reinhardt@amd.comvoid
1768879Ssteve.reinhardt@amd.comMemTest::init()
1778879Ssteve.reinhardt@amd.com{
1788879Ssteve.reinhardt@amd.com    // By the time init() is called, the ports should be hooked up.
1798879Ssteve.reinhardt@amd.com    blockSize = cachePort.peerBlockSize();
1809227Sandreas.hansson@arm.com    blockAddrMask = blockSize - 1;
1819227Sandreas.hansson@arm.com    traceBlockAddr = blockAddr(traceBlockAddr);
1828879Ssteve.reinhardt@amd.com
1838879Ssteve.reinhardt@amd.com    // initial memory contents for both physical memory and functional
1848879Ssteve.reinhardt@amd.com    // memory should be 0; no need to initialize them.
1858879Ssteve.reinhardt@amd.com}
1868120Sgblack@eecs.umich.edu
1878947Sandreas.hansson@arm.com
1887816Ssteve.reinhardt@amd.comvoid
1895871Snate@binkert.orgMemTest::completeRequest(PacketPtr pkt)
1905871Snate@binkert.org{
1916121Snate@binkert.org    Request *req = pkt->req;
1925871Snate@binkert.org
1935871Snate@binkert.org    if (issueDmas) {
1949926Sstan.czerniawski@arm.com        dmaOutstanding = false;
1959926Sstan.czerniawski@arm.com    }
1969119Sandreas.hansson@arm.com
19710068Sandreas.hansson@arm.com    DPRINTF(MemTest, "completing %s at address %x (blk %x) %s\n",
19810068Sandreas.hansson@arm.com            pkt->isWrite() ? "write" : "read",
199955SN/A            req->getPaddr(), blockAddr(req->getPaddr()),
2009416SAndreas.Sandberg@ARM.com            pkt->isError() ? "error" : "success");
2019416SAndreas.Sandberg@ARM.com
2029416SAndreas.Sandberg@ARM.com    MemTestSenderState *state =
2039416SAndreas.Sandberg@ARM.com        dynamic_cast<MemTestSenderState *>(pkt->senderState);
2049416SAndreas.Sandberg@ARM.com
2059416SAndreas.Sandberg@ARM.com    uint8_t *data = state->data;
2069416SAndreas.Sandberg@ARM.com    uint8_t *pkt_data = pkt->getPtr<uint8_t>();
2075871Snate@binkert.org
2085871Snate@binkert.org    //Remove the address from the list of outstanding
2099416SAndreas.Sandberg@ARM.com    std::set<unsigned>::iterator removeAddr =
2109416SAndreas.Sandberg@ARM.com        outstandingAddrs.find(req->getPaddr());
2115871Snate@binkert.org    assert(removeAddr != outstandingAddrs.end());
212955SN/A    outstandingAddrs.erase(removeAddr);
2136121Snate@binkert.org
2148881Smarc.orr@gmail.com    if (pkt->isError()) {
2156121Snate@binkert.org        if (!suppress_func_warnings) {
2166121Snate@binkert.org          warn("Functional Access failed for %x at %x\n",
2171533SN/A               pkt->isWrite() ? "write" : "read", req->getPaddr());
2189239Sandreas.hansson@arm.com        }
2199239Sandreas.hansson@arm.com    } else {
2209239Sandreas.hansson@arm.com        if (pkt->isRead()) {
2219239Sandreas.hansson@arm.com            if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
2229239Sandreas.hansson@arm.com                panic("%s: read of %x (blk %x) @ cycle %d "
2239239Sandreas.hansson@arm.com                      "returns %x, expected %x\n", name(),
2249239Sandreas.hansson@arm.com                      req->getPaddr(), blockAddr(req->getPaddr()), curTick(),
2259239Sandreas.hansson@arm.com                      *pkt_data, *data);
2269239Sandreas.hansson@arm.com            }
2279239Sandreas.hansson@arm.com
2289239Sandreas.hansson@arm.com            numReads++;
2299239Sandreas.hansson@arm.com            numReadsStat++;
2306655Snate@binkert.org
2316655Snate@binkert.org            if (numReads == (uint64_t)nextProgressMessage) {
2326655Snate@binkert.org                ccprintf(cerr, "%s: completed %d read, %d write accesses @%d\n",
2336655Snate@binkert.org                         name(), numReads, numWrites, curTick());
2345871Snate@binkert.org                nextProgressMessage += progressInterval;
2355871Snate@binkert.org            }
2365863Snate@binkert.org
2375871Snate@binkert.org            if (maxLoads != 0 && numReads >= maxLoads)
2388878Ssteve.reinhardt@amd.com                exitSimLoop("maximum number of loads reached");
2395871Snate@binkert.org        } else {
2405871Snate@binkert.org            assert(pkt->isWrite());
2415871Snate@binkert.org            funcProxy.writeBlob(req->getPaddr(), pkt_data, req->getSize());
2425863Snate@binkert.org            numWrites++;
2436121Snate@binkert.org            numWritesStat++;
2445863Snate@binkert.org        }
2455871Snate@binkert.org    }
2468336Ssteve.reinhardt@amd.com
2478336Ssteve.reinhardt@amd.com    noResponseCycles = 0;
2488336Ssteve.reinhardt@amd.com    delete state;
2498336Ssteve.reinhardt@amd.com    delete [] data;
2504678Snate@binkert.org    delete pkt->req;
2518336Ssteve.reinhardt@amd.com    delete pkt;
2528336Ssteve.reinhardt@amd.com}
2538336Ssteve.reinhardt@amd.com
2544678Snate@binkert.orgvoid
2554678Snate@binkert.orgMemTest::regStats()
2564678Snate@binkert.org{
2574678Snate@binkert.org    using namespace Stats;
2587827Snate@binkert.org
2597827Snate@binkert.org    numReadsStat
2608336Ssteve.reinhardt@amd.com        .name(name() + ".num_reads")
2614678Snate@binkert.org        .desc("number of read accesses completed")
2628336Ssteve.reinhardt@amd.com        ;
2638336Ssteve.reinhardt@amd.com
2648336Ssteve.reinhardt@amd.com    numWritesStat
2658336Ssteve.reinhardt@amd.com        .name(name() + ".num_writes")
2668336Ssteve.reinhardt@amd.com        .desc("number of write accesses completed")
2678336Ssteve.reinhardt@amd.com        ;
2685871Snate@binkert.org
2695871Snate@binkert.org    numCopiesStat
2708336Ssteve.reinhardt@amd.com        .name(name() + ".num_copies")
2718336Ssteve.reinhardt@amd.com        .desc("number of copy accesses completed")
2728336Ssteve.reinhardt@amd.com        ;
2738336Ssteve.reinhardt@amd.com}
2748336Ssteve.reinhardt@amd.com
2755871Snate@binkert.orgvoid
2768336Ssteve.reinhardt@amd.comMemTest::tick()
2778336Ssteve.reinhardt@amd.com{
2788336Ssteve.reinhardt@amd.com    if (!tickEvent.scheduled())
2798336Ssteve.reinhardt@amd.com        schedule(tickEvent, curTick() + ticks(1));
2808336Ssteve.reinhardt@amd.com
2814678Snate@binkert.org    if (++noResponseCycles >= 500000) {
2825871Snate@binkert.org        if (issueDmas) {
2834678Snate@binkert.org            cerr << "DMA tester ";
2848336Ssteve.reinhardt@amd.com        }
2858336Ssteve.reinhardt@amd.com        cerr << name() << ": deadlocked at cycle " << curTick() << endl;
2868336Ssteve.reinhardt@amd.com        fatal("");
2878336Ssteve.reinhardt@amd.com    }
2888336Ssteve.reinhardt@amd.com
2898336Ssteve.reinhardt@amd.com    if (accessRetry || (issueDmas && dmaOutstanding)) {
2908336Ssteve.reinhardt@amd.com        DPRINTF(MemTest, "MemTester waiting on accessRetry or DMA response\n");
2918336Ssteve.reinhardt@amd.com        return;
2928336Ssteve.reinhardt@amd.com    }
2938336Ssteve.reinhardt@amd.com
2948336Ssteve.reinhardt@amd.com    //make new request
2958336Ssteve.reinhardt@amd.com    unsigned cmd = random() % 100;
2968336Ssteve.reinhardt@amd.com    unsigned offset = random() % size;
2978336Ssteve.reinhardt@amd.com    unsigned base = random() % 2;
2988336Ssteve.reinhardt@amd.com    uint64_t data = random();
2998336Ssteve.reinhardt@amd.com    unsigned access_size = random() % 4;
3008336Ssteve.reinhardt@amd.com    bool uncacheable = (random() % 100) < percentUncacheable;
3015871Snate@binkert.org
3026121Snate@binkert.org    unsigned dma_access_size = random() % 4;
303955SN/A
304955SN/A    //If we aren't doing copies, use id as offset, and do a false sharing
3052632Sstever@eecs.umich.edu    //mem tester
3062632Sstever@eecs.umich.edu    //We can eliminate the lower bits of the offset, and then use the id
307955SN/A    //to offset within the blks
308955SN/A    offset = blockAddr(offset);
309955SN/A    offset += id;
310955SN/A    access_size = 0;
3118878Ssteve.reinhardt@amd.com    dma_access_size = 0;
312955SN/A
3132632Sstever@eecs.umich.edu    Request *req = new Request();
3142632Sstever@eecs.umich.edu    Request::Flags flags;
3152632Sstever@eecs.umich.edu    Addr paddr;
3162632Sstever@eecs.umich.edu
3172632Sstever@eecs.umich.edu    if (uncacheable) {
3182632Sstever@eecs.umich.edu        flags.set(Request::UNCACHEABLE);
3192632Sstever@eecs.umich.edu        paddr = uncacheAddr + offset;
3208268Ssteve.reinhardt@amd.com    } else  {
3218268Ssteve.reinhardt@amd.com        paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
3228268Ssteve.reinhardt@amd.com    }
3238268Ssteve.reinhardt@amd.com    bool do_functional = (random() % 100 < percentFunctional) && !uncacheable;
3248268Ssteve.reinhardt@amd.com
3258268Ssteve.reinhardt@amd.com    if (issueDmas) {
3268268Ssteve.reinhardt@amd.com        paddr &= ~((1 << dma_access_size) - 1);
3272632Sstever@eecs.umich.edu        req->setPhys(paddr, 1 << dma_access_size, flags, masterId);
3282632Sstever@eecs.umich.edu        req->setThreadContext(id,0);
3292632Sstever@eecs.umich.edu    } else {
3302632Sstever@eecs.umich.edu        paddr &= ~((1 << access_size) - 1);
3318268Ssteve.reinhardt@amd.com        req->setPhys(paddr, 1 << access_size, flags, masterId);
3322632Sstever@eecs.umich.edu        req->setThreadContext(id,0);
3338268Ssteve.reinhardt@amd.com    }
3348268Ssteve.reinhardt@amd.com    assert(req->getSize() == 1);
3358268Ssteve.reinhardt@amd.com
3368268Ssteve.reinhardt@amd.com    uint8_t *result = new uint8_t[8];
3373718Sstever@eecs.umich.edu
3382634Sstever@eecs.umich.edu    if (cmd < percentReads) {
3392634Sstever@eecs.umich.edu        // read
3405863Snate@binkert.org
3412638Sstever@eecs.umich.edu        // For now we only allow one outstanding request per address
3428268Ssteve.reinhardt@amd.com        // per tester This means we assume CPU does write forwarding
3432632Sstever@eecs.umich.edu        // to reads that alias something in the cpu store buffer.
3442632Sstever@eecs.umich.edu        if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) {
3452632Sstever@eecs.umich.edu            delete [] result;
3462632Sstever@eecs.umich.edu            delete req;
3472632Sstever@eecs.umich.edu            return;
3481858SN/A        }
3493716Sstever@eecs.umich.edu
3502638Sstever@eecs.umich.edu        outstandingAddrs.insert(paddr);
3512638Sstever@eecs.umich.edu
3522638Sstever@eecs.umich.edu        // ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin
3532638Sstever@eecs.umich.edu        funcProxy.readBlob(req->getPaddr(), result, req->getSize());
3542638Sstever@eecs.umich.edu
3552638Sstever@eecs.umich.edu        DPRINTF(MemTest,
3562638Sstever@eecs.umich.edu                "id %d initiating %sread at addr %x (blk %x) expecting %x\n",
3575863Snate@binkert.org                id, do_functional ? "functional " : "", req->getPaddr(),
3585863Snate@binkert.org                blockAddr(req->getPaddr()), *result);
3595863Snate@binkert.org
360955SN/A        PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
3615341Sstever@gmail.com        pkt->setSrc(0);
3625341Sstever@gmail.com        pkt->dataDynamicArray(new uint8_t[req->getSize()]);
3635863Snate@binkert.org        MemTestSenderState *state = new MemTestSenderState(result);
3647756SAli.Saidi@ARM.com        pkt->senderState = state;
3655341Sstever@gmail.com
3666121Snate@binkert.org        if (do_functional) {
3674494Ssaidi@eecs.umich.edu            assert(pkt->needsResponse());
3686121Snate@binkert.org            pkt->setSuppressFuncError();
3691105SN/A            cachePort.sendFunctional(pkt);
3702667Sstever@eecs.umich.edu            completeRequest(pkt);
3712667Sstever@eecs.umich.edu        } else {
3722667Sstever@eecs.umich.edu            sendPkt(pkt);
3732667Sstever@eecs.umich.edu        }
3746121Snate@binkert.org    } else {
3752667Sstever@eecs.umich.edu        // write
3765341Sstever@gmail.com
3775863Snate@binkert.org        // For now we only allow one outstanding request per addreess
3785341Sstever@gmail.com        // per tester.  This means we assume CPU does write forwarding
3795341Sstever@gmail.com        // to reads that alias something in the cpu store buffer.
3805341Sstever@gmail.com        if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) {
3818120Sgblack@eecs.umich.edu            delete [] result;
3825341Sstever@gmail.com            delete req;
3838120Sgblack@eecs.umich.edu            return;
3845341Sstever@gmail.com        }
3858120Sgblack@eecs.umich.edu
3866121Snate@binkert.org        outstandingAddrs.insert(paddr);
3876121Snate@binkert.org
3888980Ssteve.reinhardt@amd.com        DPRINTF(MemTest, "initiating %swrite at addr %x (blk %x) value %x\n",
3899396Sandreas.hansson@arm.com                do_functional ? "functional " : "", req->getPaddr(),
3905397Ssaidi@eecs.umich.edu                blockAddr(req->getPaddr()), data & 0xff);
3915397Ssaidi@eecs.umich.edu
3927727SAli.Saidi@ARM.com        PacketPtr pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast);
3938268Ssteve.reinhardt@amd.com        pkt->setSrc(0);
3946168Snate@binkert.org        uint8_t *pkt_data = new uint8_t[req->getSize()];
3955341Sstever@gmail.com        pkt->dataDynamicArray(pkt_data);
3968120Sgblack@eecs.umich.edu        memcpy(pkt_data, &data, req->getSize());
3978120Sgblack@eecs.umich.edu        MemTestSenderState *state = new MemTestSenderState(result);
3988120Sgblack@eecs.umich.edu        pkt->senderState = state;
3996814Sgblack@eecs.umich.edu
4005863Snate@binkert.org        if (do_functional) {
4018120Sgblack@eecs.umich.edu            pkt->setSuppressFuncError();
4025341Sstever@gmail.com            cachePort.sendFunctional(pkt);
4035863Snate@binkert.org            completeRequest(pkt);
4048268Ssteve.reinhardt@amd.com        } else {
4056121Snate@binkert.org            sendPkt(pkt);
4066121Snate@binkert.org        }
4078268Ssteve.reinhardt@amd.com    }
4085742Snate@binkert.org}
4095742Snate@binkert.org
4105341Sstever@gmail.comvoid
4115742Snate@binkert.orgMemTest::doRetry()
4125742Snate@binkert.org{
4135341Sstever@gmail.com    if (cachePort.sendTiming(retryPkt)) {
4146017Snate@binkert.org        DPRINTF(MemTest, "accessRetry setting to false\n");
4156121Snate@binkert.org        accessRetry = false;
4166017Snate@binkert.org        retryPkt = NULL;
4177816Ssteve.reinhardt@amd.com    }
4187756SAli.Saidi@ARM.com}
4197756SAli.Saidi@ARM.com
4207756SAli.Saidi@ARM.com
4217756SAli.Saidi@ARM.comvoid
4227756SAli.Saidi@ARM.comMemTest::printAddr(Addr a)
4237756SAli.Saidi@ARM.com{
4247756SAli.Saidi@ARM.com    cachePort.printAddr(a);
4257756SAli.Saidi@ARM.com}
4267816Ssteve.reinhardt@amd.com
4277816Ssteve.reinhardt@amd.com
4287816Ssteve.reinhardt@amd.comMemTest *
4297816Ssteve.reinhardt@amd.comMemTestParams::create()
4307816Ssteve.reinhardt@amd.com{
4317816Ssteve.reinhardt@amd.com    return new MemTest(this);
4327816Ssteve.reinhardt@amd.com}
4337816Ssteve.reinhardt@amd.com