mem,ext: Integrating DRAMSim3 with gem5
Adding DRAMSim3 source code to the gem5 source code, the original code was taken from umd-memsys github at https://github.com/umd-memsys/ Change-Id: I32c982206f33b0acf2121f322d15baa064c412c4 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31757 Reviewed-by: Ayaz Akram <yazakram@ucdavis.edu> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
14
ext/dramsim3/README
Normal file
14
ext/dramsim3/README
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Follow these steps to get DRAMSim3 as part of gem5
|
||||||
|
|
||||||
|
1. Download DRAMSim3
|
||||||
|
1.1 Go to ext/dramsim3 (this directory)
|
||||||
|
1.2 Clone DRAMSim3: git clone git@github.com:umd-memsys/DRAMSim3.git DRAMsim3
|
||||||
|
1.3 cd DRAMSim3 && mkdir build
|
||||||
|
1.4 cd build
|
||||||
|
1.5 cmake ..
|
||||||
|
1.6 make
|
||||||
|
|
||||||
|
2. Compile gem5
|
||||||
|
2.1 cd gem5
|
||||||
|
2.2 Business as usual
|
||||||
|
|
||||||
69
ext/dramsim3/SConscript
Normal file
69
ext/dramsim3/SConscript
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# -*- mode:python -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2013 ARM Limited
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# The license below extends only to copyright in the software and shall
|
||||||
|
# not be construed as granting a license to any other intellectual
|
||||||
|
# property including but not limited to intellectual property relating
|
||||||
|
# to a hardware implementation of the functionality of the software
|
||||||
|
# licensed hereunder. You may use the software subject to the license
|
||||||
|
# terms below provided that you ensure that this notice is replicated
|
||||||
|
# unmodified and in its entirety in all distributions of the software,
|
||||||
|
# modified or unmodified, in source code or in binary form.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met: redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer;
|
||||||
|
# redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution;
|
||||||
|
# neither the name of the copyright holders nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
Import('main')
|
||||||
|
|
||||||
|
thermal = False
|
||||||
|
|
||||||
|
# See if we got a cloned DRAMSim3 repo as a subdirectory and set the
|
||||||
|
# HAVE_DRAMSIM flag accordingly
|
||||||
|
if not os.path.exists(Dir('.').srcnode().abspath + '/DRAMsim3'):
|
||||||
|
main['HAVE_DRAMSIM3'] = False
|
||||||
|
Return()
|
||||||
|
|
||||||
|
# We have got the folder, so add the library and build the wrappers
|
||||||
|
main['HAVE_DRAMSIM3'] = True
|
||||||
|
|
||||||
|
|
||||||
|
dramsim_path = os.path.join(Dir('#').abspath, 'ext/dramsim3/DRAMsim3/')
|
||||||
|
|
||||||
|
if thermal:
|
||||||
|
superlu_path = os.path.join(dramsim_path, 'ext/SuperLU_MT_3.1/lib')
|
||||||
|
main.Prepend(CPPPATH=Dir('.'))
|
||||||
|
main.Append(LIBS=['dramsim3', 'superlu_mt_OPENMP', 'm', 'f77blas',
|
||||||
|
'atlas', 'gomp'],
|
||||||
|
LIBPATH=[dramsim_path, superlu_path])
|
||||||
|
else:
|
||||||
|
main.Prepend(CPPPATH=Dir('.'))
|
||||||
|
# a littel hacky but can get a shared library working
|
||||||
|
main.Append(LIBS=['dramsim3', 'gomp'],
|
||||||
|
LIBPATH=[dramsim_path], # compile-time lookup
|
||||||
|
RPATH=[dramsim_path], # runtime lookup
|
||||||
|
CPPPATH=[dramsim_path+'/src/'])
|
||||||
54
src/mem/DRAMsim3.py
Normal file
54
src/mem/DRAMsim3.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Copyright (c) 2013 ARM Limited
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# The license below extends only to copyright in the software and shall
|
||||||
|
# not be construed as granting a license to any other intellectual
|
||||||
|
# property including but not limited to intellectual property relating
|
||||||
|
# to a hardware implementation of the functionality of the software
|
||||||
|
# licensed hereunder. You may use the software subject to the license
|
||||||
|
# terms below provided that you ensure that this notice is replicated
|
||||||
|
# unmodified and in its entirety in all distributions of the software,
|
||||||
|
# modified or unmodified, in source code or in binary form.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met: redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer;
|
||||||
|
# redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution;
|
||||||
|
# neither the name of the copyright holders nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# Authors: Andreas Hansson
|
||||||
|
|
||||||
|
from m5.params import *
|
||||||
|
from m5.objects.AbstractMemory import *
|
||||||
|
|
||||||
|
# A wrapper for DRAMSim3 multi-channel memory controller
|
||||||
|
class DRAMsim3(AbstractMemory):
|
||||||
|
type = 'DRAMsim3'
|
||||||
|
cxx_header = "mem/dramsim3.hh"
|
||||||
|
|
||||||
|
# A single port for now
|
||||||
|
port = ResponsePort("port for receiving requests from"
|
||||||
|
"the CPU or other requestor")
|
||||||
|
|
||||||
|
configFile = Param.String("ext/dramsim3/DRAMsim3/configs/"
|
||||||
|
"DDR4_8Gb_x8_2400.ini",
|
||||||
|
"The configuration file to use with DRAMSim3")
|
||||||
|
filePath = Param.String("ext/dramsim3/DRAMsim3/",
|
||||||
|
"Directory to prepend to file names")
|
||||||
@@ -91,6 +91,11 @@ if env['HAVE_DRAMSIM']:
|
|||||||
Source('dramsim2_wrapper.cc')
|
Source('dramsim2_wrapper.cc')
|
||||||
Source('dramsim2.cc')
|
Source('dramsim2.cc')
|
||||||
|
|
||||||
|
if env['HAVE_DRAMSIM3']:
|
||||||
|
SimObject('DRAMsim3.py')
|
||||||
|
Source('dramsim3_wrapper.cc')
|
||||||
|
Source('dramsim3.cc')
|
||||||
|
|
||||||
SimObject('MemChecker.py')
|
SimObject('MemChecker.py')
|
||||||
Source('mem_checker.cc')
|
Source('mem_checker.cc')
|
||||||
Source('mem_checker_monitor.cc')
|
Source('mem_checker_monitor.cc')
|
||||||
@@ -115,6 +120,7 @@ DebugFlag('MemoryAccess')
|
|||||||
DebugFlag('PacketQueue')
|
DebugFlag('PacketQueue')
|
||||||
DebugFlag('StackDist')
|
DebugFlag('StackDist')
|
||||||
DebugFlag("DRAMSim2")
|
DebugFlag("DRAMSim2")
|
||||||
|
DebugFlag("DRAMsim3")
|
||||||
DebugFlag('HMCController')
|
DebugFlag('HMCController')
|
||||||
DebugFlag('SerialLink')
|
DebugFlag('SerialLink')
|
||||||
DebugFlag('TokenPort')
|
DebugFlag('TokenPort')
|
||||||
|
|||||||
395
src/mem/dramsim3.cc
Normal file
395
src/mem/dramsim3.cc
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 ARM Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* The license below extends only to copyright in the software and shall
|
||||||
|
* not be construed as granting a license to any other intellectual
|
||||||
|
* property including but not limited to intellectual property relating
|
||||||
|
* to a hardware implementation of the functionality of the software
|
||||||
|
* licensed hereunder. You may use the software subject to the license
|
||||||
|
* terms below provided that you ensure that this notice is replicated
|
||||||
|
* unmodified and in its entirety in all distributions of the software,
|
||||||
|
* modified or unmodified, in source code or in binary form.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Authors: Andreas Hansson
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mem/dramsim3.hh"
|
||||||
|
|
||||||
|
#include "base/callback.hh"
|
||||||
|
#include "base/trace.hh"
|
||||||
|
#include "debug/DRAMsim3.hh"
|
||||||
|
#include "debug/Drain.hh"
|
||||||
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
DRAMsim3::DRAMsim3(const Params* p) :
|
||||||
|
AbstractMemory(p),
|
||||||
|
port(name() + ".port", *this),
|
||||||
|
read_cb(std::bind(&DRAMsim3::readComplete,
|
||||||
|
this, 0, std::placeholders::_1)),
|
||||||
|
write_cb(std::bind(&DRAMsim3::writeComplete,
|
||||||
|
this, 0, std::placeholders::_1)),
|
||||||
|
wrapper(p->configFile, p->filePath, read_cb, write_cb),
|
||||||
|
retryReq(false), retryResp(false), startTick(0),
|
||||||
|
nbrOutstandingReads(0), nbrOutstandingWrites(0),
|
||||||
|
sendResponseEvent([this]{ sendResponse(); }, name()),
|
||||||
|
tickEvent([this]{ tick(); }, name())
|
||||||
|
{
|
||||||
|
DPRINTF(DRAMsim3,
|
||||||
|
"Instantiated DRAMsim3 with clock %d ns and queue size %d\n",
|
||||||
|
wrapper.clockPeriod(), wrapper.queueSize());
|
||||||
|
|
||||||
|
// Register a callback to compensate for the destructor not
|
||||||
|
// being called. The callback prints the DRAMsim3 stats.
|
||||||
|
registerExitCallback([this]() { wrapper.printStats(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::init()
|
||||||
|
{
|
||||||
|
AbstractMemory::init();
|
||||||
|
|
||||||
|
if (!port.isConnected()) {
|
||||||
|
fatal("DRAMsim3 %s is unconnected!\n", name());
|
||||||
|
} else {
|
||||||
|
port.sendRangeChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (system()->cacheLineSize() != wrapper.burstSize())
|
||||||
|
fatal("DRAMsim3 burst size %d does not match cache line size %d\n",
|
||||||
|
wrapper.burstSize(), system()->cacheLineSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::startup()
|
||||||
|
{
|
||||||
|
startTick = curTick();
|
||||||
|
|
||||||
|
// kick off the clock ticks
|
||||||
|
schedule(tickEvent, clockEdge());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::resetStats() {
|
||||||
|
wrapper.resetStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::sendResponse()
|
||||||
|
{
|
||||||
|
assert(!retryResp);
|
||||||
|
assert(!responseQueue.empty());
|
||||||
|
|
||||||
|
DPRINTF(DRAMsim3, "Attempting to send response\n");
|
||||||
|
|
||||||
|
bool success = port.sendTimingResp(responseQueue.front());
|
||||||
|
if (success) {
|
||||||
|
responseQueue.pop_front();
|
||||||
|
|
||||||
|
DPRINTF(DRAMsim3, "Have %d read, %d write, %d responses outstanding\n",
|
||||||
|
nbrOutstandingReads, nbrOutstandingWrites,
|
||||||
|
responseQueue.size());
|
||||||
|
|
||||||
|
if (!responseQueue.empty() && !sendResponseEvent.scheduled())
|
||||||
|
schedule(sendResponseEvent, curTick());
|
||||||
|
|
||||||
|
if (nbrOutstanding() == 0)
|
||||||
|
signalDrainDone();
|
||||||
|
} else {
|
||||||
|
retryResp = true;
|
||||||
|
|
||||||
|
DPRINTF(DRAMsim3, "Waiting for response retry\n");
|
||||||
|
|
||||||
|
assert(!sendResponseEvent.scheduled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
DRAMsim3::nbrOutstanding() const
|
||||||
|
{
|
||||||
|
return nbrOutstandingReads + nbrOutstandingWrites + responseQueue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::tick()
|
||||||
|
{
|
||||||
|
// Only tick when it's timing mode
|
||||||
|
if (system()->isTimingMode()) {
|
||||||
|
wrapper.tick();
|
||||||
|
|
||||||
|
// is the connected port waiting for a retry, if so check the
|
||||||
|
// state and send a retry if conditions have changed
|
||||||
|
if (retryReq && nbrOutstanding() < wrapper.queueSize()) {
|
||||||
|
retryReq = false;
|
||||||
|
port.sendRetryReq();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
schedule(tickEvent, curTick() + wrapper.clockPeriod() * SimClock::Int::ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tick
|
||||||
|
DRAMsim3::recvAtomic(PacketPtr pkt)
|
||||||
|
{
|
||||||
|
access(pkt);
|
||||||
|
|
||||||
|
// 50 ns is just an arbitrary value at this point
|
||||||
|
return pkt->cacheResponding() ? 0 : 50000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::recvFunctional(PacketPtr pkt)
|
||||||
|
{
|
||||||
|
pkt->pushLabel(name());
|
||||||
|
|
||||||
|
functionalAccess(pkt);
|
||||||
|
|
||||||
|
// potentially update the packets in our response queue as well
|
||||||
|
for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i)
|
||||||
|
pkt->trySatisfyFunctional(*i);
|
||||||
|
|
||||||
|
pkt->popLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DRAMsim3::recvTimingReq(PacketPtr pkt)
|
||||||
|
{
|
||||||
|
// if a cache is responding, sink the packet without further action
|
||||||
|
if (pkt->cacheResponding()) {
|
||||||
|
pendingDelete.reset(pkt);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we should not get a new request after committing to retry the
|
||||||
|
// current one, but unfortunately the CPU violates this rule, so
|
||||||
|
// simply ignore it for now
|
||||||
|
if (retryReq)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// if we cannot accept we need to send a retry once progress can
|
||||||
|
// be made
|
||||||
|
bool can_accept = nbrOutstanding() < wrapper.queueSize();
|
||||||
|
|
||||||
|
// keep track of the transaction
|
||||||
|
if (pkt->isRead()) {
|
||||||
|
if (can_accept) {
|
||||||
|
outstandingReads[pkt->getAddr()].push(pkt);
|
||||||
|
|
||||||
|
// we count a transaction as outstanding until it has left the
|
||||||
|
// queue in the controller, and the response has been sent
|
||||||
|
// back, note that this will differ for reads and writes
|
||||||
|
++nbrOutstandingReads;
|
||||||
|
}
|
||||||
|
} else if (pkt->isWrite()) {
|
||||||
|
if (can_accept) {
|
||||||
|
outstandingWrites[pkt->getAddr()].push(pkt);
|
||||||
|
|
||||||
|
++nbrOutstandingWrites;
|
||||||
|
|
||||||
|
// perform the access for writes
|
||||||
|
accessAndRespond(pkt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// keep it simple and just respond if necessary
|
||||||
|
accessAndRespond(pkt);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (can_accept) {
|
||||||
|
// we should never have a situation when we think there is space,
|
||||||
|
// and there isn't
|
||||||
|
assert(wrapper.canAccept(pkt->getAddr(), pkt->isWrite()));
|
||||||
|
|
||||||
|
DPRINTF(DRAMsim3, "Enqueueing address %lld\n", pkt->getAddr());
|
||||||
|
|
||||||
|
// @todo what about the granularity here, implicit assumption that
|
||||||
|
// a transaction matches the burst size of the memory (which we
|
||||||
|
// cannot determine without parsing the ini file ourselves)
|
||||||
|
wrapper.enqueue(pkt->getAddr(), pkt->isWrite());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
retryReq = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::recvRespRetry()
|
||||||
|
{
|
||||||
|
DPRINTF(DRAMsim3, "Retrying\n");
|
||||||
|
|
||||||
|
assert(retryResp);
|
||||||
|
retryResp = false;
|
||||||
|
sendResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::accessAndRespond(PacketPtr pkt)
|
||||||
|
{
|
||||||
|
DPRINTF(DRAMsim3, "Access for address %lld\n", pkt->getAddr());
|
||||||
|
|
||||||
|
bool needsResponse = pkt->needsResponse();
|
||||||
|
|
||||||
|
// do the actual memory access which also turns the packet into a
|
||||||
|
// response
|
||||||
|
access(pkt);
|
||||||
|
|
||||||
|
// turn packet around to go back to requester if response expected
|
||||||
|
if (needsResponse) {
|
||||||
|
// access already turned the packet into a response
|
||||||
|
assert(pkt->isResponse());
|
||||||
|
// Here we pay for xbar additional delay and to process the payload
|
||||||
|
// of the packet.
|
||||||
|
Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay;
|
||||||
|
// Reset the timings of the packet
|
||||||
|
pkt->headerDelay = pkt->payloadDelay = 0;
|
||||||
|
|
||||||
|
DPRINTF(DRAMsim3, "Queuing response for address %lld\n",
|
||||||
|
pkt->getAddr());
|
||||||
|
|
||||||
|
// queue it to be sent back
|
||||||
|
responseQueue.push_back(pkt);
|
||||||
|
|
||||||
|
// if we are not already waiting for a retry, or are scheduled
|
||||||
|
// to send a response, schedule an event
|
||||||
|
if (!retryResp && !sendResponseEvent.scheduled())
|
||||||
|
schedule(sendResponseEvent, time);
|
||||||
|
} else {
|
||||||
|
// queue the packet for deletion
|
||||||
|
pendingDelete.reset(pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DRAMsim3::readComplete(unsigned id, uint64_t addr)
|
||||||
|
{
|
||||||
|
|
||||||
|
DPRINTF(DRAMsim3, "Read to address %lld complete\n", addr);
|
||||||
|
|
||||||
|
// get the outstanding reads for the address in question
|
||||||
|
auto p = outstandingReads.find(addr);
|
||||||
|
assert(p != outstandingReads.end());
|
||||||
|
|
||||||
|
// first in first out, which is not necessarily true, but it is
|
||||||
|
// the best we can do at this point
|
||||||
|
PacketPtr pkt = p->second.front();
|
||||||
|
p->second.pop();
|
||||||
|
|
||||||
|
if (p->second.empty())
|
||||||
|
outstandingReads.erase(p);
|
||||||
|
|
||||||
|
// no need to check for drain here as the next call will add a
|
||||||
|
// response to the response queue straight away
|
||||||
|
assert(nbrOutstandingReads != 0);
|
||||||
|
--nbrOutstandingReads;
|
||||||
|
|
||||||
|
// perform the actual memory access
|
||||||
|
accessAndRespond(pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DRAMsim3::writeComplete(unsigned id, uint64_t addr)
|
||||||
|
{
|
||||||
|
|
||||||
|
DPRINTF(DRAMsim3, "Write to address %lld complete\n", addr);
|
||||||
|
|
||||||
|
// get the outstanding reads for the address in question
|
||||||
|
auto p = outstandingWrites.find(addr);
|
||||||
|
assert(p != outstandingWrites.end());
|
||||||
|
|
||||||
|
// we have already responded, and this is only to keep track of
|
||||||
|
// what is outstanding
|
||||||
|
p->second.pop();
|
||||||
|
if (p->second.empty())
|
||||||
|
outstandingWrites.erase(p);
|
||||||
|
|
||||||
|
assert(nbrOutstandingWrites != 0);
|
||||||
|
--nbrOutstandingWrites;
|
||||||
|
|
||||||
|
if (nbrOutstanding() == 0)
|
||||||
|
signalDrainDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
Port&
|
||||||
|
DRAMsim3::getPort(const std::string &if_name, PortID idx)
|
||||||
|
{
|
||||||
|
if (if_name != "port") {
|
||||||
|
return ClockedObject::getPort(if_name, idx);
|
||||||
|
} else {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DrainState
|
||||||
|
DRAMsim3::drain()
|
||||||
|
{
|
||||||
|
// check our outstanding reads and writes and if any they need to
|
||||||
|
// drain
|
||||||
|
return nbrOutstanding() != 0 ? DrainState::Draining : DrainState::Drained;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRAMsim3::MemoryPort::MemoryPort(const std::string& _name,
|
||||||
|
DRAMsim3& _memory)
|
||||||
|
: SlavePort(_name, &_memory), memory(_memory)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
AddrRangeList
|
||||||
|
DRAMsim3::MemoryPort::getAddrRanges() const
|
||||||
|
{
|
||||||
|
AddrRangeList ranges;
|
||||||
|
ranges.push_back(memory.getAddrRange());
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tick
|
||||||
|
DRAMsim3::MemoryPort::recvAtomic(PacketPtr pkt)
|
||||||
|
{
|
||||||
|
return memory.recvAtomic(pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::MemoryPort::recvFunctional(PacketPtr pkt)
|
||||||
|
{
|
||||||
|
memory.recvFunctional(pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DRAMsim3::MemoryPort::recvTimingReq(PacketPtr pkt)
|
||||||
|
{
|
||||||
|
// pass it to the memory controller
|
||||||
|
return memory.recvTimingReq(pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3::MemoryPort::recvRespRetry()
|
||||||
|
{
|
||||||
|
memory.recvRespRetry();
|
||||||
|
}
|
||||||
|
|
||||||
|
DRAMsim3*
|
||||||
|
DRAMsim3Params::create()
|
||||||
|
{
|
||||||
|
return new DRAMsim3(this);
|
||||||
|
}
|
||||||
218
src/mem/dramsim3.hh
Normal file
218
src/mem/dramsim3.hh
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 ARM Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* The license below extends only to copyright in the software and shall
|
||||||
|
* not be construed as granting a license to any other intellectual
|
||||||
|
* property including but not limited to intellectual property relating
|
||||||
|
* to a hardware implementation of the functionality of the software
|
||||||
|
* licensed hereunder. You may use the software subject to the license
|
||||||
|
* terms below provided that you ensure that this notice is replicated
|
||||||
|
* unmodified and in its entirety in all distributions of the software,
|
||||||
|
* modified or unmodified, in source code or in binary form.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* DRAMsim3
|
||||||
|
*/
|
||||||
|
#ifndef __MEM_DRAMSIM3_HH__
|
||||||
|
#define __MEM_DRAMSIM3_HH__
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "mem/abstract_mem.hh"
|
||||||
|
#include "mem/dramsim3_wrapper.hh"
|
||||||
|
#include "mem/qport.hh"
|
||||||
|
#include "params/DRAMsim3.hh"
|
||||||
|
|
||||||
|
class DRAMsim3 : public AbstractMemory
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The memory port has to deal with its own flow control to avoid
|
||||||
|
* having unbounded storage that is implicitly created in the port
|
||||||
|
* itself.
|
||||||
|
*/
|
||||||
|
class MemoryPort : public SlavePort
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
DRAMsim3& memory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MemoryPort(const std::string& _name, DRAMsim3& _memory);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Tick recvAtomic(PacketPtr pkt);
|
||||||
|
|
||||||
|
void recvFunctional(PacketPtr pkt);
|
||||||
|
|
||||||
|
bool recvTimingReq(PacketPtr pkt);
|
||||||
|
|
||||||
|
void recvRespRetry();
|
||||||
|
|
||||||
|
AddrRangeList getAddrRanges() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
MemoryPort port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback functions
|
||||||
|
*/
|
||||||
|
std::function<void(uint64_t)> read_cb;
|
||||||
|
std::function<void(uint64_t)> write_cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual DRAMsim3 wrapper
|
||||||
|
*/
|
||||||
|
DRAMsim3Wrapper wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the connected port waiting for a retry from us
|
||||||
|
*/
|
||||||
|
bool retryReq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we waiting for a retry for sending a response.
|
||||||
|
*/
|
||||||
|
bool retryResp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep track of when the wrapper is started.
|
||||||
|
*/
|
||||||
|
Tick startTick;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep track of what packets are outstanding per
|
||||||
|
* address, and do so separately for reads and writes. This is
|
||||||
|
* done so that we can return the right packet on completion from
|
||||||
|
* DRAMSim.
|
||||||
|
*/
|
||||||
|
std::unordered_map<Addr, std::queue<PacketPtr> > outstandingReads;
|
||||||
|
std::unordered_map<Addr, std::queue<PacketPtr> > outstandingWrites;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of outstanding transactions so that we can
|
||||||
|
* block any further requests until there is space in DRAMsim3 and
|
||||||
|
* the sending queue we need to buffer the response packets.
|
||||||
|
*/
|
||||||
|
unsigned int nbrOutstandingReads;
|
||||||
|
unsigned int nbrOutstandingWrites;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue to hold response packets until we can send them
|
||||||
|
* back. This is needed as DRAMsim3 unconditionally passes
|
||||||
|
* responses back without any flow control.
|
||||||
|
*/
|
||||||
|
std::deque<PacketPtr> responseQueue;
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int nbrOutstanding() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a packet is ready, use the "access()" method in
|
||||||
|
* AbstractMemory to actually create the response packet, and send
|
||||||
|
* it back to the outside world requestor.
|
||||||
|
*
|
||||||
|
* @param pkt The packet from the outside world
|
||||||
|
*/
|
||||||
|
void accessAndRespond(PacketPtr pkt);
|
||||||
|
|
||||||
|
void sendResponse();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event to schedule sending of responses
|
||||||
|
*/
|
||||||
|
EventFunctionWrapper sendResponseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Progress the controller one clock cycle.
|
||||||
|
*/
|
||||||
|
void tick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event to schedule clock ticks
|
||||||
|
*/
|
||||||
|
EventFunctionWrapper tickEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upstream caches need this packet until true is returned, so
|
||||||
|
* hold it for deletion until a subsequent call
|
||||||
|
*/
|
||||||
|
std::unique_ptr<Packet> pendingDelete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef DRAMsim3Params Params;
|
||||||
|
DRAMsim3(const Params *p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read completion callback.
|
||||||
|
*
|
||||||
|
* @param id Channel id of the responder
|
||||||
|
* @param addr Address of the request
|
||||||
|
* @param cycle Internal cycle count of DRAMsim3
|
||||||
|
*/
|
||||||
|
void readComplete(unsigned id, uint64_t addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write completion callback.
|
||||||
|
*
|
||||||
|
* @param id Channel id of the responder
|
||||||
|
* @param addr Address of the request
|
||||||
|
* @param cycle Internal cycle count of DRAMsim3
|
||||||
|
*/
|
||||||
|
void writeComplete(unsigned id, uint64_t addr);
|
||||||
|
|
||||||
|
DrainState drain() override;
|
||||||
|
|
||||||
|
virtual Port& getPort(const std::string& if_name,
|
||||||
|
PortID idx = InvalidPortID) override;
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
void startup() override;
|
||||||
|
|
||||||
|
void resetStats() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Tick recvAtomic(PacketPtr pkt);
|
||||||
|
void recvFunctional(PacketPtr pkt);
|
||||||
|
bool recvTimingReq(PacketPtr pkt);
|
||||||
|
void recvRespRetry();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __MEM_DRAMSIM3_HH__
|
||||||
153
src/mem/dramsim3_wrapper.cc
Normal file
153
src/mem/dramsim3_wrapper.cc
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 ARM Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* The license below extends only to copyright in the software and shall
|
||||||
|
* not be construed as granting a license to any other intellectual
|
||||||
|
* property including but not limited to intellectual property relating
|
||||||
|
* to a hardware implementation of the functionality of the software
|
||||||
|
* licensed hereunder. You may use the software subject to the license
|
||||||
|
* terms below provided that you ensure that this notice is replicated
|
||||||
|
* unmodified and in its entirety in all distributions of the software,
|
||||||
|
* modified or unmodified, in source code or in binary form.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When building the debug binary, we need to undo the command-line
|
||||||
|
* definition of DEBUG not to clash with DRAMsim3 print macros that
|
||||||
|
* are included for no obvious reason.
|
||||||
|
*/
|
||||||
|
#ifdef DEBUG
|
||||||
|
#undef DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mem/dramsim3_wrapper.hh"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "DRAMsim3/src/dramsim3.h"
|
||||||
|
#include "base/compiler.hh"
|
||||||
|
#include "base/logging.hh"
|
||||||
|
|
||||||
|
DRAMsim3Wrapper::DRAMsim3Wrapper(const std::string& config_file,
|
||||||
|
const std::string& working_dir,
|
||||||
|
std::function<void(uint64_t)> read_cb,
|
||||||
|
std::function<void(uint64_t)> write_cb) :
|
||||||
|
dramsim(dramsim3::GetMemorySystem(config_file, working_dir,
|
||||||
|
read_cb, write_cb)),
|
||||||
|
_clockPeriod(0.0), _queueSize(0), _burstSize(0)
|
||||||
|
{
|
||||||
|
// there is no way of getting DRAMsim3 to tell us what frequency
|
||||||
|
// it is assuming, so we have to extract it ourselves
|
||||||
|
_clockPeriod = dramsim->GetTCK();
|
||||||
|
|
||||||
|
if (!_clockPeriod)
|
||||||
|
fatal("DRAMsim3 wrapper failed to get clock\n");
|
||||||
|
|
||||||
|
// we also need to know what transaction queue size DRAMsim3 is
|
||||||
|
// using so we can stall when responses are blocked
|
||||||
|
_queueSize = dramsim->GetQueueSize();
|
||||||
|
|
||||||
|
if (!_queueSize)
|
||||||
|
fatal("DRAMsim3 wrapper failed to get queue size\n");
|
||||||
|
|
||||||
|
|
||||||
|
// finally, get the data bus bits and burst length so we can add a
|
||||||
|
// sanity check for the burst size
|
||||||
|
unsigned int dataBusBits = dramsim->GetBusBits();
|
||||||
|
unsigned int burstLength = dramsim->GetBurstLength();
|
||||||
|
|
||||||
|
if (!dataBusBits || !burstLength)
|
||||||
|
fatal("DRAMsim3 wrapper failed to get burst size\n");
|
||||||
|
|
||||||
|
_burstSize = dataBusBits * burstLength / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRAMsim3Wrapper::~DRAMsim3Wrapper()
|
||||||
|
{
|
||||||
|
delete dramsim;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3Wrapper::printStats()
|
||||||
|
{
|
||||||
|
dramsim->PrintStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3Wrapper::resetStats()
|
||||||
|
{
|
||||||
|
dramsim->ResetStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3Wrapper::setCallbacks(std::function<void(uint64_t)> read_complete,
|
||||||
|
std::function<void(uint64_t)> write_complete)
|
||||||
|
{
|
||||||
|
dramsim->RegisterCallbacks(read_complete, write_complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DRAMsim3Wrapper::canAccept(uint64_t addr, bool is_write) const
|
||||||
|
{
|
||||||
|
return dramsim->WillAcceptTransaction(addr, is_write);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3Wrapper::enqueue(uint64_t addr, bool is_write)
|
||||||
|
{
|
||||||
|
bool success M5_VAR_USED = dramsim->AddTransaction(addr, is_write);
|
||||||
|
assert(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
DRAMsim3Wrapper::clockPeriod() const
|
||||||
|
{
|
||||||
|
return _clockPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
DRAMsim3Wrapper::queueSize() const
|
||||||
|
{
|
||||||
|
return _queueSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
DRAMsim3Wrapper::burstSize() const
|
||||||
|
{
|
||||||
|
return _burstSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DRAMsim3Wrapper::tick()
|
||||||
|
{
|
||||||
|
dramsim->ClockTick();
|
||||||
|
}
|
||||||
|
|
||||||
160
src/mem/dramsim3_wrapper.hh
Normal file
160
src/mem/dramsim3_wrapper.hh
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 ARM Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* The license below extends only to copyright in the software and shall
|
||||||
|
* not be construed as granting a license to any other intellectual
|
||||||
|
* property including but not limited to intellectual property relating
|
||||||
|
* to a hardware implementation of the functionality of the software
|
||||||
|
* licensed hereunder. You may use the software subject to the license
|
||||||
|
* terms below provided that you ensure that this notice is replicated
|
||||||
|
* unmodified and in its entirety in all distributions of the software,
|
||||||
|
* modified or unmodified, in source code or in binary form.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* DRAMsim3Wrapper declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MEM_DRAMSIM3_WRAPPER_HH__
|
||||||
|
#define __MEM_DRAMSIM3_WRAPPER_HH__
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward declaration to avoid includes
|
||||||
|
*/
|
||||||
|
namespace dramsim3 {
|
||||||
|
|
||||||
|
class MemorySystem;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class to avoid having DRAMsim3 names like ClockDomain etc
|
||||||
|
* clashing with the normal gem5 world. Many of the DRAMsim3 headers
|
||||||
|
* do not make use of namespaces, and quite a few also open up
|
||||||
|
* std. The only thing that needs to be exposed externally are the
|
||||||
|
* callbacks. This wrapper effectively avoids clashes by not including
|
||||||
|
* any of the conventional gem5 headers (e.g. Packet or SimObject).
|
||||||
|
*/
|
||||||
|
class DRAMsim3Wrapper
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
dramsim3::MemorySystem* dramsim;
|
||||||
|
|
||||||
|
double _clockPeriod;
|
||||||
|
|
||||||
|
unsigned int _queueSize;
|
||||||
|
|
||||||
|
unsigned int _burstSize;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T extractConfig(const std::string& field_name,
|
||||||
|
const std::string& file_name) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of the DRAMsim3 multi-channel memory
|
||||||
|
* controller using a specific config and system description.
|
||||||
|
*
|
||||||
|
* @param config_file Memory config file
|
||||||
|
* @param working_dir Path pre-pended to config files
|
||||||
|
*/
|
||||||
|
DRAMsim3Wrapper(const std::string& config_file,
|
||||||
|
const std::string& working_dir,
|
||||||
|
std::function<void(uint64_t)> read_cb,
|
||||||
|
std::function<void(uint64_t)> write_cb);
|
||||||
|
~DRAMsim3Wrapper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the stats gathered in DRAMsim3.
|
||||||
|
*/
|
||||||
|
void printStats();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset stats (useful for fastforwarding switch)
|
||||||
|
*/
|
||||||
|
void resetStats();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the callbacks to use for read and write completion.
|
||||||
|
*
|
||||||
|
* @param read_callback Callback used for read completions
|
||||||
|
* @param write_callback Callback used for write completions
|
||||||
|
*/
|
||||||
|
void setCallbacks(std::function<void(uint64_t)> read_complete,
|
||||||
|
std::function<void(uint64_t)> write_complete);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the controller can accept a new packet or not.
|
||||||
|
*
|
||||||
|
* @return true if the controller can accept transactions
|
||||||
|
*/
|
||||||
|
bool canAccept(uint64_t addr, bool is_write) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue a packet. This assumes that canAccept has returned true.
|
||||||
|
*
|
||||||
|
* @param pkt Packet to turn into a DRAMsim3 transaction
|
||||||
|
*/
|
||||||
|
void enqueue(uint64_t addr, bool is_write);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the internal clock period used by DRAMsim3, specified in
|
||||||
|
* ns.
|
||||||
|
*
|
||||||
|
* @return The clock period of the DRAM interface in ns
|
||||||
|
*/
|
||||||
|
double clockPeriod() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the transaction queue size used by DRAMsim3.
|
||||||
|
*
|
||||||
|
* @return The queue size counted in number of transactions
|
||||||
|
*/
|
||||||
|
unsigned int queueSize() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the burst size in bytes used by DRAMsim3.
|
||||||
|
*
|
||||||
|
* @return The burst size in bytes (data width * burst length)
|
||||||
|
*/
|
||||||
|
unsigned int burstSize() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Progress the memory controller one cycle
|
||||||
|
*/
|
||||||
|
void tick();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__MEM_DRAMSIM3_WRAPPER_HH__
|
||||||
Reference in New Issue
Block a user