Merge branch 'master' of git.rhrk.uni-kl.de:EIT-Wehn/dram.vp.system

This commit is contained in:
Matthias Jung
2017-06-25 18:10:05 +02:00
59 changed files with 1927 additions and 82 deletions

View File

@@ -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;}
};

View File

@@ -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;}

View File

@@ -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 \
@@ -111,7 +112,12 @@ SOURCES += \
src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp \
src/simulation/TraceSetup.cpp \
src/simulation/DRAMSys.cpp \
src/simulation/Setup.cpp
src/simulation/Setup.cpp \
src/error/ECC/Bit.cpp \
src/error/ECC/ECC.cpp \
src/error/ECC/Word.cpp \
src/error/eccbaseclass.cpp \
src/error/ecchamming.cpp
HEADERS += \
src/common/third_party/tinyxml2/tinyxml2.h \
@@ -130,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 \
@@ -174,7 +181,12 @@ HEADERS += \
src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.h \
src/simulation/TraceSetup.h \
src/simulation/DRAMSys.h \
src/simulation/Setup.h
src/simulation/Setup.h \
src/error/ECC/Bit.h \
src/error/ECC/ECC.h \
src/error/ECC/Word.h \
src/error/eccbaseclass.h \
src/error/ecchamming.h
thermalsim = $$(THERMALSIM)
isEmpty(thermalsim) {

View File

@@ -8,13 +8,5 @@
<PowerDownMode value="NoPowerDown" />
<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>

View File

@@ -8,13 +8,5 @@
<PowerDownMode value="NoPowerDown" />
<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>

View File

@@ -0,0 +1,12 @@
<mcconfig>
<BankwiseLogic value="0"/>
<OpenPagePolicy value="1" />
<MaxNrOfTransactions value="8" />
<Scheduler value="FIFO" />
<Capsize value="5" />
<!-- 4 Modes: NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF -->
<PowerDownMode value="NoPowerDown" />
<PowerDownTimeout value="100" />
<!-- Error Modelling -->
<ControllerCoreDisableRefresh value="0"/>
</mcconfig>

View File

@@ -8,14 +8,6 @@
<PowerDownMode value="NoPowerDown" />
<PowerDownTimeout value="100" />
<!-- Error Model: -->
<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>

View File

@@ -8,13 +8,5 @@
<PowerDownMode value="NoPowerDown" />
<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>

View 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>

View File

@@ -0,0 +1,55 @@
<!DOCTYPE memspec SYSTEM "memspec.dtd">
<memspec>
<parameter id="memoryId" type="string" value="MICRON_1Gb_DDR3-1600_8bit_G" />
<parameter id="memoryType" type="string" value="DDR3" />
<memarchitecturespec>
<parameter id="width" type="uint" value="8" />
<parameter id="nbrOfBanks" type="uint" value="8" />
<parameter id="nbrOfRanks" type="uint" value="1" />
<parameter id="nbrOfColumns" type="uint" value="1024" />
<parameter id="nbrOfRows" type="uint" value="16384" />
<parameter id="dataRate" type="uint" value="2" />
<parameter id="burstLength" type="uint" value="8" />
</memarchitecturespec>
<memtimingspec>
<parameter id="clkMhz" type="double" value="800" />
<parameter id="RC" type="uint" value="38" />
<parameter id="RCD" type="uint" value="10" />
<parameter id="RL" type="uint" value="10" />
<parameter id="RP" type="uint" value="10" />
<parameter id="RFC" type="uint" value="88" />
<parameter id="RAS" type="uint" value="28" />
<parameter id="WL" type="uint" value="8" />
<parameter id="AL" type="uint" value="0" />
<parameter id="DQSCK" type="uint" value="0" />
<parameter id="RTP" type="uint" value="6" />
<parameter id="WR" type="uint" value="12" />
<parameter id="XP" type="uint" value="6" />
<parameter id="XPDLL" type="uint" value="20" />
<parameter id="XS" type="uint" value="96" />
<parameter id="XSDLL" type="uint" value="512" />
<parameter id="REFI" type="uint" value="300000000" />
<parameter id="CL" type="uint" value="10" />
<parameter id="FAW" type="uint" value="24" />
<parameter id="RRD" type="uint" value="5" />
<parameter id="CCD" type="uint" value="4" />
<parameter id="WTR" type="uint" value="6" />
<parameter id="CKE" type="uint" value="3" />
<parameter id="CKESR" type="uint" value="4" />
</memtimingspec>
<mempowerspec>
<parameter id="idd0" type="double" value="70.0" />
<parameter id="idd2p0" type="double" value="12.0" />
<parameter id="idd2p1" type="double" value="30.0" />
<parameter id="idd2n" type="double" value="45.0" />
<parameter id="idd3p0" type="double" value="35.0" />
<parameter id="idd3p1" type="double" value="35.0" />
<parameter id="idd3n" type="double" value="45.0" />
<parameter id="idd4w" type="double" value="145.0" />
<parameter id="idd4r" type="double" value="140.0" />
<parameter id="idd5" type="double" value="170.0" />
<parameter id="idd6" type="double" value="8.0" />
<parameter id="vdd" type="double" value="1.5" />
</mempowerspec>
</memspec>

View File

@@ -0,0 +1,61 @@
<!DOCTYPE memspec SYSTEM "memspec.dtd">
<memspec>
<parameter id="memoryId" type="string" value="wideio_less_refresh" />
<parameter id="memoryType" type="string" value="WIDEIO_SDR" />
<memarchitecturespec>
<parameter id="width" type="uint" value="128" />
<parameter id="nbrOfBanks" type="uint" value="8" />
<parameter id="nbrOfColumns" type="uint" value="128" />
<parameter id="nbrOfRows" type="uint" value="8192" />
<parameter id="dataRate" type="uint" value="1" />
<parameter id="burstLength" type="uint" value="4" />
</memarchitecturespec>
<memtimingspec>
<parameter id="clkMhz" type="double" value="166" />
<parameter id="RC" type="uint" value="9" /><!--tRP+tRAS-->
<parameter id="RCD" type="uint" value="3" />
<parameter id="RL" type="uint" value="3" />
<parameter id="RP" type="uint" value="3" />
<parameter id="RFC" type="uint" value="22" />
<parameter id="RAS" type="uint" value="6" />
<parameter id="WL" type="uint" value="1" />
<parameter id="AL" type="uint" value="0" />
<parameter id="RTP" type="uint" value="4" />
<parameter id="WR" type="uint" value="2" />
<parameter id="XP" type="uint" value="2" />
<parameter id="XS" type="uint" value="20" /><!--tRFC+2clk-->
<parameter id="REFI" type="uint" value="166000000000" />
<parameter id="TAW" type="uint" value="10" />
<parameter id="RRD" type="uint" value="2" />
<parameter id="CCD" type="uint" value="1" />
<parameter id="WTR" type="uint" value="3" />
<parameter id="CKE" type="uint" value="3" />
<parameter id="CKESR" type="uint" value="3" />
</memtimingspec>
<mempowerspec>
<parameter id="idd0" type="double" value="5.88" />
<parameter id="idd02" type="double" value="21.18" />
<parameter id="idd2p0" type="double" value="0.05" />
<parameter id="idd2p02" type="double" value="0.17" />
<parameter id="idd2p1" type="double" value="0.05" />
<parameter id="idd2p12" type="double" value="0.17" />
<parameter id="idd2n" type="double" value="0.13" />
<parameter id="idd2n2" type="double" value="4.04" />
<parameter id="idd3p0" type="double" value="0.25" />
<parameter id="idd3p02" type="double" value="1.49" />
<parameter id="idd3p1" type="double" value="0.25" />
<parameter id="idd3p12" type="double" value="1.49" />
<parameter id="idd3n" type="double" value="0.52" />
<parameter id="idd3n2" type="double" value="6.55" />
<parameter id="idd4r" type="double" value="1.41" />
<parameter id="idd4r2" type="double" value="85.73" />
<parameter id="idd4w" type="double" value="1.42" />
<parameter id="idd4w2" type="double" value="60.79" />
<parameter id="idd5" type="double" value="14.43" />
<parameter id="idd52" type="double" value="48.17" />
<parameter id="idd6" type="double" value="0.07" />
<parameter id="idd62" type="double" value="0.27" />
<parameter id="vdd" type="double" value="1.8" />
<parameter id="vdd2" type="double" value="1.2" />
</mempowerspec>
</memspec>

View File

@@ -11,4 +11,13 @@
<NumberOfDevicesOnDIMM value = "8" />
<CheckTLM2Protocol value = "0" />
<AddressOffset value = "0" />
<ECCControllerMode value = "Disabled" />
<ErrorChipSeed value="42" />
<ErrorCSVFile value="" />
<!-- Modes:
- NoStorage,
- Store (store data without errormodel),
- ErrorModel (store data with errormodel)
-->
<StoreMode value="NoStorage" />
</simconfig>

View File

@@ -11,6 +11,15 @@
<NumberOfDevicesOnDIMM value = "8" />
<CheckTLM2Protocol value = "0" />
<AddressOffset value = "0" />
<ECCControllerMode value = "Disabled" />
<ErrorChipSeed value="42" />
<ErrorCSVFile value="" />
<!-- Modes:
- NoStorage,
- Store (store data without errormodel),
- ErrorModel (store data with errormodel)
-->
<StoreMode value="NoStorage" />
<!-- Gem5 Related Configuration:
In the memory controller file the storage mode should be set to Store
E.g. the DRAM is located at 0x80000000 for gem5

View File

@@ -0,0 +1,23 @@
<simconfig>
<SimulationName value="ddr3" />
<Debug value="0" />
<DatabaseRecording value="1" />
<PowerAnalysis value="1" />
<EnableWindowing value = "1" />
<WindowSize value="1000" />
<ThermalSimulation value="0"/>
<SimulationProgressBar value="1"/>
<NumberOfMemChannels value="1"/>
<NumberOfDevicesOnDIMM value = "8" />
<CheckTLM2Protocol value = "0" />
<AddressOffset value = "0" />
<ECCControllerMode value = "Hamming" />
<ErrorChipSeed value="42" />
<ErrorCSVFile value="" />
<!-- Modes:
- NoStorage,
- Store (store data without errormodel),
- ErrorModel (store data with errormodel)
-->
<StoreMode value="ErrorModel" />
</simconfig>

View 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>

View File

@@ -10,5 +10,14 @@
<NumberOfMemChannels value="4"/>
<NumberOfDevicesOnDIMM value = "1" />
<CheckTLM2Protocol value = "0" />
<ECCControllerMode value = "Disabled" />
<ErrorChipSeed value="42" />
<ErrorCSVFile value="../../DRAMSys/simulator/resources/error/wideio.csv" />
<!-- Modes:
- NoStorage,
- Store (store data without errormodel),
- ErrorModel (store data with errormodel)
-->
<StoreMode value="NoStorage" />
</simconfig>

View File

@@ -0,0 +1,23 @@
<simconfig>
<SimulationName value="wideio_ecc" />
<Debug value="0" />
<DatabaseRecording value="1" />
<PowerAnalysis value="1" />
<EnableWindowing value = "1" />
<WindowSize value="1000" />
<ThermalSimulation value="0"/>
<SimulationProgressBar value="1"/>
<NumberOfMemChannels value="1"/>
<NumberOfDevicesOnDIMM value = "1" />
<CheckTLM2Protocol value = "0" />
<ECCControllerMode value = "Hamming" />
<ErrorChipSeed value="42" />
<ErrorCSVFile value="../../DRAMSys/simulator/resources/error/wideio.csv" />
<!-- Modes:
- NoStorage,
- Store (store data without errormodel),
- ErrorModel (store data with errormodel)
-->
<StoreMode value="ErrorModel" />
</simconfig>

View File

@@ -10,5 +10,14 @@
<NumberOfMemChannels value="1"/>
<NumberOfDevicesOnDIMM value = "1" />
<CheckTLM2Protocol value = "0" />
<ECCControllerMode value = "Disabled" />
<ErrorChipSeed value="42" />
<ErrorCSVFile value="../../DRAMSys/simulator/resources/error/wideio.csv" />
<!-- Modes:
- NoStorage,
- Store (store data without errormodel),
- ErrorModel (store data with errormodel)
-->
<StoreMode value="NoStorage" />
</simconfig>

View File

@@ -5,14 +5,18 @@
OTHER_FILES += resources/simulations/ddr3-example.xml
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
OTHER_FILES += resources/configs/simulator/ddr3.xml
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
@@ -60,12 +64,19 @@ OTHER_FILES += resources/traces/mediabench-adpcmdecode_32.stl
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
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
@@ -108,6 +119,8 @@ OTHER_FILES += resources/configs/memspecs/MICRON_4Gb_LPDDR3-1600_32bit_A.xml
OTHER_FILES += resources/configs/memspecs/SAMSUNG_K4B1G1646E_1Gb_DDR3-1600_16bit.xml
OTHER_FILES += resources/configs/memspecs/SAMSUNG_K4B4G1646Q_4Gb_DDR3-1066_16bit.xml
OTHER_FILES += resources/configs/memspecs/wideio.xml
OTHER_FILES += resources/configs/memspecs/wideio_less_refresh.xml
OTHER_FILES += resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml
# Address Mapping Configs
OTHER_FILES += resources/configs/amconfigs/am_ddr3.xml
@@ -134,3 +147,6 @@ OTHER_FILES += resources/configs/thermalsim/mem.flp
OTHER_FILES += resources/configs/thermalsim/powerInfo.xml
OTHER_FILES += resources/configs/thermalsim/stack.stk
OTHER_FILES += resources/configs/thermalsim/config.xml
# Error Simulation data
OTHER_FILES += resources/error/wideio.csv

View File

@@ -0,0 +1,22 @@
<simulation>
<!-- Configuration for the DRAMSys Simulator -->
<simconfig src="ddr3_ecc.xml" />
<!-- Temperature Simulator Configuration -->
<thermalconfig src="config.xml" />
<!-- Memory Device Specification: Which Device is used for Wide I/O -->
<memspec src="MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml"></memspec>
<!-- Addressmapping Configuration of the Memory Controller -->
<addressmapping src="am_ddr3_8x1Gbx8_dimm_p1KB_brc.xml"></addressmapping>
<!-- Memory Controller Configuration -->
<mcconfig src="fifo_ecc.xml"/>
<!--
The following trace setup is only used in standalone mode.
In library mode e.g. in Platform Architect the trace setup is ignored.
-->
<tracesetup>
<!--
This device mimics an processor running at 1 GHz.
-->
<device clkMhz="1000">test_ecc.stl</device>
</tracesetup>
</simulation>

View 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>

View File

@@ -0,0 +1,22 @@
<simulation>
<!-- Configuration for the DRAMSys Simulator -->
<simconfig src="wideio_ecc.xml" />
<!-- Temperature Simulator Configuration -->
<thermalconfig src="config.xml" />
<!-- Memory Device Specification: Which Device is used for Wide I/O -->
<memspec src="wideio_less_refresh.xml"></memspec>
<!-- Addressmapping Configuration of the Memory Controller -->
<addressmapping src="am_wideio.xml"></addressmapping>
<!-- Memory Controller Configuration -->
<mcconfig src="fifo_ecc.xml"/>
<!--
The following trace setup is only used in standalone mode.
In library mode e.g. in Platform Architect the trace setup is ignored.
-->
<tracesetup>
<!--
This device mimics an processor running at 1 GHz.
-->
<device clkMhz="1000">test_ecc.stl</device>
</tracesetup>
</simulation>

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -110,6 +110,19 @@ EPowerDownMode string2PDNMode(string s)
}
}
ECCControllerMode string2ECCControllerMode(string s)
{
if(s == "Disabled")
return ECCControllerMode::Disabled;
else if(s == "Hamming")
return ECCControllerMode::Hamming;
else
{
SC_REPORT_FATAL("Configuration", ("Unknown ECCControllerMode: " + s).c_str());
throw;
}
}
enum sc_time_unit string2TimeUnit(string s)
{
if (s == "s")
@@ -140,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")
@@ -201,6 +222,8 @@ void Configuration::setParameter(std::string name, std::string value)
}
else if(name == "CheckTLM2Protocol")
CheckTLM2Protocol = string2bool(value);
else if(name == "ECCControllerMode")
ECCMode = string2ECCControllerMode(value);
// Specification for ErrorChipSeed, ErrorCSVFile path and StoreMode
else if(name == "ErrorChipSeed")
ErrorChipSeed = string2int(value);
@@ -309,3 +332,15 @@ unsigned int Configuration::getBytesPerBurst()
return bytesPerBurst;
}
// Changes the number of bytes depeding on the ECC Controller. This function is needed for modules which get data directly or indirectly from the ECC Controller
unsigned int Configuration::adjustNumBytesAfterECC(unsigned nBytes)
{
// Manipulate the number of bytes only if there is an ECC Controller selected
if(ECCMode == ECCControllerMode::Disabled)
return nBytes;
else
{
assert(pECC != nullptr);
return pECC->AllocationSize(nBytes);
}
}

View File

@@ -45,10 +45,14 @@
#include "thermalSimConfig.h"
#include "../../../common/Utils.h"
#include "../../../error/eccbaseclass.h"
enum class StorageMode{NoStorage, Store, ErrorModel};
enum class EPowerDownMode{NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF};
enum class ECCControllerMode{Disabled, Hamming};
struct Configuration
{
static std::string memspecUri;
@@ -62,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;
@@ -81,6 +87,9 @@ struct Configuration
bool SimulationProgressBar = false;
unsigned int NumberOfDevicesOnDIMM = 1;
bool CheckTLM2Protocol = false;
ECCControllerMode ECCMode = ECCControllerMode::Disabled;
ECCBaseClass* pECC = nullptr;
bool gem5 = false;
unsigned long long int AddressOffset = 0;
// MemSpec (from DRAM-Power XML)
@@ -100,6 +109,7 @@ struct Configuration
std::uint64_t getSimMemSizeInBytes();
unsigned int getDataBusWidth();
unsigned int getBytesPerBurst();
unsigned int adjustNumBytesAfterECC(unsigned bytes);
void setPathToResources(std::string path);
std::string getPathToResources();

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -121,3 +121,8 @@ deque<gp*>::iterator FR_FCFS::FindRowHit(Bank bank)
return queue.end();
}
gp* FR_FCFS::getPendingRequest(Bank bank)
{
return NULL;
}

