@celox-sim/celox 0.1.13 → 0.1.15

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/src/e2e.bench.ts CHANGED
@@ -10,21 +10,21 @@
10
10
  */
11
11
 
12
12
  import { readFileSync } from "node:fs";
13
- import { resolve, dirname } from "node:path";
13
+ import { dirname, resolve } from "node:path";
14
14
  import { fileURLToPath } from "node:url";
15
- import { bench, describe, afterAll } from "vitest";
16
- import { Simulator } from "./simulator.js";
15
+ import { afterAll, bench, describe } from "vitest";
16
+ import { createSimulatorBridge, loadNativeAddon } from "./napi-helpers.js";
17
17
  import { Simulation } from "./simulation.js";
18
- import type { ModuleDefinition, SimulationTimeoutError } from "./types.js";
19
- import {
20
- loadNativeAddon,
21
- createSimulatorBridge,
22
- } from "./napi-helpers.js";
18
+ import { Simulator } from "./simulator.js";
19
+ import type { ModuleDefinition } from "./types.js";
23
20
 
24
21
  const __benchDir = dirname(fileURLToPath(import.meta.url));
25
- const VERYL_STD = resolve(__benchDir, "../../../deps/veryl/crates/std/veryl/src");
22
+ const VERYL_STD = resolve(
23
+ __benchDir,
24
+ "../../../deps/veryl/crates/std/veryl/src",
25
+ );
26
26
  function readVeryl(...parts: string[]): string {
27
- return readFileSync(resolve(VERYL_STD, ...parts), "utf8");
27
+ return readFileSync(resolve(VERYL_STD, ...parts), "utf8");
28
28
  }
29
29
 
30
30
  const CODE = `
@@ -48,111 +48,111 @@ const CODE = `
48
48
  `;
49
49
 
50
50
  interface TopPorts {
51
- rst: bigint;
52
- readonly cnt: { at(i: number): bigint; readonly length: number };
51
+ rst: bigint;
52
+ readonly cnt: { at(i: number): bigint; readonly length: number };
53
53
  }
54
54
 
55
55
  describe("simulation", () => {
56
- bench(
57
- "simulation_build_top_n1000",
58
- () => {
59
- const sim = Simulator.fromSource<TopPorts>(CODE, "Top");
60
- sim.dispose();
61
- },
62
- { iterations: 3, time: 0 },
63
- );
64
-
65
- const sim = Simulator.fromSource<TopPorts>(CODE, "Top");
66
-
67
- // Reset sequence
68
- sim.dut.rst = 1n;
69
- sim.tick();
70
- sim.dut.rst = 0n;
71
- sim.tick();
72
-
73
- afterAll(() => {
74
- sim.dispose();
75
- });
76
-
77
- bench("simulation_tick_top_n1000_x1", () => {
78
- sim.tick();
79
- });
80
-
81
- bench(
82
- "simulation_tick_top_n1000_x1000000",
83
- () => {
84
- for (let i = 0; i < 1_000_000; i++) {
85
- sim.tick();
86
- }
87
- },
88
- { iterations: 3, time: 0 },
89
- );
90
-
91
- // Testbench pattern: write input + tick + read back
92
- bench("testbench_tick_top_n1000_x1", () => {
93
- sim.dut.rst = 0n;
94
- sim.tick();
95
- // biome-ignore lint: read to measure full testbench cycle
96
- sim.dut.rst;
97
- });
98
-
99
- bench(
100
- "testbench_tick_top_n1000_x1000000",
101
- () => {
102
- for (let i = 0; i < 1_000_000; i++) {
103
- sim.dut.rst = 0n;
104
- sim.tick();
105
- // biome-ignore lint: read to measure full testbench cycle
106
- sim.dut.rst;
107
- }
108
- },
109
- { iterations: 3, time: 0 },
110
- );
111
-
112
- // Array access via .at() — use ModuleDefinition with arrayDims
113
- const addon = loadNativeAddon();
114
- const TopModule: ModuleDefinition<TopPorts> = {
115
- __celox_module: true,
116
- name: "Top",
117
- source: CODE,
118
- ports: {
119
- clk: { direction: "input", type: "clock", width: 1 },
120
- rst: { direction: "input", type: "reset", width: 1 },
121
- cnt: { direction: "output", type: "logic", width: 32, arrayDims: [1000] },
122
- },
123
- events: ["clk"],
124
- };
125
- const simArr = Simulator.create<TopPorts>(TopModule, {
126
- __nativeCreate: createSimulatorBridge(addon),
127
- });
128
- simArr.dut.rst = 1n;
129
- simArr.tick();
130
- simArr.dut.rst = 0n;
131
- simArr.tick();
132
-
133
- afterAll(() => {
134
- simArr.dispose();
135
- });
136
-
137
- bench("testbench_array_tick_top_n1000_x1", () => {
138
- simArr.dut.rst = 0n;
139
- simArr.tick();
140
- // biome-ignore lint: read array element to measure .at() overhead
141
- simArr.dut.cnt.at(0);
142
- });
143
-
144
- bench(
145
- "testbench_array_tick_top_n1000_x1000000",
146
- () => {
147
- for (let i = 0; i < 1_000_000; i++) {
148
- simArr.dut.rst = 0n;
149
- simArr.tick();
150
- // biome-ignore lint: read array element to measure .at() overhead
151
- simArr.dut.cnt.at(0);
152
- }
153
- },
154
- { iterations: 3, time: 0 },
155
- );
56
+ bench(
57
+ "simulation_build_top_n1000",
58
+ () => {
59
+ const sim = Simulator.fromSource<TopPorts>(CODE, "Top");
60
+ sim.dispose();
61
+ },
62
+ { iterations: 3, time: 0 },
63
+ );
64
+
65
+ const sim = Simulator.fromSource<TopPorts>(CODE, "Top");
66
+
67
+ // Reset sequence
68
+ sim.dut.rst = 1n;
69
+ sim.tick();
70
+ sim.dut.rst = 0n;
71
+ sim.tick();
72
+
73
+ afterAll(() => {
74
+ sim.dispose();
75
+ });
76
+
77
+ bench("simulation_tick_top_n1000_x1", () => {
78
+ sim.tick();
79
+ });
80
+
81
+ bench(
82
+ "simulation_tick_top_n1000_x1000000",
83
+ () => {
84
+ for (let i = 0; i < 1_000_000; i++) {
85
+ sim.tick();
86
+ }
87
+ },
88
+ { iterations: 3, time: 0 },
89
+ );
90
+
91
+ // Testbench pattern: write input + tick + read back
92
+ bench("testbench_tick_top_n1000_x1", () => {
93
+ sim.dut.rst = 0n;
94
+ sim.tick();
95
+ //read to measure full testbench cycle
96
+ sim.dut.rst;
97
+ });
98
+
99
+ bench(
100
+ "testbench_tick_top_n1000_x1000000",
101
+ () => {
102
+ for (let i = 0; i < 1_000_000; i++) {
103
+ sim.dut.rst = 0n;
104
+ sim.tick();
105
+ //read to measure full testbench cycle
106
+ sim.dut.rst;
107
+ }
108
+ },
109
+ { iterations: 3, time: 0 },
110
+ );
111
+
112
+ // Array access via .at() — use ModuleDefinition with arrayDims
113
+ const addon = loadNativeAddon();
114
+ const TopModule: ModuleDefinition<TopPorts> = {
115
+ __celox_module: true,
116
+ name: "Top",
117
+ sources: [{ path: "bench.veryl", content: CODE }],
118
+ ports: {
119
+ clk: { direction: "input", type: "clock", width: 1 },
120
+ rst: { direction: "input", type: "reset", width: 1 },
121
+ cnt: { direction: "output", type: "logic", width: 32, arrayDims: [1000] },
122
+ },
123
+ events: ["clk"],
124
+ };
125
+ const simArr = Simulator.create<TopPorts>(TopModule, {
126
+ __nativeCreate: createSimulatorBridge(addon),
127
+ });
128
+ simArr.dut.rst = 1n;
129
+ simArr.tick();
130
+ simArr.dut.rst = 0n;
131
+ simArr.tick();
132
+
133
+ afterAll(() => {
134
+ simArr.dispose();
135
+ });
136
+
137
+ bench("testbench_array_tick_top_n1000_x1", () => {
138
+ simArr.dut.rst = 0n;
139
+ simArr.tick();
140
+ //read array element to measure .at() overhead
141
+ simArr.dut.cnt.at(0);
142
+ });
143
+
144
+ bench(
145
+ "testbench_array_tick_top_n1000_x1000000",
146
+ () => {
147
+ for (let i = 0; i < 1_000_000; i++) {
148
+ simArr.dut.rst = 0n;
149
+ simArr.tick();
150
+ //read array element to measure .at() overhead
151
+ simArr.dut.cnt.at(0);
152
+ }
153
+ },
154
+ { iterations: 3, time: 0 },
155
+ );
156
156
  });
157
157
 
158
158
  /**
@@ -162,45 +162,45 @@ describe("simulation", () => {
162
162
  * scheduling overhead of the time-based API.
163
163
  */
164
164
  describe("overhead", () => {
165
- // Simulator.tick — same as Rust simulator_tick_x10000
166
- const simTick = Simulator.fromSource<TopPorts>(CODE, "Top");
167
- simTick.dut.rst = 1n;
168
- simTick.tick();
169
- simTick.dut.rst = 0n;
170
- simTick.tick();
171
-
172
- afterAll(() => {
173
- simTick.dispose();
174
- });
175
-
176
- bench(
177
- "simulator_tick_x10000",
178
- () => {
179
- for (let i = 0; i < 10_000; i++) {
180
- simTick.tick();
181
- }
182
- },
183
- { iterations: 3, time: 0 },
184
- );
185
-
186
- // Simulation.step — same as Rust simulation_step_x20000
187
- const simStep = Simulation.fromSource<TopPorts>(CODE, "Top");
188
- simStep.addClock("clk", { period: 10 });
189
-
190
- afterAll(() => {
191
- simStep.dispose();
192
- });
193
-
194
- bench(
195
- "simulation_step_x20000",
196
- () => {
197
- // 20000 steps = 10000 cycles (rising + falling)
198
- for (let i = 0; i < 20_000; i++) {
199
- simStep.step();
200
- }
201
- },
202
- { iterations: 3, time: 0 },
203
- );
165
+ // Simulator.tick — same as Rust simulator_tick_x10000
166
+ const simTick = Simulator.fromSource<TopPorts>(CODE, "Top");
167
+ simTick.dut.rst = 1n;
168
+ simTick.tick();
169
+ simTick.dut.rst = 0n;
170
+ simTick.tick();
171
+
172
+ afterAll(() => {
173
+ simTick.dispose();
174
+ });
175
+
176
+ bench(
177
+ "simulator_tick_x10000",
178
+ () => {
179
+ for (let i = 0; i < 10_000; i++) {
180
+ simTick.tick();
181
+ }
182
+ },
183
+ { iterations: 3, time: 0 },
184
+ );
185
+
186
+ // Simulation.step — same as Rust simulation_step_x20000
187
+ const simStep = Simulation.fromSource<TopPorts>(CODE, "Top");
188
+ simStep.addClock("clk", { period: 10 });
189
+
190
+ afterAll(() => {
191
+ simStep.dispose();
192
+ });
193
+
194
+ bench(
195
+ "simulation_step_x20000",
196
+ () => {
197
+ // 20000 steps = 10000 cycles (rising + falling)
198
+ for (let i = 0; i < 20_000; i++) {
199
+ simStep.step();
200
+ }
201
+ },
202
+ { iterations: 3, time: 0 },
203
+ );
204
204
  });
205
205
 
206
206
  /**
@@ -208,44 +208,44 @@ describe("overhead", () => {
208
208
  * above but uses the Simulation API instead of Simulator.
209
209
  */
210
210
  describe("simulation-time-based", () => {
211
- bench(
212
- "simulation_time_build_top_n1000",
213
- () => {
214
- const sim = Simulation.fromSource<TopPorts>(CODE, "Top");
215
- sim.dispose();
216
- },
217
- { iterations: 3, time: 0 },
218
- );
219
-
220
- const sim = Simulation.fromSource<TopPorts>(CODE, "Top");
221
- sim.addClock("clk", { period: 10 });
222
-
223
- afterAll(() => {
224
- sim.dispose();
225
- });
226
-
227
- bench("simulation_time_step_x1", () => {
228
- sim.step();
229
- });
230
-
231
- bench(
232
- "simulation_time_step_x1000000",
233
- () => {
234
- for (let i = 0; i < 1_000_000; i++) {
235
- sim.step();
236
- }
237
- },
238
- { iterations: 3, time: 0 },
239
- );
240
-
241
- bench(
242
- "simulation_time_runUntil_1000000",
243
- () => {
244
- const base = sim.time();
245
- sim.runUntil(base + 1_000_000);
246
- },
247
- { iterations: 3, time: 0 },
248
- );
211
+ bench(
212
+ "simulation_time_build_top_n1000",
213
+ () => {
214
+ const sim = Simulation.fromSource<TopPorts>(CODE, "Top");
215
+ sim.dispose();
216
+ },
217
+ { iterations: 3, time: 0 },
218
+ );
219
+
220
+ const sim = Simulation.fromSource<TopPorts>(CODE, "Top");
221
+ sim.addClock("clk", { period: 10 });
222
+
223
+ afterAll(() => {
224
+ sim.dispose();
225
+ });
226
+
227
+ bench("simulation_time_step_x1", () => {
228
+ sim.step();
229
+ });
230
+
231
+ bench(
232
+ "simulation_time_step_x1000000",
233
+ () => {
234
+ for (let i = 0; i < 1_000_000; i++) {
235
+ sim.step();
236
+ }
237
+ },
238
+ { iterations: 3, time: 0 },
239
+ );
240
+
241
+ bench(
242
+ "simulation_time_runUntil_1000000",
243
+ () => {
244
+ const base = sim.time();
245
+ sim.runUntil(base + 1_000_000);
246
+ },
247
+ { iterations: 3, time: 0 },
248
+ );
249
249
  });
250
250
 
251
251
  /**
@@ -255,7 +255,7 @@ describe("simulation-time-based", () => {
255
255
  * maxSteps guard to measure overhead.
256
256
  */
257
257
  describe("testbench-helpers", () => {
258
- const COUNTER_CODE = `
258
+ const COUNTER_CODE = `
259
259
  module Counter (
260
260
  clk: input clock,
261
261
  rst: input reset,
@@ -278,71 +278,71 @@ describe("testbench-helpers", () => {
278
278
  }
279
279
  `;
280
280
 
281
- interface CounterPorts {
282
- rst: bigint;
283
- en: bigint;
284
- readonly count: bigint;
285
- }
286
-
287
- // waitForCycles benchmark
288
- const simWait = Simulation.fromSource<CounterPorts>(COUNTER_CODE, "Counter");
289
- simWait.addClock("clk", { period: 10 });
290
- simWait.dut.rst = 1n;
291
- simWait.runUntil(20);
292
- simWait.dut.rst = 0n;
293
- simWait.dut.en = 1n;
294
-
295
- afterAll(() => {
296
- simWait.dispose();
297
- });
298
-
299
- bench(
300
- "waitForCycles_x1000",
301
- () => {
302
- simWait.waitForCycles("clk", 1000);
303
- },
304
- { iterations: 3, time: 0 },
305
- );
306
-
307
- bench(
308
- "manual_step_loop_x2000",
309
- () => {
310
- for (let i = 0; i < 2000; i++) {
311
- simWait.step();
312
- }
313
- },
314
- { iterations: 3, time: 0 },
315
- );
316
-
317
- // runUntil: fast Rust path vs guarded TS path
318
- const simRun = Simulation.fromSource<CounterPorts>(COUNTER_CODE, "Counter");
319
- simRun.addClock("clk", { period: 10 });
320
- simRun.dut.rst = 1n;
321
- simRun.runUntil(20);
322
- simRun.dut.rst = 0n;
323
- simRun.dut.en = 1n;
324
-
325
- afterAll(() => {
326
- simRun.dispose();
327
- });
328
-
329
- bench(
330
- "runUntil_fast_path_100000",
331
- () => {
332
- const base = simRun.time();
333
- simRun.runUntil(base + 100_000);
334
- },
335
- { iterations: 3, time: 0 },
336
- );
337
-
338
- bench(
339
- "runUntil_guarded_100000",
340
- () => {
341
- const base = simRun.time();
342
- simRun.runUntil(base + 100_000, { maxSteps: 1_000_000 });
343
- },
344
- { iterations: 3, time: 0 },
345
- );
281
+ interface CounterPorts {
282
+ rst: bigint;
283
+ en: bigint;
284
+ readonly count: bigint;
285
+ }
286
+
287
+ // waitForCycles benchmark
288
+ const simWait = Simulation.fromSource<CounterPorts>(COUNTER_CODE, "Counter");
289
+ simWait.addClock("clk", { period: 10 });
290
+ simWait.dut.rst = 1n;
291
+ simWait.runUntil(20);
292
+ simWait.dut.rst = 0n;
293
+ simWait.dut.en = 1n;
294
+
295
+ afterAll(() => {
296
+ simWait.dispose();
297
+ });
298
+
299
+ bench(
300
+ "waitForCycles_x1000",
301
+ () => {
302
+ simWait.waitForCycles("clk", 1000);
303
+ },
304
+ { iterations: 3, time: 0 },
305
+ );
306
+
307
+ bench(
308
+ "manual_step_loop_x2000",
309
+ () => {
310
+ for (let i = 0; i < 2000; i++) {
311
+ simWait.step();
312
+ }
313
+ },
314
+ { iterations: 3, time: 0 },
315
+ );
316
+
317
+ // runUntil: fast Rust path vs guarded TS path
318
+ const simRun = Simulation.fromSource<CounterPorts>(COUNTER_CODE, "Counter");
319
+ simRun.addClock("clk", { period: 10 });
320
+ simRun.dut.rst = 1n;
321
+ simRun.runUntil(20);
322
+ simRun.dut.rst = 0n;
323
+ simRun.dut.en = 1n;
324
+
325
+ afterAll(() => {
326
+ simRun.dispose();
327
+ });
328
+
329
+ bench(
330
+ "runUntil_fast_path_100000",
331
+ () => {
332
+ const base = simRun.time();
333
+ simRun.runUntil(base + 100_000);
334
+ },
335
+ { iterations: 3, time: 0 },
336
+ );
337
+
338
+ bench(
339
+ "runUntil_guarded_100000",
340
+ () => {
341
+ const base = simRun.time();
342
+ simRun.runUntil(base + 100_000, { maxSteps: 1_000_000 });
343
+ },
344
+ { iterations: 3, time: 0 },
345
+ );
346
346
  });
