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