[ion/crc32] crc32Byte and crc32Word

This commit is contained in:
Léa Saviot
2019-04-25 16:08:30 +02:00
parent 9fb7eb9f92
commit 380ac52cd8
11 changed files with 63 additions and 33 deletions

View File

@@ -12,7 +12,7 @@ uint32_t CurveViewRange::rangeChecksum() {
float data[4] = {xMin(), xMax(), yMin(), yMax()};
size_t dataLengthInBytes = 4*sizeof(float);
assert((dataLengthInBytes & 0x3) == 0); // Assert that dataLengthInBytes is a multiple of 4
return Ion::crc32((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
return Ion::crc32Word((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
}
float CurveViewRange::yGridUnit() {

View File

@@ -135,7 +135,7 @@ uint32_t DoublePairStore::storeChecksum() const {
for (int i = 0; i < k_numberOfSeries; i++) {
checkSumPerSeries[i] = storeChecksumForSeries(i);
}
return Ion::crc32(checkSumPerSeries, k_numberOfSeries);
return Ion::crc32Word(checkSumPerSeries, k_numberOfSeries);
}
uint32_t DoublePairStore::storeChecksumForSeries(int series) const {
@@ -151,9 +151,9 @@ uint32_t DoublePairStore::storeChecksumForSeries(int series) const {
assert((dataLengthInBytesPerDataColumn & 0x3) == 0); // Assert that dataLengthInBytes is a multiple of 4
uint32_t checkSumPerColumn[k_numberOfColumnsPerSeries];
for (int i = 0; i < k_numberOfColumnsPerSeries; i++) {
checkSumPerColumn[i] = Ion::crc32((uint32_t *)m_data[series][i], dataLengthInBytesPerDataColumn/sizeof(uint32_t));
checkSumPerColumn[i] = Ion::crc32Word((uint32_t *)m_data[series][i], dataLengthInBytesPerDataColumn/sizeof(uint32_t));
}
return Ion::crc32(checkSumPerColumn, k_numberOfColumnsPerSeries);
return Ion::crc32Word(checkSumPerColumn, k_numberOfColumnsPerSeries);
}
double DoublePairStore::defaultValue(int series, int i, int j) const {

View File

@@ -17,7 +17,7 @@ uint32_t InteractiveCurveViewRange::rangeChecksum() {
float data[5] = {m_xMin, m_xMax, m_yMin, m_yMax, m_yAuto ? 1.0f : 0.0f};
size_t dataLengthInBytes = 5*sizeof(float);
assert((dataLengthInBytes & 0x3) == 0); // Assert that dataLengthInBytes is a multiple of 4
return Ion::crc32((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
return Ion::crc32Word((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
}
void InteractiveCurveViewRange::setYAuto(bool yAuto) {

View File

@@ -25,7 +25,7 @@ uint32_t Store::barChecksum() const {
double data[2] = {m_barWidth, m_firstDrawnBarAbscissa};
size_t dataLengthInBytes = 2*sizeof(double);
assert((dataLengthInBytes & 0x3) == 0); // Assert that dataLengthInBytes is a multiple of 4
return Ion::crc32((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
return Ion::crc32Word((uint32_t *)data, dataLengthInBytes/sizeof(uint32_t));
}
/* Histogram bars */

View File

@@ -33,11 +33,8 @@ const char * patchLevel();
const char * fccId();
// CRC32 : non xor-ed, non reversed, direct, polynomial 4C11DB7
// Only accepts whole 32bit values
uint32_t crc32(const uint32_t * data, size_t length);
// crc32 of a string padded with 0 to get a 32bit value
uint32_t crc32PaddedString(const char * s, int length);
uint32_t crc32Word(const uint32_t * data, size_t length); // Only accepts whole 32bit values
uint32_t crc32Byte(const uint8_t * data, size_t length);
// Provides a true random number
uint32_t random();

View File

@@ -46,7 +46,7 @@ void CRC(const char * input) {
// Disable the cache to make many cache accesses
Ion::Device::Cache::disable();
uint32_t crc = Ion::crc32PaddedString(reinterpret_cast<const char *>(internal ? 0x08000000 : 0x90000000), length);
uint32_t crc = Ion::crc32Byte(reinterpret_cast<const uint8_t *>(internal ? 0x08000000 : 0x90000000), length);
Ion::Device::Cache::enable();

View File

@@ -5,19 +5,31 @@ namespace Ion {
using namespace Device::Regs;
uint32_t crc32(const uint32_t * data, size_t length) {
uint32_t crc32Byte(const uint8_t * data, size_t length) {
bool initialCRCEngineState = RCC.AHB1ENR()->getCRCEN();
RCC.AHB1ENR()->setCRCEN(true);
CRC.CR()->setRESET(true);
const uint32_t * end = data + length;
const uint8_t * end = data + length;
int wordSize = (length * sizeof(uint8_t)) / sizeof(uint32_t);
// Make as many word accesses as possible
for (int i = 0; i < wordSize; i++) {
CRC.DR_WordAccess()->set(*((uint32_t *)data));
data += 4;
}
// Scanning the remaining data with byte accesses
while (data < end) {
CRC.DR()->set(*data++);
CRC.DR_ByteAccess()->set(*data++);
}
uint32_t result = CRC.DR()->get();
uint32_t result = CRC.DR_WordAccess()->get();
RCC.AHB1ENR()->setCRCEN(initialCRCEngineState);
return result;
}
uint32_t crc32Word(const uint32_t * data, size_t length) {
return crc32Byte((const uint8_t *)data, length * (sizeof(uint32_t)/sizeof(uint8_t)));
}
}

View File

@@ -9,7 +9,9 @@ namespace Regs {
class CRC {
public:
class DR : public Register32 {
class DR_ByteAccess : public Register8 {
};
class DR_WordAccess : public Register32 {
};
class CR : Register32 {
@@ -18,7 +20,8 @@ public:
};
constexpr CRC() {};
REGS_REGISTER_AT(DR, 0x00);
REGS_REGISTER_AT(DR_ByteAccess, 0x00);
REGS_REGISTER_AT(DR_WordAccess, 0x00);
REGS_REGISTER_AT(CR, 0x08);
private:
constexpr uint32_t Base() const {

View File

@@ -10,16 +10,29 @@ static uint32_t crc32(uint32_t crc, uint8_t data) {
return crc;
}
uint32_t Ion::crc32(const uint32_t * data, size_t length) {
const uint8_t * dataByte = (const uint8_t *)data;
uint32_t crc32Helper(const uint8_t * data, size_t length, bool wordAccess) {
size_t uint32ByteLength = sizeof(uint32_t)/sizeof(uint8_t);
uint32_t crc = 0xFFFFFFFF;
for (int i = 0; i < (int)length; i++) {
// FIXME: Assumes little-endian byte order!
size_t byteLength = (wordAccess ? length * uint32ByteLength : length);
size_t wordLength = byteLength / uint32ByteLength;
for (int i = 0; i < (int)wordLength; i++) {
// FIXME: Assumes little-endian byte order!
for (int j = uint32ByteLength-1; j >= 0; j--) {
// scan byte by byte to avoid alignment issue when building for emscripten platform
crc = ::crc32(crc, dataByte[i*uint32ByteLength+j]);
crc = crc32(crc, data[i*uint32ByteLength+j]);
}
}
for (int i = (int) wordLength * uint32ByteLength; i < byteLength; i++) {
crc = crc32(crc, data[i]);
}
return crc;
}
uint32_t Ion::crc32Word(const uint32_t * data, size_t length) {
return crc32Helper((const uint8_t *) data, length, true);
}
uint32_t Ion::crc32Byte(const uint8_t * data, size_t length) {
return crc32Helper(data, length, false);
}

View File

@@ -70,8 +70,8 @@ uint32_t Storage::Record::checksum() {
uint32_t crc32Results[2];
crc32Results[0] = m_fullNameCRC32;
Data data = value();
crc32Results[1] = Ion::crc32PaddedString((const char *)data.buffer, data.size);
return Ion::crc32(crc32Results, 2);
crc32Results[1] = Ion::crc32Byte((const uint8_t *)data.buffer, data.size);
return Ion::crc32Word(crc32Results, 2);
}
Storage::Record::Record(const char * basename, int basenameLength, const char * extension, int extensionLength) {
@@ -80,9 +80,9 @@ Storage::Record::Record(const char * basename, int basenameLength, const char *
// We compute the CRC32 of the CRC32s of the basename and the extension
uint32_t crc32Results[2];
crc32Results[0] = Ion::crc32PaddedString(basename, basenameLength);
crc32Results[1] = Ion::crc32PaddedString(extension, extensionLength);
m_fullNameCRC32 = Ion::crc32(crc32Results, 2);
crc32Results[0] = Ion::crc32Byte((const uint8_t *)basename, basenameLength);
crc32Results[1] = Ion::crc32Byte((const uint8_t *)extension, extensionLength);
m_fullNameCRC32 = Ion::crc32Word(crc32Results, 2);
}
// STORAGE
@@ -113,7 +113,7 @@ size_t Storage::availableSize() {
}
uint32_t Storage::checksum() {
return Ion::crc32PaddedString(m_buffer, endBuffer()-m_buffer);
return Ion::crc32Byte((const uint8_t *) m_buffer, endBuffer()-m_buffer);
}
void Storage::notifyChangeToDelegate(const Record record) const {

View File

@@ -3,8 +3,13 @@
#include <assert.h>
QUIZ_CASE(ion_crc32) {
uint32_t input[] = { 0x48656C6C, 0x6F2C2077 };
quiz_assert(Ion::crc32(input, 1) == 0x93591FFD);
quiz_assert(Ion::crc32(input, 2) == 0x72EAD3FB);
}
uint32_t inputWord[] = { 0x48656C6C, 0x6F2C2077 };
quiz_assert(Ion::crc32Word(inputWord, 1) == 0x93591FFD);
quiz_assert(Ion::crc32Word(inputWord, 2) == 0x72EAD3FB);
uint8_t inputBytes[] = {0x6C, 0x6C, 0x65, 0x48, 0x77, 0x20, 0x2C, 0x6F};
quiz_assert(Ion::crc32Byte(inputBytes, 1) == 0xD7A1E247);
quiz_assert(Ion::crc32Byte(inputBytes, 4) == 0x93591FFD);
quiz_assert(Ion::crc32Byte(inputBytes, 6) == 0x7BCD4EB3);
quiz_assert(Ion::crc32Byte(inputBytes, 8) == 0x72EAD3FB);
}