347
347
 
348
348
  /**
@@ -351,64 +351,64 @@ describe("testbench-helpers", () => {
351
351
  * Compares build time and tick performance with and without optimization.
352
352
  */
353
353
  describe("optimize-flag", () => {
354
- bench(
355
- "build_without_optimize",
356
- () => {
357
- const sim = Simulator.fromSource<TopPorts>(CODE, "Top");
358
- sim.dispose();
359
- },
360
- { iterations: 3, time: 0 },
361
- );
362
-
363
- bench(
364
- "build_with_optimize",
365
- () => {
366
- const sim = Simulator.fromSource<TopPorts>(CODE, "Top", {
367
- optimize: true,
368
- });
369
- sim.dispose();
370
- },
371
- { iterations: 3, time: 0 },
372
- );
373
-
374
- const simNoOpt = Simulator.fromSource<TopPorts>(CODE, "Top");
375
- simNoOpt.dut.rst = 1n;
376
- simNoOpt.tick();
377
- simNoOpt.dut.rst = 0n;
378
- simNoOpt.tick();
379
-
380
- const simOpt = Simulator.fromSource<TopPorts>(CODE, "Top", {
381
- optimize: true,
382
- });
383
- simOpt.dut.rst = 1n;
384
- simOpt.tick();
385
- simOpt.dut.rst = 0n;
386
- simOpt.tick();
387
-
388
- afterAll(() => {
389
- simNoOpt.dispose();
390
- simOpt.dispose();
391
- });
392
-
393
- bench(
394
- "tick_x10000_without_optimize",
395
- () => {
396
- for (let i = 0; i < 10_000; i++) {
397
- simNoOpt.tick();
398
- }
399
- },
400
- { iterations: 3, time: 0 },
401
- );
402
-
403
- bench(
404
- "tick_x10000_with_optimize",
405
- () => {
406
- for (let i = 0; i < 10_000; i++) {
407
- simOpt.tick();
408
- }
409
- },
410
- { iterations: 3, time: 0 },
411
- );
354
+ bench(
355
+ "build_without_optimize",
356
+ () => {
357
+ const sim = Simulator.fromSource<TopPorts>(CODE, "Top");
358
+ sim.dispose();
359
+ },
360
+ { iterations: 3, time: 0 },
361
+ );
362
+
363
+ bench(
364
+ "build_with_optimize",
365
+ () => {
366
+ const sim = Simulator.fromSource<TopPorts>(CODE, "Top", {
367
+ optimize: true,
368
+ });
369
+ sim.dispose();
370
+ },
371
+ { iterations: 3, time: 0 },
372
+ );
373
+
374
+ const simNoOpt = Simulator.fromSource<TopPorts>(CODE, "Top");
375
+ simNoOpt.dut.rst = 1n;
376
+ simNoOpt.tick();
377
+ simNoOpt.dut.rst = 0n;
378
+ simNoOpt.tick();
379
+
380
+ const simOpt = Simulator.fromSource<TopPorts>(CODE, "Top", {
381
+ optimize: true,
382
+ });
383
+ simOpt.dut.rst = 1n;
384
+ simOpt.tick();
385
+ simOpt.dut.rst = 0n;
386
+ simOpt.tick();
387
+
388
+ afterAll(() => {
389
+ simNoOpt.dispose();
390
+ simOpt.dispose();
391
+ });
392
+
393
+ bench(
394
+ "tick_x10000_without_optimize",
395
+ () => {
396
+ for (let i = 0; i < 10_000; i++) {
397
+ simNoOpt.tick();
398
+ }
399
+ },
400
+ { iterations: 3, time: 0 },
401
+ );
402
+
403
+ bench(
404
+ "tick_x10000_with_optimize",
405
+ () => {
406
+ for (let i = 0; i < 10_000; i++) {
407
+ simOpt.tick();
408
+ }
409
+ },
410
+ { iterations: 3, time: 0 },
411
+ );
412
412
  });
