From 380ac52cd878da045f8fe0db633755a2dc9679d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 25 Apr 2019 16:08:30 +0200 Subject: [PATCH] [ion/crc32] crc32Byte and crc32Word --- apps/shared/curve_view_range.cpp | 2 +- apps/shared/double_pair_store.cpp | 6 ++--- apps/shared/interactive_curve_view_range.cpp | 2 +- apps/statistics/store.cpp | 2 +- ion/include/ion.h | 7 ++---- ion/src/device/bench/command/crc.cpp | 2 +- ion/src/device/shared/drivers/crc32.cpp | 20 +++++++++++++---- ion/src/device/shared/regs/crc.h | 7 ++++-- ion/src/shared/crc32.cpp | 23 +++++++++++++++----- ion/src/shared/storage.cpp | 12 +++++----- ion/test/crc32.cpp | 13 +++++++---- 11 files changed, 63 insertions(+), 33 deletions(-) diff --git a/apps/shared/curve_view_range.cpp b/apps/shared/curve_view_range.cpp index 8673ce7db..d22a9ad02 100644 --- a/apps/shared/curve_view_range.cpp +++ b/apps/shared/curve_view_range.cpp @@ -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() { diff --git a/apps/shared/double_pair_store.cpp b/apps/shared/double_pair_store.cpp index 1a4a1064e..d298aa21b 100644 --- a/apps/shared/double_pair_store.cpp +++ b/apps/shared/double_pair_store.cpp @@ -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 { diff --git a/apps/shared/interactive_curve_view_range.cpp b/apps/shared/interactive_curve_view_range.cpp index 7bf8f63eb..77dd260ea 100644 --- a/apps/shared/interactive_curve_view_range.cpp +++ b/apps/shared/interactive_curve_view_range.cpp @@ -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) { diff --git a/apps/statistics/store.cpp b/apps/statistics/store.cpp index 6f8ee619a..6fcd49385 100644 --- a/apps/statistics/store.cpp +++ b/apps/statistics/store.cpp @@ -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 */ diff --git a/ion/include/ion.h b/ion/include/ion.h index 8049b52f8..aa3de318e 100644 --- a/ion/include/ion.h +++ b/ion/include/ion.h @@ -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(); diff --git a/ion/src/device/bench/command/crc.cpp b/ion/src/device/bench/command/crc.cpp index e136e5064..9d82d1144 100644 --- a/ion/src/device/bench/command/crc.cpp +++ b/ion/src/device/bench/command/crc.cpp @@ -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(internal ? 0x08000000 : 0x90000000), length); + uint32_t crc = Ion::crc32Byte(reinterpret_cast(internal ? 0x08000000 : 0x90000000), length); Ion::Device::Cache::enable(); diff --git a/ion/src/device/shared/drivers/crc32.cpp b/ion/src/device/shared/drivers/crc32.cpp index 41fe5ab25..cb97c4962 100644 --- a/ion/src/device/shared/drivers/crc32.cpp +++ b/ion/src/device/shared/drivers/crc32.cpp @@ -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))); +} + } diff --git a/ion/src/device/shared/regs/crc.h b/ion/src/device/shared/regs/crc.h index b761cf342..e3b468179 100644 --- a/ion/src/device/shared/regs/crc.h +++ b/ion/src/device/shared/regs/crc.h @@ -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 { diff --git a/ion/src/shared/crc32.cpp b/ion/src/shared/crc32.cpp index 8f9f50a6b..8b95ed102 100644 --- a/ion/src/shared/crc32.cpp +++ b/ion/src/shared/crc32.cpp @@ -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); +} diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index 0ad38552f..5ce462a52 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -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 { diff --git a/ion/test/crc32.cpp b/ion/test/crc32.cpp index daee8758f..87b2158a2 100644 --- a/ion/test/crc32.cpp +++ b/ion/test/crc32.cpp @@ -3,8 +3,13 @@ #include 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); +}