Add HTTPS e2e test scaffolding + UCI networking notes - #21
Merged
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UCI banner: ULTIMATE 64 ELITE (UCI) → UCI NETWORKING
Insert 16 NOPs after every STA to UCI_CONTROL/UCI_CMD_DATA via a uci_fence macro defined in uci_regs.inc. At 48 MHz, 16 NOPs = 32 cycles = ~0.67us, giving the FPGA time to latch each write. At 1 MHz the overhead is 32us per write -- negligible for networking. Unlike the LDA UCI_STATUS fence approach, NOPs cannot interfere with the UCI state machine. 11 fence sites total: 8 in uci_cmd.s (uci_abort, uci_begin_cmd, uci_put_byte, uci_push_wait, uci_check_err CLR_ERR, uci_drain_resp NEXT_DATA, uci_drain_status NEXT_DATA, uci_ack) and 3 in net.s (hostname write loop, null terminator, send data loop). Test results on U64E hardware: - 1 MHz: PASS (HTTP 200, body "HELLO FROM TEST SERVER") - 48 MHz: FAIL (write-side fencing alone is insufficient; read-side timing also needs work at turbo -- follow-up needed) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three categories of changes for turbo-speed UCI register access: 1. Read-side fencing: uci_fence (48 NOPs) after every LDA from $DF1C-$DF1F — UCI_STATUS, UCI_ID, UCI_RESP_DATA, UCI_STATUS_DATA. Without this, reads return stale/glitched values at 8+ MHz. 2. Post-PUSH_CMD settle delay: 255-iteration delay loop in uci_push_wait so the FPGA has time to latch the command and assert CMD_BUSY before the CPU starts polling. At 48 MHz the original uci_fence alone was only 2 us — the FPGA needs ~27 us. 3. 16-bit spin-wait in uci_read_resp_bytes: DATA_AV may not be set immediately after push_wait returns (e.g. TCP_CONNECT waits for a full network round-trip). The old code bailed on the first DATA_AV=0; the new code spins up to 65536 iterations (~150 ms at 48 MHz) before giving up. Also bumped uci_fence from 16 to 48 NOPs (0.67 us -> 2 us at 48 MHz) and converted two short branches to JMPs to fix range errors caused by the larger fence expansions. Verified: both BACKEND=uci and default ip65 builds succeed. 1 MHz baseline HTTP test passes. 48 MHz testing blocked on U64 power cycle — to be verified after device recovery. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The FPGA needs ~38 µs of wall-clock time between UCI register accesses. A 48-NOP sled (2 µs at 48 MHz) was far too short, and even a 256-NOP sled (10.7 µs at 48 MHz, the max that fits in the code segment) was insufficient. Replace the NOP sled with a nested delay loop (OUTER=5, INNER=100, ~2525 cycles = ~52 µs at 48 MHz, ~2.5 ms at 1 MHz). Binary search found the minimum at OUTER=3 INNER=122 (~38.4 µs); the chosen values provide 35% margin. Verified passing at both 1 MHz and 48 MHz on U64E hardware. Also convert all branches that span a fence expansion to JMP trampolines, since even the 14-byte delay loop can exceed the 8-bit branch range in tight loops. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update CLAUDE.md to reflect that UCI networking works at 48 MHz turbo via a nested delay-loop fence (~52us per UCI register access). All four test scenarios pass on real U64E: 22B and 1460B responses at both 1 MHz and 48 MHz. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UCI NOP-sled fencing for turbo speed support
- tools/uci/test_https_local.py: reusable HTTPS e2e harness that runs a local TLS 1.3 listener, DMAs a 6502 stub calling http_get, toggles 48 MHz turbo, captures full post-run diagnostics, and optionally streams the 6510 bus (DEBUG_CAPTURE=1) with bounded capture for post-mortem. Reproducibly exposes an unresolved TLS 1.3 handshake stall at tls_state=0x03 on real U64E at 48 MHz. - CLAUDE.md: note the new test, record the TLS stall as a known issue, and document the wall-clock-vs-cycle-count design requirement for any future bounded-timeout work on the UCI adapter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an HTTPS e2e test harness for the UCI backend and records lessons from the recent investigation of TLS-at-48-MHz behaviour.
tools/uci/test_https_local.py— end-to-end HTTPS test against a local Python TLS listener. Reuses the ECDSA-P256 self-signed cert fromtools/https_e2e/certs/, DMAs a 6502 stub that callshttp_get, flips the U64E to 48 MHz turbo, captures a full diagnostic block on both pass and timeout paths, and optionally streams the 6510 bus with bounded capture (DEBUG_CAPTURE=1) using themax_bytes=/filter=kwargs added toc64-test-harness'sDebugCapturein Add bounded capture options to DebugCapture (max_bytes, filter) c64-test-harness#56 .CLAUDE.md— adds a note about the test, a known-issue entry for the TLS 1.3 handshake stall it exposes, and a design requirement that any future bounded-timeout work on the UCI spin-wait helpers must use a wall-clock time source.Context on the known issue
Master is reliable for DHCP and plain HTTP at all turbo speeds (1 MHz through 48 MHz). HTTPS / TLS 1.3 handshake at 48 MHz reproducibly stalls at
tls_state=0x03after the server completes its flight — root cause is not yet identified. This PR does not attempt a fix; it only lands the scaffolding and the notes so a future effort has a running start.Test plan
make BACKEND=ucibuilds cleanly.python3 tools/uci/test_http_local.pypasses on a real U64E (DHCP succeeds at turbo, plain-HTTP GET returns the expected body) — confirms master baseline.python3 tools/uci/test_https_local.pyreachestls_state=0x03(and then times out — that's the known issue this test was written to capture).🤖 Generated with Claude Code
Originally posted by @JC-000 on 2026-04-17