-
Notifications
You must be signed in to change notification settings - Fork 3k
MbedCRC: improve init value handling and tests #11897
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@kjbracey-arm, thank you for your changes. |
c06dc9e
to
61b4756
Compare
Please review astyle failures |
Yeah, I think that's going to be a "disable" comment, unless there's a trick to make it realise what it's looking at. It doesn't always get templates wrong, so not quite sure what's upsetting it here. |
As the main change for CRC was reverted, this needs work (or rather a new PR with the fix included?). |
Now waiting for #11957. |
Preceding PR in - rebased. |
CI started |
Test run: FAILEDSummary: 1 of 4 test jobs failed Failed test jobs:
|
@kjbracey-arm looks like we have some ci failures, could you investigate please. |
I'm only seeing serial errors from DISCO_L475VG_IOT01A, as with quite a few of the PRs from yesterday. |
@kjbracey-arm I will try running this again then |
CI restarted |
Test run: FAILEDSummary: 1 of 4 test jobs failed Failed test jobs:
|
CI restarted |
Test run: FAILEDSummary: 1 of 11 test jobs failed Failed test jobs:
|
Failures are related (crc test failing). |
Clang emits warnings if it can see a declaration when it needs a templated variable. Add declarations for the specialisations in MbedCRC.cpp to MbedCRC.h keep it quiet. Tighten up a little by making all `_crc_table` references conditional on tables being configured on.
GCC 9 and sufficiently-new Clang (including ARM Compiler 6.13) give us access to the C++20 (draft) `is_constant_evaluated` test. Allows us to restrict code to compile-time only. This is particularly useful when using assembler intrinsics, which the compiler cannot optimise or compile-time evaluate. It allows us to write something like constexpr uint32_t reverse_bits(uint32_t x) { if (is_constant_evaluated(x)) { // C code to do calculation here return x; } else { // an assembler intrinsic that cannot be optimised return __RBIT(x); } } This can then be totally compile-time given a constant input. (In this example, ultimately it would be a good idea to include this functionality in CMSIS's GCC `__RBIT`, which needs it because GCC requires use of assembler. Clang implements `__RBIT` as a built-in, meaning it can already compute it at compile-time, so does not benefit.).
Init values often need reflection, and use of `__RBIT` prevents constant init being done at compile time (unless `__RBIT` uses a compiler intrinsic, which it doesn't for GCC). Rather than try to handle constants 0U and -1U with a special case to avoid the RBIT, which can in turn lead to runtime bloat for nonconstant inits, use a C++20 style is_constant_evaluated() check to switch between C and assembly forms. This reduces code-size for non-constant init, by eliminating a runtime condition, and allows the bit-reversal of any constant init to happen at compile time.
CRC tests failed to exercise handling of the initial and final-xor values with respect to reflection parameters. Add tests covering this. Expected behaviour is that the initial value is always non-reflected and the final-xor happens after the optional output reflection.
Original default constructor implementation wasn't quite working properly; it didn't cope with the new "mode_limit" parameter. Change mechanism so that this now works: MbedCRC<POLY32_BIT_ANSI_CRC, 32, CrcMode::TABLE> crc;
Test corrected - hardware was right, my original hand calculation was wrong. (7-bit 0x3A bit-reversed is 0x2E, not 0x4E). |
CI restarted |
Test run: FAILEDSummary: 1 of 11 test jobs failed Failed test jobs:
|
Test restarted, hw failure |
There was just one RTC failure, Irestarted the test to confirm |
Description (required)
Improve handling of init values for the CRC, particularly for GCC which cannot optimise the
RBIT
instruction. Let the compiler do the reversal when we're evaluating a constant.Summary of change (What the change is for and why)
This PR follows on from observations made while producing the fix #11896.
LittleFS or other users passing non-constant init values could be penalised at run-time by the special-case for all-zero or all-one init values, intended to make those values compile-time computable. Eliminate the special-case values and use a new
is_constant_evaluated
check - constant evaluation is done using a C expression, runtime is alwaysRBIT
. This check requires GCC 9 or later - code generation after this patch might be worse pre-GCC 9.Clang code generation does not seem to be affected - its
__RBIT
is implemented as an intrinsic, so it already knows that__RBIT(__RBIT(x))
is the same asx
and thatx == 0 || x == -1 ? x : __RBIT(x)
is the same as__RBIT(x)
. It doesn't matter to Clang if we always use__RBIT
.Add tests for init and final-xor values - there was no test coverage for whether those values get reflected, as all tests with reflection used all-0 or all-1 values.
Remove duplicate tests -
POLY_16BIT_MAXIM
=POLY_16BIT_IBM
andPOLY_32BIT_POSIX
=POLY_32BIT_ANSI
.Documentation (Details of any document updates required)
n/a
Pull request type (required)
Depends on #11957
Test results (required)