EccBaseClass ready to use. ECCHammnigClass created.
This commit is contained in:
@@ -114,7 +114,9 @@ SOURCES += \
|
||||
src/simulation/Setup.cpp \
|
||||
src/error/ECC/Bit.cpp \
|
||||
src/error/ECC/ECC.cpp \
|
||||
src/error/ECC/Word.cpp
|
||||
src/error/ECC/Word.cpp \
|
||||
src/error/eccbaseclass.cpp \
|
||||
src/error/ecchamming.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/common/third_party/tinyxml2/tinyxml2.h \
|
||||
@@ -178,10 +180,11 @@ HEADERS += \
|
||||
src/simulation/TraceSetup.h \
|
||||
src/simulation/DRAMSys.h \
|
||||
src/simulation/Setup.h \
|
||||
src/error/controllerECC.h \
|
||||
src/error/ECC/Bit.h \
|
||||
src/error/ECC/ECC.h \
|
||||
src/error/ECC/Word.h
|
||||
src/error/ECC/Word.h \
|
||||
src/error/eccbaseclass.h \
|
||||
src/error/ecchamming.h
|
||||
|
||||
thermalsim = $$(THERMALSIM)
|
||||
isEmpty(thermalsim) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "Word.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
using std::cout;
|
||||
|
||||
@@ -47,7 +49,7 @@ void CWord::Set(unsigned data)
|
||||
}
|
||||
}
|
||||
|
||||
void CWord::Set(unsigned char* data, unsigned lengthInBits)
|
||||
void CWord::Set(const unsigned char* data, unsigned lengthInBits)
|
||||
{
|
||||
deque<CBit>::iterator it;
|
||||
if (m_nBitLength < lengthInBits)
|
||||
@@ -143,6 +145,9 @@ void CWord::Print()
|
||||
|
||||
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++)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
CBit* GetAt(unsigned nBitPos);
|
||||
|
||||
void Set(unsigned data);
|
||||
void Set(unsigned char* data, unsigned lengthInBits);
|
||||
void Set(const unsigned char* data, unsigned lengthInBits);
|
||||
void Rotate();
|
||||
|
||||
bool Insert(unsigned npos, CBit b);
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
#ifndef CONTROLLERECC_H
|
||||
#define CONTROLLERECC_H
|
||||
|
||||
#include <systemc.h>
|
||||
|
||||
#include "ECC/ECC.h"
|
||||
|
||||
#include "../common/xmlAddressdecoder.h"
|
||||
#include "../common/DebugManager.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tlm;
|
||||
|
||||
struct ControllerECC: sc_module
|
||||
{
|
||||
private:
|
||||
map<unsigned char*, unsigned char*> m_mDataPointer;
|
||||
|
||||
public:
|
||||
tlm_utils::multi_passthrough_target_socket<ControllerECC> t_socket;
|
||||
tlm_utils::multi_passthrough_initiator_socket<ControllerECC> i_socket;
|
||||
|
||||
SC_CTOR(ControllerECC)
|
||||
: t_socket("t_socket")
|
||||
, i_socket("i_socket")
|
||||
{
|
||||
t_socket.register_nb_transport_fw(this, &ControllerECC::nb_transport_fw);
|
||||
i_socket.register_nb_transport_bw(this, &ControllerECC::nb_transport_bw);
|
||||
}
|
||||
|
||||
// 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 && phase == BEGIN_REQ)
|
||||
{
|
||||
// Get data and length
|
||||
unsigned nDataLength = trans.get_data_length();
|
||||
unsigned char* pData = trans.get_data_ptr();
|
||||
|
||||
// Calculate how many 64 bit blocks are there
|
||||
unsigned nBlocks = nDataLength>>3;
|
||||
|
||||
// Create new data array for data with ECC
|
||||
unsigned char* pDataECC = new unsigned char[nBlocks*9];
|
||||
memset(pDataECC, 0x0, nBlocks*9*sizeof(unsigned char));
|
||||
|
||||
// Create 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<<3], 64);
|
||||
|
||||
// Extend data word
|
||||
ECC::ExtendWord(dataword);
|
||||
|
||||
checkbits = 0;
|
||||
|
||||
// Calculate Checkbits
|
||||
ECC::CalculateCheckbits(dataword, checkbits);
|
||||
ECC::InsertCheckbits(dataword, checkbits);
|
||||
|
||||
// Calculate Parity
|
||||
ECC::CalculateParityBit(dataword, checkbits[7]);
|
||||
|
||||
// Copy old data
|
||||
memcpy(&pDataECC[i*9], &pData[i<<3], 8);
|
||||
|
||||
// Save hamming code + parity bit in the last byte
|
||||
checkbits.Copy(&pDataECC[i*9+8]);
|
||||
}
|
||||
|
||||
// Change transport data length
|
||||
trans.set_data_length(nBlocks*9);
|
||||
|
||||
// store old data
|
||||
m_mDataPointer[pDataECC] = trans.get_data_ptr();
|
||||
|
||||
// Set new data
|
||||
trans.set_data_ptr(pDataECC);
|
||||
}
|
||||
else if(trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_REQ)
|
||||
{
|
||||
// 64 -> 72
|
||||
|
||||
// Get data length
|
||||
unsigned nDataLength = trans.get_data_length();
|
||||
|
||||
// Create new pointer
|
||||
nDataLength += nDataLength>>3;
|
||||
unsigned char* new_ptr = new unsigned char [nDataLength];
|
||||
|
||||
// store old data ptr
|
||||
m_mDataPointer[new_ptr] = trans.get_data_ptr();
|
||||
|
||||
// Set new data
|
||||
trans.set_data_ptr(new_ptr);
|
||||
|
||||
// Change transport data length
|
||||
trans.set_data_length(nDataLength);
|
||||
}
|
||||
|
||||
return i_socket[id]->nb_transport_fw( trans, phase, delay );
|
||||
}
|
||||
|
||||
|
||||
// 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 == BEGIN_RESP)
|
||||
{
|
||||
// Get data and length
|
||||
unsigned nDataLength = trans.get_data_length();
|
||||
unsigned char* pData = trans.get_data_ptr();
|
||||
|
||||
// Calculate how many 72 bit blocks are there
|
||||
unsigned nBlocks = nDataLength/9;
|
||||
|
||||
// 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);
|
||||
|
||||
// load data pointer
|
||||
auto it = m_mDataPointer.find(trans.get_data_ptr());
|
||||
assert(it != m_mDataPointer.end());
|
||||
|
||||
unsigned char* pDataECC = it->second;
|
||||
|
||||
// delete data pointer from map
|
||||
m_mDataPointer.erase(it);
|
||||
|
||||
// Copy data
|
||||
memcpy(pDataECC, pData, nBlocks<<3);
|
||||
|
||||
// delete old data
|
||||
delete[] trans.get_data_ptr();
|
||||
|
||||
// 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(trans.get_data_ptr());
|
||||
assert(it != m_mDataPointer.end());
|
||||
|
||||
trans.set_data_ptr(it->second);
|
||||
|
||||
// delete data pointer from map
|
||||
m_mDataPointer.erase(it);
|
||||
|
||||
// Change transport data length
|
||||
trans.set_data_length((nDataLength/9)<<3);
|
||||
}
|
||||
|
||||
return t_socket[id]->nb_transport_bw( trans, phase, delay );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CONTROLLERECC_H
|
||||
83
DRAMSys/simulator/src/error/eccbaseclass.cpp
Normal file
83
DRAMSys/simulator/src/error/eccbaseclass.cpp
Normal file
@@ -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 );
|
||||
}
|
||||
67
DRAMSys/simulator/src/error/eccbaseclass.h
Normal file
67
DRAMSys/simulator/src/error/eccbaseclass.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef ECCBASECLASS_H
|
||||
#define ECCBASECLASS_H
|
||||
|
||||
#include <systemc.h>
|
||||
#include <tlm.h>
|
||||
#include <tlm_utils/multi_passthrough_initiator_socket.h>
|
||||
#include <tlm_utils/multi_passthrough_target_socket.h>
|
||||
|
||||
#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<unsigned char*, DataStruct> 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<ECCBaseClass> t_socket;
|
||||
tlm_utils::multi_passthrough_initiator_socket<ECCBaseClass> 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
|
||||
160
DRAMSys/simulator/src/error/ecchamming.cpp
Normal file
160
DRAMSys/simulator/src/error/ecchamming.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#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]);
|
||||
}
|
||||
|
||||
cout << "Encode:\r\n";
|
||||
for(unsigned i = 0; i < nDataIn; i++)
|
||||
{
|
||||
cout << setw(2) << setfill('0') << hex << uppercase << (int)pDataIn[i];
|
||||
}
|
||||
cout << endl;
|
||||
for(unsigned i = 0; i < nDataOut; i++)
|
||||
{
|
||||
cout << setw(2) << setfill('0') << hex << uppercase << (int)pDataOut[i];
|
||||
}
|
||||
cout << endl << endl;
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
dataword.Print();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
cout << "Decode:\r\n";
|
||||
for(unsigned i = 0; i < nDataIn; i++)
|
||||
{
|
||||
cout << setw(2) << setfill('0') << hex << uppercase << (int)pDataIn[i];
|
||||
}
|
||||
cout << endl;
|
||||
for(unsigned i = 0; i < nDataOut; i++)
|
||||
{
|
||||
cout << setw(2) << setfill('0') << hex << uppercase << (int)pDataOut[i];
|
||||
}
|
||||
cout << endl << endl;
|
||||
}
|
||||
41
DRAMSys/simulator/src/error/ecchamming.h
Normal file
41
DRAMSys/simulator/src/error/ecchamming.h
Normal file
@@ -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
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "../common/Utils.h"
|
||||
#include "../simulation/TemperatureController.h"
|
||||
#include "../controller/Controller.h"
|
||||
#include "../error/ecchamming.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -192,7 +193,7 @@ void DRAMSys::instantiateModules(const string &traceName,
|
||||
switch (Configuration::getInstance().ECCMode)
|
||||
{
|
||||
case ECCControllerMode::Hamming:
|
||||
ecc = new ControllerECC("ControllerECC");
|
||||
ecc = new ECCHamming("ECCHamming");
|
||||
break;
|
||||
default:
|
||||
ecc = 0;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "../controller/Controller.h"
|
||||
#include "../common/third_party/tinyxml2/tinyxml2.h"
|
||||
#include "../common/tlm2_base_protocol_checker.h"
|
||||
#include "../error/controllerECC.h"
|
||||
#include "../error/eccbaseclass.h"
|
||||
|
||||
class DRAMSys: public sc_module
|
||||
{
|
||||
@@ -80,7 +80,7 @@ private:
|
||||
controllersTlmCheckers;
|
||||
|
||||
// All transactions pass first through the ECC Controller
|
||||
ControllerECC *ecc;
|
||||
ECCBaseClass *ecc;
|
||||
// All transactions pass through the same arbiter
|
||||
Arbiter *arbiter;
|
||||
// Each DRAM unit has a controller
|
||||
|
||||
Reference in New Issue
Block a user