import assert from "node:assert/strict"; import { HalRuntime, parseCompSource } from "./hal-runtime.mjs"; import { SimSession, CONTEXT_ID } from "./sim-session.mjs"; const parsed = parseCompSource("component and2;\npin in bit in0;\npin in bit in1;\npin out bit out;\nfunction _ nofp;\n"); assert.equal(parsed.status, "verified"); assert.equal(parseCompSource("pin in bit missing;").code, "hal_component_missing"); assert.equal(parseCompSource("component unknown;\n").code, "hal_component_unsupported"); assert.equal(parseCompSource("component abs_s64;\npin in s64 in;\n").code, "hal_type_unsupported"); const hal = new HalRuntime(); assert.equal(hal.configure({ threads: [{ name: "servo-thread", period_ticks: 1 }], components: [ { instance: "gate", type: "and2", thread: "servo-thread" }, { instance: "constant", type: "constant", thread: "servo-thread" }, { instance: "xy", type: "corexy_by_hal", thread: "servo-thread" }, ] }).status, "verified"); assert.equal(hal.setPin("gate.in0", 1).status, "verified"); assert.equal(hal.setPin("gate.in1", 1).status, "verified"); assert.equal(hal.setParam("constant.value", 3.5).status, "verified"); assert.equal(hal.setPin("xy.j0-motor-pos-cmd", 6).status, "verified"); assert.equal(hal.setPin("xy.j1-motor-pos-cmd", 2).status, "verified"); assert.equal(hal.setPin("xy.alpha-fb", 4).status, "verified"); assert.equal(hal.setPin("xy.beta-fb", 1).status, "verified"); assert.equal(hal.step(1).status, "verified"); assert.equal(hal.getPin("gate.out").value, 1); assert.equal(hal.getPin("constant.out").value, 3.5); assert.equal(hal.getPin("xy.alpha-cmd").value, 4); assert.equal(hal.getPin("xy.j0-motor-pos-fb").value, 5); assert.equal(hal.state.components.find((item) => item.instance === "xy").calls, 1); assert.equal(hal.setFailure("gate", true).status, "verified"); assert.equal(hal.step(2).code, "hal_function_failure"); assert.equal(hal.state.tick, 1); const saved = hal.export(); const restored = new HalRuntime(); assert.deepEqual(restored.restore(saved), saved); assert.equal(hal.setPin("constant.out", Number.NaN).code, "hal_value_invalid"); const batch = new HalRuntime(); assert.equal(batch.configure({ components: [{ module: "constant", instances: ["c0", "c1"] }] }).status, "verified"); assert.equal(batch.state.components.length, 2); const core = { _sim_protocol_reset() {}, _sim_protocol_accept() { return 0; }, _sim_create() { return 0; }, _sim_load_workspace() { return 0; }, _sim_step() { return 0; }, _sim_protocol_set_tick() { return 0; }, }; const session = new SimSession(core, { sessionId: "hal-state" }); const base = { schema_version: 1, context_id: CONTEXT_ID, session_id: "hal-state" }; const send = (kind, seq, operation_id, payload = {}) => session.accept({ ...base, kind, seq, operation_id, payload }); send("HELLO", 1); send("SESSION_ATTACH", 2, "attach"); send("LOAD_WORKSPACE", 3, "workspace", { root_path: "/workspace" }); assert.equal(send("HAL_COMMAND", 4, "hal-thread", { action: "thread", name: "servo-thread", period_ticks: 1 }).payload.hal_runtime.threads["servo-thread"].period_ticks, 1); assert.equal(send("HAL_COMMAND", 5, "hal-component", { action: "component", instance: "gate", type: "and2", thread: "servo-thread" }).payload.hal_runtime.components.length, 1); send("HAL_SET", 6, "hal-in0", { target: "pin", name: "gate.in0", value: 1 }); send("HAL_SET", 7, "hal-in1", { target: "pin", name: "gate.in1", value: 1 }); const stepped = send("SIM_STEP", 8, "hal-step", { cycles: 1 }); assert.equal(stepped.payload.hal_runtime.pins["gate.out"].value, 1); const checkpoint = send("CHECKPOINT", 9, "hal-checkpoint").payload.checkpoint; assert.equal(checkpoint.state.hal_runtime.schema, "sim_hal_runtime.v1"); console.log(`hal_runtime=passed tick=${hal.state.tick} components=${hal.state.components.length} worker_tick=${stepped.payload.hal_runtime.tick}`);