View File

@@ -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;

View File

@@ -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:

View 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;
}

View 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

View File

@@ -0,0 +1,27 @@
#include "Bit.h"
#include <iostream>
using std::cout;
CBit::CBit(VALUE nVal)
{
m_nValue = nVal;
}
CBit::~CBit()
{
}
void CBit::Print()
{
if (m_nValue == ZERO)
{
cout <<"0";
}
else
{
cout << "1";
}
}

View File

@@ -0,0 +1,73 @@
#pragma once
class CBit
{
public:
enum VALUE
{
ZERO = 0,
ONE = 1
};
protected:
VALUE m_nValue;
public:
CBit(VALUE nVal = ZERO);
virtual ~CBit();
inline void Set() { m_nValue = ONE; };
inline void Clear() { m_nValue = ZERO; };
inline unsigned Get()
{
if(m_nValue == ONE)
return 1;
else
return 0;
};
void Print();
CBit& operator=(unsigned d)
{
if (d == 0 )
{
m_nValue = ZERO;
}
else
{
m_nValue = ONE;
}
return *this;
}
friend CBit operator^(CBit l, const CBit& r)
{
if (l.m_nValue == r.m_nValue)
{
return CBit(ZERO);
}
else
{
return CBit(ONE);
}
}
CBit& operator^=(const CBit& r)
{
if (m_nValue == r.m_nValue)
{
m_nValue = ZERO;
}
else
{
m_nValue = ONE;
}
return *this;
}
inline bool operator==(const CBit::VALUE& r)
{
return m_nValue == r;
}
};

