From f5f8068fac59b4f16046c2022c2fc7c7e447ef4c Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 25 Aug 2026 12:40:53 -0300 Subject: zig-p4: pure-Zig ESP32-P4 toolchain build.zig generates the linker script and drives Zig's own LLD; tools/image.zig turns the ELF into a flashable image and tools/{rom,serial}.zig speak the mask ROM loader over the UART. No CMake, ninja, idf.py, esptool, or external linker. src/soc.zig is a comptime register model over ESP-IDF's own *_reg.h headers; src/hal/ adds peripheral sequences; src/io/ implements std.Io for the chip; src/oracle/ diffs this HAL against ESP-IDF's on the die. --- src/io/host.zig | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/io/host.zig (limited to 'src/io/host.zig') diff --git a/src/io/host.zig b/src/io/host.zig new file mode 100644 index 0000000..7239f1a --- /dev/null +++ b/src/io/host.zig @@ -0,0 +1,76 @@ +//! The host half of the scheduler's machine seam: the same eight declarations as `chip.zig`, for a +//! machine that is not the chip. +//! +//! This exists so the scheduler itself can be tested where it can be debugged. Everything above +//! `context.zig` and this file is portable - the run queue, the futex, cancellation, deadline +//! arithmetic - and all of it is the part where a mistake is a silent hang on the die. +//! +//! The clock here is **virtual**, not the wall clock, and that is the point. `ticks` returns a +//! counter that only advances when the scheduler idles, so a test that sleeps three tasks for +//! 5 ms, 1 ms and 3 ms finishes instantly and in a fixed order, with no tolerance windows and no +//! flakiness under load. It also means the scheduler's own deadlock watchdog is testable: the +//! no-deadline idle advances the clock too, so a watchdog measured in ticks still fires. + +const std = @import("std"); + +/// The chip's rate, kept identically here so the host exercises the same tick/nanosecond arithmetic +/// (`* 125 / 2`) rather than a rounder number that would hide a division bug. +pub const ticks_hz: u64 = 16_000_000; + +var virtual: u64 = 0; + +pub fn init() void { + virtual = 0; +} + +pub fn ticks() u64 { + return virtual; +} + +/// No interrupts to mask on the host, and the scheduler is single-threaded, so this is a shape +/// rather than a mechanism. It still has to exist: it is what makes the chip's masked regions +/// reachable in a host test. +pub const Guard = struct { + pub inline fn release(_: Guard) void {} +}; + +pub inline fn mask() Guard { + return .{}; +} + +/// Advance the virtual clock. With a deadline, jump straight to it - nothing else can happen in +/// between on a host with no interrupts, so waiting is pure delay. Without one, advance by a +/// millisecond so that a caller spinning on "nothing runnable, nothing scheduled" reaches its +/// watchdog instead of looping forever. +pub fn idle(deadline: ?u64) void { + if (deadline) |d| { + if (d > virtual) virtual = d; + } else { + virtual += ticks_hz / 1000; + } +} + +/// Enough of `ets_printf`'s shape to typecheck the arguments, printed in Zig's own spelling. The +/// crash path is the only caller, and on the host the interesting question is whether it runs at +/// all, not how it looks. +pub inline fn print(comptime fmt: [*:0]const u8, args: anytype) void { + std.debug.print("{s} <- {any}\n", .{ std.mem.span(fmt), args }); +} + +/// No hardware RNG. Returns zero rather than something plausible: `p4.zig` mixes this with the +/// clock and its own state, and a zero here makes it obvious in a test that the hardware +/// contribution is absent instead of quietly supplying the entropy the chip is being asked about. +pub inline fn entropyWord() u32 { + return 0; +} + +/// Deliberately constant: a host test that asserts something about the generator's output wants a +/// fixed seed, and the chip's own seed noise is `soc.cycles()`, which no host has. +pub inline fn noise() u64 { + return 0x0420_0cafe_0420; +} + +/// Test-only: move the virtual clock forward by hand. +pub fn advance(n: u64) void { + virtual += n; +} -- cgit v1.3