Skip to content

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

Merged
merged 6 commits into from
Jan 9, 2020
Merged

Conversation

kjbracey
Copy link
Contributor

@kjbracey kjbracey commented Nov 19, 2019

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 always RBIT. 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 as x and that x == 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 and POLY_32BIT_POSIX = POLY_32BIT_ANSI.

Documentation (Details of any document updates required)

n/a


Pull request type (required)

[X] Patch update (Bug fix / Target update / Docs update / Test update / Refactor)
[] Feature update (New feature / Functionality change / New API)
[] Major update (Breaking change E.g. Return code change / API behaviour change)

Depends on #11957


Test results (required)

[] No Tests required for this change (E.g docs only update)
[] Covered by existing mbed-os tests (Greentea or Unittest)
[X] Tests / results supplied as part of this PR

@ciarmcom
Copy link
Member

@kjbracey-arm, thank you for your changes.
@ARMmbed/mbed-os-hal @ARMmbed/mbed-os-core @ARMmbed/mbed-os-test @ARMmbed/mbed-os-maintainers please review.

@kjbracey kjbracey force-pushed the crc branch 2 times, most recently from c06dc9e to 61b4756 Compare November 20, 2019 13:06
@0xc0170
Copy link
Contributor

0xc0170 commented Nov 21, 2019

Please review astyle failures

@kjbracey
Copy link
Contributor Author

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.

@0xc0170
Copy link
Contributor

0xc0170 commented Nov 27, 2019

As the main change for CRC was reverted, this needs work (or rather a new PR with the fix included?).

@kjbracey
Copy link
Contributor Author

Now waiting for #11957.

@kjbracey
Copy link
Contributor Author

kjbracey commented Dec 4, 2019

Preceding PR in - rebased.

@adbridge
Copy link
Contributor

CI started

@mbed-ci
Copy link

mbed-ci commented Dec 13, 2019

Test run: FAILED

Summary: 1 of 4 test jobs failed
Build number : 1
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_unittests

@adbridge
Copy link
Contributor

@kjbracey-arm looks like we have some ci failures, could you investigate please.

@kjbracey
Copy link
Contributor Author

I'm only seeing serial errors from DISCO_L475VG_IOT01A, as with quite a few of the PRs from yesterday.

@adbridge
Copy link
Contributor

@kjbracey-arm I will try running this again then

@adbridge
Copy link
Contributor

CI restarted

@mbed-ci
Copy link

mbed-ci commented Dec 24, 2019

Test run: FAILED

Summary: 1 of 4 test jobs failed
Build number : 3
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_build-IAR

@0xc0170
Copy link
Contributor

0xc0170 commented Jan 2, 2020

CI restarted

@mbed-ci
Copy link

mbed-ci commented Jan 2, 2020

Test run: FAILED

Summary: 1 of 11 test jobs failed
Build number : 4
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_greentea-test

@0xc0170
Copy link
Contributor

0xc0170 commented Jan 2, 2020

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;
@kjbracey
Copy link
Contributor Author

kjbracey commented Jan 8, 2020

Test corrected - hardware was right, my original hand calculation was wrong. (7-bit 0x3A bit-reversed is 0x2E, not 0x4E).

@0xc0170
Copy link
Contributor

0xc0170 commented Jan 8, 2020

CI restarted

@mbed-ci
Copy link

mbed-ci commented Jan 8, 2020

Test run: FAILED

Summary: 1 of 11 test jobs failed
Build number : 5
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_greentea-test

@0xc0170
Copy link
Contributor

0xc0170 commented Jan 8, 2020

Test restarted, hw failure

@0xc0170
Copy link
Contributor

0xc0170 commented Jan 9, 2020

There was just one RTC failure, Irestarted the test to confirm

@0xc0170 0xc0170 added release-version: 6.0.0-alpha-1 First pre-release version of 6.0.0 and removed needs: CI labels Jan 9, 2020
@0xc0170 0xc0170 merged commit 8c4ed4a into ARMmbed:master Jan 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-version: 6.0.0-alpha-1 First pre-release version of 6.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants