Skip to content

Retracted the claim that a second TCM bank costs the data cache - #633

Merged
fdesbiens merged 1 commit into
eclipse-threadx:devfrom
fdesbiens:feature/r52-s32z280-retract-tcm-rationale
Aug 17, 2026
Merged

Retracted the claim that a second TCM bank costs the data cache#633
fdesbiens merged 1 commit into
eclipse-threadx:devfrom
fdesbiens:feature/r52-s32z280-retract-tcm-rationale

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

entry.S and readme_s32z280.txt both stated that enabling any second TCM bank removes all measurable data-cache benefit on this part, with five configurations as evidence:

ATCM only                      cache gain 24%
ATCM + BTCM                    cache gain  0%
ATCM + BTCM + CTCM             cache gain  0%
ATCM + BTCM at another base    cache gain  0%
ATCM + CTCM, BTCM disabled     cache gain  0%

Both concluded the cause was "not a particular bank, not its address, not the ECC preload — enabling a second bank at all". Both cited the Cortex-R52 and S32Z2 errata as not covering it, and offered a RAM pool shared between the LLC and the TCMs as the likely mechanism. A defect report went to NXP on that basis.

It was the benchmark

The benchmark was bimodal with respect to where its timing loop fell inside a 64-byte cache line — reporting either 24% or nothing at all for identical silicon (see #631). Every one of those five configurations was an edit to entry.S, so every one shifted the code that followed and moved the loop between modes.

Adding two nop instructions to entry.S reproduces the "second bank" figure exactly, to the digit. The report to NXP has been withdrawn.

Re-measured with the alignment sweep

loop offset in line ATCM only ATCM + CTCM
0 gain 0 gain 0
16 gain 0 gain 0
32 gain 240/1000 gain 240/1000
48 gain 240/1000 gain 240/1000

Indistinguishable. Enabling a second bank costs nothing measurable.

What the texts say now

The banks stay disabled, but for the ordinary reason that nothing in this example uses them — not because of a phantom regression. Enabling one is a single line, with the ECC preload before any read (TRM 6.2.2) and an MPU region as the only prerequisites, both already handled for ATCM.

The readme also states the general point, which outlasts the TCM detail: a single-figure timing result from this example cannot be compared across builds unless the timed loop's alignment is controlled, because almost any change shifts code. That is why the cache and handler measurements now sweep alignments.

Scope

Comments and documentation only; no generated code changes. Verified on the board anyway since entry.S was touched — six of six probes pass, sweep unchanged, all three targets build clean.

entry.S and readme_s32z280.txt both stated that enabling any second TCM bank
removes all measurable data-cache benefit on this part, and gave five
configurations as evidence: ATCM alone at a 24% cache gain, four combinations
involving a second bank at none. Both concluded the cause was not a particular
bank, not its address and not the ECC preload, but enabling a second bank at
all. Both cited the Cortex-R52 and S32Z2 errata as not covering it and offered
a shared RAM pool between the LLC and the TCMs as an explanation. A defect
report went to NXP on that basis.

It was an artifact of the benchmark. That benchmark was bimodal with respect to
where its timing loop fell inside a 64-byte cache line, reporting either 24% or
nothing at all for identical silicon, and every one of those five
configurations was an edit to entry.S, so every one shifted the code that
followed and moved the loop between modes. Adding two nop instructions
reproduces the "second bank" figure exactly, to the digit. The report to NXP
has been withdrawn.

Re-measured with the alignment sweep added in eclipse-threadx#631, one bank and two are
indistinguishable:

    loop offset in line      ATCM only      ATCM + CTCM
    0                        gain 0         gain 0
    16                       gain 0         gain 0
    32                       gain 240/1000  gain 240/1000
    48                       gain 240/1000  gain 240/1000

So enabling a second bank costs nothing measurable. The banks stay disabled,
but for the ordinary reason that nothing in this example uses them, and both
texts now say that instead. Enabling one is a single line, with the ECC preload
before any read (TRM 6.2.2) and an MPU region as the only prerequisites, both
already handled for ATCM.

The readme also now states the general point, which outlasts the TCM detail: a
single-figure timing result from this example cannot be compared across builds
unless the timed loop's alignment is controlled, because almost any change
shifts code.

Comments and documentation only; no generated code changes. Verified on the
board regardless, since entry.S was touched: six of six probes pass and the
sweep is unchanged.

Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
@fdesbiens
fdesbiens merged commit 35de568 into eclipse-threadx:dev Aug 17, 2026
4 checks passed
@fdesbiens
fdesbiens deleted the feature/r52-s32z280-retract-tcm-rationale branch August 17, 2026 17:46
fdesbiens added a commit that referenced this pull request Aug 18, 2026
…s result (#638)

#636 reported that a stack in BTCM gave a threefold tighter spread than DRAM0
for stack-heavy work. That measurement used a single code placement, which is
the methodology #631 and #633 exist to correct: the cache benchmark got an
alignment sweep and the interrupt handler got one, and this measurement never
did. It was noticed when #637 added two threads to the same image and the figure
moved -- both spreads came out near 6500 and the minima rose 15%.

The recursive body is now generated at four placements and all four are
measured, per placement, in one image.

    placement    BTCM min / spread     DRAM0 min / spread
    offset 0      41854 / 6850          42036 / 6880
    offset 16     48670 / 1946          48792 / 1978
    offset 32     42388 / 6914          42752 / 7018
    offset 48     48914 / 1860          49198 / 6786

Reproducible across runs to within a few hundred cycles.

Spread is dominated by code placement rather than by the memory holding the
stack. It ranges from 1860 to 6914 depending on where the body falls in a cache
line, and placement also moves the minimum by 17%, from 41854 to 49214. Against
that, the memory contributes a consistent but small advantage: BTCM's minimum is
lower at all four placements, by 0.4% to 0.9%.

BTCM's spread beats DRAM0's decisively at one placement of the four, offset 48,
at 1860 against 6786. At the other three the two are within 2% of each other.
So the effect #636 reported is real where it occurs and is not a property of the
part: quoting it as one invited the reader to expect it everywhere.

#636's claim should be read as qualified by this. A stack in BTCM buys a small
consistent improvement in the best case and a large improvement in spread at
some code placements and not others. Anyone building a determinism argument on
it needs the placement sweep in the loop, not a single figure.

The pad nops that displace each placement execute on every recursion level
rather than once, so each placement carries a slightly different constant cost,
about 0.6% at the widest. That cancels in the BTCM against DRAM0 comparison,
which is made at the same placement, and does not affect spread within one.

Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant