diff --git a/DRAMSys/simulator/library.pro b/DRAMSys/simulator/library.pro
index 4cac1673..a0bb357c 100644
--- a/DRAMSys/simulator/library.pro
+++ b/DRAMSys/simulator/library.pro
@@ -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) {
diff --git a/DRAMSys/simulator/resources/configs/mcconfigs/fifo.xml b/DRAMSys/simulator/resources/configs/mcconfigs/fifo.xml
index 08135f13..b09a4cfa 100644
--- a/DRAMSys/simulator/resources/configs/mcconfigs/fifo.xml
+++ b/DRAMSys/simulator/resources/configs/mcconfigs/fifo.xml
@@ -8,13 +8,5 @@
-
-
-
-
diff --git a/DRAMSys/simulator/resources/configs/mcconfigs/fifoStrict.xml b/DRAMSys/simulator/resources/configs/mcconfigs/fifoStrict.xml
index 5c58a9c5..7ca1a824 100644
--- a/DRAMSys/simulator/resources/configs/mcconfigs/fifoStrict.xml
+++ b/DRAMSys/simulator/resources/configs/mcconfigs/fifoStrict.xml
@@ -8,13 +8,5 @@
-
-
-
-
diff --git a/DRAMSys/simulator/resources/configs/mcconfigs/fifo_ecc.xml b/DRAMSys/simulator/resources/configs/mcconfigs/fifo_ecc.xml
new file mode 100644
index 00000000..b09a4cfa
--- /dev/null
+++ b/DRAMSys/simulator/resources/configs/mcconfigs/fifo_ecc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DRAMSys/simulator/resources/configs/mcconfigs/fr_fcfs.xml b/DRAMSys/simulator/resources/configs/mcconfigs/fr_fcfs.xml
index fad8b021..0ff319b0 100644
--- a/DRAMSys/simulator/resources/configs/mcconfigs/fr_fcfs.xml
+++ b/DRAMSys/simulator/resources/configs/mcconfigs/fr_fcfs.xml
@@ -8,14 +8,6 @@
-
-
-
-
diff --git a/DRAMSys/simulator/resources/configs/mcconfigs/par_bs.xml b/DRAMSys/simulator/resources/configs/mcconfigs/par_bs.xml
index 78a8afd7..63fb4a27 100644
--- a/DRAMSys/simulator/resources/configs/mcconfigs/par_bs.xml
+++ b/DRAMSys/simulator/resources/configs/mcconfigs/par_bs.xml
@@ -8,13 +8,5 @@
-
-
-
-
diff --git a/DRAMSys/simulator/resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml b/DRAMSys/simulator/resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml
new file mode 100644
index 00000000..7a94a932
--- /dev/null
+++ b/DRAMSys/simulator/resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DRAMSys/simulator/resources/configs/memspecs/wideio_less_refresh.xml b/DRAMSys/simulator/resources/configs/memspecs/wideio_less_refresh.xml
new file mode 100644
index 00000000..f8aa3190
--- /dev/null
+++ b/DRAMSys/simulator/resources/configs/memspecs/wideio_less_refresh.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DRAMSys/simulator/resources/configs/simulator/ddr3-single-device.xml b/DRAMSys/simulator/resources/configs/simulator/ddr3-single-device.xml
index 35fd3dec..354ad0d5 100644
--- a/DRAMSys/simulator/resources/configs/simulator/ddr3-single-device.xml
+++ b/DRAMSys/simulator/resources/configs/simulator/ddr3-single-device.xml
@@ -11,4 +11,13 @@
+
+
+
+
+
diff --git a/DRAMSys/simulator/resources/configs/simulator/ddr3.xml b/DRAMSys/simulator/resources/configs/simulator/ddr3.xml
index 9e322605..d48f6a8d 100644
--- a/DRAMSys/simulator/resources/configs/simulator/ddr3.xml
+++ b/DRAMSys/simulator/resources/configs/simulator/ddr3.xml
@@ -11,6 +11,15 @@
+
+
+
+
+
+
+
diff --git a/DRAMSys/simulator/resources/configs/simulator/wideio.xml b/DRAMSys/simulator/resources/configs/simulator/wideio.xml
index 8ba8f3ba..34c328c3 100644
--- a/DRAMSys/simulator/resources/configs/simulator/wideio.xml
+++ b/DRAMSys/simulator/resources/configs/simulator/wideio.xml
@@ -10,5 +10,14 @@
+
+
+
+
+
diff --git a/DRAMSys/simulator/resources/configs/simulator/wideio_ecc.xml b/DRAMSys/simulator/resources/configs/simulator/wideio_ecc.xml
new file mode 100644
index 00000000..49967b58
--- /dev/null
+++ b/DRAMSys/simulator/resources/configs/simulator/wideio_ecc.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DRAMSys/simulator/resources/configs/simulator/wideio_thermal.xml b/DRAMSys/simulator/resources/configs/simulator/wideio_thermal.xml
index 42dcda72..f3a99d72 100644
--- a/DRAMSys/simulator/resources/configs/simulator/wideio_thermal.xml
+++ b/DRAMSys/simulator/resources/configs/simulator/wideio_thermal.xml
@@ -10,5 +10,14 @@
+
+
+
+
+
diff --git a/DRAMSys/simulator/src/error/error.csv b/DRAMSys/simulator/resources/error/wideio.csv
similarity index 100%
rename from DRAMSys/simulator/src/error/error.csv
rename to DRAMSys/simulator/resources/error/wideio.csv
diff --git a/DRAMSys/simulator/resources/resources.pri b/DRAMSys/simulator/resources/resources.pri
index 914daa88..f240b193 100644
--- a/DRAMSys/simulator/resources/resources.pri
+++ b/DRAMSys/simulator/resources/resources.pri
@@ -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
diff --git a/DRAMSys/simulator/resources/simulations/ddr3-ecc.xml b/DRAMSys/simulator/resources/simulations/ddr3-ecc.xml
new file mode 100644
index 00000000..5760612c
--- /dev/null
+++ b/DRAMSys/simulator/resources/simulations/ddr3-ecc.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test_ecc.stl
+
+
diff --git a/DRAMSys/simulator/resources/simulations/wideio-ecc.xml b/DRAMSys/simulator/resources/simulations/wideio-ecc.xml
new file mode 100644
index 00000000..ead21319
--- /dev/null
+++ b/DRAMSys/simulator/resources/simulations/wideio-ecc.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test_ecc.stl
+
+
diff --git a/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp b/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp
index f0fd7f68..6cb0ffb9 100644
--- a/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp
+++ b/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp
@@ -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);
+ }
+}
diff --git a/DRAMSys/simulator/src/controller/core/configuration/Configuration.h b/DRAMSys/simulator/src/controller/core/configuration/Configuration.h
index 2f158053..082d7530 100644
--- a/DRAMSys/simulator/src/controller/core/configuration/Configuration.h
+++ b/DRAMSys/simulator/src/controller/core/configuration/Configuration.h
@@ -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();
diff --git a/DRAMSys/simulator/src/error/ECC/Bit.cpp b/DRAMSys/simulator/src/error/ECC/Bit.cpp
new file mode 100644
index 00000000..55f28ebf
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ECC/Bit.cpp
@@ -0,0 +1,27 @@
+#include "Bit.h"
+
+#include
+
+using std::cout;
+
+CBit::CBit(VALUE nVal)
+{
+ m_nValue = nVal;
+}
+
+
+CBit::~CBit()
+{
+}
+
+void CBit::Print()
+{
+ if (m_nValue == ZERO)
+ {
+ cout <<"0";
+ }
+ else
+ {
+ cout << "1";
+ }
+}
diff --git a/DRAMSys/simulator/src/error/ECC/Bit.h b/DRAMSys/simulator/src/error/ECC/Bit.h
new file mode 100644
index 00000000..bfdda476
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ECC/Bit.h
@@ -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;
+ }
+};
+
diff --git a/DRAMSys/simulator/src/error/ECC/ECC.cpp b/DRAMSys/simulator/src/error/ECC/ECC.cpp
new file mode 100644
index 00000000..6cfaffe9
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ECC/ECC.cpp
@@ -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];
+}
diff --git a/DRAMSys/simulator/src/error/ECC/ECC.h b/DRAMSys/simulator/src/error/ECC/ECC.h
new file mode 100644
index 00000000..3e9b8238
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ECC/ECC.h
@@ -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);
+}
diff --git a/DRAMSys/simulator/src/error/ECC/ECC_Test.cpp b/DRAMSys/simulator/src/error/ECC/ECC_Test.cpp
new file mode 100644
index 00000000..dcbd884e
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ECC/ECC_Test.cpp
@@ -0,0 +1,128 @@
+// ECC_Test.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
+//
+
+#include "stdafx.h"
+#include
+#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;
+}
+
diff --git a/DRAMSys/simulator/src/error/ECC/Word.cpp b/DRAMSys/simulator/src/error/ECC/Word.cpp
new file mode 100644
index 00000000..fbf82ef3
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ECC/Word.cpp
@@ -0,0 +1,157 @@
+#include "Word.h"
+
+#include
+#include
+#include
+
+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::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::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 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::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::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::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;
+ }
+}
diff --git a/DRAMSys/simulator/src/error/ECC/Word.h b/DRAMSys/simulator/src/error/ECC/Word.h
new file mode 100644
index 00000000..efcdd981
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ECC/Word.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include
+#include "Bit.h"
+
+using std::deque;
+
+
+class CWord
+{
+protected:
+
+ unsigned m_nBitLength;
+ deque 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;
+ }
+};
+
diff --git a/DRAMSys/simulator/src/error/eccbaseclass.cpp b/DRAMSys/simulator/src/error/eccbaseclass.cpp
new file mode 100644
index 00000000..10deaa02
--- /dev/null
+++ b/DRAMSys/simulator/src/error/eccbaseclass.cpp
@@ -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 );
+}
diff --git a/DRAMSys/simulator/src/error/eccbaseclass.h b/DRAMSys/simulator/src/error/eccbaseclass.h
new file mode 100644
index 00000000..1c64f51d
--- /dev/null
+++ b/DRAMSys/simulator/src/error/eccbaseclass.h
@@ -0,0 +1,67 @@
+#ifndef ECCBASECLASS_H
+#define ECCBASECLASS_H
+
+#include
+#include
+#include
+#include
+
+#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 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 t_socket;
+ tlm_utils::multi_passthrough_initiator_socket 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
diff --git a/DRAMSys/simulator/src/error/ecchamming.cpp b/DRAMSys/simulator/src/error/ecchamming.cpp
new file mode 100644
index 00000000..d2d1e466
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ecchamming.cpp
@@ -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);
+ }
+}
diff --git a/DRAMSys/simulator/src/error/ecchamming.h b/DRAMSys/simulator/src/error/ecchamming.h
new file mode 100644
index 00000000..99c548fb
--- /dev/null
+++ b/DRAMSys/simulator/src/error/ecchamming.h
@@ -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
diff --git a/DRAMSys/simulator/src/error/errormodel.cpp b/DRAMSys/simulator/src/error/errormodel.cpp
index 4e397377..e1010f6a 100644
--- a/DRAMSys/simulator/src/error/errormodel.cpp
+++ b/DRAMSys/simulator/src/error/errormodel.cpp
@@ -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;
diff --git a/DRAMSys/simulator/src/simulation/DRAMSys.cpp b/DRAMSys/simulator/src/simulation/DRAMSys.cpp
index 515c292c..4378b721 100644
--- a/DRAMSys/simulator/src/simulation/DRAMSys.cpp
+++ b/DRAMSys/simulator/src/simulation/DRAMSys.cpp
@@ -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;
diff --git a/DRAMSys/simulator/src/simulation/DRAMSys.h b/DRAMSys/simulator/src/simulation/DRAMSys.h
index 3f1aeca9..63ea9052 100644
--- a/DRAMSys/simulator/src/simulation/DRAMSys.h
+++ b/DRAMSys/simulator/src/simulation/DRAMSys.h
@@ -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*>
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 controllers;
diff --git a/DRAMSys/simulator/src/simulation/Dram.h b/DRAMSys/simulator/src/simulation/Dram.h
index a5254d97..61d5f941 100644
--- a/DRAMSys/simulator/src/simulation/Dram.h
+++ b/DRAMSys/simulator/src/simulation/Dram.h
@@ -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;
diff --git a/DRAMSys/simulator/src/simulation/StlPlayer.cpp b/DRAMSys/simulator/src/simulation/StlPlayer.cpp
index 75817aba..5bf712ed 100644
--- a/DRAMSys/simulator/src/simulation/StlPlayer.cpp
+++ b/DRAMSys/simulator/src/simulation/StlPlayer.cpp
@@ -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())
diff --git a/README.md b/README.md
index eb3e5f75..75ce2bc9 100644
--- a/README.md
+++ b/README.md
@@ -544,6 +544,7 @@ Below, the sub-configurations are listed and explained.
+
```
@@ -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**