From 11d428c1d5b18331ecbbfe048cd9fe3351b01caf Mon Sep 17 00:00:00 2001 From: Johannes Feldmann Date: Thu, 13 Apr 2017 18:59:56 +0200 Subject: [PATCH] ECC implementierung fertig gestellt. --- ...CRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml | 55 ++++++ .../resources/configs/simulator/ddr3_ecc.xml | 22 +++ DRAMSys/simulator/resources/resources.pri | 5 +- .../resources/simulations/ddr3-ecc.xml | 22 +++ DRAMSys/simulator/src/error/ECC/ECC.cpp | 14 +- DRAMSys/simulator/src/error/controllerECC.h | 165 ++++++++++++++---- DRAMSys/simulator/src/error/errormodel.cpp | 7 +- DRAMSys/simulator/src/simulation/main.cpp | 2 +- 8 files changed, 252 insertions(+), 40 deletions(-) create mode 100644 DRAMSys/simulator/resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml create mode 100644 DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml create mode 100644 DRAMSys/simulator/resources/simulations/ddr3-ecc.xml 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/simulator/ddr3_ecc.xml b/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml new file mode 100644 index 00000000..f1f7bcf8 --- /dev/null +++ b/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/simulator/resources/resources.pri b/DRAMSys/simulator/resources/resources.pri index 37b75724..3d02ddb8 100644 --- a/DRAMSys/simulator/resources/resources.pri +++ b/DRAMSys/simulator/resources/resources.pri @@ -140,4 +140,7 @@ DISTFILES += \ $$PWD/configs/mcconfigs/fifo_ecc.xml \ $$PWD/simulations/wideio-ecc.xml \ $$PWD/traces/test_ecc.stl \ - $$PWD/configs/memspecs/wideio_less_refresh.xml + $$PWD/configs/memspecs/wideio_less_refresh.xml \ + $$PWD/simulations/ddr3-ecc.xml \ + $$PWD/configs/simulator/ddr3_ecc.xml \ + $$PWD/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml 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/src/error/ECC/ECC.cpp b/DRAMSys/simulator/src/error/ECC/ECC.cpp index a041496e..b8e15743 100644 --- a/DRAMSys/simulator/src/error/ECC/ECC.cpp +++ b/DRAMSys/simulator/src/error/ECC/ECC.cpp @@ -31,13 +31,17 @@ void ECC::CalculateCheckbits(CWord & v, CWord & p) { // Hamming-Code Prüfbits füllen unsigned i = 1, l = 0; - while (i < v.GetLength()) + + // Last bit is the parity bit - don't use this in the algorithm for hamming code + unsigned len = v.GetLength()-1; + + while (i < len) { - for (unsigned j = (i - 1); j < v.GetLength(); j += (i << 1)) + for (unsigned j = (i - 1); j < len; j += (i << 1)) { for (unsigned k = 0; k < (i); k++) { - if(j + k >= v.GetLength()) + if(j + k >= len) break; p[l] ^= v[j + k]; } @@ -51,7 +55,7 @@ void ECC::InsertCheckbits(CWord& v, CWord p) { // Prüfbits einfügen unsigned i = 1, j = 0; - while (i <= v.GetLength()) + while (i <= v.GetLength()-1) { v[i - 1] = p[j++]; i <<= 1; @@ -63,7 +67,7 @@ void ECC::ExtractCheckbits(CWord v, CWord & p) { // Prüfbits extrahieren unsigned i = 1, j = 0; - while(i <= v.GetLength()) + while(i <= v.GetLength()-1) { p[j++] = v[i - 1]; i <<= 1; diff --git a/DRAMSys/simulator/src/error/controllerECC.h b/DRAMSys/simulator/src/error/controllerECC.h index 94a2ce6e..509e1036 100644 --- a/DRAMSys/simulator/src/error/controllerECC.h +++ b/DRAMSys/simulator/src/error/controllerECC.h @@ -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) + if(trans.get_command() == TLM_WRITE_COMMAND && trans.get_response_status() == TLM_INCOMPLETE_RESPONSE) { // Get data and length unsigned nDataLength = trans.get_data_length(); @@ -53,10 +53,12 @@ public: // Fill in current data block dataword.Set(&pData[i<<3], 64); - dataword.Print(); + // Extend data word ECC::ExtendWord(dataword); + checkbits = 0; + // Calculate Checkbits ECC::CalculateCheckbits(dataword, checkbits); ECC::InsertCheckbits(dataword, checkbits); @@ -67,13 +69,21 @@ public: // Copy old data memcpy(&pDataECC[i*9], &pData[i<<3], 8); - dataword.Print(); - checkbits.Print(); - // Save new data 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); @@ -82,14 +92,24 @@ public: // Set new data trans.set_data_ptr(pDataECC); - - // Allocate memory if necessary - //if(m_mBuffer[trans.get_address()].size() != trans.get_data_length()) - // m_mBuffer[trans.get_address()].resize(trans.get_data_length()); - - // Copy data - //memcpy(m_mBuffer[trans.get_address()].data(), trans.get_data_ptr(), trans.get_data_length()); } + else if(trans.get_response_status() == TLM_INCOMPLETE_RESPONSE) + { + // 64 -> 72 + + // Get data length + unsigned nDataLength = trans.get_data_length(); + + // delete old data + delete[] trans.get_data_ptr(); + + // Set new data + nDataLength += nDataLength>>3; + trans.set_data_ptr(new unsigned char [nDataLength]); + + // Change transport data length + trans.set_data_length(nDataLength); + } return i_socket[id]->nb_transport_fw( trans, phase, delay ); } @@ -99,27 +119,108 @@ public: { if(trans.get_command() == TLM_READ_COMMAND && phase == 3) { - if(m_mBuffer[trans.get_address()].size() == trans.get_data_length()) - { - // Data can be compared, they got the same size - int error = memcmp(m_mBuffer[trans.get_address()].data(), trans.get_data_ptr(), trans.get_data_length()); - if(error) - { - // Data not equal - cout << "\nError Detected: Address: 0x" << hex << trans.get_address(); + // Get data and length + unsigned nDataLength = trans.get_data_length(); + unsigned char* pData = trans.get_data_ptr(); - for(unsigned n = 0; n < trans.get_data_length(); n++) - { - if(m_mBuffer[trans.get_address()].data()[n] != trans.get_data_ptr()[n]) - { - cout << "\n\t\tError Byte " << dec << n << " Orig: 0x" << hex << (int)m_mBuffer[trans.get_address()].data()[n] - << " Read: 0x" << hex << (int)trans.get_data_ptr()[n]; - } - } - cout << endl; - } - } - } + // 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++) + { + // Create all variables needed for calulation + CWord dataword(64); + CWord checkbits(8); + + // Fill in current data block + dataword.Set(&pData[i*9], 64); + checkbits.Set(&pData[i*9+8], 8); + + // Extend data word + ECC::ExtendWord(dataword); + + // Insert old checkbits + ECC::InsertCheckbits(dataword, checkbits); + ECC::InsertParityBit(dataword, checkbits[7]); + + checkbits = 0; + + // Calculate Checkbits + ECC::CalculateCheckbits(dataword, checkbits); + + // Calculate Parity + ECC::CalculateParityBit(dataword, checkbits[7]); + + // Translate Checkbits + bool bParity = checkbits[7] == CBit::ONE; + + unsigned char c = 0; + checkbits.Rotate(); + checkbits.Copy(&c); + c &= 0x7F; + + // Parity Error? + if(bParity) + { + // Parity Error + + if(c == 0) + { + // Only Parity Bit broken - continue + cout << "Parity Bit error" << endl; + continue; + } + else + { + // Data or Hamming Code Bit broken + cout << "Single Error Detected" << endl; + continue; + } + } + else + { + // No Parity Error + + if(c == 0) + { + // No error at all - continue + continue; + } + else + { + // Double error detected + cout << "Double Error Detected (Block " << i << ")." << endl; + continue; + } + } + } + // Change transport data length + trans.set_data_length(nBlocks<<3); + + // New Data + unsigned char* pDataECC = new unsigned char[nBlocks<<3]; + + // Copy data + memcpy(pDataECC, pData, nBlocks<<3); + + // delete old data + delete[] trans.get_data_ptr(); + + // Set new data + trans.set_data_ptr(pDataECC); + } return t_socket[id]->nb_transport_bw( trans, phase, delay ); } }; diff --git a/DRAMSys/simulator/src/error/errormodel.cpp b/DRAMSys/simulator/src/error/errormodel.cpp index 91eb789b..5ff3693f 100644 --- a/DRAMSys/simulator/src/error/errormodel.cpp +++ b/DRAMSys/simulator/src/error/errormodel.cpp @@ -49,7 +49,12 @@ void errorModel::init() burstLenght = Configuration::getInstance().memSpec.BurstLength; numberOfColumns = Configuration::getInstance().memSpec.NumberOfColumns; bytesPerColumn = xmlAddressDecoder::getInstance().amount["bytes"]; - numberOfRows = Configuration::getInstance().memSpec.NumberOfRows; + if(Configuration::getInstance().EnableControllerECC) + { + bytesPerColumn += bytesPerColumn>>3; + } + + numberOfRows = Configuration::getInstance().memSpec.NumberOfRows; numberOfBitErrorEvents = 0; diff --git a/DRAMSys/simulator/src/simulation/main.cpp b/DRAMSys/simulator/src/simulation/main.cpp index 18b474e9..0bb75469 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/wideio-ecc.xml"; + SimulationXML = resources + "simulations/ddr3-ecc.xml"; } std::vector players;