@celox-sim/celox 0.1.11 → 0.1.13

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
@@ -9,6 +9,9 @@
9
9
  * 4. Simulator::tick vs Simulation::step overhead
10
10
  */
11
11
 
12
+ import { readFileSync } from "node:fs";
13
+ import { resolve, dirname } from "node:path";
14
+ import { fileURLToPath } from "node:url";
12
15
  import { bench, describe, afterAll } from "vitest";
13
16
  import { Simulator } from "./simulator.js";
14
17
  import { Simulation } from "./simulation.js";
@@ -18,6 +21,12 @@ import {
18
21
  createSimulatorBridge,
19
22
  } from "./napi-helpers.js";
20
23
 
24
+ const __benchDir = dirname(fileURLToPath(import.meta.url));
25
+ const VERYL_STD = resolve(__benchDir, "../../../deps/veryl/crates/std/veryl/src");
26
+ function readVeryl(...parts: string[]): string {
27
+ return readFileSync(resolve(VERYL_STD, ...parts), "utf8");
28
+ }
29
+
21
30
  const CODE = `
22
31
  module Top #(
23
32
  param N: u32 = 1000,
@@ -401,3 +410,308 @@ describe("optimize-flag", () => {
401
410
  { iterations: 3, time: 0 },
402
411
  );
403
412
  });
413
+
414
+ // ────────────────────────────────────────────────────────────
415
+ // Stdlib benchmarks — mirrors crates/celox/benches/simulation.rs
416
+ // ────────────────────────────────────────────────────────────
417
+
418
+ // --- Linear SEC (P=6): Hamming encoder/decoder, combinational ---
419
+
420
+ const LINEAR_SEC_SRC =
421
+ readVeryl("coding/linear_sec_encoder.veryl") +
422
+ readVeryl("coding/linear_sec_decoder.veryl") +
423
+ `
424
+ module Top #(
425
+ param P: u32 = 6,
426
+ const K: u32 = (1 << P) - 1,
427
+ const N: u32 = K - P,
428
+ )(
429
+ i_word : input logic<N>,
430
+ o_codeword : output logic<K>,
431
+ o_word : output logic<N>,
432
+ o_corrected: output logic,
433
+ ) {
434
+ inst u_enc: linear_sec_encoder #(P: P) (i_word, o_codeword);
435
+ inst u_dec: linear_sec_decoder #(P: P) (
436
+ i_codeword: o_codeword,
437
+ o_word,
438
+ o_corrected,
439
+ );
440
+ }
441
+ `;
442
+
443
+ interface LinearSecPorts {
444
+ i_word: bigint;
445
+ readonly o_codeword: bigint;
446
+ readonly o_word: bigint;
447
+ readonly o_corrected: bigint;
448
+ }
449
+
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
+ );
498
+ });
499
+
500
+ // --- Countones (W=64): recursive combinational popcount tree ---
501
+
502
+ const COUNTONES_SRC =
503
+ readVeryl("countones/countones.veryl") +
504
+ `
505
+ module Top (
506
+ i_data: input logic<64>,
507
+ o_ones: output logic<7>,
508
+ ) {
509
+ inst u: countones #(W: 64) (i_data, o_ones);
510
+ }
511
+ `;
512
+
513
+ interface CountonesPorts {
514
+ i_data: bigint;
515
+ readonly o_ones: bigint;
516
+ }
517
+
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
+ );
553
+ });
554
+
555
+ // --- std::counter (WIDTH=32): sequential up-counter ---
556
+
557
+ const STD_COUNTER_SRC =
558
+ readVeryl("counter/counter.veryl") +
559
+ `
560
+ module Top (
561
+ clk : input clock,
562
+ rst : input reset,
563
+ i_up : input logic,
564
+ o_count: output logic<32>,
565
+ ) {
566
+ inst u: counter #(WIDTH: 32) (
567
+ i_clk : clk,
568
+ i_rst : rst,
569
+ i_clear : 1'b0,
570
+ i_set : 1'b0,
571
+ i_set_value : 32'b0,
572
+ i_up,
573
+ i_down : 1'b0,
574
+ o_count,
575
+ o_count_next: _,
576
+ o_wrap_around: _,
577
+ );
578
+ }
579
+ `;
580
+
581
+ interface StdCounterPorts {
582
+ rst: bigint;
583
+ i_up: bigint;
584
+ readonly o_count: bigint;
585
+ }
586
+
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
+ );
634
+ });
635
+
636
+ // --- std::gray_counter (WIDTH=32): Gray-encoded sequential counter ---
637
+
638
+ const GRAY_COUNTER_SRC =
639
+ readVeryl("counter/counter.veryl") +
640
+ readVeryl("gray/gray_encoder.veryl") +
641
+ readVeryl("gray/gray_counter.veryl") +
642
+ `
643
+ module Top (
644
+ clk : input clock,
645
+ rst : input reset,
646
+ i_up : input logic,
647
+ o_count: output logic<32>,
648
+ ) {
649
+ inst u: gray_counter #(WIDTH: 32) (
650
+ i_clk : clk,
651
+ i_rst : rst,
652
+ i_clear : 1'b0,
653
+ i_set : 1'b0,
654
+ i_set_value : 32'b0,
655
+ i_up,
656
+ i_down : 1'b0,
657
+ o_count,
658
+ o_count_next: _,
659
+ o_wrap_around: _,
660
+ );
661
+ }
662
+ `;
663
+
664
+ interface GrayCounterPorts {
665
+ rst: bigint;
666
+ i_up: bigint;
667
+ readonly o_count: bigint;
668
+ }
669
+
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
+ );
717
+ });