diff --git a/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml b/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml
index f1f7bcf8..0d192422 100644
--- a/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml
+++ b/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml
@@ -12,11 +12,4 @@
-
-
diff --git a/DRAMSys/simulator/resources/resources.pri b/DRAMSys/simulator/resources/resources.pri
index 7d191a53..ac3384bf 100644
--- a/DRAMSys/simulator/resources/resources.pri
+++ b/DRAMSys/simulator/resources/resources.pri
@@ -6,6 +6,7 @@ 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
# Simulator Files
OTHER_FILES += resources/configs/simulator/wideio.xml
@@ -13,7 +14,7 @@ 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
# Scripts
OTHER_FILES += resources/scripts/address_scrambler.pl
@@ -112,6 +113,7 @@ OTHER_FILES += resources/configs/memspecs/SAMSUNG_K4B1G1646E_1Gb_DDR3-1600_16bit
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
diff --git a/DRAMSys/simulator/src/error/ECC/ECC.cpp b/DRAMSys/simulator/src/error/ECC/ECC.cpp
index b8e15743..6cfaffe9 100644
--- a/DRAMSys/simulator/src/error/ECC/ECC.cpp
+++ b/DRAMSys/simulator/src/error/ECC/ECC.cpp
@@ -1,22 +1,32 @@
#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;
- // n = 2^k - k - 1
+ // 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 SEC-DED
+ 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)
{
@@ -24,17 +34,33 @@ void ECC::ExtendWord(CWord & v)
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)
{
- // Hamming-Code Prüfbits füllen
- unsigned i = 1, l = 0;
+ 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))
@@ -51,21 +77,26 @@ void ECC::CalculateCheckbits(CWord & v, CWord & p)
}
}
+// ************************************************************************************************
+// 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)
{
- // Prüfbits einfügen
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)
{
- // Prüfbits extrahieren
unsigned i = 1, j = 0;
while(i <= v.GetLength()-1)
{
@@ -74,6 +105,9 @@ void ECC::ExtractCheckbits(CWord v, CWord & p)
}
}
+// ************************************************************************************************
+// Function which calculates the overal parity
+// Simply XOR all bits
void ECC::CalculateParityBit(CWord v, CBit & p)
{
// Paritybit
@@ -84,11 +118,15 @@ void ECC::CalculateParityBit(CWord v, CBit & p)
}
}
+// ************************************************************************************************
+// 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
index 8379999a..3e9b8238 100644
--- a/DRAMSys/simulator/src/error/ECC/ECC.h
+++ b/DRAMSys/simulator/src/error/ECC/ECC.h
@@ -3,12 +3,30 @@
#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);
- // Erweitert das Wort um zusätzliche Bits für die Berechnung des Hamming-Codes
+ // 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);
diff --git a/DRAMSys/simulator/src/error/controllerECC.h b/DRAMSys/simulator/src/error/controllerECC.h
index 509e1036..9ca85fe8 100644
--- a/DRAMSys/simulator/src/error/controllerECC.h
+++ b/DRAMSys/simulator/src/error/controllerECC.h
@@ -14,7 +14,7 @@ using namespace tlm;
struct ControllerECC: sc_module
{
private:
- map> m_mBuffer;
+ map m_mDataPointer;
public:
tlm_utils::multi_passthrough_target_socket t_socket;
@@ -31,7 +31,7 @@ public:
// Forward interface
virtual tlm::tlm_sync_enum nb_transport_fw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay )
{
- if(trans.get_command() == TLM_WRITE_COMMAND && trans.get_response_status() == TLM_INCOMPLETE_RESPONSE)
+ if(trans.get_command() == TLM_WRITE_COMMAND && phase == BEGIN_REQ)
{
// Get data and length
unsigned nDataLength = trans.get_data_length();
@@ -69,47 +69,37 @@ public:
// Copy old data
memcpy(&pDataECC[i*9], &pData[i<<3], 8);
- // Save new data
+ // Save hamming code + parity bit in the last byte
checkbits.Copy(&pDataECC[i*9+8]);
}
- // Print all
-// for(unsigned i = 0; i < nBlocks; i++)
-// {
-// for(unsigned j = 0; j < 9; j++)
-// {
-// cout << setw(2) << setfill('0') << hex << uppercase << (int)pDataECC[i*9+j];
-// }
-// cout << endl;
-// }
-// cout << endl;
-
// Change transport data length
trans.set_data_length(nBlocks*9);
- // delete old data
- delete[] trans.get_data_ptr();
+ // store old data
+ m_mDataPointer[id] = trans.get_data_ptr();
// Set new data
trans.set_data_ptr(pDataECC);
}
- else if(trans.get_response_status() == TLM_INCOMPLETE_RESPONSE)
- {
- // 64 -> 72
+ else if(trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_REQ)
+ {
+ // 64 -> 72
- // Get data length
- unsigned nDataLength = trans.get_data_length();
+ // Get data length
+ unsigned nDataLength = trans.get_data_length();
- // delete old data
- delete[] trans.get_data_ptr();
+ // store old data
+ m_mDataPointer[id] = trans.get_data_ptr();
- // Set new data
- nDataLength += nDataLength>>3;
- trans.set_data_ptr(new unsigned char [nDataLength]);
+ // Set new data
+ nDataLength += nDataLength>>3;
+ trans.set_data_ptr(new unsigned char [nDataLength]);
+
+ // Change transport data length
+ trans.set_data_length(nDataLength);
+ }
- // Change transport data length
- trans.set_data_length(nDataLength);
- }
return i_socket[id]->nb_transport_fw( trans, phase, delay );
}
@@ -117,7 +107,7 @@ public:
// Backward interface
virtual tlm::tlm_sync_enum 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 == 3)
+ if(trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_RESP)
{
// Get data and length
unsigned nDataLength = trans.get_data_length();
@@ -126,17 +116,6 @@ public:
// Calculate how many 72 bit blocks are there
unsigned nBlocks = nDataLength/9;
- // Print all
-// for(unsigned i = 0; i < nBlocks; i++)
-// {
-// for(unsigned j = 0; j < 9; j++)
-// {
-// cout << setw(2) << setfill('0') << hex << uppercase << (int)pData[i*9+j];
-// }
-// cout << endl;
-// }
-// cout << endl;
-
// Verify ECC data for every block
for(unsigned i = 0; i < nBlocks; i++)
{
@@ -209,8 +188,11 @@ public:
// Change transport data length
trans.set_data_length(nBlocks<<3);
- // New Data
- unsigned char* pDataECC = new unsigned char[nBlocks<<3];
+ // load data pointer
+ auto it = m_mDataPointer.find(id);
+ assert(it != m_mDataPointer.end());
+
+ unsigned char* pDataECC = it->second;
// Copy data
memcpy(pDataECC, pData, nBlocks<<3);
@@ -221,6 +203,26 @@ public:
// Set new data
trans.set_data_ptr(pDataECC);
}
+ else if(trans.get_command() == TLM_WRITE_COMMAND && phase == BEGIN_RESP)
+ {
+ // 72 -> 64
+
+ // delete old data
+ delete[] trans.get_data_ptr();
+
+ // Get data length
+ unsigned nDataLength = trans.get_data_length();
+
+ // load data pointer
+ auto it = m_mDataPointer.find(id);
+ assert(it != m_mDataPointer.end());
+
+ trans.set_data_ptr(it->second);
+
+ // Change transport data length
+ trans.set_data_length((nDataLength/9)<<3);
+ }
+
return t_socket[id]->nb_transport_bw( trans, phase, delay );
}
};
diff --git a/DRAMSys/simulator/src/simulation/main.cpp b/DRAMSys/simulator/src/simulation/main.cpp
index 0bb75469..18e00f77 100644
--- a/DRAMSys/simulator/src/simulation/main.cpp
+++ b/DRAMSys/simulator/src/simulation/main.cpp
@@ -72,7 +72,7 @@ int sc_main(int argc, char **argv)
}
else
{
- SimulationXML = resources + "simulations/ddr3-ecc.xml";
+ SimulationXML = resources + "simulations/ddr3-example.xml";
}
std::vector players;
diff --git a/README.md b/README.md
index eb3e5f75..06e96cb6 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
+ - *EnableControllerECC* (boolean)
+ - "1": enables the ECC Controller with classic SECDED implementation
+ - "0": disables the ECC Controller with classic SECDED implementation
- **Temperature Simulator Configuration**