diff --git a/build.sh b/build.sh index cb75768..0e1fcf2 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Markus Maiwald (Architect) | Voxis Forge (AI) + + set -e # Nexus Rumpk Build Script v0.4 @@ -220,13 +223,13 @@ nim c \ --mm:arc \ --noMain:on \ --cc:clang \ - --passC:"-target ${ZIG_TARGET/-freestanding-none/-unknown-none} -ffreestanding -fno-stack-protector -fno-builtin $ARCH_FLAGS -I$RUMPK_DIR/core/include" \ + --passC:"-target ${ZIG_TARGET/-freestanding-none/-unknown-none} -ffreestanding -fno-stack-protector -fno-builtin $ARCH_FLAGS -I$RUMPK_DIR/core/include -O3 -flto" \ --define:useMalloc \ --define:nimNoLibc \ --define:noSignalHandler \ --define:$NIM_DEFINE \ - -d:release \ -d:danger \ + --opt:speed \ --nimcache:"$BUILD_DIR/nimcache" \ --path:"$RUMPK_DIR/core" \ -c \ @@ -261,6 +264,7 @@ for cfile in "$BUILD_DIR/nimcache"/*.c; do -I"$RUMPK_DIR/core/include" \ -I/usr/lib/nim \ -I"$RUMPK_DIR/core" \ + -O3 -flto \ -c "$cfile" \ -o "$ofile" NIM_OBJS="$NIM_OBJS $ofile" @@ -320,6 +324,7 @@ nim c \ --os:any \ -d:is_membrane \ -d:danger \ + --opt:speed \ -d:useMalloc \ -d:nimNoLibc \ -d:noSignalHandler \ @@ -350,6 +355,7 @@ for cfile in "$BUILD_DIR/membrane_nimcache"/*.c; do -I"$RUMPK_DIR/libs/membrane" \ -I"$RUMPK_DIR/libs/membrane/include" \ -I"$RUMPK_DIR/vendor/lwip/src/include" \ + -O3 -flto \ -c "$cfile" \ -o "$ofile" MEMBRANE_NIM_OBJS="$MEMBRANE_NIM_OBJS $ofile" diff --git a/core/kernel.nim b/core/kernel.nim index c3086b3..15e2922 100644 --- a/core/kernel.nim +++ b/core/kernel.nim @@ -1,5 +1,5 @@ +# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI) # Rumpk Layer 1: The Logic Core (Autonomous Immune System) -# Markus Maiwald (Architect) | Voxis Forge (AI) {.push stackTrace: off, lineTrace: off.} @@ -36,7 +36,51 @@ proc kprint*(s: cstring) {.exportc, cdecl.} = proc kprintln*(s: cstring) {.exportc, cdecl.} = kprint(s); kprint("\n") +# ========================================================= +# Shared Infrastructure +# ========================================================= + +const SYSTABLE_BASE = 0x83000000'u64 + +# Global Rings (The Pipes - L0 Physics) +var guest_rx_hal: HAL_Ring[IonPacket] +var guest_tx_hal: HAL_Ring[IonPacket] +var guest_event_hal: HAL_Ring[IonPacket] +var guest_cmd_hal: HAL_Ring[CmdPacket] + +# Shared Channels (The Valves - L1 Logic) +var chan_rx*: SovereignChannel[IonPacket] +var chan_tx*: SovereignChannel[IonPacket] +var chan_event*: SovereignChannel[IonPacket] +var chan_cmd*: SovereignChannel[CmdPacket] + +proc get_ion_load(): int = + ## Calculate load of the Command Ring (The Heartbeat of the NPLs) + let head = guest_cmd_hal.head + let tail = guest_cmd_hal.tail + let mask = guest_cmd_hal.mask + return int((head - tail) and mask) + proc rumpk_yield_internal() {.cdecl, exportc.} = + let load = get_ion_load() + + # 🏛️ ADAPTIVE GOVERNOR (Phase 3) + if load > 0: + # WAR MODE: Priority to IO Loop. Bypass NexShell/Watchdog. + if current_fiber == addr fiber_subject: + switch(addr fiber_ion) + return + elif current_fiber == addr fiber_ion: + # If Subject is the main producer, we must let it run + switch(addr fiber_subject) + return + elif load == 0: + # IDLE MODE (Phase 3): No pending commands. + # In a purely cooperative system, we don't WFI here to avoid hanging + # without a timer IRQ. The Watchdog will manage the sleep. + discard + + # Normal Round Robin logic if current_fiber == addr fiber_ion: switch(addr fiber_nexshell) elif current_fiber == addr fiber_nexshell: @@ -56,19 +100,7 @@ proc fiber_yield*() {.exportc, cdecl.} = -const SYSTABLE_BASE = 0x83000000'u64 -# Global Rings (The Pipes - L0 Physics) -var guest_rx_hal: HAL_Ring[IonPacket] -var guest_tx_hal: HAL_Ring[IonPacket] -var guest_event_hal: HAL_Ring[IonPacket] -var guest_cmd_hal: HAL_Ring[CmdPacket] - -# Shared Channels (The Valves - L1 Logic) -var chan_rx*: SovereignChannel[IonPacket] -var chan_tx*: SovereignChannel[IonPacket] -var chan_event*: SovereignChannel[IonPacket] -var chan_cmd*: SovereignChannel[CmdPacket] @@ -113,8 +145,8 @@ proc ion_fiber_entry() {.cdecl.} = var cmd: CmdPacket while true: - # 1. Process Commands - if chan_cmd.recv(cmd): + # 1. Process Commands (Drain the ring!) + while chan_cmd.recv(cmd): if cmd.kind == uint32(CMD_ION_STOP): kprintln("[ION] STOP received. Suspending IO.") ion_paused = true @@ -123,13 +155,12 @@ proc ion_fiber_entry() {.cdecl.} = kprintln("[ION] START received. Resuming IO.") ion_paused = false - # 2. Process Data (if not paused) + # 2. Process Data (if not paused, Drain the ring!) if not ion_paused: - if chan_tx.recv(pkt): - kprintln("[ION] Packet intercepted. Generating Telemetry...") + while chan_tx.recv(pkt): + # High speed telemetry logic var alert = IonPacket(id: 777, len: 42) chan_event.send(alert) - kprintln("[ION] Event dispatched.") fiber_yield() diff --git a/core/watchdog.nim b/core/watchdog.nim index bcf5da3..f0529b0 100644 --- a/core/watchdog.nim +++ b/core/watchdog.nim @@ -1,3 +1,4 @@ + # Watchdog Fiber - Logic Core Immune System const MAX_PAUSE_TICKS = 1_000_000'u64 @@ -29,5 +30,14 @@ proc watchdog_loop() {.cdecl.} = chan_cmd.send(cmd) # Cooperative Multitasking: Must yield! + # 🏛️ ADAPTIVE GOVERNOR (Phase 3: IDLE) + # Disabled for pure cooperative benchmarking (no timer IRQ) + # if not ion_paused: + # asm """ + # csrsi sstatus, 2 + # wfi + # csrci sstatus, 2 + # """ + fiber_yield() # asm "wfi" diff --git a/npl/bench_ion.zig b/npl/bench_ion.zig new file mode 100644 index 0000000..689a011 --- /dev/null +++ b/npl/bench_ion.zig @@ -0,0 +1,150 @@ +// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI) +// RUMPK NPL // BENCHMARK (THE SPEED FREAK) + +const std = @import("std"); + +// 1. The SysTable Contract (Must match Kernel!) +const ION_BASE = 0x83000000; + +const IonPacket = extern struct { + data: u64, + phys: u64, + len: u16, + id: u16, +}; + +const CmdPacket = extern struct { + kind: u32, + arg: u32, +}; + +const RingBufferPacket = extern struct { + head: u32, + tail: u32, + mask: u32, + data: [256]IonPacket, +}; + +const RingBufferCmd = extern struct { + head: u32, + tail: u32, + mask: u32, + data: [256]CmdPacket, +}; + +const SysTable = extern struct { + magic: u32, + s_rx: *RingBufferPacket, + s_tx: *RingBufferPacket, + s_event: *RingBufferPacket, + s_cmd: *RingBufferCmd, +}; + +fn get_systable() *SysTable { + return @ptrFromInt(ION_BASE); +} + +inline fn read_cycles() u64 { + var cycles: u64 = undefined; + // RISC-V 64-bit cycle counter + asm volatile ("rdcycle %[cycles]" + : [cycles] "=r" (cycles), + ); + return cycles; +} + +export fn main() c_int { + const sys = get_systable(); + print("[BENCH] Warming up ION...\n"); + + if (sys.magic != 0x4E585553) { + print("[BENCH] Magic mismatch! 0x"); + print_hex(sys.magic); + print("\n"); + return 1; + } + + var i: usize = 0; + const ITERATIONS = 100_000; + + // 1. Calibrate (Measure overhead of reading cycles) + const t0 = read_cycles(); + const t1 = read_cycles(); + const overhead = t1 - t0; + + print("[BENCH] Timer Overhead: "); + print_u64(overhead); + print(" cycles\n"); + + // 2. The Loop + print("[BENCH] Starting 100k IO ops (Raw Ring Push - NO YIELD)...\n"); + const start = read_cycles(); + + const cmd_ring = sys.s_cmd; + while (i < ITERATIONS) : (i += 1) { + // Measure Pure Ring Push (Physics) + while (true) { + const head = @atomicLoad(u32, &cmd_ring.head, .monotonic); + const tail = @atomicLoad(u32, &cmd_ring.tail, .monotonic); + + const next = (head + 1) & cmd_ring.mask; + if (next != tail) { + cmd_ring.data[head & cmd_ring.mask] = .{ .kind = 0, .arg = @intCast(i) }; + @atomicStore(u32, &cmd_ring.head, next, .release); + // fiber_yield(); // BYPASS FOR RAW SPEED + break; + } else { + // Ring full - yield to let Kernel process + fiber_yield(); + } + } + } + + const end = read_cycles(); + const total_cycles = (end - start) - overhead; + const avg = total_cycles / ITERATIONS; + + print("[BENCH] Total Cycles: "); + print_u64(total_cycles); + print("\n"); + print("[BENCH] Result: "); + print_u64(avg); + print(" cycles/op\n"); + + return 0; +} + +// OS Shims +extern fn write(fd: c_int, buf: [*]const u8, count: usize) isize; + +const YIELD_LOC = 0x83000FF0; +fn fiber_yield() void { + const ptr: *const *const fn () callconv(.c) void = @ptrFromInt(YIELD_LOC); + const func = ptr.*; + func(); +} + +fn print(text: []const u8) void { + _ = write(1, text.ptr, text.len); +} + +fn print_u64(val: u64) void { + var buf: [32]u8 = undefined; + const s = std.fmt.bufPrint(&buf, "{}", .{val}) catch "ERR"; + print(s); +} + +fn print_hex(val: u32) void { + var buf: [16]u8 = undefined; + const s = std.fmt.bufPrint(&buf, "{x}", .{val}) catch "ERR"; + print(s); +} + +pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn { + _ = error_return_trace; + _ = ret_addr; + print("\n[BENCH] PANIC: "); + print(msg); + print("\n"); + while (true) {} +}