@celox-sim/celox 0.1.13 → 0.1.14
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 +1 -1
- package/dist/dut.d.ts.map +1 -1
- package/dist/dut.js +23 -10
- package/dist/dut.js.map +1 -1
- package/dist/index.d.ts +8 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -10
- package/dist/index.js.map +1 -1
- package/dist/napi-bridge.d.ts +1 -1
- package/dist/napi-bridge.d.ts.map +1 -1
- package/dist/napi-bridge.js +1 -1
- package/dist/napi-bridge.js.map +1 -1
- package/dist/napi-helpers.d.ts +11 -2
- package/dist/napi-helpers.d.ts.map +1 -1
- package/dist/napi-helpers.js +23 -0
- package/dist/napi-helpers.js.map +1 -1
- package/dist/simulation.d.ts.map +1 -1
- package/dist/simulation.js +29 -13
- package/dist/simulation.js.map +1 -1
- package/dist/simulator.d.ts.map +1 -1
- package/dist/simulator.js +28 -12
- package/dist/simulator.js.map +1 -1
- package/dist/types.d.ts +6 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/src/dut.test.ts +1037 -742
- package/src/dut.ts +580 -528
- package/src/e2e.bench.ts +512 -509
- package/src/e2e.test.ts +1847 -1574
- package/src/index.ts +46 -46
- package/src/matchers.ts +81 -81
- package/src/napi-bridge.ts +5 -5
- package/src/napi-helpers.ts +475 -400
- package/src/simulation.test.ts +395 -368
- package/src/simulation.ts +502 -430
- package/src/simulator.test.ts +201 -168
- package/src/simulator.ts +317 -267
- package/src/types.ts +102 -98
package/src/e2e.bench.ts
CHANGED
|
@@ -10,21 +10,21 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { readFileSync } from "node:fs";
|
|
13
|
-
import {
|
|
13
|
+
import { dirname, resolve } from "node:path";
|
|
14
14
|
import { fileURLToPath } from "node:url";
|
|
15
|
-
import { bench, describe
|
|
16
|
-
import {
|
|
15
|
+
import { afterAll, bench, describe } from "vitest";
|
|
16
|
+
import { createSimulatorBridge, loadNativeAddon } from "./napi-helpers.js";
|
|
17
17
|
import { Simulation } from "./simulation.js";
|
|
18
|
-
import
|
|
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(
|
|
22
|
+
const VERYL_STD = resolve(
|
|
23
|
+
__benchDir,
|
|
24
|
+
"../../../deps/veryl/crates/std/veryl/src",
|
|
25
|
+
);
|
|
26
26
|
function readVeryl(...parts: string[]): string {
|
|
27
|
-
|
|
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
|
-
|
|
52
|
-
|
|
51
|
+
rst: bigint;
|
|
52
|
+
readonly cnt: { at(i: number): bigint; readonly length: number };
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
describe("simulation", () => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
+
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
|
+
//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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
-
|
|
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
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
-
|
|
422
|
-
|
|
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
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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
|
-
|
|
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
|
-
|
|
515
|
-
|
|
514
|
+
i_data: bigint;
|
|
515
|
+
readonly o_ones: bigint;
|
|
516
516
|
}
|
|
517
517
|
|
|
518
518
|
describe("stdlib-countones", () => {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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
|
-
|
|
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
|
-
|
|
583
|
-
|
|
584
|
-
|
|
582
|
+
rst: bigint;
|
|
583
|
+
i_up: bigint;
|
|
584
|
+
readonly o_count: bigint;
|
|
585
585
|
}
|
|
586
586
|
|
|
587
587
|
describe("stdlib-counter", () => {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
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
|
-
|
|
640
|
-
|
|
641
|
-
|
|
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
|
-
|
|
666
|
-
|
|
667
|
-
|
|
665
|
+
rst: bigint;
|
|
666
|
+
i_up: bigint;
|
|
667
|
+
readonly o_count: bigint;
|
|
668
668
|
}
|
|
669
669
|
|
|
670
670
|
describe("stdlib-gray-counter", () => {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
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
|
});
|