Merge pull request #164 from jfeldman/master

ECC Controller implementation with basic Hamming code
This commit is contained in:
fzeder
2017-06-22 14:56:33 +02:00
committed by GitHub Enterprise
37 changed files with 1323 additions and 56 deletions

View File

@@ -112,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 \
@@ -176,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,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

@@ -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,6 +5,8 @@
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
@@ -12,6 +14,8 @@ 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
@@ -60,6 +64,7 @@ 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
@@ -70,6 +75,7 @@ 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
@@ -113,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
@@ -139,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,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

@@ -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")
@@ -209,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);
@@ -317,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;
@@ -83,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)
@@ -102,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

@@ -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,34 +234,46 @@ 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;

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

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

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