@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/dist/dut.d.ts.map +1 -1
- package/dist/dut.js +106 -1
- package/dist/dut.js.map +1 -1
- package/dist/napi-helpers.d.ts +5 -0
- package/dist/napi-helpers.d.ts.map +1 -1
- package/dist/napi-helpers.js +34 -2
- package/dist/napi-helpers.js.map +1 -1
- package/dist/simulation.d.ts +1 -0
- package/dist/simulation.d.ts.map +1 -1
- package/dist/simulation.js +6 -3
- package/dist/simulation.js.map +1 -1
- package/package.json +2 -2
- package/src/dut.test.ts +271 -0
- package/src/dut.ts +131 -1
- package/src/e2e.bench.ts +314 -0
- package/src/e2e.test.ts +379 -3
- package/src/napi-helpers.ts +37 -2
- package/src/simulation.ts +6 -2
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
|
+
});
|