View File

@@ -0,0 +1,133 @@
#include "ECC.h"
// ************************************************************************************************
// Function which calculates the number of additional bits needed for a given number of data bits
// to store the hamming code and parity bit for a SECDED implementation
unsigned ECC::GetNumParityBits(unsigned nDataBits)
{
unsigned nParityBits = 0;
// Function to calculate the nube of bits: n = 2^k - k - 1
// ( Source: Hacker's Delight; p. 310; math. function 1 )
while (nDataBits > ((1 << nParityBits) - nParityBits - 1))
{
++nParityBits;
}
return nParityBits+1; // +1 for the parity bit
}
// ************************************************************************************************
// Function which extends a given data word to the needed length for a SECDED code
void ECC::ExtendWord(CWord & v)
{
unsigned end = v.GetLength() + ECC::GetNumParityBits(v.GetLength());
// Insert x bits for the hamming code at positions where pos = 2^a; a = [0..N]
// In "Hacker's Delight" the smallest index is 1 - But in this beautiful C-Code it's 0 as it
// should be. That's why there is a '-1' in the call of v.Insert.
unsigned i = 1;
while (i < end)
{
v.Insert(i-1, CBit());
i <<= 1;
}
// Append one bit for the parity
v.Append(CBit());
}
// ************************************************************************************************
// Function which calculates the Hamming Code bits of an extended Data word.
// Function ExtendWord must be called before calling this function
// The calculated bits are stored in p, so the length of p should be at least
// 'GetNumParityBits(#data bits)-1'
void ECC::CalculateCheckbits(CWord & v, CWord & p)
{
unsigned i = 1, l = 0;
// Last bit is the parity bit - don't use this in the algorithm for hamming code
unsigned len = v.GetLength()-1;
// Following Graph should show you the behaviour of this algorithm
// #Data bits: 11 #Hamming bits: 4 -> SECDED bits: 16 (incl. parity bit)
// Hamming Code Bit: | Bits used -> data(X)/Hamming Code(H) // Bit unused -
// 0 | H-X-X-X-X-X-X-X
// 1 | -HX--XX--XX--XX
// 2 | ---HXXX----XXXX
// 3 | -------HXXXXXXX
// For further information read "Hacker's delight" chapter 15
// ATTENTION: The order of indices is different from the one in the book,
// but it doesn't matter in which order your data or check bits are.
// But it should be the same for encoding and decoding
while (i < len)
{
for (unsigned j = (i - 1); j < len; j += (i << 1))
{
for (unsigned k = 0; k < (i); k++)
{
if(j + k >= len)
break;
p[l] ^= v[j + k];
}
}
l++;
i <<= 1;
}
}
// ************************************************************************************************
// Function which inserts the checkbits which were calculated with 'CalculateCheckbits' in the
// extended data word. This is needed to calculate a proper parity of ALL bits to achive a SECDED
// behaviour.
void ECC::InsertCheckbits(CWord& v, CWord p)
{
unsigned i = 1, j = 0;
while (i <= v.GetLength()-1)
{
v[i - 1] = p[j++];
i <<= 1;
}
}
// ************************************************************************************************
// Function which extracts the checkbits out of an extended data word. This is needed to check for
// bit error in the data word.
void ECC::ExtractCheckbits(CWord v, CWord & p)
{
unsigned i = 1, j = 0;
while(i <= v.GetLength()-1)
{
p[j++] = v[i - 1];
i <<= 1;
}
}
// ************************************************************************************************
// Function which calculates the overal parity
// Simply XOR all bits
void ECC::CalculateParityBit(CWord v, CBit & p)
{
// Paritybit
p = CBit::ZERO;
for (unsigned i = 0; i < v.GetLength(); i++)
{
p ^= v[i];
}
}
// ************************************************************************************************
// Function to insert the parity bit into the extended data word
void ECC::InsertParityBit(CWord& v, CBit p)
{
v[v.GetLength() - 1] = p;
}
// ************************************************************************************************
// Function to extract the parity bit out of an extended data word.
void ECC::ExtractParityBit(CWord v, CBit & p)
{
p = v[v.GetLength() - 1];
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include "Word.h"
#include "Bit.h"
// ************************************************************************************************
//
// | __/ __/ __| | __| _ _ _ __| |_(_)___ _ _ ___
// | _| (_| (__ | _| || | ' \/ _| _| / _ \ ' \(_-<
// |___\___\___| |_| \_,_|_||_\__|\__|_\___/_||_/__/
//
// ------------------------------------------------------------------------------------------------
// ECC Implementation as described in "Hacker's Delight - second Edition" by Henry S. Warren, Jr.
// ------------------------------------------------------------------------------------------------
// This namespace gives you some handy functions to get a SEC-DED implementation.
//
// SEC-DED: Single Error Correction - Double Error Detection
// This is the most common error correction code (ECC).
// It consists of two different correction codes: Haming code + parity code.
//
// For further details read chapter 15 of "Hacker's Delight - second Edition"
// ************************************************************************************************
namespace ECC
{
unsigned GetNumParityBits(unsigned nDataBits);
// Extends the data word that it can be used with hamming code
// Several bits will be included at specific places
void ExtendWord(CWord &v);
void CalculateCheckbits(CWord &v, CWord & p);
void InsertCheckbits(CWord& v, CWord p);
void ExtractCheckbits(CWord v, CWord& p);
void CalculateParityBit(CWord v, CBit& p);
void InsertParityBit(CWord& v, CBit p);
void ExtractParityBit(CWord v, CBit& p);
}

View File

@@ -0,0 +1,128 @@
// ECC_Test.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//
#include "stdafx.h"
#include <time.h>
#include "ECC.h"
int main()
{
// Random number init
srand(time(NULL));
// Erstellen
unsigned size = 4;
CWord p(ECC::GetNumParityBits(size)), v(size);
// Daten eingeben
for (unsigned a = 0; a < 16; a++)
{
v = a;
v.Rotate();
ECC::ExtendWord(v);
printf("%d:\t", a);
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::InsertCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
ECC::InsertParityBit(v, p[3]);
v.Print();
v.Resize(size);
}
printf("\r\n");
for (unsigned x = 0; x < 100; x++)
{
//Get random number
unsigned a = rand() % 16;
v.Resize(size);
v = a;
v.Rotate();
ECC::ExtendWord(v);
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::InsertCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
ECC::InsertParityBit(v, p[3]);
v.Print();
// Insert error
unsigned pos = rand() % 8;
v[pos] ^= CBit(CBit::ONE);
printf("Data: %d, Error at pos %d: ", a, pos + 1);
v[pos].Print();
printf("\r\n");
v.Print();
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
printf("%d:\t", a);
p.Print();
// Interpreting Data
unsigned syndrome = 0;
for (unsigned i = 0; i < p.GetLength() - 1; i++)
{
if (p[i] == CBit::ONE)
syndrome += (1 << i);
}
if (p[3] == CBit::ZERO)
{
// Parity even
if (syndrome)
{
// Double error
printf("Double error detected.\r\n");
break;
}
else
{
// No Error
printf("No error detected.\r\n");
break;
}
}
else
{
// Parity odd
if (syndrome)
{
// Bit error
printf("Error detected in Bit %d.\r\n", syndrome);
if (syndrome == pos + 1)
continue;
else
break;
}
else
{
// Overall parity Error
printf("Overall parity error detected.\r\n");
if (pos == 7 || pos == 3 || pos == 1 || pos == 0)
continue;
else
break;
}
}
}
system("pause");
return 0;
}

View File

@@ -0,0 +1,157 @@
#include "Word.h"
#include <math.h>
#include <iostream>
#include <string.h>
using std::cout;
CWord::CWord(unsigned nBitLength)
: m_nBitLength(nBitLength)
{
m_word.resize(nBitLength);
}
CWord::~CWord()
{
}
CBit * CWord::GetAt(unsigned nBitPos)
{
if (nBitPos < m_nBitLength)
{
return &m_word.at(nBitPos);
}
return nullptr;
}
void CWord::Set(unsigned data)
{
deque<CBit>::iterator it;
if (m_nBitLength < sizeof(data))
{
it = m_word.begin();
for (unsigned i = 0; i < m_nBitLength; i++)
{
(*it++) = data & 1;
data >>= 1;
}
}
else
{
for (it = m_word.begin(); it != m_word.end(); it++)
{
(*it) = data & 1;
data >>= 1;
}
}
}
void CWord::Set(const unsigned char* data, unsigned lengthInBits)
{
deque<CBit>::iterator it;
if (m_nBitLength < lengthInBits)
{
it = m_word.begin();
for (unsigned pos = 0; pos < m_nBitLength; pos++)
{
(*it) = data[pos>>3] & (1 << (7-(pos&7)));
it++;
}
}
else
{
unsigned pos = 0;
for (it = m_word.begin(); it != m_word.end(); it++)
{
(*it) = data[pos>>3] & (1 << (7-(pos&7)));
++pos;
}
}
}
void CWord::Rotate()
{
deque<CBit> buffer = m_word;
for (unsigned i = 0; i < m_nBitLength; i++)
{
m_word.at(m_nBitLength -i -1) = buffer.at(i);
}
}
bool CWord::Insert(unsigned npos, CBit b)
{
if (npos >= m_nBitLength)
return false;
deque<CBit>::iterator it = m_word.begin() + npos;
m_word.insert(it, b);
m_nBitLength++;
return true;
}
bool CWord::Delete(unsigned npos)
{
if (npos >= m_nBitLength)
return false;
deque<CBit>::iterator it = m_word.begin() + npos;
m_word.erase(it);
m_nBitLength++;
return true;
}
void CWord::Append(CBit b)
{
m_word.push_back(b);
m_nBitLength++;
}
void CWord::Resize(unsigned nsize)
{
m_word.resize(nsize);
m_nBitLength = nsize;
}
bool CWord::PartShiftRight(unsigned nPos, unsigned nShift)
{
if(nPos >= m_nBitLength)
return false;
/*for (unsigned i = 0; i < nShift; i++)
{
m_word.insert()
}*/
return true;
}
void CWord::Print()
{
deque<CBit>::iterator it;
for (it = m_word.begin(); it != m_word.end(); it++)
{
(*it).Print();
}
cout << "\r\n";
}
void CWord::Copy(unsigned char* ptr)
{
unsigned len = ceil(m_word.size()/8);
memset(ptr, 0, len);
unsigned pos = 0;
for(auto it = m_word.begin(); it != m_word.end(); it++)
{
ptr[pos>>3] |= (*it).Get() << (7-(pos&7));
++pos;
}
}

View File

@@ -0,0 +1,63 @@
#pragma once
#include <deque>
#include "Bit.h"
using std::deque;
class CWord
{
protected:
unsigned m_nBitLength;
deque<CBit> m_word;
public:
CWord(unsigned nBitLength);
virtual ~CWord();
CBit* GetAt(unsigned nBitPos);
void Set(unsigned data);
void Set(const unsigned char* data, unsigned lengthInBits);
void Rotate();
bool Insert(unsigned npos, CBit b);
bool Delete(unsigned npos);
void Copy(unsigned char* ptr);
void Append(CBit b);
void Resize(unsigned nsize);
bool PartShiftRight(unsigned nPos, unsigned nShift);
inline unsigned GetLength() const { return m_nBitLength; };
void Print();
CWord& operator=(unsigned d)
{
Set(d);
return *this;
}
CBit& operator[](unsigned nPos)
{
return m_word.at(nPos);
}
friend CWord operator >> (CWord l, const unsigned& r)
{
for (unsigned i = 0; i < r; i++)
{
l.m_word.pop_front();
l.m_word.push_back(CBit(CBit::VALUE::ZERO));
}
return l;
}
};

View File

@@ -0,0 +1,83 @@
#include "eccbaseclass.h"
tlm::tlm_sync_enum ECCBaseClass::nb_transport_fw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay )
{
if(trans.get_command() == TLM_WRITE_COMMAND && phase == BEGIN_REQ)
{
// Allocate memory for encoded data using the size provided by AllocationEncode
unsigned nEncodedDataSize = AllocationSize(trans.get_data_length());
assert(nEncodedDataSize != 0);
unsigned char* pEncodedData = new unsigned char[nEncodedDataSize];
// Save memory pointer and size
m_mDataPointer[pEncodedData].pData = trans.get_data_ptr();
m_mDataPointer[pEncodedData].nDataSize = trans.get_data_length();
// Data Encoding
Encode(trans.get_data_ptr(), trans.get_data_length(), pEncodedData, nEncodedDataSize);
// Change transport data length and pointer
trans.set_data_length(nEncodedDataSize);
trans.set_data_ptr(pEncodedData);
}
else if(trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_REQ)
{
// Allocate memory for reading data using the size provided by AllocationEncode
unsigned nReadDataSize = AllocationSize(trans.get_data_length());
assert(nReadDataSize != 0);
unsigned char* pReadData = new unsigned char[nReadDataSize];
// Save memory pointer and size
m_mDataPointer[pReadData].pData = trans.get_data_ptr();
m_mDataPointer[pReadData].nDataSize = trans.get_data_length();
// Change transport data length and pointer
trans.set_data_length(nReadDataSize);
trans.set_data_ptr(pReadData);
}
return i_socket[id]->nb_transport_fw( trans, phase, delay );
}
// Backward interface
tlm::tlm_sync_enum ECCBaseClass::nb_transport_bw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay )
{
if(trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_RESP)
{
//Look for the corresponding data pointer for decoding
auto it = m_mDataPointer.find(trans.get_data_ptr());
assert(it != m_mDataPointer.end());
// Data Decoding
Decode(trans.get_data_ptr(), trans.get_data_length(), it->second.pData, it->second.nDataSize);
// delete data pointer from map
m_mDataPointer.erase(it);
// Delete data pointer used for encoded data
delete[] trans.get_data_ptr();
// Set data pointer and size for decoded data
trans.set_data_ptr(it->second.pData);
trans.set_data_length(it->second.nDataSize);
}
else if(trans.get_command() == TLM_WRITE_COMMAND && phase == BEGIN_RESP)
{
//Look for the corresponding data pointer for decoding
auto it = m_mDataPointer.find(trans.get_data_ptr());
assert(it != m_mDataPointer.end());
// delete data pointer from map
m_mDataPointer.erase(it);
// Delete data pointer used for encoded data
delete[] trans.get_data_ptr();
// Set data pointer and size for decoded data
trans.set_data_ptr(it->second.pData);
trans.set_data_length(it->second.nDataSize);
}
return t_socket[id]->nb_transport_bw( trans, phase, delay );
}