413
413
 
414
414
  // ────────────────────────────────────────────────────────────
@@ -418,9 +418,9 @@ describe("optimize-flag", () => {
418
418
  // --- Linear SEC (P=6): Hamming encoder/decoder, combinational ---
419
419
 
420
420
  const LINEAR_SEC_SRC =
421
- readVeryl("coding/linear_sec_encoder.veryl") +
422
- readVeryl("coding/linear_sec_decoder.veryl") +
423
- `
421
+ readVeryl("coding/linear_sec_encoder.veryl") +
422
+ readVeryl("coding/linear_sec_decoder.veryl") +
423
+ `
424
424
  module Top #(
425
425
  param P: u32 = 6,
426
426
  const K: u32 = (1 << P) - 1,
@@ -441,67 +441,67 @@ module Top #(
441
441
  `;
442
442
 
443
443
  interface LinearSecPorts {
444
- i_word: bigint;
445
- readonly o_codeword: bigint;
446
- readonly o_word: bigint;
447
- readonly o_corrected: bigint;
444
+ i_word: bigint;
445
+ readonly o_codeword: bigint;
446
+ readonly o_word: bigint;
447
+ readonly o_corrected: bigint;
448
448
  }
449
449
 
450
450
  describe("stdlib-linear-sec", () => {
451
- bench(
452
- "simulation_build_linear_sec_p6",
453
- () => {
454
- const sim = Simulator.fromSource<LinearSecPorts>(LINEAR_SEC_SRC, "Top");
455
- sim.dispose();
456
- },
457
- { iterations: 3, time: 0 },
458
- );
459
-
460
- const sim = Simulator.fromSource<LinearSecPorts>(LINEAR_SEC_SRC, "Top");
461
-
462
- afterAll(() => {
463
- sim.dispose();
464
- });
465
-
466
- let linearSecInput = 0n;
467
- bench("simulation_eval_linear_sec_p6_x1", () => {
468
- sim.dut.i_word = linearSecInput++;
469
- // biome-ignore lint: read to measure eval
470
- sim.dut.o_word;
471
- });
472
-
473
- bench(
474
- "simulation_eval_linear_sec_p6_x1000000",
475
- () => {
476
- let input = 0n;
477
- for (let i = 0; i < 1_000_000; i++) {
478
- sim.dut.i_word = input++;
479
- // biome-ignore lint: read to measure eval
480
- sim.dut.o_word;
481
- }
482
- },
483
- { iterations: 3, time: 0 },
484
- );
485
-
486
- bench(
487
- "testbench_eval_linear_sec_p6_x1000000",
488
- () => {
489
- let input = 0n;
490
- for (let i = 0; i < 1_000_000; i++) {
491
- sim.dut.i_word = input++;
492
- // biome-ignore lint: read corrected flag
493
- sim.dut.o_corrected;
494
- }
495
- },
496
- { iterations: 3, time: 0 },
497
- );
451
+ bench(
452
+ "simulation_build_linear_sec_p6",
453
+ () => {
454
+ const sim = Simulator.fromSource<LinearSecPorts>(LINEAR_SEC_SRC, "Top");
455
+ sim.dispose();
456
+ },
457
+ { iterations: 3, time: 0 },
458
+ );
459
+
460
+ const sim = Simulator.fromSource<LinearSecPorts>(LINEAR_SEC_SRC, "Top");
461
+
462
+ afterAll(() => {
463
+ sim.dispose();
464
+ });
465
+
466
+ let linearSecInput = 0n;
467
+ bench("simulation_eval_linear_sec_p6_x1", () => {
468
+ sim.dut.i_word = linearSecInput++;
469
+ //read to measure eval
470
+ sim.dut.o_word;
471
+ });
472
+
473
+ bench(
474
+ "simulation_eval_linear_sec_p6_x1000000",
475
+ () => {
476
+ let input = 0n;
477
+ for (let i = 0; i < 1_000_000; i++) {
478
+ sim.dut.i_word = input++;
479
+ //read to measure eval
480
+ sim.dut.o_word;
481
+ }
482
+ },
483
+ { iterations: 3, time: 0 },
484
+ );
485
+
486
+ bench(
487
+ "testbench_eval_linear_sec_p6_x1000000",
488
+ () => {
489
+ let input = 0n;
490
+ for (let i = 0; i < 1_000_000; i++) {
491
+ sim.dut.i_word = input++;
492
+ //read corrected flag
493
+ sim.dut.o_corrected;
494
+ }
495
+ },
496
+ { iterations: 3, time: 0 },
497
+ );
498
498
  });
499
499
 
500
500
  // --- Countones (W=64): recursive combinational popcount tree ---
501
501
 
502
502
  const COUNTONES_SRC =
503
- readVeryl("countones/countones.veryl") +
504
- `
503
+ readVeryl("countones/countones.veryl") +
504
+ `
505
505
  module Top (
506
506
  i_data: input logic<64>,
507
507
  o_ones: output logic<7>,
@@ -511,52 +511,52 @@ module Top (
511
511
  `;
512
512
 
513
513
  interface CountonesPorts {
514
- i_data: bigint;
515
- readonly o_ones: bigint;
514
+ i_data: bigint;
515
+ readonly o_ones: bigint;
516
516
  }
517
517
 
518
518
  describe("stdlib-countones", () => {
519
- bench(
520
- "simulation_build_countones_w64",
521
- () => {
522
- const sim = Simulator.fromSource<CountonesPorts>(COUNTONES_SRC, "Top");
523
- sim.dispose();
524
- },
525
- { iterations: 3, time: 0 },
526
- );
527
-
528
- const sim = Simulator.fromSource<CountonesPorts>(COUNTONES_SRC, "Top");
529
-
530
- afterAll(() => {
531
- sim.dispose();
532
- });
533
-
534
- let countonesInput = 0n;
535
- bench("simulation_eval_countones_w64_x1", () => {
536
- sim.dut.i_data = countonesInput++;
537
- // biome-ignore lint: read to measure eval
538
- sim.dut.o_ones;
539
- });
540
-
541
- bench(
542
- "simulation_eval_countones_w64_x1000000",
543
- () => {
544
- let input = 0n;
545
- for (let i = 0; i < 1_000_000; i++) {
546
- sim.dut.i_data = input++;
547
- // biome-ignore lint: read to measure eval
548
- sim.dut.o_ones;
549
- }
550
- },
551
- { iterations: 3, time: 0 },
552
- );
519
+ bench(
520
+ "simulation_build_countones_w64",
521
+ () => {
522
+ const sim = Simulator.fromSource<CountonesPorts>(COUNTONES_SRC, "Top");
523
+ sim.dispose();
524
+ },
525
+ { iterations: 3, time: 0 },
526
+ );
527
+
528
+ const sim = Simulator.fromSource<CountonesPorts>(COUNTONES_SRC, "Top");
529
+
530
+ afterAll(() => {
531
+ sim.dispose();
532
+ });
533
+
534
+ let countonesInput = 0n;
535
+ bench("simulation_eval_countones_w64_x1", () => {
536
+ sim.dut.i_data = countonesInput++;
537
+ //read to measure eval
538
+ sim.dut.o_ones;
539
+ });
540
+
541
+ bench(
542
+ "simulation_eval_countones_w64_x1000000",
543
+ () => {
544
+ let input = 0n;
545
+ for (let i = 0; i < 1_000_000; i++) {
546
+ sim.dut.i_data = input++;
547
+ //read to measure eval
548
+ sim.dut.o_ones;
549
+ }
550
+ },
551
+ { iterations: 3, time: 0 },
552
+ );
553
553
  });
554
554
 
555
555
  // --- std::counter (WIDTH=32): sequential up-counter ---
556
556
 
557
557
  const STD_COUNTER_SRC =
558
- readVeryl("counter/counter.veryl") +
559
- `
558
+ readVeryl("counter/counter.veryl") +
559
+ `
560
560
  module Top (
561
561
  clk : input clock,
562
562
  rst : input reset,
@@ -579,67 +579,67 @@ module Top (
579
579
  `;
580
580
 
581
581
  interface StdCounterPorts {
582
- rst: bigint;
583
- i_up: bigint;
584
- readonly o_count: bigint;
582
+ rst: bigint;
583
+ i_up: bigint;
584
+ readonly o_count: bigint;
585
585
  }
586
586
 
587
587
  describe("stdlib-counter", () => {
588
- bench(
589
- "simulation_build_std_counter_w32",
590
- () => {
591
- const sim = Simulator.fromSource<StdCounterPorts>(STD_COUNTER_SRC, "Top");
592
- sim.dispose();
593
- },
594
- { iterations: 3, time: 0 },
595
- );
596
-
597
- const sim = Simulator.fromSource<StdCounterPorts>(STD_COUNTER_SRC, "Top");
598
- sim.dut.rst = 1n;
599
- sim.dut.i_up = 0n;
600
- sim.tick();
601
- sim.dut.rst = 0n;
602
- sim.dut.i_up = 1n;
603
- sim.tick();
604
-
605
- afterAll(() => {
606
- sim.dispose();
607
- });
608
-
609
- bench("simulation_tick_std_counter_w32_x1", () => {
610
- sim.tick();
611
- });
612
-
613
- bench(
614
- "simulation_tick_std_counter_w32_x1000000",
615
- () => {
616
- for (let i = 0; i < 1_000_000; i++) {
617
- sim.tick();
618
- }
619
- },
620
- { iterations: 3, time: 0 },
621
- );
622
-
623
- bench(
624
- "testbench_tick_std_counter_w32_x1000000",
625
- () => {
626
- for (let i = 0; i < 1_000_000; i++) {
627
- sim.tick();
628
- // biome-ignore lint: read to measure testbench cycle
629
- sim.dut.o_count;
630
- }
631
- },
632
- { iterations: 3, time: 0 },
633
- );
588
+ bench(
589
+ "simulation_build_std_counter_w32",
590
+ () => {
591
+ const sim = Simulator.fromSource<StdCounterPorts>(STD_COUNTER_SRC, "Top");
592
+ sim.dispose();
593
+ },
594
+ { iterations: 3, time: 0 },
595
+ );
596
+
597
+ const sim = Simulator.fromSource<StdCounterPorts>(STD_COUNTER_SRC, "Top");
598
+ sim.dut.rst = 1n;
599
+ sim.dut.i_up = 0n;
600
+ sim.tick();
601
+ sim.dut.rst = 0n;
602
+ sim.dut.i_up = 1n;
603
+ sim.tick();
604
+
605
+ afterAll(() => {
606
+ sim.dispose();
607
+ });
608
+
609
+ bench("simulation_tick_std_counter_w32_x1", () => {
610
+ sim.tick();
611
+ });
612
+
613
+ bench(
614
+ "simulation_tick_std_counter_w32_x1000000",
615
+ () => {
616
+ for (let i = 0; i < 1_000_000; i++) {
617
+ sim.tick();
618
+ }
619
+ },
620
+ { iterations: 3, time: 0 },
621
+ );
622
+
623
+ bench(
624
+ "testbench_tick_std_counter_w32_x1000000",
625
+ () => {
626
+ for (let i = 0; i < 1_000_000; i++) {
627
+ sim.tick();
628
+ //read to measure testbench cycle
629
+ sim.dut.o_count;
630
+ }
631
+ },
632
+ { iterations: 3, time: 0 },
633
+ );
634
634
  });
635
635
 
636
636
  // --- std::gray_counter (WIDTH=32): Gray-encoded sequential counter ---
637
637
 
638
638
  const GRAY_COUNTER_SRC =
639
- readVeryl("counter/counter.veryl") +
640
- readVeryl("gray/gray_encoder.veryl") +
641
- readVeryl("gray/gray_counter.veryl") +
642
- `
639
+ readVeryl("counter/counter.veryl") +
640
+ readVeryl("gray/gray_encoder.veryl") +
641
+ readVeryl("gray/gray_counter.veryl") +
642
+ `
643
643
  module Top (
644
644
  clk : input clock,
645
645
  rst : input reset,
@@ -662,56 +662,59 @@ module Top (
662
662
  `;
663
663
 
664
664
  interface GrayCounterPorts {
665
- rst: bigint;
666
- i_up: bigint;
667
- readonly o_count: bigint;
665
+ rst: bigint;
666
+ i_up: bigint;
667
+ readonly o_count: bigint;
668
668
  }
669
669
 
670
670
  describe("stdlib-gray-counter", () => {
671
- bench(
672
- "simulation_build_gray_counter_w32",
673
- () => {
674
- const sim = Simulator.fromSource<GrayCounterPorts>(GRAY_COUNTER_SRC, "Top");
675
- sim.dispose();
676
- },
677
- { iterations: 3, time: 0 },
678
- );
679
-
680
- const sim = Simulator.fromSource<GrayCounterPorts>(GRAY_COUNTER_SRC, "Top");
681
- sim.dut.rst = 1n;
682
- sim.dut.i_up = 0n;
683
- sim.tick();
684
- sim.dut.rst = 0n;
685
- sim.dut.i_up = 1n;
686
- sim.tick();
687
-
688
- afterAll(() => {
689
- sim.dispose();
690
- });
691
-
692
- bench("simulation_tick_gray_counter_w32_x1", () => {
693
- sim.tick();
694
- });
695
-
696
- bench(
697
- "simulation_tick_gray_counter_w32_x1000000",
698
- () => {
699
- for (let i = 0; i < 1_000_000; i++) {
700
- sim.tick();
701
- }
702
- },
703
- { iterations: 3, time: 0 },
704
- );
705
-
706
- bench(
707
- "testbench_tick_gray_counter_w32_x1000000",
708
- () => {
709
- for (let i = 0; i < 1_000_000; i++) {
710
- sim.tick();
711
- // biome-ignore lint: read to measure testbench cycle
712
- sim.dut.o_count;
713
- }
714
- },
715
- { iterations: 3, time: 0 },
716
- );
671
+ bench(
672
+ "simulation_build_gray_counter_w32",
673
+ () => {
674
+ const sim = Simulator.fromSource<GrayCounterPorts>(
675
+ GRAY_COUNTER_SRC,
676
+ "Top",
677
+ );
678
+ sim.dispose();
679
+ },
680
+ { iterations: 3, time: 0 },
681
+ );
682
+
683
+ const sim = Simulator.fromSource<GrayCounterPorts>(GRAY_COUNTER_SRC, "Top");
684
+ sim.dut.rst = 1n;
685
+ sim.dut.i_up = 0n;
686
+ sim.tick();
687
+ sim.dut.rst = 0n;
688
+ sim.dut.i_up = 1n;
689
+ sim.tick();
690
+
691
+ afterAll(() => {
692
+ sim.dispose();
693
+ });
694
+
695
+ bench("simulation_tick_gray_counter_w32_x1", () => {
696
+ sim.tick();
697
+ });
698
+
699
+ bench(
700
+ "simulation_tick_gray_counter_w32_x1000000",
701
+ () => {
702
+ for (let i = 0; i < 1_000_000; i++) {
703
+ sim.tick();
704
+ }
705
+ },
706
+ { iterations: 3, time: 0 },
707
+ );
708
+
709
+ bench(
710
+ "testbench_tick_gray_counter_w32_x1000000",
711
+ () => {
712
+ for (let i = 0; i < 1_000_000; i++) {
713
+ sim.tick();
714
+ //read to measure testbench cycle
715
+ sim.dut.o_count;
716
+ }
717
+ },
718
+ { iterations: 3, time: 0 },
719
+ );
717
720
  });