feat: implement DMA IRQ handling and WS2812 completion race tests

This commit is contained in:
maksyuki committed 2026-10-10 09:35:49 +08:00
1 parent 3e46cc80e2
commit 4db27524a6
5 files changed
+503 -14

No files matched your search

+18 -2
View File
@@ -5,16 +5,25 @@
static const rs_dma_session_t *rs_dma_owners[RS_DMA_CHANNEL_COUNT];
#ifdef RS_DMA_TEST_MMIO
uint32_t rs_dma_test_irq_save(void);
void rs_dma_test_irq_restore(uint32_t saved);
#endif
static uint32_t rs_dma_lock(void) {
uint32_t saved = 0U;
#if defined(__riscv) && defined(CSR_ENABLE)
#ifdef RS_DMA_TEST_MMIO
saved = rs_dma_test_irq_save();
#elif defined(__riscv) && defined(CSR_ENABLE)
__asm__ volatile("csrrci %0, mstatus, 8" : "=r"(saved)::"memory");
#endif
return saved;
}
static void rs_dma_unlock(uint32_t saved) {
#if defined(__riscv) && defined(CSR_ENABLE)
#ifdef RS_DMA_TEST_MMIO
rs_dma_test_irq_restore(saved);
#elif defined(__riscv) && defined(CSR_ENABLE)
if ((saved & UINT32_C(8)) != 0U) {
__asm__ volatile("csrsi mstatus, 8" ::: "memory");
}
@@ -185,6 +194,7 @@ rs_status_t rs_dma_submit_tcd_chain(uint32_t channel, rs_dma_tcd_t *first, uint3
rs_status_t result;
uint32_t control;
uint32_t burst;
uint32_t saved;
result = rs_dma_tcd_validate(channel, current);
if (result != RS_OK) {
@@ -208,14 +218,20 @@ rs_status_t rs_dma_submit_tcd_chain(uint32_t channel, rs_dma_tcd_t *first, uint3
config.crc_expected = current->crc_expected;
config.priority = (uint8_t)((control >> RS_DMA_TCD_PRIORITY_SHIFT) & UINT32_C(0x3));
config.burst_beats = (uint8_t)burst;
/* Publish configuration, TCD and START before an ISR can lease the
* idle channel. Nested helpers preserve this outer interrupt mask.
* Restore interrupts before the bounded completion wait. */
saved = rs_dma_lock();
result = rs_dma_configure(channel, &config);
if (result != RS_OK) {
rs_dma_unlock(saved);
return result;
}
RS_DMA_CH_REG(channel, RS_DMA_CH_REG_TCD_HEAD) = (uint32_t)(uintptr_t)current;
RS_DMA_CH_REG(channel, RS_DMA_CH_REG_TCD_COUNT) = UINT32_C(1);
rs_dma_fence();
result = rs_dma_start(channel);
rs_dma_unlock(saved);
if (result != RS_OK) {
return result;
}
+5 -1
View File
@@ -419,7 +419,11 @@ rs_status_t rs_ws2812_dma_service(uint64_t now) {
return rs_ws2812_dma_finish();
}
if ((transmitter_flags & RS_WS2812_STATUS_BUSY) == 0U) {
return rs_ws2812_dma_fail(RS_EIO);
/* Completion may occur between the interrupt and status reads, and
* sticky DONE can lag the core's idle transition. Observe terminal
* events on the next bounded service call; never refill an idle core.
* Errors, aborts and the deadline remain checked on every call. */
return RS_OK;
}
if (rs_ws2812_transfer.remaining == 0U) {
rs_ws2812_write_register(RS_WS2812_INTR_STATE_OFFSET, RS_WS2812_INTR_FIFO_LOW);
+284
View File
@@ -3,6 +3,9 @@
This record covers the two P1 findings approved for follow-up on
`bab01352f8f7c80e39546b04e3ed37a3d927f475` plus the existing P3 worktree.
It does not approve Mini fabric enablement or advance TINY-R2-P4.
Earlier sections retain their original development status and attribution;
the source-bound campaign below records completed validation on `3e46cc8`.
The final section separately records the subsequent two HAL race fixes.
## Retained Tiny Icarus finding: closed
@@ -182,6 +185,10 @@ STA observations qualify a new physical operating point.
## Compiler-matrix execution corrections (2026-10-09)
The intermediate snapshots below are historical. The final source-bound results
later in this record supersede their in-progress status without relabeling any
failed attempt or earlier artifact.
The initial flat-image collector could not read `_stack_point` from its symbol
listing. Flat placement now falls back to the retained linker map's explicit
`PROVIDE (_stack_point = .)` value; the exact SRAM endpoint and 4 KiB stack
@@ -286,3 +293,280 @@ the selected target's successful simulation checks. This behavioral-only run
provides no Mini synthesis, netlist, STA or physical evidence. Mini lint baseline
differences remain non-blocking observations, separately retained in the
`56f28cd9230c` variant's `meta/rtl-lint-warnings.json`.
## Final source-bound P3 matrix (2026-10-10)
After the external style commit and the publication/configuration corrections
settled, the final campaign was run against commit
`3e46cc80e2d2243233d284b7cd9583714b0773bb`, source digest
`a7fc5112cd6f20df956243c4d081a6a31ede6192cd270e3c13340557b0e58776`.
Its master record is
`build/ics55-tiny-performance-2026-10-09-17-10-53cc6674d532/meta/tiny-r2-p3/matrix/attempt-3jy5g5vo/record.json`;
the final report is in the same root at `meta/tiny-r2-p3/report.json`.
All eight cases pass image collection, normal Tiny acceptance and three cold
Verilator runs. The selected native Icarus cases also pass three cold runs:
- `compat-os-flat`: 7464.762, 7891.159 and 7428.430 seconds;
- `perf-o2-lto-flat`: 5841.742, 5890.497 and 6149.375 seconds;
- `perf-o2-plain-banked`: 5951.447, 6345.716 and 5964.039 seconds.
The collector validates Tiny `TEST_STATUS`/`SIM_TEST_PASS`, forbidden markers,
matched retained image/model/tool artifacts, source digests, three repetitions,
and cross-simulator sample identity. `report.json` remains
`measurement_complete`; the ledger's human phase gate is still required.
The earlier 09-25, 15-10 and 16-45 campaigns remain historical: source changes
during execution included the `352b200` style commit, the configuration/publication
repairs, and the performance profile's trailing-newline change. Their raw passing
samples and provenance failures are retained and are not relabeled as final
evidence. The final campaign uses the complete committed corrections in `3e46cc8`.
### Current validation and commands
The tested primary platform is TINY/ICS55, external SAFE24 with HAVE_PLL=YES
but the PLL parked off. CPU and the existing 128 KiB main SRAM remain at SYS24.
The IHP130 compatibility profile keeps no PLL. Dependencies, warning baselines,
metrics policy, hardware integration and the frozen specification blob
`7e19de49d49efaafacccfa85671e314d53dd15a4` are unchanged by this validation.
After activating `.cache/retrosoc/development/tiny-r2-p1/activate.sh`, the matrix
and final report commands were:
```sh
make CONFIG=configs/benchmark/ics55-tiny-performance.mk SOC=TINY PDK=ICS55 \
BUILD_TIMESTAMP=2026-10-09-17-10 SOC_SIM_TIME=21600 JOBS=3 \
TINY_P3_RESUME=NO tiny-r2-p3-matrix
make CONFIG=configs/benchmark/ics55-tiny-performance.mk SOC=TINY PDK=ICS55 \
BUILD_TIMESTAMP=2026-10-09-17-10 tiny-r2-p3-report
```
The current full Pytest run reports **1629 passed, 1 skipped** in 4200.10 seconds.
The one skipped PDF inspection test requires `pypdf`, absent from this environment;
it is not a hardware or simulation pass. Its command, complete log and result are
in the matrix root under `meta/tiny-r2-p3/quality/pytest.{log,json}`. The previous
4 failures and 94 fixture errors remain in their old logs; they are resolved by
the configuration declaration and publication/source-fixture corrections in
`3e46cc8`. The focused correction check also passed 149 tests with the same one
PDF skip. No PDF or publication source revision was advanced by these checks.
`ruff check .`, dependency-lock validation and `git diff --check` pass. The
current C format/policy/host and RTL format/style/readiness checks pass; their
exact Make command and outputs are retained under
`meta/tiny-r2-p3/quality/policy.{log,json}`. These are the repository's mechanical
quality checks, not complete MISRA certification; no new deviation is recorded.
Regression dry-runs selected TINY explicitly for both PDKs and MINI with
`--behavioral-only`. Tiny nightly resolves to the same commands as PR, so it was
not executed a second time. The final executions were:
```sh
BUILD_TIMESTAMP=2026-10-09-19-55 python3 scripts/regress.py --root . --suite pr --soc TINY --pdk ICS55
BUILD_TIMESTAMP=2026-10-09-19-56 python3 scripts/regress.py --root . --suite pr --soc TINY --pdk IHP130
JAVA_TOOL_OPTIONS=-Dsbt.server.forcestart=true BUILD_TIMESTAMP=2026-10-09-19-57 \
python3 scripts/regress.py --root . --suite pr --soc MINI --pdk ICS55 --behavioral-only
```
All three exit zero. Current evidence roots and results are:
| Scope | Evidence root below `build/` | Result |
| --- | --- | --- |
| Tiny ICS55 PR | `ics55-tiny-2026-10-09-19-55-42d5beccb726/` | `meta/tiny-r2-p3/regress-ics55.{log,json}`; behavioral/JTAG, netlist boot, synthesis and STA commands pass |
| Tiny IHP130 PR | `ihp130-tiny-2026-10-09-19-56-bff91e3529ba/` | `meta/tiny-r2-p3/regress-ihp130.{log,json}`; same target-specific gates pass |
| Mini ICS55 behavioral-only | `ics55-2026-10-09-19-57-d1cacf6d3b62/` | `meta/tiny-r2-p3/regress-mini.{log,json}`; SDRAM Verilator and Icarus assembly boot pass |
Each Tiny PR's HAVE_SVA=YES Verilator acceptance has its separate configuration
variant, identified in the retained command/log. Mini's SDRAM run uses
`dc24d22ad53d` and assembly boot uses `ec9e1f2e9c2c` at the same 19-57 timestamp.
Mini behavioral-only supplies no synthesis, netlist, STA or physical evidence.
The additional IHP130 performance/banked normal-firmware check also passes:
```sh
make CONFIG=configs/ci/ihp130-tiny.mk SOC=TINY PDK=IHP130 \
BUILD_TIMESTAMP=2026-10-10-00-13 SW_ISA_PROFILE=TINY_PERF SW_OPT=O2 SW_LTO=NO \
LINK_TYPE=ld2_tiny_banked SIMU=VERILATOR firmware sim
```
Its root is `build/ihp130-tiny-2026-10-10-00-13-8648aa4845d9/`, with the exact
command/result at `meta/tiny-r2-p3/performance-banked.{log,json}` and strict Tiny
simulation check at `sim/verilator/result-sim-check.json`. This is normal
firmware compatibility; it is not an additional IHP130 compiler measurement matrix.
The ICS55 platform auditor captured inputs before this execution and successfully
produced `meta/tiny-ics55-p1/report.json` in the actual APP=ci_smoke variant. This
reuses the platform audit under P3; its original phase label is unchanged. Metrics
were explicitly collected in each actual synthesis/STA variant rather than the
regression runner's final default-bringup observation directory:
| TINY PDK | Cells | Reported library area | Max WNS (ns) | Max TNS (ns) |
| --- | ---: | ---: | ---: | ---: |
| ICS55 | 197677 | 1786686.260799 | -41.14 | -508669.53 |
| IHP130 | 208547 | 9109320.296998 | -94.28 | -1594880.00 |
Both min WNS/TNS values are zero in these smoke reports. Full reports are at
`sta/opensta/timing_metrics.rpt` and `meta/metrics.json` within the corresponding
APP=ci_smoke roots. Library area is not placed/routed die area; negative margins
remain unclosed. No 96/192/240 MHz operation, routed/PVT signoff or physical
qualification is claimed, and no half-rate main-SRAM fallback is introduced.
Lint comparisons remain non-blocking observations: ICS55 Tiny has 459 new
signatures relative to its baseline, IHP130 Tiny 403, and Mini ICS55 1536 new /
118 resolved; all three have zero increased signatures. Counts are not attribution
of every warning to P3. The reports are in each timestamp's lint variant
(`303f95040df3`, `2dc2e5c747e5`, and `56f28cd9230c` respectively), under
`meta/rtl-lint-warnings.json`. Baselines were not edited.
### Software measurements and remaining boundaries
Each row below uses the retained P3 workload (1024 words, four jobs, 4096 CPU
iterations, seed `0x12345678`). Cycle counts are raw measured windows; the report
also retains the separate empty-window calibration, retired instructions, bus
observations and CPI. These are different compiler/layout binaries, not a
matched-binary architectural speedup claim.
| Case | BIN bytes | CPU cycles | Copy cycles | Burst-16 DMA cycles | Chunk-256 cycles | Observed stack bytes |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| compat-os-flat | 11132 | 98682 | 164096 | 18881 | 511389 | 692 |
| perf-o2-plain-flat | 10148 | 73951 | 127157 | 16520 | 373812 | 648 |
| perf-o2-lto-flat | 8592 | 73974 | 127180 | 13980 | 339167 | 552 |
| perf-o3-plain-flat | 10404 | 73951 | 127157 | 16058 | 372690 | 628 |
| perf-o3-lto-flat | 9872 | 73974 | 127180 | 13980 | 339167 | 564 |
| perf-os-plain-flat | 8000 | 74064 | 139487 | 18421 | 394248 | 692 |
| perf-os-lto-flat | 6360 | 74064 | 139484 | 14169 | 343769 | 584 |
| perf-o2-plain-banked | 10184 | 73954 | 114875 | 16523 | 374016 | 648 |
Compare compatible Os with performance Os to hold optimization/layout fixed;
compare performance O2 with/without LTO to isolate that selection; compare the
two O2/no-LTO rows for placement. BIN bytes exclude BSS, and observed stack use
does not prove a static upper bound. Each image reserves at least 4096 stack
bytes. Bank conflicts remain unavailable because P4 hardware is not implemented.
The original P1 binaries and their historical phase/source identities are retained.
Current Mini PIO compatibility is additionally retained at
`build/ics55-2026-10-09-20-00-d0c568d0142e/meta/tiny-r2-p3/pio-retry/evidence.json`.
The initial default 180-second attempt emits SIM_TEST_TIMEOUT despite emulator
exit zero, and fails the simulation checker. A retry of the identical model and
BIN with `--fast-flash -t 1800` passes in 323.930 seconds, including 4/16/33/65-word
frames, IRQ count 5, exact waveform/reset-low checks, underflow/abort recovery,
and observer totals `frames=6 completed=4 underflows=1 aborts=2 dma_starts=0`.
The evidence records the before/after model and BIN hashes, command, manifest,
compile/run logs and a post-build recheck of 487 compiled input sizes/mtimes.
It is explicitly a post-build audit; neither the failed timeout nor the original
unsupported Mini DMA attempt is relabeled as a passing run.
Product-integrated WS2812 DMA/IRQ service budgets remain deferred under approved
option A to an actual supported route, including Tiny R2-P6. Full-product,
physical, silicon and publication-PDF qualification remain outside these results.
Human review and acceptance of TINY-R2-P3 are required before authorizing any
R2-P4 implementation; this execution does not automatically advance a phase.
## Subsequent P1 HAL race fixes (2026-10-10)
This approved follow-up starts from `3e46cc80e2d2243233d284b7cd9583714b0773bb`
and preserves the preceding uncommitted documentation/evidence updates. The
specification remains blob `7e19de49d49efaafacccfa85671e314d53dd15a4`.
Only `crt/src/hal/dma.c`, `crt/src/hal/ws2812.c` and
`tests/c/test_runtime.c` change executable/test source. No public interface,
register, RTL, profile, dependency, warning baseline or metric policy changes.
- WS2812: completing between INTR_STATE and STATUS reads no longer produces a
false I/O error. Idle without an observed sticky DONE retains ownership and
returns to the caller; the next bounded service checks error, abort, deadline
and completion again. No refill is admitted to an idle core. DMA response
draining and source-buffer lifetime rules are unchanged.
- DMA: one outer interrupt save/restore spans legacy TCD configuration,
descriptor publication and START, including ownership rejection. Nested HAL
helpers preserve the saved mask; the blocking completion wait is outside this
critical section. Test-only IRQ hooks model a pending ISR at mask restoration
and do not appear in target builds.
- Deterministic production-HAL host tests cover an ISR trying to lease the
channel during TCD publication, rejection without modifying an existing lease,
an initially masked caller, completion between WS2812 register reads, delayed
sticky DONE, genuine error/abort and expiry while idle. Existing final-B drain,
timeout ownership and 16-word FIFO admission tests remain enabled.
New evidence is rooted at
`build/ics55-tiny-2026-10-10-09-00-b4aa59f3e5d9/meta/tiny-r2-p3-races/`.
The timestamp is a fixed build label; each structured result records actual UTC
start/end times. `source.json` records the base revision, dirty state, locked
tool identities, input hashes, source archive and worktree patch. Its combined
ICS55/IHP130 source/test/spec digest is
`dfa171fc1adbdfc5c7c9d31ef4ac7ba1a66710caac0fb13b869ddac89186b2f7`.
This digest's input set differs from the earlier compiler-matrix input set.
Before fixes, `host-red.{log,json}` records host test exit 10 (TCD race).
After the TCD fix alone, `host-ws-red.{log,json}` records exit 11 (WS2812 race).
Both fail the enclosing Make command. `host-green.{log,json}` passes after both
fixes; `policy.{log,json}` additionally covers the final error/abort/deadline and
interrupt-mask cases, C formatting and policy checks. `focused.{log,json}` has
156 passing tests, including P3, Tiny baseline, DMA/register parity, WS2812 RTL
and publication API behavior. No new MISRA deviation is introduced. These are
partial project checks, not complete MISRA certification.
Commands run with the existing locked environment:
```sh
source .cache/retrosoc/development/tiny-r2-p1/activate.sh
make sw-format-check sw-policy-check sw-host-test
python3 -m pytest -q tests/test_tiny_r2_p3.py tests/test_tiny.py \
tests/test_tiny_r2_baseline.py tests/test_dma.py \
tests/test_dma_register_parity.py tests/test_ws2812.py \
tests/test_publication_api_bundle.py
ruff check .
git diff --check
python3 scripts/regress.py --root . --suite pr --soc TINY --pdk ICS55 --dry-run
python3 scripts/regress.py --root . --suite nightly --soc TINY --pdk ICS55 --dry-run
python3 scripts/regress.py --root . --suite pr --soc TINY --pdk IHP130 --dry-run
python3 scripts/regress.py --root . --suite pr --soc MINI --pdk ICS55 --behavioral-only --dry-run
BUILD_TIMESTAMP=2026-10-10-09-00 JOBS=3 JAVA_TOOL_OPTIONS=-Dsbt.server.forcestart=true \
python3 scripts/regress.py --root . --suite pr --soc TINY --pdk ICS55
BUILD_TIMESTAMP=2026-10-10-09-00 JOBS=3 JAVA_TOOL_OPTIONS=-Dsbt.server.forcestart=true \
python3 scripts/regress.py --root . --suite pr --soc TINY --pdk IHP130
BUILD_TIMESTAMP=2026-10-10-09-00 JOBS=3 JAVA_TOOL_OPTIONS=-Dsbt.server.forcestart=true \
python3 scripts/regress.py --root . --suite pr --soc MINI --pdk ICS55 --behavioral-only
JAVA_TOOL_OPTIONS=-Dsbt.server.forcestart=true make CONFIG=configs/ci/ics55.mk \
SOC=MINI PDK=ICS55 APP=ci_smoke WS2812_P3_ACCEPTANCE=YES HAVE_CSR=YES \
LINK_TYPE=ld2_all_sram SIMU=VERILATOR VERILATOR_SIM_ARGS=--fast-flash \
SOC_SIM_TIME=3600 BUILD_TIMESTAMP=2026-10-10-09-00 JOBS=3 firmware sim
```
Regression dry-runs passed; Tiny PR and nightly select identical commands, so
the long run is not duplicated. All three regression executions passed once;
their exact commands and verdicts are retained as
`regress-{tiny-ics55,tiny-ihp130,mini-ics55}.{log,json}` in the new evidence root.
Durations are 3210.491 seconds (Tiny ICS55), 2205.505 seconds (Tiny IHP130),
and 3170.591 seconds (Mini ICS55 behavioral-only). Mini PIO passes once in
423.766 seconds including build, with 4/16/33/65-word frames, five IRQs and
observer totals `frames=6 completed=4 underflows=1 aborts=2 dma_starts=0`.
Its variant is `build/ics55-2026-10-10-09-00-d0c568d0142e/`.
`audit.py` and `evidence.json` retain the final artifact audit: all 1287 captured
source/test/spec inputs are unchanged, 487 Mini PIO compiled inputs retain their
recorded sizes/mtimes, and the firmware/model/log/result hashes are recorded.
The Mini model audit is explicitly post-build. Eight ordinary regression
simulations are independently checked against their executable success marker,
command exit and forbidden-error rules. All selected targets, including the
current Mini assembly fixture, require `SIM_TEST_PASS`; UART output is not used
to infer success. This evidence is in addition to the separate PIO audit.
Current Tiny synthesis/netlist/STA results are in
`build/ics55-tiny-2026-10-10-09-00-42d5beccb726/` and
`build/ihp130-tiny-2026-10-10-09-00-bff91e3529ba/`. Both netlist checks pass;
STA command success does not mean timing closure. Observed max WNS/TNS remain
-41.14 ns / -508669.53 ns (ICS55) and -94.28 ns / -1594880.00 ns (IHP130),
with min WNS/TNS zero. Raw reports are `sta/opensta/timing_metrics.rpt`.
Lint baseline comparisons still fail as non-blocking regression observations:
459 new signatures for ICS55 Tiny, 403 for IHP130 Tiny, and 1536 new / 118
resolved for Mini, with zero increased signatures. No baseline was changed.
Build logs also retain a roughly four-second generated-file clock-skew warning;
these were fresh variant builds, and the input audit passed.
The old compiler/layout matrix, full Pytest and earlier timing observations stay
bound to `3e46cc8`; they are not reattributed to this follow-up. The compiler
matrix and full Pytest are not rerun for these isolated C changes (no build or
Python implementation changes). Product-integrated WS2812 DMA/IRQ budgets remain
deferred under option A; no Mini DMA-to-MMIO route is added. Human P3 acceptance
and separate approval are still required before R2-P4. Per the maintainer's
instruction, long checks default to a single execution; additional repetitions
need a concrete failure/inconsistency or an explicit frozen acceptance rule.
+54 -10
View File
@@ -1,14 +1,58 @@
# Tiny MCU Verification Record
## TINY-R2-P3 implementation in progress (2026-10-08–09)
## TINY-R2-P3 implementation in progress (2026-10-08–10)
The retained source-bound compiler/layout matrix is complete for commit
`3e46cc80e2d2243233d284b7cd9583714b0773bb`, source digest
`a7fc5112cd6f20df956243c4d081a6a31ede6192cd270e3c13340557b0e58776`.
All eight configurations pass ordinary Tiny acceptance and three deterministic
Verilator cold starts. `compat-os-flat`, `perf-o2-lto-flat` and
`perf-o2-plain-banked` also pass three native Icarus cold starts, with exact
cross-simulator sample identity. The structured measurement report is
`build/ics55-tiny-performance-2026-10-09-17-10-53cc6674d532/meta/tiny-r2-p3/report.json`.
It records software measurements only; it does not close phase acceptance,
physical timing, hardware bank conflict or Mini integrated-DMA gates.
Quality evidence for that committed source is complete: full Pytest reports 1629 passed and
one environment skip for missing `pypdf`; focused P3 tests and the embedded/RTL
quality checks pass. Its Tiny PR regressions pass for ICS55 and IHP130, and
Mini ICS55 behavioral-only compatibility passes. Negative STA margins and
non-blocking lint observations remain recorded as observations.
Exact commands, measurements, current evidence roots and remaining qualification
limits are in the final section of the [P3 review-fix record](tiny-soc-r2-p3-review-fixes.md).
Human review and acceptance remain required before any R2-P4 work.
### Subsequent P1 race-fix follow-up
The approved follow-up fixes WS2812 completion between register reads and
legacy TCD publication across an ISR lease acquisition. Current source is
`3e46cc8` plus the two HAL fixes and deterministic host tests; the matrix above
remains evidence for the original commit. New evidence is under
`build/ics55-tiny-2026-10-10-09-00-b4aa59f3e5d9/meta/tiny-r2-p3-races/`.
The two new tests fail before their respective fixes and pass afterward;
C format/policy/host checks and 156 focused tests pass. Mini PIO compatibility
also passes once with strict SIM_TEST_PASS and no forbidden markers. Tiny
ICS55/IHP130 PR and Mini ICS55 behavioral regressions each pass once. Final
`evidence.json` checks all 1287 source inputs, 487 Mini PIO compiled inputs and
all eight ordinary regression simulations. Lint baseline differences and
negative STA remain observations; no timing closure is claimed. See the final
review-fix section for commands, hashes, exact paths and unrun gates.
Per the maintainer's follow-up instruction, long checks default to one execution;
repeat only for a concrete failure/inconsistency or an explicit acceptance
requirement. This follow-up does not repeat the three-cold-start compiler matrix.
It does not waive any frozen qualification requirement or reattribute old runs.
### Historical development snapshot
The 2026-10-09 execution snapshot in the [P3 review-fix record](tiny-soc-r2-p3-review-fixes.md)
records all eight ordinary Tiny/Verilator compiler experiments completed, with
selected Icarus groups still running. The current-source full Pytest result is
selected Icarus groups still running at that snapshot. The then-current full Pytest result was
1531 passed, 4 failed, 94 fixture errors and 1 skipped; configuration-declaration
and publication source/fixture drift remain open. IHP130 Tiny PR completes with
and publication source/fixture drift were still open. IHP130 Tiny PR completed with
non-blocking lint observations and negative STA margin. These results do not
close the remaining matrix, quality or human phase-acceptance gates.
replace the final results above or imply human phase acceptance.
The [P3 review-fix record](tiny-soc-r2-p3-review-fixes.md) closes the retained
banked O2 Icarus finding: all three runs completed successfully and match the
@@ -28,8 +72,8 @@ is bound at
underflow/abort recovery, zero DMA starts and strict TEST_STATUS/SIM_TEST_PASS.
Focused checks report 96 passed; C/RTL quality, Ruff and diff checks pass.
The old Mini DMA failure remains failed/unsupported evidence, not a PIO pass.
The full compiler/placement matrix, broader current-source regressions and human
phase acceptance remain pending. See the review-fix record for exact commands,
The full compiler/placement matrix and broader regressions were pending in this
initial record; human phase acceptance remains pending. See the review-fix record for exact commands,
artifacts, historical attribution and unrun gates.
The user explicitly approved the P3 preflight and implementation on source
@@ -42,9 +86,9 @@ Original phase IDs, historical evidence and qualification limits are retained.
The [P3 runbook](tiny-soc-r2-software-scheduling.md) defines compiler/layout
experiments, shared finite DMA/WS2812 service, ownership and exact commands.
Implementation and validation are in progress; this entry does not claim
phase completion or performance improvement. The existing GNU toolchain is
used first, as requested; no dependency version has been changed.
The initial entry recorded implementation and validation in progress; it did not
claim phase completion or performance improvement. The existing GNU toolchain
was used as requested; no dependency version has been changed.
Early development testing found a compressed-instruction acceptance bug:
`rs_mcu_unmapped_probe` assembled its faulting load as 16-bit `4108`, while
@@ -448,7 +492,7 @@ not a prerequisite to the architectural improvements in R2-P3 through R2-P5.
| TINY-R2-P0 - Performance Contract and Roadmap Freeze | Reviewable requirements, exact old/new phase mapping, invariant package/IO counts, same-frequency CPU/main-SRAM ownership, explicit performance budgets, links and commands. Record actual documentation checks separately. | Documentation freeze only; no hardware result |
| TINY-R2-P1 - Reproducible Baseline, Constraints and Measurements | Reviewed source/profile/lock/tool identity; current 24 MHz functional and workload baseline; clocks, reset endpoints, constraints and timing-exception audit; counters and comparison methodology. Historical WNS is a risk reference, not a refreshed measurement. | Functional/measurement baseline accepted by explicit P2 approval on 2026-10-06; timing, warning and physical gaps retained |
| TINY-R2-P2 - Reset Distribution and CPU/SRAM Clock Feasibility | Reset distribution and payload-reset semantics; locked IHP130 main-SRAM macro timing, candidate common CPU/SRAM periods and representative paths; early clock/reset feasibility with explicit gaps. No final routed/PVT pass is implied. | Implementation and evidence ready for review; all analyzed rates retain timing failures; phase acceptance pending human review |
| TINY-R2-P3 - Software and DMA Scheduling | Compiler and placement A/B results, finite DMA ownership, burst/chunk scheduling, WS2812 refill budget and workload correctness on the available platform. | Pending |
| TINY-R2-P3 - Software and DMA Scheduling | Compiler and placement A/B results, finite DMA ownership, burst/chunk scheduling and available-path correctness; approved option A retains product DMA/IRQ budget qualification for the platform that supplies the route. | Matrix retained on `3e46cc8`; subsequent two P1 HAL fixes and focused/compatibility checks complete in the worktree; human review/acceptance pending |
| TINY-R2-P4 - Dual-Port Hazard3 and Four-Bank Local SRAM | Actual separate I/D paths, four independent 32 KiB bank frontends, SYS-clocked physical main-SRAM macros, local latency/fairness, FENCE.I, debug/reset and early inventory/SDC/macro-binding updates. | Pending |
| TINY-R2-P5 - Per-Target Concurrent Fabric | Cross-target concurrency, one combined transaction per target, central-DMA read/write overlap, AW/W binding, errors, simultaneous faults/counters and accepted-transfer drain. | Pending |
| TINY-R2-P6 - Shared IP and Eight-Channel DMA Integration | Legacy P7 obligations; shared PWM reporting, I2S slave and alternate-input-route prerequisites; common ABI/HAL parity; Crypto banks/lifecycle; truthful capabilities and affected Mini compatibility. | Pending |
+142 -1
View File
@@ -69,9 +69,47 @@ volatile uint32_t rs_dma_test_mmio[1024];
static uint32_t ws_registers[16];
static uint32_t ws_pushed;
static uint32_t ws_pixels[33];
static uint32_t ws_idle_on_interrupt_read;
static uint32_t dma_irq_enabled = 8U;
static bool dma_irq_pending;
static rs_dma_session_t dma_irq_owner;
static rs_status_t dma_irq_result;
uint32_t rs_dma_test_irq_save(void) {
const uint32_t saved = dma_irq_enabled;
dma_irq_enabled = 0U;
return saved;
}
void rs_dma_test_irq_restore(uint32_t saved) {
dma_irq_enabled = saved;
if ((saved != 0U) && dma_irq_pending) {
dma_irq_pending = false;
/* Model START taking effect before an interrupt can execute. */
if (RS_DMA_CH_REG(3U, RS_DMA_CH_REG_CTRL) == RS_DMA_CH_CTRL_START) {
RS_DMA_CH_REG(3U, RS_DMA_CH_REG_STATUS) = RS_DMA_STATUS_BUSY;
}
dma_irq_result = rs_dma_session_acquire(&dma_irq_owner, 3U);
if (dma_irq_result == RS_OK) {
const rs_dma_config_t config = {.kind = RS_DMA_KIND_MM_TO_MM,
.source = 0x3000U, .destination = 0x4000U, .byte_count = 16U,
.width = RS_DMA_WIDTH_32, .source_increment = true,
.destination_increment = true, .burst_beats = 1U};
dma_irq_result = rs_dma_session_configure(&dma_irq_owner, &config);
}
}
}
uint32_t rs_ws2812_test_read(uint32_t offset) {
return ws_registers[offset / 4U];
const uint32_t value = ws_registers[offset / 4U];
if ((offset == 0x30U) && (ws_idle_on_interrupt_read != 0U)) {
ws_registers[0x18U / 4U] = 8U;
if (ws_idle_on_interrupt_read == 1U) {
ws_registers[0x30U / 4U] |= RS_WS2812_INTR_DONE;
}
ws_idle_on_interrupt_read = 0U;
}
return value;
}
void rs_ws2812_test_write(uint32_t offset, uint32_t value) {
@@ -105,6 +143,107 @@ static void ws_test_reset(void) {
ws_registers[0x18U / 4U] = 8U;
ws_registers[0x24U / 4U] = 3U;
ws_pushed = 0U;
ws_idle_on_interrupt_read = 0U;
}
static int test_dma_tcd_preemption(void) {
static _Alignas(64) rs_dma_tcd_t tcd = {
.source = 0x1000U, .destination = 0x2000U, .byte_count = 32U, .y_count = 1U,
.control = RS_DMA_TCD_VALID | RS_DMA_TCD_SRC_INC | RS_DMA_TCD_DST_INC |
(UINT32_C(1) << RS_DMA_TCD_BURST_SHIFT)};
rs_status_t result;
bool valid;
ws_test_reset();
dma_irq_pending = true;
dma_irq_result = RS_OK;
result = rs_dma_submit_tcd(3U, &tcd, 1U);
valid = (result == RS_ETIMEOUT) && (dma_irq_result == RS_EIO) &&
!dma_irq_pending && (dma_irq_enabled == 8U) &&
(RS_DMA_CH_REG(3U, RS_DMA_CH_REG_TCD_HEAD) == (uint32_t)(uintptr_t)&tcd) &&
(RS_DMA_CH_REG(3U, RS_DMA_CH_REG_TCD_COUNT) == 1U) &&
(RS_DMA_CH_REG(3U, RS_DMA_CH_REG_SRC_ADDR) == tcd.source);
RS_DMA_CH_REG(3U, RS_DMA_CH_REG_STATUS) = 0U;
(void)rs_dma_session_release(&dma_irq_owner);
if (!valid) {
return 1;
}
/* An already leased direct channel must remain untouched on rejection. */
if (rs_dma_session_acquire(&dma_irq_owner, 3U) != RS_OK) {
return 2;
}
RS_DMA_CH_REG(3U, RS_DMA_CH_REG_SRC_ADDR) = 0x3000U;
result = rs_dma_submit_tcd(3U, &tcd, 1U);
valid = (result == RS_EIO) && (dma_irq_enabled == 8U) &&
(RS_DMA_CH_REG(3U, RS_DMA_CH_REG_TCD_HEAD) == 0U) &&
(RS_DMA_CH_REG(3U, RS_DMA_CH_REG_TCD_COUNT) == 0U) &&
(RS_DMA_CH_REG(3U, RS_DMA_CH_REG_SRC_ADDR) == 0x3000U);
(void)rs_dma_session_release(&dma_irq_owner);
if (!valid) {
return 3;
}
/* Calling from an already masked context must not enable interrupts. */
dma_irq_enabled = 0U;
result = rs_dma_submit_tcd(3U, &tcd, 1U);
valid = (result == RS_ETIMEOUT) && (dma_irq_enabled == 0U);
dma_irq_enabled = 8U;
return valid ? 0 : 4;
}
static int test_ws2812_completion_race(void) {
rs_ws2812_dma_status_t transfer;
for (uint32_t delay = 1U; delay <= 2U; ++delay) {
ws_test_reset();
if (rs_ws2812_dma_begin(ws_pixels, 4U, 0U, 100U) != RS_OK) {
return 1;
}
/* Complete after INTR_STATE was sampled, before STATUS is sampled.
* The second case also delays the sticky DONE latch until next service. */
ws_idle_on_interrupt_read = delay;
if (rs_ws2812_dma_service(1U) != RS_OK) {
return 2;
}
(void)rs_ws2812_dma_status(&transfer);
if (!transfer.active || transfer.draining || transfer.dma_pending) {
return 3;
}
ws_registers[0x30U / 4U] |= RS_WS2812_INTR_DONE;
if (rs_ws2812_dma_service(2U) != RS_OK) {
return 4;
}
(void)rs_ws2812_dma_status(&transfer);
if (transfer.active || (transfer.result != RS_OK) ||
(ws_registers[0x24U / 4U] != 3U)) {
return 5;
}
}
/* An idle core without DONE must still terminate on error, abort or the
* original deadline; waiting for the sticky latch cannot hide a failure. */
for (uint32_t failure = 0U; failure < 3U; ++failure) {
const rs_status_t expected = (failure == 2U) ? RS_ETIMEOUT : RS_EIO;
ws_test_reset();
if (rs_ws2812_dma_begin(ws_pixels, 4U, 0U, 3U) != RS_OK) {
return 6;
}
ws_idle_on_interrupt_read = 2U;
if (rs_ws2812_dma_service(1U) != RS_OK) {
return 7;
}
if (failure == 0U) {
ws_registers[0x2cU / 4U] = 1U;
} else if (failure == 1U) {
ws_registers[0x30U / 4U] = RS_WS2812_INTR_ABORTED;
}
if (rs_ws2812_dma_service(3U) != expected) {
return 8;
}
(void)rs_ws2812_dma_service(4U);
(void)rs_ws2812_dma_service(5U);
(void)rs_ws2812_dma_status(&transfer);
if (transfer.active || (transfer.result != expected)) {
return 9;
}
}
return 0;
}
static int test_dma_sessions(void) {
@@ -2989,6 +3128,8 @@ int main(void) {
test_ws2812_helpers(),
test_dma_sessions(),
test_ws2812_refill(),
test_dma_tcd_preemption(),
test_ws2812_completion_race(),
test_timer_helpers(),
test_psram_helpers(),
test_sdram_helpers(),