View File

@@ -0,0 +1,67 @@
#ifndef ECCBASECLASS_H
#define ECCBASECLASS_H
#include <systemc.h>
#include <tlm.h>
#include <tlm_utils/multi_passthrough_initiator_socket.h>
#include <tlm_utils/multi_passthrough_target_socket.h>
#include "ECC/ECC.h"
#include "../common/xmlAddressdecoder.h"
#include "../common/DebugManager.h"
using namespace std;
using namespace tlm;
class ECCBaseClass : sc_module
{
public:
struct DataStruct
{
unsigned char* pData;
unsigned int nDataSize;
};
private:
map<unsigned char*, DataStruct> m_mDataPointer;
public:
// Function prototype for calculated the size of memory needed for saving the encoded data
// Input nBytes: Number of bytes which have to be encoded
// Return value: Number of bytes which have to be allocated for storing the encoded data
virtual unsigned AllocationSize(unsigned nBytes) = 0;
protected:
// Function prototype for encoding data.
// Data pointer is provided in pDataIn, length in Bytes provided in nDataIn
// Result should be written in pDataOut, which has a size of nDataOut.
// pDataOut is already allocated with a size given by function AllocationEncode
virtual void Encode(const unsigned char* pDataIn, const unsigned nDataIn, unsigned char* pDataOut, const unsigned nDataOut) = 0;
// Function prototype for decoding data.
// Data pointer is provided in pDataIn, length in Bytes provided in nDataIn
// Result should be written in pDataOut, which has a size of nDataOut.
// pDataOut is already allocated with a size given by function AllocationDecode
virtual void Decode(const unsigned char* pDataIn, const unsigned nDataIn, unsigned char* pDataOut, const unsigned nDataOut) = 0;
public:
tlm_utils::multi_passthrough_target_socket<ECCBaseClass> t_socket;
tlm_utils::multi_passthrough_initiator_socket<ECCBaseClass> i_socket;
SC_CTOR(ECCBaseClass)
: t_socket("t_socket")
, i_socket("i_socket")
{
t_socket.register_nb_transport_fw(this, &ECCBaseClass::nb_transport_fw);
i_socket.register_nb_transport_bw(this, &ECCBaseClass::nb_transport_bw);
}
// Forward interface
tlm::tlm_sync_enum nb_transport_fw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay );
// Backward interface
tlm::tlm_sync_enum nb_transport_bw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay );
};
#endif // ECCBASECLASS_H

View File

@@ -0,0 +1,134 @@
#include "ecchamming.h"
#include "ECC/ECC.h"
unsigned ECCHamming::AllocationSize(unsigned nBytes)
{
// For this hamming for 8 bytes one extra byte is needed:l
return nBytes + ceil(nBytes / m_nDatawordSize) * m_nCodewordSize;
}
void ECCHamming::Encode(const unsigned char* pDataIn, const unsigned nDataIn, unsigned char* pDataOut, const unsigned nDataOut)
{
// Calculate how many 8 byte blocks are there
unsigned nBlocks = nDataIn/m_nDatawordSize;
// No partly filled blocks are supported
assert(nDataIn % m_nDatawordSize == 0);
// Create ECC data for every block
for(unsigned i = 0; i < nBlocks; i++)
{
// Create all variables needed for calulation
CWord dataword(InBits(m_nDatawordSize)); // Size in bits
CWord codeword(InBits(m_nCodewordSize)); // Size in bits
// Fill in current data block
dataword.Set(&pDataIn[i*m_nDatawordSize], InBits(m_nDatawordSize));
// Extend data word. It grows from m_nDatawordSize to m_nDatawordSize + m_nCodewordSize
ECC::ExtendWord(dataword);
// Initialize the codeword with zeros
codeword = 0;
// Calculate Checkbits
ECC::CalculateCheckbits(dataword, codeword);
ECC::InsertCheckbits(dataword, codeword);
// Calculate Parity
ECC::CalculateParityBit(dataword, codeword[7]);
// Check if there is enough space in the output array (should always be)
assert((i+1)*(m_nDatawordSize + m_nCodewordSize) <= nDataOut);
// Copy old data
memcpy(&pDataOut[i*(m_nDatawordSize + m_nCodewordSize)], &pDataIn[i*m_nDatawordSize], m_nDatawordSize);
// Save hamming code + parity bit in the last byte
codeword.Copy(&pDataOut[i*(m_nDatawordSize + m_nCodewordSize)+m_nDatawordSize]);
}
}
void ECCHamming::Decode(const unsigned char* pDataIn, const unsigned nDataIn, unsigned char* pDataOut, const unsigned nDataOut)
{
// Calculate how many 9 byte blocks are there
unsigned nBlocks = nDataIn/(m_nDatawordSize + m_nCodewordSize);
// No partly filled blocks are supported
assert(nDataIn % (m_nDatawordSize + m_nCodewordSize) == 0);
// Verify ECC data for every block
for(unsigned i = 0; i < nBlocks; i++)
{
// Create all variables needed for calulation
CWord dataword(InBits(m_nDatawordSize)); // Size in bits
CWord codeword(InBits(m_nCodewordSize)); // Size in bits
// Fill in current data block
dataword.Set(&pDataIn[i*(m_nDatawordSize + m_nCodewordSize)], InBits(m_nDatawordSize));
codeword.Set(&pDataIn[i*(m_nDatawordSize + m_nCodewordSize)+m_nDatawordSize], InBits(m_nCodewordSize));
// Extend data word. It grows from m_nDatawordSize to m_nDatawordSize + m_nCodewordSize
ECC::ExtendWord(dataword);
// Insert old codeword
ECC::InsertCheckbits(dataword, codeword);
ECC::InsertParityBit(dataword, codeword[7]);
// Reset codeword
codeword = 0;
// Calculate Checkbits again
ECC::CalculateCheckbits(dataword, codeword);
// Calculate Parity again
ECC::CalculateParityBit(dataword, codeword[7]);
// Translate codeword
bool bParity = codeword[7] == CBit::ONE;
// calculate syndrome
unsigned char c = 0;
codeword.Rotate();
codeword.Copy(&c);
c &= 0x7F;
// Parity Error?
if(bParity)
{
// Parity Error
if(c == 0)
{
// Only Parity Bit broken - continue
cout << "Parity Bit error" << endl;
}
else
{
// Data or Hamming Code Bit broken
cout << "Single Error Detected" << endl;
}
}
else
{
// No Parity Error
if(c == 0)
{
// No error at all - continue
}
else
{
// Double error detected
cout << "Double Error Detected (Block " << i << ")." << endl;
}
}
// Check if there is enough space in the output array (should always be)
assert((i+1)*(m_nDatawordSize) <= nDataOut);
// Copy data
memcpy(&pDataOut[i*m_nDatawordSize], &pDataIn[i*(m_nDatawordSize + m_nCodewordSize)], m_nDatawordSize);
}
}

