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