From 474d13236867d8d3007bc2c3e9ba54b29f3b82ef Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Fri, 5 Jun 2026 02:10:08 -0300 Subject: [PATCH] test(chipbus): Phase 0 live proof - two real WASM chips exchange a byte End-to-end proof of the chip-to-chip net-key fix through the real ChipRuntime + PinManager (not a unit stub). Two chips compiled from C with wasi-sdk: - bus-driver.c: drives 0xA5 onto D0..D7 at setup. - bus-reader.c: polls D0..D7 on a 1ms timer, mirrors onto OUT0..OUT7. Wired chip-to-chip with no board; with the chipbus flag both chips' Dn pins resolve to one shared net key, so the reader reproduces 0xA5. - sdk/examples/bus-{driver,reader}.{c,chip.json}: the proof chips. - __tests__/fixtures/chipbus/*.wasm: committed fixtures (regenerate with the test_intel/scripts/compile-chip.sh flags). - __tests__/chipbus-twochip-integration.test.ts: loads the fixtures via a relative path; skipIf they are absent. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../chipbus-twochip-integration.test.ts | 104 ++++++++++++++++++ .../fixtures/chipbus/bus-driver.wasm | Bin 0 -> 19647 bytes .../fixtures/chipbus/bus-reader.wasm | Bin 0 -> 20518 bytes .../sdk/examples/bus-driver.c | 20 ++++ .../sdk/examples/bus-driver.chip.json | 9 ++ .../sdk/examples/bus-reader.c | 34 ++++++ .../sdk/examples/bus-reader.chip.json | 9 ++ 7 files changed, 176 insertions(+) create mode 100644 frontend/src/__tests__/chipbus-twochip-integration.test.ts create mode 100644 frontend/src/__tests__/fixtures/chipbus/bus-driver.wasm create mode 100644 frontend/src/__tests__/fixtures/chipbus/bus-reader.wasm create mode 100644 test/test_custom_chips/sdk/examples/bus-driver.c create mode 100644 test/test_custom_chips/sdk/examples/bus-driver.chip.json create mode 100644 test/test_custom_chips/sdk/examples/bus-reader.c create mode 100644 test/test_custom_chips/sdk/examples/bus-reader.chip.json diff --git a/frontend/src/__tests__/chipbus-twochip-integration.test.ts b/frontend/src/__tests__/chipbus-twochip-integration.test.ts new file mode 100644 index 00000000..9255f51f --- /dev/null +++ b/frontend/src/__tests__/chipbus-twochip-integration.test.ts @@ -0,0 +1,104 @@ +/** + * Multi-chip digital bus — Phase 0 LIVE proof with REAL compiled WASM chips. + * + * This is the "2 chips exchange a real byte" milestone (03-phases.md, D-008), + * end-to-end through the actual ChipRuntime + PinManager + the chipbus net-key + * resolver — not a unit stub. Two chips compiled from C with wasi-sdk: + * - bus-driver: drives 0xA5 onto D0..D7 at setup (OUTPUT_HIGH/LOW). + * - bus-reader: polls D0..D7 on a 1ms timer, mirrors onto OUT0..OUT7. + * Wired chip-to-chip (D0..D7 straight across), no board. With the chipbus flag + * the two chips' Dn pins resolve to ONE shared net key, so the reader observes + * the driver's byte and reproduces 0xA5 on OUT. + * + * Sources: test/test_custom_chips/sdk/examples/{bus-driver,bus-reader}.c. + * Fixtures (.wasm) are committed alongside this test; regenerate with: + * clang --target=wasm32-unknown-wasip1 -O2 -nostartfiles -Wl,--import-memory \ + * -Wl,--export-table -Wl,--no-entry -Wl,--export=chip_setup \ + * -Wl,--allow-undefined -I test/test_custom_chips/sdk/include -o + * (same flags as test_intel/scripts/compile-chip.sh). + */ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import { readFileSync, existsSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { PinManager } from '../simulation/PinManager'; +import { ChipInstance } from '../simulation/customChips/ChipRuntime'; +import { + resolveChipNetKey, + setChipBusEnabledForTest, + resetChipNetIndexForTest, + type ChipNetState, +} from '../simulation/customChips/chipNets'; +import { syntheticChipPin } from '../simulation/customChips/syntheticPins'; + +const driverWasmPath = fileURLToPath(new URL('./fixtures/chipbus/bus-driver.wasm', import.meta.url)); +const readerWasmPath = fileURLToPath(new URL('./fixtures/chipbus/bus-reader.wasm', import.meta.url)); +const haveFixtures = existsSync(driverWasmPath) && existsSync(readerWasmPath); + +const chip = (id: string) => ({ id, metadataId: 'custom-chip' }); +const wire = (aId: string, aPin: string, bId: string, bPin: string) => ({ + start: { componentId: aId, pinName: aPin }, + end: { componentId: bId, pinName: bPin }, +}); +const range = (n: number) => Array.from({ length: n }, (_, i) => i); + +// The data bus: driver.D0..D7 wired straight across to reader.D0..D7, no board. +const STATE: ChipNetState = { + wires: range(8).map((i) => wire('driver', `D${i}`, 'reader', `D${i}`)), + components: [chip('driver'), chip('reader')], + boards: [], +}; + +// Mirror what traceDetailed hands CustomChipPart's `wires` map: a chip-to-chip +// net resolves to the shared net key; an unwired chip pin (the reader's OUTn) +// falls back to its own synthetic key (rule 3). +function pinKey(chipId: string, pin: string): number { + return resolveChipNetKey(STATE, chipId, pin) ?? syntheticChipPin(chipId, pin); +} + +describe.skipIf(!haveFixtures)('chipbus Phase 0 — two REAL chips exchange a byte', () => { + beforeAll(() => { + setChipBusEnabledForTest(true); + resetChipNetIndexForTest(); + }); + afterAll(() => { + setChipBusEnabledForTest(null); + resetChipNetIndexForTest(); + }); + + it('reader reproduces the driver byte 0xA5 over the shared chip-to-chip bus', async () => { + const driverWasm = new Uint8Array(readFileSync(driverWasmPath)); + const readerWasm = new Uint8Array(readFileSync(readerWasmPath)); + + // The bus pins resolve to ONE shared key for both chips (root cause A fix). + expect(pinKey('driver', 'D0')).toBe(pinKey('reader', 'D0')); + + const pm = new PinManager(); + + const driverWires = new Map( + range(8).map((i) => [`D${i}`, pinKey('driver', `D${i}`)] as [string, number]), + ); + const readerWires = new Map([ + ...range(8).map((i) => [`D${i}`, pinKey('reader', `D${i}`)] as [string, number]), + ...range(8).map((i) => [`OUT${i}`, pinKey('reader', `OUT${i}`)] as [string, number]), + ]); + + const driver = await ChipInstance.create({ wasm: driverWasm, pinManager: pm, wires: driverWires }); + driver.start(); // chip_setup drives 0xA5 onto the shared D0..D7 net keys. + + const reader = await ChipInstance.create({ wasm: readerWasm, pinManager: pm, wires: readerWires }); + reader.start(); + + // Fire the reader's 1ms polling timer (advance sim time well past it). + reader.tickTimers(5_000_000n); + + // Reconstruct the byte the reader mirrored onto OUT0..OUT7. + let out = 0; + for (const i of range(8)) { + if (pm.getPinState(pinKey('reader', `OUT${i}`))) out |= 1 << i; + } + expect(out).toBe(0xa5); + + driver.dispose(); + reader.dispose(); + }); +}); diff --git a/frontend/src/__tests__/fixtures/chipbus/bus-driver.wasm b/frontend/src/__tests__/fixtures/chipbus/bus-driver.wasm new file mode 100644 index 0000000000000000000000000000000000000000..8fe492d38700750532fc487c0a3002b36b8e562f GIT binary patch literal 19647 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 ZQyo1gG3lv$%xvbHs-{YO)u5U9{x3JG_v-)v literal 0 HcmV?d00001 diff --git a/frontend/src/__tests__/fixtures/chipbus/bus-reader.wasm b/frontend/src/__tests__/fixtures/chipbus/bus-reader.wasm new file mode 100644 index 0000000000000000000000000000000000000000..7b31fc38ec608236ba6c8ab83f910ccd20c15402 GIT binary patch literal 20518 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 i) & 1; + /* OUTPUT_HIGH/LOW drives the level at registration time, so the byte is + * present on the shared net immediately — no timer needed. */ + vx_pin_register(name, bit ? VX_OUTPUT_HIGH : VX_OUTPUT_LOW); + } +} diff --git a/test/test_custom_chips/sdk/examples/bus-driver.chip.json b/test/test_custom_chips/sdk/examples/bus-driver.chip.json new file mode 100644 index 00000000..0287d56e --- /dev/null +++ b/test/test_custom_chips/sdk/examples/bus-driver.chip.json @@ -0,0 +1,9 @@ +{ + "schema": "velxio-chip/v1", + "name": "Bus Driver (0xA5)", + "author": "Velxio", + "license": "MIT", + "description": "Drives the constant byte 0xA5 onto an 8-bit data bus D0..D7. Phase 0 chip-to-chip bus proof.", + "pins": ["D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7"], + "attributes": [] +} diff --git a/test/test_custom_chips/sdk/examples/bus-reader.c b/test/test_custom_chips/sdk/examples/bus-reader.c new file mode 100644 index 00000000..b9e10303 --- /dev/null +++ b/test/test_custom_chips/sdk/examples/bus-reader.c @@ -0,0 +1,34 @@ +/* + * bus-reader — Phase 0 chip-to-chip bus proof (project/multichip-bus/ in the + * velxio-prod repo). Reads the 8-bit data bus D0..D7 and mirrors it onto + * OUT0..OUT7 (which would drive 8 LEDs in the app). Polls on a 1 ms timer so it + * is order-independent w.r.t. the driver's setup. If chip-to-chip keying works, + * OUT == whatever the driver put on the bus (0xA5). + */ +#include "velxio-chip.h" + +static vx_pin D[8]; +static vx_pin OUT[8]; + +static void poll(void* ud) { + (void)ud; + for (int i = 0; i < 8; i++) { + int v = vx_pin_read(D[i]); + vx_pin_write(OUT[i], v); + } +} + +void chip_setup(void) { + char dn[4] = {'D', '0', 0, 0}; + for (int i = 0; i < 8; i++) { + dn[1] = (char)('0' + i); + D[i] = vx_pin_register(dn, VX_INPUT); + } + char on[5] = {'O', 'U', 'T', '0', 0}; + for (int i = 0; i < 8; i++) { + on[3] = (char)('0' + i); + OUT[i] = vx_pin_register(on, VX_OUTPUT_LOW); + } + vx_timer t = vx_timer_create(poll, (void*)0); + vx_timer_start(t, 1000000ULL, true); /* 1 ms, repeating */ +} diff --git a/test/test_custom_chips/sdk/examples/bus-reader.chip.json b/test/test_custom_chips/sdk/examples/bus-reader.chip.json new file mode 100644 index 00000000..54124cfd --- /dev/null +++ b/test/test_custom_chips/sdk/examples/bus-reader.chip.json @@ -0,0 +1,9 @@ +{ + "schema": "velxio-chip/v1", + "name": "Bus Reader (8 LEDs)", + "author": "Velxio", + "license": "MIT", + "description": "Reads an 8-bit data bus D0..D7 and mirrors it onto OUT0..OUT7. Phase 0 chip-to-chip bus proof.", + "pins": ["D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7"], + "attributes": [] +}