View File

@@ -0,0 +1,41 @@
#ifndef ECCHAMMIMG_H
#define ECCHAMMIMG_H
#include "eccbaseclass.h"
class ECCHamming : public ECCBaseClass
{
private:
// Hamming constants for this special implementation
const unsigned m_nDatawordSize = 8; // bytes
const unsigned m_nCodewordSize = 1; // bytes
inline unsigned InBits(unsigned n){return n<<3;}; // use this if constants are needed in bits
public:
// Function prototype for calculated the size of memory needed for saving the encoded data
// Input nBytes: Number of bytes which have to be encoded
// Return value: Number of bytes which have to be allocated for storing the encoded data
virtual unsigned AllocationSize(unsigned nBytes);
protected:
// Function prototype for encoding data.
// Data pointer is provided in pDataIn, length in Bytes provided in nDataIn
// Result should be written in pDataOut, which has a size of nDataOut.
// pDataOut is already allocated with a size given by function AllocationEncode
virtual void Encode(const unsigned char* pDataIn, const unsigned nDataIn, unsigned char* pDataOut, const unsigned nDataOut);
// Function prototype for decoding data.
// Data pointer is provided in pDataIn, length in Bytes provided in nDataIn
// Result should be written in pDataOut, which has a size of nDataOut.
// pDataOut is already allocated with a size given by function AllocationDecode
virtual void Decode(const unsigned char* pDataIn, const unsigned nDataIn, unsigned char* pDataOut, const unsigned nDataOut);
public:
ECCHamming(::sc_core::sc_module_name name) : ECCBaseClass(name)
{};
};
#endif // ECCHAMMIMG_H

View File

@@ -49,7 +49,11 @@ void errorModel::init()
burstLenght = Configuration::getInstance().memSpec.BurstLength;
numberOfColumns = Configuration::getInstance().memSpec.NumberOfColumns;
bytesPerColumn = xmlAddressDecoder::getInstance().amount["bytes"];
numberOfRows = Configuration::getInstance().memSpec.NumberOfRows;
// Adjust number of bytes per column dynamically to the selected ecc controller
bytesPerColumn = Configuration::getInstance().adjustNumBytesAfterECC(bytesPerColumn);
numberOfRows = Configuration::getInstance().memSpec.NumberOfRows;
numberOfBitErrorEvents = 0;

