diff --git a/DRAMSys/simulator/src/error/ECC/Bit.cpp b/DRAMSys/simulator/src/error/ECC/Bit.cpp new file mode 100644 index 00000000..b5faee9a --- /dev/null +++ b/DRAMSys/simulator/src/error/ECC/Bit.cpp @@ -0,0 +1,25 @@ +#include "stdafx.h" +#include "Bit.h" + + +CBit::CBit(VALUE nVal) +{ + m_nValue = nVal; +} + + +CBit::~CBit() +{ +} + +void CBit::Print() +{ + if (m_nValue == ZERO) + { + printf("0"); + } + else + { + printf("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..74aec5da --- /dev/null +++ b/DRAMSys/simulator/src/error/ECC/Bit.h @@ -0,0 +1,66 @@ +#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; }; + + void Print(); + + CBit& operator=(DWORD 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..bbd230ba --- /dev/null +++ b/DRAMSys/simulator/src/error/ECC/ECC.cpp @@ -0,0 +1,91 @@ +#include "stdafx.h" + +#include "ECC.h" + +unsigned ECC::GetNumParityBits(unsigned nDataBits) +{ + unsigned nParityBits = 0; + + // n = 2^k - k - 1 + while (nDataBits > ((1 << nParityBits) - nParityBits - 1)) + { + ++nParityBits; + } + + return nParityBits+1; // +1 for SEC-DED +} + +void ECC::ExtendWord(CWord & v) +{ + unsigned end = v.GetLength() + ECC::GetNumParityBits(v.GetLength()); + + unsigned i = 1; + while (i < end) + { + v.Insert(i-1, CBit()); + i <<= 1; + } + + v.Append(CBit()); +} + +void ECC::CalculateCheckbits(CWord & v, CWord & p) +{ + // Hamming-Code Prüfbits füllen + unsigned i = 1, l = 0; + while (i < v.GetLength()) + { + for (unsigned j = (i - 1); j < v.GetLength(); j += (i << 1)) + { + for (unsigned k = 0; k < (i); k++) + { + p[l] ^= v[j + k]; + } + } + l++; + i <<= 1; + } +} + +void ECC::InsertCheckbits(CWord& v, CWord p) +{ + // Prüfbits einfügen + unsigned i = 1, j = 0; + while (i <= v.GetLength()) + { + v[i - 1] = p[j++]; + i <<= 1; + } + +} + +void ECC::ExtractCheckbits(CWord v, CWord & p) +{ + // Prüfbits extrahieren + unsigned i = 1, j = 0; + while(i <= v.GetLength()) + { + p[j++] = v[i - 1]; + i <<= 1; + } +} + +void ECC::CalculateParityBit(CWord v, CBit & p) +{ + // Paritybit + p = CBit::ZERO; + for (unsigned i = 0; i < v.GetLength(); i++) + { + p ^= v[i]; + } +} + +void ECC::InsertParityBit(CWord& v, CBit p) +{ + v[v.GetLength() - 1] = p; +} + +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..8379999a --- /dev/null +++ b/DRAMSys/simulator/src/error/ECC/ECC.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Word.h" +#include "Bit.h" + +namespace ECC +{ + + unsigned GetNumParityBits(unsigned nDataBits); + + // Erweitert das Wort um zusätzliche Bits für die Berechnung des Hamming-Codes + 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..a94bdad7 --- /dev/null +++ b/DRAMSys/simulator/src/error/ECC/Word.cpp @@ -0,0 +1,117 @@ +#include "stdafx.h" +#include "Word.h" + + +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(DWORD 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::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(); + } + printf("\r\n"); +} diff --git a/DRAMSys/simulator/src/error/ECC/Word.h b/DRAMSys/simulator/src/error/ECC/Word.h new file mode 100644 index 00000000..e3ae7c66 --- /dev/null +++ b/DRAMSys/simulator/src/error/ECC/Word.h @@ -0,0 +1,60 @@ +#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(DWORD data); + void Rotate(); + + bool Insert(unsigned npos, CBit b); + bool Delete(unsigned npos); + + 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=(DWORD 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; + } +}; +