virtual-machine 0.0.30 → 0.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- export { WorkerErrorMessage, WorkerHaltedMessage, WorkerInitMessage, WorkerOutboundMessage, WorkerReadyMessage } from './worker.js';
2
-
3
1
  /* tslint:disable */
4
2
  /* eslint-disable */
5
3
 
@@ -18,6 +16,9 @@ declare class WasmVm {
18
16
  [Symbol.dispose](): void;
19
17
  /**
20
18
  * Get a byte from the UART output buffer, if available.
19
+ *
20
+ * In SMP mode, this checks both the shared UART output buffer (for worker output)
21
+ * and the local UART buffer (for hart 0 output).
21
22
  */
22
23
  get_output(): number | undefined;
23
24
  /**
@@ -29,15 +30,42 @@ declare class WasmVm {
29
30
  * Print a status message to UART output (visible in browser).
30
31
  */
31
32
  print_status(message: string): void;
33
+ /**
34
+ * Start worker threads for secondary harts (1..num_harts).
35
+ *
36
+ * Workers run in parallel with the main thread, sharing DRAM and CLINT
37
+ * via SharedArrayBuffer.
38
+ *
39
+ * # Arguments
40
+ * * `worker_url` - URL to the worker script (e.g., "/worker.js")
41
+ */
42
+ start_workers(worker_url: string): void;
32
43
  /**
33
44
  * Get the current network connection status.
34
45
  * This checks the actual connection state by seeing if an IP was assigned.
35
46
  */
36
47
  network_status(): NetworkStatus;
48
+ /**
49
+ * Create a new VM instance with a specified number of harts.
50
+ *
51
+ * # Arguments
52
+ * * `kernel` - ELF kernel binary
53
+ * * `num_harts` - Number of harts (0 = auto-detect)
54
+ */
55
+ static new_with_harts(kernel: Uint8Array, num_harts: number): WasmVm;
37
56
  /**
38
57
  * Get current memory usage (DRAM size) in bytes.
39
58
  */
40
59
  get_memory_usage(): bigint;
60
+ /**
61
+ * Get the SharedArrayBuffer for external worker management.
62
+ * Returns None if not in SMP mode.
63
+ */
64
+ get_shared_buffer(): SharedArrayBuffer | undefined;
65
+ /**
66
+ * Terminate all workers.
67
+ */
68
+ terminate_workers(): void;
41
69
  /**
42
70
  * Disconnect from the network.
43
71
  */
@@ -54,17 +82,32 @@ declare class WasmVm {
54
82
  connect_webtransport(url: string, cert_hash?: string | null): void;
55
83
  /**
56
84
  * Create a new VM instance and load a kernel (ELF or raw binary).
85
+ *
86
+ * If SharedArrayBuffer is available, the VM will use true parallel
87
+ * execution with Web Workers. Otherwise, falls back to single-threaded mode.
88
+ *
89
+ * Hart count is auto-detected as half of hardware_concurrency.
90
+ * Use `new_with_harts()` to specify a custom hart count.
57
91
  */
58
92
  constructor(kernel: Uint8Array);
59
93
  /**
60
- * Execute one instruction on each CPU (round-robin).
94
+ * Execute one instruction on hart 0 (primary hart).
95
+ *
96
+ * In SMP mode, secondary harts run in Web Workers and execute in parallel.
97
+ * This method only steps hart 0, which handles I/O coordination.
98
+ *
61
99
  * Returns true if the VM is still running, false if halted.
62
100
  */
63
101
  step(): boolean;
64
102
  /**
65
103
  * Push an input byte to the UART.
104
+ * In SMP mode, this also writes to the shared input buffer so workers can receive it.
66
105
  */
67
106
  input(byte: number): void;
107
+ /**
108
+ * Check if running in SMP mode (with workers).
109
+ */
110
+ is_smp(): boolean;
68
111
  /**
69
112
  * Execute up to N instructions in a batch.
70
113
  * Returns the number of instructions actually executed.
@@ -86,15 +129,75 @@ declare class WasmVm {
86
129
  * This should be called before starting execution if the kernel needs a filesystem.
87
130
  */
88
131
  load_disk(disk_image: Uint8Array): void;
132
+ /**
133
+ * Get the number of harts configured.
134
+ */
135
+ num_harts(): number;
136
+ }
137
+
138
+ declare class WorkerState {
139
+ free(): void;
140
+ [Symbol.dispose](): void;
141
+ /**
142
+ * Execute a batch of instructions and return.
143
+ *
144
+ * This is designed to be called repeatedly from JavaScript, allowing
145
+ * the event loop to yield between batches. This prevents the worker
146
+ * from blocking indefinitely and allows it to respond to messages.
147
+ *
148
+ * Returns a WorkerStepResult indicating whether to continue, halt, etc.
149
+ */
150
+ step_batch(batch_size: number): WorkerStepResult;
151
+ /**
152
+ * Get the total step count.
153
+ */
154
+ step_count(): bigint;
155
+ /**
156
+ * Create a new worker state for a secondary hart.
157
+ */
158
+ constructor(hart_id: number, shared_mem: any, entry_pc: bigint);
159
+ /**
160
+ * Get the hart ID.
161
+ */
162
+ hart_id(): number;
163
+ }
164
+
165
+ /**
166
+ * Result of executing a batch of instructions.
167
+ */
168
+ declare enum WorkerStepResult {
169
+ /**
170
+ * Continue executing - call step_batch again
171
+ */
172
+ Continue = 0,
173
+ /**
174
+ * Halt requested via control region
175
+ */
176
+ Halted = 1,
177
+ /**
178
+ * Shutdown requested by guest (RequestedTrap)
179
+ */
180
+ Shutdown = 2,
181
+ /**
182
+ * Fatal error occurred
183
+ */
184
+ Error = 3,
89
185
  }
90
186
 
91
187
  /**
92
- * Worker entry point, called from JavaScript.
188
+ * Check interrupts for this hart using the shared CLINT.
93
189
  *
94
- * # Arguments
95
- * * `hart_id` - This worker's hart ID (1, 2, 3, ...)
96
- * * `shared_mem` - SharedArrayBuffer containing DRAM
97
- * * `entry_pc` - Kernel entry point address
190
+ * This is called periodically by the worker to check for:
191
+ * - Software interrupts (IPI via MSIP)
192
+ * - Timer interrupts (MTIP)
193
+ */
194
+ declare function worker_check_interrupts(hart_id: number, shared_mem: any): bigint;
195
+
196
+ /**
197
+ * Legacy worker entry point - DEPRECATED.
198
+ *
199
+ * This function runs a blocking infinite loop. Use WorkerState + step_batch instead
200
+ * for cooperative scheduling that doesn't block the worker's event loop.
98
201
  */
99
202
  declare function worker_entry(hart_id: number, shared_mem: any, entry_pc: bigint): void;
100
203
 
@@ -103,27 +206,40 @@ type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Modul
103
206
  interface InitOutput {
104
207
  readonly memory: WebAssembly.Memory;
105
208
  readonly __wbg_wasmvm_free: (a: number, b: number) => void;
209
+ readonly __wbg_workerstate_free: (a: number, b: number) => void;
106
210
  readonly wasmvm_connect_webtransport: (a: number, b: number, c: number, d: number, e: number) => [number, number];
107
211
  readonly wasmvm_disconnect_network: (a: number) => void;
108
212
  readonly wasmvm_get_memory_usage: (a: number) => bigint;
109
213
  readonly wasmvm_get_output: (a: number) => number;
214
+ readonly wasmvm_get_shared_buffer: (a: number) => any;
110
215
  readonly wasmvm_halt_code: (a: number) => bigint;
111
216
  readonly wasmvm_input: (a: number, b: number) => void;
112
217
  readonly wasmvm_is_halted: (a: number) => number;
218
+ readonly wasmvm_is_smp: (a: number) => number;
113
219
  readonly wasmvm_load_disk: (a: number, b: number, c: number) => void;
114
220
  readonly wasmvm_network_status: (a: number) => number;
115
221
  readonly wasmvm_new: (a: number, b: number) => [number, number, number];
222
+ readonly wasmvm_new_with_harts: (a: number, b: number, c: number) => [number, number, number];
223
+ readonly wasmvm_num_harts: (a: number) => number;
116
224
  readonly wasmvm_print_banner: (a: number) => void;
117
225
  readonly wasmvm_print_status: (a: number, b: number, c: number) => void;
226
+ readonly wasmvm_start_workers: (a: number, b: number, c: number) => [number, number];
118
227
  readonly wasmvm_step: (a: number) => number;
119
228
  readonly wasmvm_step_n: (a: number, b: number) => number;
229
+ readonly wasmvm_terminate_workers: (a: number) => void;
120
230
  readonly wasmvm_uart_output_pending: (a: number) => number;
231
+ readonly worker_check_interrupts: (a: number, b: any) => bigint;
121
232
  readonly worker_entry: (a: number, b: any, c: bigint) => void;
122
- readonly wasm_bindgen__convert__closures_____invoke__hb4c5b5d7ccdc8795: (a: number, b: number) => void;
123
- readonly wasm_bindgen__closure__destroy__h3128a8e596085273: (a: number, b: number) => void;
124
- readonly wasm_bindgen__convert__closures_____invoke__hca46242f02098063: (a: number, b: number) => void;
233
+ readonly workerstate_hart_id: (a: number) => number;
234
+ readonly workerstate_new: (a: number, b: any, c: bigint) => number;
235
+ readonly workerstate_step_batch: (a: number, b: number) => number;
236
+ readonly workerstate_step_count: (a: number) => bigint;
125
237
  readonly wasm_bindgen__convert__closures_____invoke__h39d3e89751b07765: (a: number, b: number, c: any) => void;
126
238
  readonly wasm_bindgen__closure__destroy__hf225e18fc5ab9bc1: (a: number, b: number) => void;
239
+ readonly wasm_bindgen__convert__closures_____invoke__h67573e759d30b522: (a: number, b: number) => void;
240
+ readonly wasm_bindgen__closure__destroy__h1c929db64e64ab27: (a: number, b: number) => void;
241
+ readonly wasm_bindgen__convert__closures_____invoke__hb59a63b35a5a8674: (a: number, b: number, c: any) => void;
242
+ readonly wasm_bindgen__convert__closures_____invoke__hf580618779cd5844: (a: number, b: number) => void;
127
243
  readonly __wbindgen_malloc: (a: number, b: number) => number;
128
244
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
129
245
  readonly __wbindgen_exn_store: (a: number) => void;
@@ -163,12 +279,65 @@ declare const __pkg_riscv_vm_NetworkStatus: typeof NetworkStatus;
163
279
  type __pkg_riscv_vm_SyncInitInput = SyncInitInput;
164
280
  type __pkg_riscv_vm_WasmVm = WasmVm;
165
281
  declare const __pkg_riscv_vm_WasmVm: typeof WasmVm;
282
+ type __pkg_riscv_vm_WorkerState = WorkerState;
283
+ declare const __pkg_riscv_vm_WorkerState: typeof WorkerState;
284
+ type __pkg_riscv_vm_WorkerStepResult = WorkerStepResult;
285
+ declare const __pkg_riscv_vm_WorkerStepResult: typeof WorkerStepResult;
166
286
  declare const __pkg_riscv_vm_initSync: typeof initSync;
287
+ declare const __pkg_riscv_vm_worker_check_interrupts: typeof worker_check_interrupts;
167
288
  declare const __pkg_riscv_vm_worker_entry: typeof worker_entry;
168
289
  declare namespace __pkg_riscv_vm {
169
- export { type __pkg_riscv_vm_InitInput as InitInput, type __pkg_riscv_vm_InitOutput as InitOutput, __pkg_riscv_vm_NetworkStatus as NetworkStatus, type __pkg_riscv_vm_SyncInitInput as SyncInitInput, __pkg_riscv_vm_WasmVm as WasmVm, __wbg_init as default, __pkg_riscv_vm_initSync as initSync, __pkg_riscv_vm_worker_entry as worker_entry };
290
+ export { type __pkg_riscv_vm_InitInput as InitInput, type __pkg_riscv_vm_InitOutput as InitOutput, __pkg_riscv_vm_NetworkStatus as NetworkStatus, type __pkg_riscv_vm_SyncInitInput as SyncInitInput, __pkg_riscv_vm_WasmVm as WasmVm, __pkg_riscv_vm_WorkerState as WorkerState, __pkg_riscv_vm_WorkerStepResult as WorkerStepResult, __wbg_init as default, __pkg_riscv_vm_initSync as initSync, __pkg_riscv_vm_worker_check_interrupts as worker_check_interrupts, __pkg_riscv_vm_worker_entry as worker_entry };
170
291
  }
171
292
 
293
+ /**
294
+ * Worker utility types and functions.
295
+ *
296
+ * This module contains only types and side-effect-free utility functions
297
+ * that can be safely imported in Node.js or browser environments.
298
+ *
299
+ * The actual worker entry point is in worker.ts (browser-only).
300
+ */
301
+ /** Message sent from main thread to initialize the worker */
302
+ interface WorkerInitMessage {
303
+ hartId: number;
304
+ /** SharedArrayBuffer containing control + CLINT + DRAM */
305
+ sharedMem: SharedArrayBuffer;
306
+ entryPc: number;
307
+ }
308
+ /** Message sent when worker is ready to execute */
309
+ interface WorkerReadyMessage {
310
+ type: "ready";
311
+ hartId: number;
312
+ }
313
+ /** Message sent when worker has halted */
314
+ interface WorkerHaltedMessage {
315
+ type: "halted";
316
+ hartId: number;
317
+ stepCount?: number;
318
+ }
319
+ /** Message sent when an error occurs */
320
+ interface WorkerErrorMessage {
321
+ type: "error";
322
+ hartId?: number;
323
+ error: string;
324
+ }
325
+ type WorkerOutboundMessage = WorkerReadyMessage | WorkerHaltedMessage | WorkerErrorMessage;
326
+ /**
327
+ * Check if halt has been requested in the shared control region.
328
+ * This can be used for JS-side polling if needed.
329
+ */
330
+ declare function isHaltRequested(sharedMem: SharedArrayBuffer): boolean;
331
+ /**
332
+ * Request halt by setting the flag in shared memory.
333
+ * This can be called from any thread.
334
+ */
335
+ declare function requestHalt(sharedMem: SharedArrayBuffer): void;
336
+ /**
337
+ * Check if VM has halted.
338
+ */
339
+ declare function isHalted(sharedMem: SharedArrayBuffer): boolean;
340
+
172
341
  declare function WasmInternal(): Promise<typeof __pkg_riscv_vm>;
173
342
 
174
343
  interface VmOptions {
@@ -178,7 +347,10 @@ interface VmOptions {
178
347
  workerScript?: string;
179
348
  }
180
349
  /**
181
- * Create a VM instance and optionally start workers for multi-hart execution.
350
+ * Create a VM instance with optional SMP support.
351
+ *
352
+ * If SharedArrayBuffer is available (requires COOP/COEP headers), the VM
353
+ * will run in true parallel mode with Web Workers for secondary harts.
182
354
  *
183
355
  * @param kernelData - ELF kernel binary
184
356
  * @param options - VM configuration options
@@ -188,6 +360,9 @@ declare function createVM(kernelData: Uint8Array, options?: VmOptions): Promise<
188
360
  /**
189
361
  * Run the VM with an output callback for UART data.
190
362
  *
363
+ * This function manages the main execution loop, stepping hart 0 on the
364
+ * main thread. Secondary harts (if any) run in Web Workers.
365
+ *
191
366
  * @param vm - WasmVm instance
192
367
  * @param onOutput - Callback for each character output
193
368
  * @param options - Run options
@@ -198,6 +373,7 @@ declare function runVM(vm: WasmVm, onOutput: (char: string) => void, options?: {
198
373
  }): () => void;
199
374
  interface SharedMemorySupport {
200
375
  supported: boolean;
376
+ crossOriginIsolated: boolean;
201
377
  message: string;
202
378
  }
203
379
  /**
@@ -211,5 +387,41 @@ declare function checkSharedMemorySupport(): SharedMemorySupport;
211
387
  * Check if the page is cross-origin isolated (required for SharedArrayBuffer).
212
388
  */
213
389
  declare function isCrossOriginIsolated(): boolean;
390
+ /**
391
+ * Headers required for SharedArrayBuffer support.
392
+ *
393
+ * For Vite dev server, add to vite.config.ts:
394
+ * ```ts
395
+ * server: {
396
+ * headers: {
397
+ * "Cross-Origin-Opener-Policy": "same-origin",
398
+ * "Cross-Origin-Embedder-Policy": "require-corp",
399
+ * },
400
+ * },
401
+ * ```
402
+ *
403
+ * For production, configure your web server to add these headers.
404
+ */
405
+ declare const REQUIRED_HEADERS: {
406
+ readonly "Cross-Origin-Opener-Policy": "same-origin";
407
+ readonly "Cross-Origin-Embedder-Policy": "require-corp";
408
+ };
409
+ /**
410
+ * Manually create and manage workers for advanced use cases.
411
+ *
412
+ * Most users should use createVM() which handles workers automatically.
413
+ */
414
+ interface WorkerManager {
415
+ /** Start a worker for a specific hart */
416
+ startWorker(hartId: number, sharedMem: SharedArrayBuffer, entryPc: number, workerScript?: string): Worker;
417
+ /** Terminate all workers */
418
+ terminateAll(): void;
419
+ /** Get number of active workers */
420
+ count(): number;
421
+ }
422
+ /**
423
+ * Create a worker manager for manual worker control.
424
+ */
425
+ declare function createWorkerManager(): WorkerManager;
214
426
 
215
- export { NetworkStatus, type SharedMemorySupport, type VmOptions, WasmInternal, WasmVm, checkSharedMemorySupport, createVM, isCrossOriginIsolated, runVM };
427
+ export { NetworkStatus, REQUIRED_HEADERS, type SharedMemorySupport, type VmOptions, WasmInternal, WasmVm, type WorkerErrorMessage, type WorkerHaltedMessage, type WorkerInitMessage, type WorkerManager, type WorkerOutboundMessage, type WorkerReadyMessage, checkSharedMemorySupport, createVM, createWorkerManager, isCrossOriginIsolated, isHaltRequested, isHalted, requestHalt, runVM };