View File

@@ -51,6 +51,7 @@
#include "../common/Utils.h"
#include "../simulation/TemperatureController.h"
#include "../controller/Controller.h"
#include "../error/ecchamming.h"
using namespace std;
@@ -58,6 +59,9 @@ DRAMSys::DRAMSys(sc_module_name __attribute__((unused)) name,
string simulationToRun,
string pathToResources) : tSocket("DRAMSys_tSocket")
{
// Initialize ecc pointer
ecc = nullptr;
logo();
// Read Configuration Setup:
@@ -185,9 +189,25 @@ void DRAMSys::instantiateModules(const string &traceName,
// They need to be ready before creating some modules.
setupTlmRecorders(traceName, pathToResources);
// Create new ECC Controller
switch (Configuration::getInstance().ECCMode)
{
case ECCControllerMode::Hamming:
ecc = new ECCHamming("ECCHamming");
break;
default:
ecc = nullptr;
break;
}
// Save ECC Controller into the configuration struct to adjust it dynamically
Configuration::getInstance().pECC = ecc;
// Create arbiter
arbiter = new Arbiter("arbiter");
arbiter->setTlmRecorders(tlmRecorders);
// Create DRAM
for (size_t i = 0;
i < Configuration::getInstance().NumberOfMemChannels;
i++)
@@ -214,42 +234,49 @@ void DRAMSys::instantiateModules(const string &traceName,
void DRAMSys::bindSockets()
{
tSocket.bind(arbiter->tSocket);
// If ECC Controller enabled, put it between Trace and arbiter
if(Configuration::getInstance().ECCMode != ECCControllerMode::Disabled)
{
assert(ecc != nullptr);
tSocket.bind(ecc->t_socket);
ecc->i_socket.bind(arbiter->tSocket);
}
else
{
tSocket.bind(arbiter->tSocket);
}
if(Configuration::getInstance().CheckTLM2Protocol)
if(Configuration::getInstance().CheckTLM2Protocol)
{
for (size_t i = 0;
i < Configuration::getInstance().NumberOfMemChannels;
i++)
{
for (size_t i = 0;
i < Configuration::getInstance().NumberOfMemChannels;
i++)
{
arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket);
controllersTlmCheckers[i]->initiator_socket.bind(
controllers[i]->tSocket);
controllers[i]->iSocket.bind(drams[i]->tSocket);
}
arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket);
controllersTlmCheckers[i]->initiator_socket.bind(
controllers[i]->tSocket);
controllers[i]->iSocket.bind(drams[i]->tSocket);
}
else
}
else
{
for (size_t i = 0;
i < Configuration::getInstance().NumberOfMemChannels;
i++)
{
for (size_t i = 0;
i < Configuration::getInstance().NumberOfMemChannels;
i++)
{
arbiter->iSocket.bind(controllers[i]->tSocket);
controllers[i]->iSocket.bind(drams[i]->tSocket);
}
arbiter->iSocket.bind(controllers[i]->tSocket);
controllers[i]->iSocket.bind(drams[i]->tSocket);
}
}
}
DRAMSys::~DRAMSys()
{
if(ecc)
delete ecc;
delete arbiter;
for (auto controller : controllers)
{
delete controller;
}
for (auto dram : drams)
{
delete dram;
@@ -264,6 +291,11 @@ DRAMSys::~DRAMSys()
{
delete tlmChecker;
}
for (auto controller : controllers)
{
delete controller;
}
}
void DRAMSys::report(string message)

View File

@@ -51,6 +51,7 @@
#include "../controller/Controller.h"
#include "../common/third_party/tinyxml2/tinyxml2.h"
#include "../common/tlm2_base_protocol_checker.h"
#include "../error/eccbaseclass.h"
class DRAMSys: public sc_module
{
@@ -78,9 +79,10 @@ private:
std::vector<tlm_utils::tlm2_base_protocol_checker<>*>
controllersTlmCheckers;
// All transactions pass first through the ECC Controller
ECCBaseClass *ecc;
// All transactions pass through the same arbiter
Arbiter *arbiter;
// Each DRAM unit has a controller
std::vector<Controller*> controllers;

View File

@@ -92,6 +92,11 @@ struct Dram : sc_module
SC_CTOR(Dram) : tSocket("socket")
{
// 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
memory = (unsigned char *)mmap(NULL, memorySize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0);

View File

@@ -123,7 +123,7 @@ void StlPlayer::nextPayload()
unsigned long long addr = std::stoull(address.c_str(), 0, 16);
// Get the data if necessary.
if (Configuration::getInstance().StoreMode != StorageMode::NoStorage) {
if (Configuration::getInstance().StoreMode != StorageMode::NoStorage && cmd != TLM_READ_COMMAND) {
// The input trace file must provide the data to be stored into the memory.
iss >> dataStr;
if (dataStr.empty())

View File

@@ -43,6 +43,7 @@ class TracePlayerListener
public:
virtual void tracePlayerTerminates() = 0;
virtual void transactionFinished() = 0;
virtual ~TracePlayerListener(){};
};
#endif // TRACEPLAYERLISTENER_H

View File

@@ -96,8 +96,6 @@ traceSetup::traceSetup(std::string uri,
NumberOfTracePlayers = devices->size();
}
void traceSetup::tracePlayerTerminates()
{
finishedTracePlayers++;

View File

@@ -53,6 +53,7 @@ public:
virtual void tracePlayerTerminates() override;
virtual void transactionFinished() override;
virtual ~traceSetup(){};
private:
unsigned int NumberOfTracePlayers;

View File

@@ -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;
}

View File

@@ -544,6 +544,7 @@ Below, the sub-configurations are listed and explained.
<SimulationProgressBar value="1"/>
<NumberOfMemChannels value="1"/>
<NumberOfDevicesOnDIMM value = "8" />
<ECCControllerMode value = "Disabled" />
</simconfig>
```
@@ -578,6 +579,9 @@ Below, the sub-configurations are listed and explained.
- *CheckTLM2Protocol* (boolean)
- "1": enables the TLM 2.0 Protocol Checking
- "0": disables the TLM 2.0 Protocol Checking
- *ECCControllerMode* (string)
- "Disabled": No ECC Controller is used
- "Hamming": Enables an ECC Controller with classic SECDED implementation using Hamming Code
- **Temperature Simulator Configuration**