diff --git a/src/cpu/memtest/MemTest.py b/src/cpu/memtest/MemTest.py --- a/src/cpu/memtest/MemTest.py +++ b/src/cpu/memtest/MemTest.py @@ -39,6 +39,8 @@ percent_dest_unaligned = Param.Percent(50, "percent of copy dest address that are unaligned") percent_reads = Param.Percent(65, "target read percentage") + percent_dma = Param.Percent(1, "target dma percentage") + use_dma = Param.Bool(True, "issue dma requests?") percent_source_unaligned = Param.Percent(50, "percent of copy source address that are unaligned") percent_functional = Param.Percent(50, "percent of access that are functional") diff --git a/src/cpu/memtest/SConscript b/src/cpu/memtest/SConscript --- a/src/cpu/memtest/SConscript +++ b/src/cpu/memtest/SConscript @@ -30,9 +30,9 @@ Import('*') -if 'O3CPU' in env['CPU_MODELS']: - SimObject('MemTest.py') +#if 'O3CPU' in env['CPU_MODELS']: +SimObject('MemTest.py') - Source('memtest.cc') +Source('memtest.cc') - TraceFlag('MemTest') +TraceFlag('MemTest') diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -127,6 +127,8 @@ percentReads(p->percent_reads), percentFunctional(p->percent_functional), percentUncacheable(p->percent_uncacheable), + percentDMA(p->percent_dma), + useDma(p->use_dma), progressInterval(p->progress_interval), nextProgressMessage(p->progress_interval), percentSourceUnaligned(p->percent_source_unaligned), @@ -134,6 +136,7 @@ maxLoads(p->max_loads), atomic(p->atomic) { + vector cmd; cmd.push_back("/bin/ls"); vector null_vec; @@ -145,9 +148,16 @@ // Needs to be masked off once we know the block size. traceBlockAddr = p->trace_addr; - baseAddr1 = 0x100000; - baseAddr2 = 0x400000; - uncacheAddr = 0x800000; + if (useDma) { + baseAddr1 = 0x100000; + baseAddr2 = 0x200000; + uncacheAddr = 0x400000; + dmaAddr = 0x800000 + 4096*id; + } else { + baseAddr1 = 0x100000; + baseAddr2 = 0x400000; + uncacheAddr = 0x800000; + } // set up counters noResponseCycles = 0; @@ -281,6 +291,9 @@ unsigned access_size = random() % 4; bool uncacheable = (random() % 100) < percentUncacheable; + unsigned dma_access_size = random() % 4; + bool dma = (random() % 100) < percentDMA; + //If we aren't doing copies, use id as offset, and do a false sharing //mem tester //We can eliminate the lower bits of the offset, and then use the id @@ -288,6 +301,7 @@ offset = blockAddr(offset); offset += id; access_size = 0; + dma_access_size = 0; Request *req = new Request(); Request::Flags flags; @@ -296,14 +310,28 @@ if (uncacheable) { flags.set(Request::UNCACHEABLE); paddr = uncacheAddr + offset; + } else if (useDma && dma) { + flags.set(Request::DMA_REQUEST); + paddr = dmaAddr + offset; + dmaAddr = (dmaAddr + 4096*8) % 0x800000; + if (dmaAddr > 0x900000) { + dmaAddr = 0x800000 + 4096*id; + } } else { paddr = ((base) ? baseAddr1 : baseAddr2) + offset; } bool probe = (random() % 100 < percentFunctional) && !uncacheable; - paddr &= ~((1 << access_size) - 1); - req->setPhys(paddr, 1 << access_size, flags); - req->setThreadContext(id,0); + if (!useDma || (useDma && !dma)) { + paddr &= ~((1 << access_size) - 1); + req->setPhys(paddr, 1 << access_size, flags); + req->setThreadContext(id,0); + } + else { + paddr &= ~((1 << dma_access_size) - 1); + req->setPhys(paddr, 1 << dma_access_size, flags); + req->setThreadContext(id,0); + } uint8_t *result = new uint8_t[8]; diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -138,6 +138,9 @@ unsigned percentReads; // target percentage of read accesses unsigned percentFunctional; // target percentage of functional accesses unsigned percentUncacheable; + unsigned percentDMA; // target percentage of dma accesses + + bool useDma; int id; @@ -157,6 +160,7 @@ Addr baseAddr1; // fix this to option Addr baseAddr2; // fix this to option Addr uncacheAddr; + Addr dmaAddr; unsigned progressInterval; // frequency of progress reports Tick nextProgressMessage; // access # for next progress report diff --git a/src/mem/request.hh b/src/mem/request.hh --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -99,6 +99,8 @@ static const FlagsType PF_EXCLUSIVE = 0x02000000; /** The request should be marked as LRU. */ static const FlagsType EVICT_NEXT = 0x04000000; + /** DMA request. */ + static const FlagsType DMA_REQUEST = 0x08000000; /** These flags are *not* cleared when a Request object is reused (assigned a new address). */ @@ -451,6 +453,7 @@ bool isSwap() const { return _flags.isSet(MEM_SWAP|MEM_SWAP_COND); } bool isCondSwap() const { return _flags.isSet(MEM_SWAP_COND); } bool isMmapedIpr() const { return _flags.isSet(MMAPED_IPR); } + bool isDmaRequest() const { return _flags.isSet(DMA_REQUEST); } bool isMisaligned() const diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc --- a/src/mem/ruby/system/DMASequencer.cc +++ b/src/mem/ruby/system/DMASequencer.cc @@ -54,7 +54,9 @@ assert(0); } - assert(!m_is_busy); // only support one outstanding DMA request + // polina: an adjustment to allow MemTest objects to try issuing dma requests without crashing the system + if (m_is_busy) return -1; + // assert(!m_is_busy); // only support one outstanding DMA request m_is_busy = true; active_request.start_paddr = paddr; diff --git a/src/mem/rubymem.cc b/src/mem/rubymem.cc --- a/src/mem/rubymem.cc +++ b/src/mem/rubymem.cc @@ -85,6 +85,12 @@ ruby_hit_callback); ruby_ports.push_back(p); } + + // polina: get DMA port here too + // hard-coded zero because only one DMASequencer per RubyMem system for now + RubyPort *dma_p = RubySystem::getPort(csprintf("DMASequencer_0"), + ruby_hit_callback); + ruby_ports.push_back(dma_p); } void @@ -236,10 +242,14 @@ RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr(), pkt->getSize(), pc, type, - RubyAccessMode_Supervisor); + RubyAccessMode_Supervisor, pkt->req->contextId()); // Submit the ruby request - RubyPort *ruby_port = ruby_mem->ruby_ports[pkt->req->contextId()]; + RubyPort *ruby_port; + if (!pkt->req->isDmaRequest()) + ruby_port = ruby_mem->ruby_ports[pkt->req->contextId()]; + else + ruby_port = ruby_mem->ruby_ports.back(); // back element should be dma port int64_t req_id = ruby_port->makeRequest(ruby_request); if (req_id == -1) { RubyMemory::SenderState *senderState =