Merge branch 'master' into master
This commit is contained in:
@@ -180,7 +180,7 @@ public:
|
||||
using AUTO_REFRESH::AUTO_REFRESH;
|
||||
protected:
|
||||
virtual QString Name() const override {return "REFA";}
|
||||
virtual bool isBankwise() const {return false;}
|
||||
virtual bool isBankwise() const override {return false;}
|
||||
};
|
||||
|
||||
class REFB : public AUTO_REFRESH
|
||||
@@ -201,7 +201,7 @@ protected:
|
||||
virtual std::vector<traceTime> getTimesOnCommandBus() const {return {span.Begin()};}
|
||||
virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const override {Q_UNUSED(drawingProperties) return getPhaseColor();}
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(10);}
|
||||
virtual bool isBankwise() const {return false;}
|
||||
virtual bool isBankwise() const override {return false;}
|
||||
};
|
||||
|
||||
class PDNAB : public Phase
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
using PDNAB::PDNAB;
|
||||
protected:
|
||||
virtual QString Name() const override {return "PDNA";}
|
||||
virtual bool isBankwise() const {return false;}
|
||||
virtual bool isBankwise() const override {return false;}
|
||||
};
|
||||
|
||||
class PDNPB : public Phase
|
||||
@@ -243,7 +243,7 @@ public:
|
||||
using PDNPB::PDNPB;
|
||||
protected:
|
||||
virtual QString Name() const override {return "PDNP";}
|
||||
virtual bool isBankwise() const {return false;}
|
||||
virtual bool isBankwise() const override {return false;}
|
||||
};
|
||||
|
||||
class SREFB : public Phase
|
||||
@@ -251,8 +251,8 @@ class SREFB : public Phase
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QString Name() const {return "SREFB";}
|
||||
virtual Qt::BrushStyle getBrushStyle() const {return Qt::Dense1Pattern;}
|
||||
virtual QString Name() const override {return "SREFB";}
|
||||
virtual Qt::BrushStyle getBrushStyle() const override {return Qt::Dense1Pattern;}
|
||||
virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const override {Q_UNUSED(drawingProperties) return getPhaseColor();}
|
||||
virtual QColor getPhaseColor() const override {return QColor(Qt::black);}
|
||||
virtual Phase::PhaseSymbol getPhaseSymbol() const override {return PhaseSymbol::Rect;}
|
||||
@@ -264,7 +264,7 @@ public:
|
||||
using SREFB::SREFB;
|
||||
protected:
|
||||
virtual QString Name() const override {return "SREF";}
|
||||
virtual bool isBankwise() const {return false;}
|
||||
virtual bool isBankwise() const override {return false;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#ifndef TIMESPAN_H
|
||||
#define TIMESPAN_H
|
||||
#include <QString>
|
||||
#include <cstdlib>
|
||||
#include "tracetime.h"
|
||||
|
||||
class Timespan
|
||||
@@ -47,7 +48,7 @@ class Timespan
|
||||
public:
|
||||
|
||||
Timespan(traceTime begin = 0, traceTime end = 0) : begin(begin), end(end){}
|
||||
traceTime timeCovered() const{return abs(End()-Begin());}
|
||||
traceTime timeCovered() const{return std::abs(End()-Begin());}
|
||||
traceTime Begin() const{return begin;}
|
||||
void setBegin(traceTime time){begin = time;}
|
||||
traceTime End() const{return end;}
|
||||
|
||||
@@ -48,7 +48,7 @@ INCLUDEPATH += ../simulator/src/common/third_party/DRAMPower/src/libdrampower
|
||||
INCLUDEPATH += $${gem5_root}/build/$${gem5_arch}/
|
||||
INCLUDEPATH += $${gem5_root}/util/tlm/examples/slave_port
|
||||
INCLUDEPATH += $${gem5_root}/util/tlm/examples/common
|
||||
INCLUDEPATH += $${gem5_root}/util/tlm/
|
||||
INCLUDEPATH += $${gem5_root}/util/tlm/src/
|
||||
INCLUDEPATH += $${gem5_root}/util/systemc
|
||||
|
||||
LIBS += -L$${systemc_home}/lib-$${systemc_target_arch} -lsystemc
|
||||
@@ -63,13 +63,13 @@ SOURCES += $${gem5_root}/util/systemc/sc_module.cc
|
||||
SOURCES += $${gem5_root}/util/systemc/stats.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/examples/common/cli_parser.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/examples/common/report_handler.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/master_transactor.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/sc_master_port.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/sc_slave_port.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/slave_transactor.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/sc_ext.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/sc_mm.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/sim_control.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/src/master_transactor.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/src/sc_master_port.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/src/sc_slave_port.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/src/slave_transactor.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/src/sc_ext.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/src/sc_mm.cc
|
||||
SOURCES += $${gem5_root}/util/tlm/src/sim_control.cc
|
||||
|
||||
SOURCES += main.cpp
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ SOURCES += \
|
||||
src/controller/scheduler/PARBS.cpp \
|
||||
src/controller/scheduler/Fr_Fcfs.cpp \
|
||||
src/controller/scheduler/Fifo.cpp \
|
||||
src/controller/scheduler/SMS.cpp \
|
||||
src/controller/core/refresh/RefreshManagerBankwise.cpp \
|
||||
src/controller/core/refresh/RefreshManager.cpp \
|
||||
src/controller/core/scheduling/checker/WriteChecker.cpp \
|
||||
@@ -135,6 +136,7 @@ HEADERS += \
|
||||
src/controller/scheduler/PARBS.h \
|
||||
src/controller/scheduler/Fr_Fcfs.h \
|
||||
src/controller/scheduler/Fifo.h \
|
||||
src/controller/scheduler/SMS.h \
|
||||
src/controller/Controller.h \
|
||||
src/controller/core/refresh/RefreshManagerBankwise.h \
|
||||
src/controller/core/refresh/RefreshManager.h \
|
||||
|
||||
16
DRAMSys/simulator/resources/configs/mcconfigs/sms.xml
Normal file
16
DRAMSys/simulator/resources/configs/mcconfigs/sms.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<mcconfig>
|
||||
<BankwiseLogic value="0"/>
|
||||
<OpenPagePolicy value="1" />
|
||||
<MaxNrOfTransactions value="20" />
|
||||
<Scheduler value="SMS" />
|
||||
<SJFProbability value="50" />
|
||||
<RequestBufferSize value = "10" />
|
||||
<PowerDownMode value="NoPowerDown" /> <!-- 4 Modes: NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF -->
|
||||
<PowerDownTimeout value="100" />
|
||||
<!-- Error Modelling -->
|
||||
<ErrorChipSeed value="42" />
|
||||
<ErrorCSVFile value="../../DRAMSys/simulator/src/error/error.csv" />
|
||||
<!-- Modes: NoStorage, Store (store data without errormodel), ErrorModel (store data with errormodel) -->
|
||||
<StoreMode value="NoStorage" />
|
||||
<ControllerCoreDisableRefresh value="0"/>
|
||||
</mcconfig>
|
||||
14
DRAMSys/simulator/resources/configs/simulator/sms.xml
Normal file
14
DRAMSys/simulator/resources/configs/simulator/sms.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<simconfig>
|
||||
<SimulationName value="sms" />
|
||||
<Debug value="0" />
|
||||
<DatabaseRecording value="1" />
|
||||
<PowerAnalysis value="1" />
|
||||
<EnableWindowing value = "1" />
|
||||
<WindowSize value="1000" />
|
||||
<ThermalSimulation value="0"/>
|
||||
<SimulationProgressBar value="1"/>
|
||||
<NumberOfMemChannels value="4"/>
|
||||
<NumberOfDevicesOnDIMM value = "1" />
|
||||
<CheckTLM2Protocol value = "0" />
|
||||
</simconfig>
|
||||
|
||||
@@ -7,6 +7,7 @@ OTHER_FILES += resources/simulations/ddr3-single-device.xml
|
||||
OTHER_FILES += resources/simulations/wideio-example.xml
|
||||
OTHER_FILES += resources/simulations/wideio-ecc.xml
|
||||
OTHER_FILES += resources/simulations/ddr3-ecc.xml
|
||||
OTHER_FILES += resources/simulations/sms-example.xml
|
||||
|
||||
# Simulator Files
|
||||
OTHER_FILES += resources/configs/simulator/wideio.xml
|
||||
@@ -15,6 +16,7 @@ OTHER_FILES += resources/configs/simulator/ddr3-single-device.xml
|
||||
OTHER_FILES += resources/configs/simulator/wideio_thermal.xml
|
||||
OTHER_FILES += resources/configs/simulator/wideio_ecc.xml
|
||||
OTHER_FILES += resources/configs/simulator/ddr3_ecc.xml
|
||||
OTHER_FILES += resources/configs/simulator/sms.xml
|
||||
|
||||
# Scripts
|
||||
OTHER_FILES += resources/scripts/address_scrambler.pl
|
||||
@@ -63,6 +65,10 @@ OTHER_FILES += resources/traces/ddr3_example.stl
|
||||
OTHER_FILES += resources/traces/ddr3_single_dev_example.stl
|
||||
OTHER_FILES += resources/traces/ddr3_SAMSUNG_M471B5674QH0_DIMM_example.stl
|
||||
OTHER_FILES += resources/traces/test_ecc.stl
|
||||
OTHER_FILES += resources/traces/sms_t1.stl
|
||||
OTHER_FILES += resources/traces/sms_t2.stl
|
||||
OTHER_FILES += resources/traces/sms_t3.stl
|
||||
OTHER_FILES += resources/traces/sms_t4.stl
|
||||
|
||||
# Memory Controller Configs
|
||||
OTHER_FILES += resources/configs/mcconfigs/fifoStrict.xml
|
||||
@@ -70,6 +76,7 @@ OTHER_FILES += resources/configs/mcconfigs/fifo.xml
|
||||
OTHER_FILES += resources/configs/mcconfigs/fr_fcfs.xml
|
||||
OTHER_FILES += resources/configs/mcconfigs/par_bs.xml
|
||||
OTHER_FILES += resources/configs/mcconfigs/fifo_ecc.xml
|
||||
OTHER_FILES += resources/configs/mcconfigs/sms.xml
|
||||
|
||||
# Memspecs
|
||||
OTHER_FILES += resources/configs/memspecs/memspec.dtd
|
||||
|
||||
21
DRAMSys/simulator/resources/scripts/memoryHog.pl
Normal file
21
DRAMSys/simulator/resources/scripts/memoryHog.pl
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl -w
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
open(LINEAR, "> ../traces/linear.stl");
|
||||
open(RANDOM, "> ../traces/random.stl");
|
||||
|
||||
my $length = shift || die ("please give length of traces");
|
||||
my $size = 0x40;
|
||||
|
||||
for(my $i=0; $i < $length; $i++)
|
||||
{
|
||||
my $r = int(rand($length));
|
||||
#print $r." ".($size*$r)."\n";
|
||||
print LINEAR "$i: read ".sprintf("0x%x",($size*$i))."\n";
|
||||
print RANDOM "$i: read ".sprintf("0x%x",($size*$r))."\n";
|
||||
}
|
||||
|
||||
|
||||
close(LINEAR);
|
||||
close(RANDOM);
|
||||
26
DRAMSys/simulator/resources/simulations/sms-example.xml
Normal file
26
DRAMSys/simulator/resources/simulations/sms-example.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<simulation>
|
||||
<!-- General Simulator Configuration (used for all simulation setups) -->
|
||||
<simconfig src="sms.xml" />
|
||||
|
||||
<!-- Temperature Simulator Configuration (used for all simulation setups) -->
|
||||
<thermalconfig src="config.xml" />
|
||||
|
||||
<memspec src="wideio.xml"></memspec>
|
||||
|
||||
<addressmapping src="am_wideio.xml"></addressmapping>
|
||||
|
||||
<mcconfig src="sms.xml"/>
|
||||
|
||||
<tracesetup id="sms">
|
||||
<device clkMhz="200">ddr3_example.stl</device>
|
||||
<device clkMhz="200">sms_t1.stl</device>
|
||||
<device clkMhz="200">sms_t2.stl</device>
|
||||
<device clkMhz="200">sms_t3.stl</device>
|
||||
<device clkMhz="200">sms_t4.stl</device>
|
||||
<device clkMhz="200">stream.stl</device>
|
||||
<device clkMhz="200">random.stl</device>
|
||||
<device clkMhz="200">chstone-adpcm_32.stl</device>
|
||||
</tracesetup>
|
||||
|
||||
</simulation>
|
||||
|
||||
@@ -343,7 +343,7 @@ void tlm2_base_protocol_checker<BUSWIDTH>::
|
||||
|
||||
BOILERPLATE
|
||||
b_transport_pre_checks(
|
||||
tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
|
||||
tlm::tlm_generic_payload& trans, sc_core::sc_time& /*delay*/)
|
||||
{
|
||||
++ m_map[&trans].b_call;
|
||||
|
||||
@@ -372,7 +372,7 @@ b_transport_pre_checks(
|
||||
|
||||
BOILERPLATE
|
||||
b_transport_post_checks(
|
||||
tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
|
||||
tlm::tlm_generic_payload& trans, sc_core::sc_time& /*delay*/)
|
||||
{
|
||||
check_response_path(trans, "b_transport");
|
||||
check_trans_not_modified(trans, "b_transport");
|
||||
@@ -914,7 +914,7 @@ get_direct_mem_ptr_pre_checks(
|
||||
|
||||
|
||||
BOILERPLATE
|
||||
get_direct_mem_ptr_post_checks( tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data )
|
||||
get_direct_mem_ptr_post_checks( tlm::tlm_generic_payload& trans, tlm::tlm_dmi& /*dmi_data*/ )
|
||||
{
|
||||
tlm::tlm_generic_payload* init = m_map[&trans].gp;
|
||||
|
||||
|
||||
@@ -53,6 +53,10 @@ void Controller::buildScheduler()
|
||||
{
|
||||
scheduler = new FR_FCFS(*controllerCore);
|
||||
}
|
||||
else if (selectedScheduler == "SMS")
|
||||
{
|
||||
scheduler = new SMS("SMS", *controllerCore, Configuration::getInstance().SJFProbability);
|
||||
}
|
||||
//else if (selectedScheduler == "PAR_BS")
|
||||
//{
|
||||
// scheduler = new PAR_BS(*controllerCore,Configuration::getInstance().RefreshAwareScheduling,
|
||||
@@ -296,6 +300,11 @@ void Controller::frontendPEQCallback(tlm_generic_payload &payload, const tlm_pha
|
||||
scheduler->schedule(&payload);
|
||||
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
|
||||
}
|
||||
else if (phase == PendingRequest)
|
||||
{
|
||||
// Schedule a pending request.
|
||||
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
if (backpressure != NULL)
|
||||
@@ -361,6 +370,7 @@ void Controller::scheduleNextFromScheduler(Bank bank)
|
||||
return;
|
||||
}
|
||||
|
||||
bool rescheduled = true;
|
||||
pair<Command, tlm::tlm_generic_payload*> nextRequest = scheduler->getNextRequest(bank);
|
||||
if(nextRequest.second != NULL)
|
||||
{
|
||||
@@ -368,7 +378,17 @@ void Controller::scheduleNextFromScheduler(Bank bank)
|
||||
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
|
||||
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(nextRequest.first) + "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
gp* pendingRequest = scheduler->getPendingRequest(bank);
|
||||
if (pendingRequest != NULL)
|
||||
{
|
||||
rescheduled = true;
|
||||
frontendPEQ.notify(*(pendingRequest), PendingRequest, Configuration::getInstance().memSpec.clk);
|
||||
}
|
||||
}
|
||||
|
||||
queue<Bank> blocked;
|
||||
while (!blockedRequests.empty()) {
|
||||
bank = blockedRequests.front();
|
||||
blockedRequests.pop();
|
||||
@@ -379,7 +399,23 @@ void Controller::scheduleNextFromScheduler(Bank bank)
|
||||
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
|
||||
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(nextRequest.first) + "] (unblocked)");
|
||||
}
|
||||
else
|
||||
{
|
||||
gp* pendingRequest = scheduler->getPendingRequest(bank);
|
||||
if(pendingRequest != NULL)
|
||||
{
|
||||
//Pending request
|
||||
if(!rescheduled)
|
||||
{
|
||||
rescheduled = true;
|
||||
frontendPEQ.notify(*(pendingRequest), PendingRequest, Configuration::getInstance().memSpec.clk);
|
||||
}
|
||||
else
|
||||
blocked.push(bank);
|
||||
}
|
||||
}
|
||||
}
|
||||
blockedRequests = blocked;
|
||||
}
|
||||
|
||||
void Controller::sendToFrontend(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
|
||||
|
||||
@@ -67,11 +67,14 @@
|
||||
#include "scheduler/Fifo.h"
|
||||
#include "scheduler/FifoStrict.h"
|
||||
#include "scheduler/Fr_Fcfs.h"
|
||||
#include "scheduler/SMS.h"
|
||||
#include "scheduler/IScheduler.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tlm;
|
||||
|
||||
DECLARE_EXTENDED_PHASE(PendingRequest);
|
||||
|
||||
struct Controller: public sc_module, public IController
|
||||
{
|
||||
public:
|
||||
@@ -85,7 +88,7 @@ public:
|
||||
tSocket.register_transport_dbg(this, &Controller::transport_dbg);
|
||||
}
|
||||
|
||||
~Controller()
|
||||
virtual ~Controller()
|
||||
{
|
||||
delete controllerCore;
|
||||
delete scheduler;
|
||||
@@ -109,7 +112,7 @@ private:
|
||||
void buildScheduler();
|
||||
void payloadEntersSystem(tlm_generic_payload& payload);
|
||||
void payloadLeavesSystem(tlm_generic_payload& payload);
|
||||
void scheduleNextFromScheduler(Bank bank);
|
||||
void scheduleNextFromScheduler(Bank bank) override;
|
||||
|
||||
// --- FRONTEND ------
|
||||
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay);
|
||||
|
||||
@@ -55,7 +55,7 @@ class ControllerCore : public sc_module
|
||||
{
|
||||
public:
|
||||
ControllerCore(sc_module_name /*name*/, IController& controller, std::map<Bank, int>& numberOfPayloads);
|
||||
virtual ~ControllerCore() ;
|
||||
virtual ~ControllerCore();
|
||||
|
||||
void scheduleRequest(Command command, tlm::tlm_generic_payload& payload);
|
||||
void triggerRefresh(tlm::tlm_generic_payload& payload);
|
||||
|
||||
@@ -153,6 +153,14 @@ void Configuration::setParameter(std::string name, std::string value)
|
||||
MaxNrOfTransactions = string2int(value);
|
||||
else if(name == "Scheduler")
|
||||
Scheduler = value;
|
||||
else if(name == "SJFProbability")
|
||||
if (string2int(value) > 100 || string2int(value) < 0) {
|
||||
SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be between 0 and 100.").c_str());
|
||||
} else {
|
||||
SJFProbability = string2int(value);
|
||||
}
|
||||
else if (name == "RequestBufferSize")
|
||||
RequestBufferSize = string2int(value);
|
||||
else if(name == "Capsize")
|
||||
Capsize = string2int(value);
|
||||
else if(name == "PowerDownTimeout")
|
||||
|
||||
@@ -66,6 +66,8 @@ struct Configuration
|
||||
bool OpenPagePolicy = true;
|
||||
unsigned int MaxNrOfTransactions = 8;
|
||||
std::string Scheduler;
|
||||
unsigned int SJFProbability;
|
||||
unsigned int RequestBufferSize;
|
||||
unsigned int Capsize = 5;
|
||||
sc_time getPowerDownTimeout(){return powerDownTimeoutInClk*memSpec.clk;}
|
||||
EPowerDownMode PowerDownMode = EPowerDownMode::Staggered;
|
||||
|
||||
@@ -60,4 +60,9 @@ pair<Command, tlm::tlm_generic_payload*> Fifo::getNextRequest(Bank bank)
|
||||
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
|
||||
}
|
||||
|
||||
gp* Fifo::getPendingRequest(Bank bank)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
|
||||
void schedule(gp* payload) override;
|
||||
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
|
||||
virtual gp* getPendingRequest(Bank bank) override;
|
||||
|
||||
private:
|
||||
std::map<Bank, std::deque<gp*>> buffer;
|
||||
|
||||
@@ -128,3 +128,7 @@ std::pair<Command, tlm::tlm_generic_payload *> FifoStrict::getNextRequest(Bank b
|
||||
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
|
||||
}
|
||||
|
||||
gp* FifoStrict::getPendingRequest(Bank bank)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
|
||||
void schedule(gp* payload) override;
|
||||
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
|
||||
virtual gp* getPendingRequest(Bank bank) override;
|
||||
|
||||
private:
|
||||
std::deque<std::pair<Bank, tlm::tlm_generic_payload *>> buffer;
|
||||
|
||||
@@ -42,20 +42,43 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
// The FR_FCFS is descibed in a 2000 paper from Rixner et al.:
|
||||
// Memory Access Scheduling
|
||||
//
|
||||
// The FR_FCFS scheduler features for each bank in the DRAM a specific
|
||||
// scheduling buffer for example:
|
||||
//
|
||||
// Bank0: OOOOOOOO
|
||||
// Bank1: OOXXXXXX
|
||||
// ... ^ ^
|
||||
// ... | |
|
||||
// ... back |
|
||||
// ... front
|
||||
// ...
|
||||
// Bank6: OOOOO0XX
|
||||
// Bank7: XXXXXXXX
|
||||
|
||||
void FR_FCFS::schedule(gp *payload)
|
||||
{
|
||||
buffer[DramExtension::getExtension(payload).getBank()].emplace_back(payload);
|
||||
|
||||
// FIXME: Question: what if the buffer is full? IMHO the schedule function
|
||||
// should provide a true or false when the placement into the buffer worked
|
||||
// out or not (?).
|
||||
buffer[DramExtension::getExtension(payload).getBank()]
|
||||
.emplace_back(payload);
|
||||
}
|
||||
|
||||
std::pair<Command, gp*> FR_FCFS::getNextRequest(Bank bank)
|
||||
{
|
||||
// If the bank is empty like Bank0 in the example we do nothing
|
||||
if(buffer[bank].empty())
|
||||
{
|
||||
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
|
||||
}
|
||||
|
||||
// In FR_FCFS row hits have always the highest priority, therefore we search
|
||||
// for row hits. If we find a row hit, we remove the transaction from the
|
||||
// queue and send it to the DRAM.
|
||||
deque<gp*>::iterator it = FindRowHit(bank);
|
||||
if(it != buffer[bank].end())
|
||||
{
|
||||
@@ -64,9 +87,19 @@ std::pair<Command, gp*> FR_FCFS::getNextRequest(Bank bank)
|
||||
return pair<Command, gp*>(getReadWriteCommand(*payload), payload);
|
||||
}
|
||||
|
||||
return pair<Command, gp*>(getNextCommand(buffer[bank].front()), buffer[bank].front());
|
||||
// If there is no row hit, the FR_FCFS takes always the oldest transaction
|
||||
// in the buffer, i.e. the transaction in the front.
|
||||
return pair<Command, gp*>(getNextCommand(buffer[bank].front()),
|
||||
buffer[bank].front());
|
||||
}
|
||||
|
||||
// This function searches for a row hit in the scheduling queue of the specific
|
||||
// bank. If no row hit is found the end of the queue is returned.
|
||||
//
|
||||
// Note: end() Returns an iterator referring to the past-the-end element in the
|
||||
// deque container. The past-the-end element is the theoretical element that
|
||||
// would follow the last element in the deque container. It does not point to
|
||||
// any element, and thus shall not be dereferenced.
|
||||
deque<gp*>::iterator FR_FCFS::FindRowHit(Bank bank)
|
||||
{
|
||||
deque<gp*> &queue = buffer[bank];
|
||||
@@ -74,14 +107,22 @@ deque<gp*>::iterator FR_FCFS::FindRowHit(Bank bank)
|
||||
if(!controllerCore.getRowBufferStates().rowBufferIsOpen(bank))
|
||||
return queue.end();
|
||||
|
||||
// Traverse the scheduling queue of the specific bank:
|
||||
for(auto it = queue.begin(); it!=queue.end(); it++)
|
||||
{
|
||||
gp* payload = *it;
|
||||
//Found row-hit
|
||||
if(DramExtension::getRow(payload) == controllerCore.getRowBufferStates().getRowInRowBuffer(bank))
|
||||
//Found row-hit and return the according iterator
|
||||
if(DramExtension::getRow(payload)
|
||||
== controllerCore.getRowBufferStates().getRowInRowBuffer(bank))
|
||||
{
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
return queue.end();
|
||||
}
|
||||
|
||||
gp* FR_FCFS::getPendingRequest(Bank bank)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
|
||||
void schedule(gp* payload) override;
|
||||
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
|
||||
virtual gp* getPendingRequest(Bank bank) override;
|
||||
|
||||
private:
|
||||
std::map<Bank, std::deque<gp*>> buffer;
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
|
||||
virtual void schedule(gp* payload) = 0;
|
||||
virtual std::pair<Command, gp*> getNextRequest(Bank bank) = 0;
|
||||
virtual gp* getPendingRequest(Bank bank) = 0;
|
||||
static std::string sendername;
|
||||
|
||||
protected:
|
||||
|
||||
357
DRAMSys/simulator/src/controller/scheduler/SMS.cpp
Normal file
357
DRAMSys/simulator/src/controller/scheduler/SMS.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
#include "SMS.h"
|
||||
#include <random>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void SMS::schedule(gp *payload)
|
||||
{
|
||||
Thread thread = DramExtension::getExtension(payload).getThread();
|
||||
bool wasEmpty = isRequestBuffersEmpty();
|
||||
|
||||
requestBuffers[thread].emplace_back(payload);
|
||||
|
||||
if (inFlightMemRequestCounter.find(thread) == inFlightMemRequestCounter.end()) {
|
||||
inFlightMemRequestCounter[thread] = 0;
|
||||
cacheMisses[thread] = 0;
|
||||
}
|
||||
inFlightMemRequestCounter[thread]++;
|
||||
cacheMisses[thread]++;
|
||||
|
||||
if (wasEmpty) {
|
||||
newRequest.notify(SC_ZERO_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<Command, gp*> SMS::getNextRequest(Bank bank)
|
||||
{
|
||||
if (bankBuffers[bank].empty())
|
||||
{
|
||||
debugManager.printDebugMessage(name(),
|
||||
"Get next request on bank " + to_string(bank.ID()) + " : EMPTY buffer");
|
||||
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gp* payload = bankBuffers[bank].front();
|
||||
Command command = IScheduler::getNextCommand(*payload);
|
||||
if (command == Command::Read || command == Command::ReadA || command == Command::Write
|
||||
|| command == Command::WriteA)
|
||||
{
|
||||
inFlightMemRequestCounter[DramExtension::getExtension(payload).getThread()]--;
|
||||
bankBuffers[bank].pop_front();
|
||||
}
|
||||
|
||||
debugManager.printDebugMessage(name(), "Get next request on bank " + to_string(bank.ID()));
|
||||
return pair<Command, tlm::tlm_generic_payload*>(command, payload);
|
||||
}
|
||||
}
|
||||
|
||||
void SMS::batchScheduler()
|
||||
{
|
||||
sc_time memClk = Configuration::getInstance().memSpec.clk;
|
||||
std::default_random_engine generator;
|
||||
std::bernoulli_distribution distribution((double) SJFprobability / 100.0);
|
||||
|
||||
while (true)
|
||||
{
|
||||
updateMPKCs(memClk);
|
||||
if (isRequestBuffersEmpty()) {
|
||||
wait(newRequest);
|
||||
} else {
|
||||
multiBatchFormation(memClk);
|
||||
if (existReadyBatches()) {
|
||||
if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) {
|
||||
if (pickSJF()) {
|
||||
drain(memClk, (*lastSelectedThread).second.front());
|
||||
(*lastSelectedThread).second.pop_front();
|
||||
}
|
||||
} else {
|
||||
if (pickRR()) {
|
||||
drain(memClk, (*lastSelectedThread).second.front());
|
||||
(*lastSelectedThread).second.pop_front();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wait(memClk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a Thread according to Shortest-Job Policy
|
||||
* Save the picked one into lastSelectedThread
|
||||
* @return true if it can, otherwise false
|
||||
*/
|
||||
bool SMS::pickSJF()
|
||||
{
|
||||
// find threads with ready batches
|
||||
std::vector<Thread> threadsWithReadyBatches;
|
||||
for (auto& each : readyBatchIters)
|
||||
{
|
||||
if (!each.second.empty())
|
||||
{
|
||||
// marked as thread with non-empty request buffer
|
||||
threadsWithReadyBatches.push_back(each.first);
|
||||
}
|
||||
}
|
||||
|
||||
if (!threadsWithReadyBatches.empty())
|
||||
{
|
||||
// pick shortest-job thread among threads with non-empty request buffer
|
||||
Thread minThread = threadsWithReadyBatches.front();
|
||||
for (auto& thread : threadsWithReadyBatches)
|
||||
{
|
||||
if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread])
|
||||
{
|
||||
minThread = thread;
|
||||
}
|
||||
}
|
||||
|
||||
// save selected thread
|
||||
lastSelectedThread = readyBatchIters.find(minThread);
|
||||
debugManager.printDebugMessage(name(),
|
||||
"[SJF] Select ready batch of thread " + to_string(minThread.ID()));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drain the picked request buffer into bank buffers
|
||||
* by move request one-by-one from start of the request buffer till last parameter
|
||||
* @param memClk
|
||||
* @param last
|
||||
*/
|
||||
void SMS::drain(sc_time memClk, std::deque<gp*>::iterator last)
|
||||
{
|
||||
Thread selectedThread = (*lastSelectedThread).first;
|
||||
unsigned int batchSize = std::distance(requestBuffers[selectedThread].begin(), last) + 1;
|
||||
for (unsigned int i = 1; i <= batchSize; i++)
|
||||
{
|
||||
Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank();
|
||||
// if(bankBuffers[bank].size() == Configuration::getInstance().BankBufferSize)
|
||||
// {
|
||||
// wait(bankBufferIsNotFull);
|
||||
// }
|
||||
wait(memClk);
|
||||
bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front());
|
||||
requestBuffers[selectedThread].pop_front();
|
||||
|
||||
debugManager.printDebugMessage(name(),
|
||||
"[SJF] Drain request in the ready batch of thread "
|
||||
+ to_string((*lastSelectedThread).first.ID()) + " to bankbuffer "
|
||||
+ to_string(bank.ID()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a Thread according to Round-Robin Policy
|
||||
* Save the picked one into lastSelectedThread
|
||||
* @return true if it can pick one, otherwise false
|
||||
*/
|
||||
bool SMS::pickRR()
|
||||
{
|
||||
std::map<Thread, std::deque<gp_deque_iterator>>::iterator nextSelectedThread;
|
||||
if (lastSelectedThread == readyBatchIters.end())
|
||||
{
|
||||
lastSelectedThread = readyBatchIters.begin();
|
||||
nextSelectedThread = lastSelectedThread;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextSelectedThread = lastSelectedThread;
|
||||
nextSelectedThread++;
|
||||
if (nextSelectedThread == readyBatchIters.end())
|
||||
nextSelectedThread = readyBatchIters.begin();
|
||||
}
|
||||
|
||||
std::map<Thread, std::deque<gp_deque_iterator>>::iterator savedOriginalNextSelectedThread = nextSelectedThread;
|
||||
|
||||
while ((*nextSelectedThread).second.empty())
|
||||
{
|
||||
nextSelectedThread++;
|
||||
if (nextSelectedThread == readyBatchIters.end())
|
||||
{
|
||||
nextSelectedThread = readyBatchIters.begin();
|
||||
}
|
||||
|
||||
if (nextSelectedThread == savedOriginalNextSelectedThread)
|
||||
{
|
||||
// the next thread is the original thread, that mean req buffer are totally empty
|
||||
// non-existed ready batch to be picked up & drained
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// save last selected thread
|
||||
lastSelectedThread = nextSelectedThread;
|
||||
debugManager.printDebugMessage(name(),
|
||||
"[RR] Select ready batch of thread " + to_string((*nextSelectedThread).first.ID()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SMS::isSystemLightlyLoaded() {
|
||||
unsigned int totalRequest = 0;
|
||||
for (auto& bankBuffer : bankBuffers) {
|
||||
totalRequest += bankBuffer.second.size();
|
||||
}
|
||||
return (totalRequest <= LOW_SYSTEM_LOAD);
|
||||
}
|
||||
|
||||
bool SMS::existLowIntensityThread() {
|
||||
for (auto& mpkcPerThread : MPKCs) {
|
||||
if (mpkcPerThread.second < LOW_MPKC) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SMS::isThresholdAgeExceeded(Thread thread, sc_time memClk, std::deque<gp*>::iterator begin, std::deque<gp*>::iterator end) {
|
||||
// find the oldest request in the thread's batch
|
||||
sc_time oldestGenerationTime = sc_time_stamp();
|
||||
for (auto reqIter = begin; reqIter != end; reqIter++) {
|
||||
sc_time reqGenerationTime = GenerationExtension::getExtension(*reqIter).TimeOfGeneration();
|
||||
if (reqGenerationTime < oldestGenerationTime) {
|
||||
oldestGenerationTime = reqGenerationTime;
|
||||
}
|
||||
}
|
||||
|
||||
// check threshold age according to the thread's MPKC
|
||||
sc_time oldestRequestAge = sc_time_stamp() - oldestGenerationTime;
|
||||
if ((MPKCs[thread] <= MEDIUM_MPKC) && (oldestRequestAge > (MEDIUM_THRESHOLD_AGE * memClk))) {
|
||||
return true;
|
||||
} else if ((MPKCs[thread] > MEDIUM_MPKC) && (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SMS::updateMPKCs(sc_time memClk) {
|
||||
if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) {
|
||||
// reset for every 10k clk cycles
|
||||
for (auto& cacheMiss : cacheMisses) {
|
||||
MPKCs[cacheMiss.first] = 0;
|
||||
}
|
||||
debugManager.printDebugMessage(name(), "Reset MKKCs");
|
||||
} else {
|
||||
// update MPKC for every thread
|
||||
for (auto& cacheMiss : cacheMisses) {
|
||||
MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / (sc_time_stamp());
|
||||
}
|
||||
debugManager.printDebugMessage(name(), "Update MPKCs");
|
||||
}
|
||||
}
|
||||
|
||||
bool SMS::isExceededReqBufferSize(Thread thread) {
|
||||
return requestBuffers[thread].size() == Configuration::getInstance().RequestBufferSize;
|
||||
}
|
||||
|
||||
bool SMS::isRequestBuffersEmpty() {
|
||||
for (auto& requestBuffer : requestBuffers) {
|
||||
if (!requestBuffer.second.empty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SMS::existReadyBatches() {
|
||||
for (auto& each : readyBatchIters) {
|
||||
if (!each.second.empty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form batch from begin iterator parameter of a request buffer
|
||||
* If this batch is deemed ready, save the iterator pointing to its last element
|
||||
* @param memClk
|
||||
* @param begin
|
||||
* @return true if this batch is ready, otherwise false
|
||||
*/
|
||||
bool SMS::batchFormation(sc_time memClk, std::pair<Thread, std::deque<gp*>> &requestBuffer,
|
||||
std::deque<gp*>::iterator beginIter)
|
||||
{
|
||||
if (requestBuffer.second.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requestBuffer.second.end() == beginIter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MPKCs[requestBuffer.first] < LOW_MPKC || isSystemLightlyLoaded())
|
||||
{
|
||||
// bypass requests by forming batch with only one request (threshold age is ZERO)
|
||||
readyBatchIters[requestBuffer.first].push_back(beginIter);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// forming batch with FIFO size & threshold age constraints
|
||||
auto firstDifferentRowAccessReqIter = beginIter;
|
||||
Row firstRow = DramExtension::getRow(*beginIter);
|
||||
while (firstDifferentRowAccessReqIter != requestBuffer.second.end()
|
||||
&& DramExtension::getRow(*firstDifferentRowAccessReqIter) == firstRow)
|
||||
{
|
||||
firstDifferentRowAccessReqIter++;
|
||||
}
|
||||
|
||||
// deem this batch ready
|
||||
if ((firstDifferentRowAccessReqIter != requestBuffer.second.end())
|
||||
|| isExceededReqBufferSize(requestBuffer.first)
|
||||
|| isThresholdAgeExceeded(requestBuffer.first, memClk, beginIter,
|
||||
firstDifferentRowAccessReqIter))
|
||||
{
|
||||
firstDifferentRowAccessReqIter--;
|
||||
readyBatchIters[requestBuffer.first].push_back(firstDifferentRowAccessReqIter);
|
||||
debugManager.printDebugMessage(name(),
|
||||
"Deem batch ready - thread " + to_string(requestBuffer.first.ID()));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SMS::multiBatchFormation(sc_time memClk)
|
||||
{
|
||||
for (auto& requestBuffer : requestBuffers)
|
||||
{
|
||||
bool formed;
|
||||
do
|
||||
{
|
||||
if (readyBatchIters[requestBuffer.first].empty())
|
||||
{
|
||||
formed = batchFormation(memClk, (std::pair<Thread, std::deque<gp*>>&)requestBuffer, requestBuffer.second.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
formed = batchFormation(memClk, (std::pair<Thread, std::deque<gp*>>&)requestBuffer, readyBatchIters[requestBuffer.first].back() + 1);
|
||||
}
|
||||
} while (formed);
|
||||
}
|
||||
}
|
||||
|
||||
gp* SMS::getPendingRequest(Bank bank)
|
||||
{
|
||||
for (auto& requestBuffer : requestBuffers) {
|
||||
for (auto& request : requestBuffer.second) {
|
||||
if (DramExtension::getBank(request) == bank) {
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
84
DRAMSys/simulator/src/controller/scheduler/SMS.h
Normal file
84
DRAMSys/simulator/src/controller/scheduler/SMS.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef SMS_H
|
||||
#define SMS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "sysc/utils/sc_report.h"
|
||||
#include "IScheduler.h"
|
||||
#include "../core/ControllerCore.h"
|
||||
#include "../core/configuration/Configuration.h"
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../../common/DebugManager.h"
|
||||
|
||||
#define LOW_SYSTEM_LOAD 16
|
||||
#define LOW_MPKC 1
|
||||
#define MEDIUM_MPKC 10
|
||||
#define MEDIUM_THRESHOLD_AGE 50
|
||||
#define HIGH_THRESHOLD_AGE 200
|
||||
#define MPKC_RESET_CYCLE 10000
|
||||
|
||||
using namespace std;
|
||||
typedef std::deque<gp*>::iterator gp_deque_iterator;
|
||||
|
||||
/**
|
||||
* SMS - Staged Memory Scheduler involves 3 steps:
|
||||
* 1. Arrage request in to each buffer of each thread
|
||||
* 2. Forming ready batches for each thread, i.e all requests access the same row. The batch is deemed
|
||||
* ready when the next request accesses different row OR When the buffer is full OR When this batch
|
||||
* is too old
|
||||
* 3. Send batches to bank buffers. The rules to send batches are Shortest-Job-First OR Round-Robin
|
||||
* How we select the rule depends on the probability we setup earlier.
|
||||
*/
|
||||
class SMS: public sc_module, public IScheduler
|
||||
{
|
||||
public:
|
||||
SMS(sc_module_name /*_name*/, ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability), debugManager(DebugManager::getInstance())
|
||||
{
|
||||
// initialize selected thread iterator
|
||||
lastSelectedThread = readyBatchIters.end();
|
||||
SC_THREAD(batchScheduler);
|
||||
}
|
||||
SC_HAS_PROCESS(SMS);
|
||||
|
||||
virtual ~SMS()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void schedule(gp *payload) override;
|
||||
virtual std::pair<Command, gp*> getNextRequest(Bank bank) override;
|
||||
virtual gp* getPendingRequest(Bank bank) override;
|
||||
|
||||
void batchScheduler();
|
||||
|
||||
private:
|
||||
std::map<Thread, std::deque<gp*>> requestBuffers;
|
||||
std::map<Bank, std::deque<gp*>> bankBuffers;
|
||||
std::map<Thread, std::deque<gp_deque_iterator>> readyBatchIters;
|
||||
|
||||
std::map<Thread, unsigned int> inFlightMemRequestCounter;
|
||||
std::map<Thread, unsigned int> cacheMisses;
|
||||
std::map<Thread, float> MPKCs;
|
||||
unsigned int SJFprobability;
|
||||
|
||||
std::map<Thread, std::deque<gp_deque_iterator>>::iterator lastSelectedThread;
|
||||
sc_event newRequest;
|
||||
|
||||
DebugManager& debugManager;
|
||||
|
||||
bool batchFormation(sc_time memClk, std::pair<Thread, std::deque<gp*>> &requestBuffer, std::deque<gp*>::iterator beginIter);
|
||||
void multiBatchFormation(sc_time memClk);
|
||||
bool pickSJF();
|
||||
bool pickRR();
|
||||
void drain(sc_time memClk, std::deque<gp*>::iterator last);
|
||||
|
||||
bool existLowIntensityThread();
|
||||
bool isSystemLightlyLoaded();
|
||||
bool isThresholdAgeExceeded(Thread thread, sc_time memClk, std::deque<gp*>::iterator begin, std::deque<gp*>::iterator end);
|
||||
bool isExceededReqBufferSize(Thread thread);
|
||||
void updateMPKCs(sc_time memClk);
|
||||
|
||||
bool isRequestBuffersEmpty();
|
||||
bool existReadyBatches();
|
||||
};
|
||||
|
||||
#endif // SMS_H
|
||||
@@ -277,11 +277,6 @@ DRAMSys::~DRAMSys()
|
||||
|
||||
delete arbiter;
|
||||
|
||||
for (auto controller : controllers)
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
for (auto dram : drams)
|
||||
{
|
||||
delete dram;
|
||||
@@ -296,6 +291,11 @@ DRAMSys::~DRAMSys()
|
||||
{
|
||||
delete tlmChecker;
|
||||
}
|
||||
|
||||
for (auto controller : controllers)
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
}
|
||||
|
||||
void DRAMSys::report(string message)
|
||||
|
||||
@@ -94,6 +94,8 @@ struct Dram : sc_module
|
||||
{
|
||||
// Adjust number of bytes per burst dynamically to the selected ecc controller
|
||||
bytesPerBurst = Configuration::getInstance().adjustNumBytesAfterECC(bytesPerBurst);
|
||||
dramController = NULL;
|
||||
tlmRecorder = NULL;
|
||||
|
||||
std::uint64_t memorySize = Configuration::getInstance().getSimMemSizeInBytes();
|
||||
// allocate and model storage of one DRAM channel using memory map
|
||||
|
||||
@@ -43,6 +43,7 @@ class TracePlayerListener
|
||||
public:
|
||||
virtual void tracePlayerTerminates() = 0;
|
||||
virtual void transactionFinished() = 0;
|
||||
virtual ~TracePlayerListener(){};
|
||||
};
|
||||
|
||||
#endif // TRACEPLAYERLISTENER_H
|
||||
|
||||
@@ -96,8 +96,6 @@ traceSetup::traceSetup(std::string uri,
|
||||
NumberOfTracePlayers = devices->size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void traceSetup::tracePlayerTerminates()
|
||||
{
|
||||
finishedTracePlayers++;
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
|
||||
virtual void tracePlayerTerminates() override;
|
||||
virtual void transactionFinished() override;
|
||||
virtual ~traceSetup(){};
|
||||
|
||||
private:
|
||||
unsigned int NumberOfTracePlayers;
|
||||
|
||||
@@ -78,15 +78,15 @@ int sc_main(int argc, char **argv)
|
||||
std::vector<StlPlayer*> players;
|
||||
|
||||
// Instantiate DRAMSys:
|
||||
DRAMSys dramSys("DRAMSys", SimulationXML, resources);
|
||||
DRAMSys *dramSys = new DRAMSys("DRAMSys", SimulationXML, resources);
|
||||
|
||||
// Instantiate STL Players:
|
||||
traceSetup(SimulationXML, resources, &players);
|
||||
traceSetup *ts = new traceSetup(SimulationXML, resources, &players);
|
||||
|
||||
// Bind STL Players with DRAMSys:
|
||||
for(auto& p : players)
|
||||
{
|
||||
p->iSocket.bind(dramSys.tSocket);
|
||||
p->iSocket.bind(dramSys->tSocket);
|
||||
}
|
||||
|
||||
// Store the starting of the simulation in wallclock time:
|
||||
@@ -105,5 +105,8 @@ int sc_main(int argc, char **argv)
|
||||
double elapsed_secs = double(clock() - simStartTime) / CLOCKS_PER_SEC;
|
||||
cout << "Simulation took " + to_string(elapsed_secs) + " seconds" << endl;
|
||||
|
||||
delete dramSys;
|
||||
delete ts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user