veryl
veryl copied to clipboard
Native Veryl tests.
As far as I understand, tests in Veryl are currently limited to inlining or referring to tests written in System Verilog and Cocotb. Perhaps we can have a language extension that allows a SV like syntax for tests, transpiling to SV test benches and with a test attribute invoke those.
At a first glance it seems pretty straight forward, but perhaps there are some underlying blockers for this.
Something like this perhaps:
module HalfAdder #() (
a : input logic,
b : input logic,
sum : output logic,
carry: output logic,
) {
always_comb {
sum = a ^ b;
carry = a & b;
}
}
#[test(half_adder)]
module test () {
var a : logic;
var b : logic;
var sum : logic;
var carry : logic;
inst half_adder: HalfAdder (
a ,
b ,
sum ,
carry ,
);
initial {
a = 0;
b = 0;
assert (sum == 0 && carry == 0);
#10; // guess we need some way to progess simulation time
// $finish; // guess we need some way to stop sim
}
}
The expected output is something like this:
module test;
logic a;
logic b;
logic sum;
logic carry;
vips_HalfAdder half_adder (a, b, sum, carry);
initial begin
a = 0;
b = 0;
assert (sum == 0 && carry == 0);
#10;
$finish;
end
endmodule
I agree introducing delay notation like #10;, as minimal support for native test description, is not so difficult.
But I concern that once it is introduced, more and more syntex for more complex test will be necessary.
I don't know whether the test logic should reside in the initial block, or if there should be some other construct. As of now this won't match the current syntax of course.
If something like this appears as a good idea, I'd be happy to try to implement it in Veryl. The idea is to get all the niceties of Veryl for writing tests. And still one can have the inline option of SV based tests, and cocotb, this should not break anything.
I agree introducing delay notation like
#10;, as minimal support for native test description, is not so difficult. But I concern that once it is introduced, more and more syntex for more complex test will be necessary.
What kind of syntax are you referring, operations for file io and such? I think more advanced tests could be done in Marlin, but small unit tests could go well Veryl.
What kind of syntax are you referring, operations for file io and such?
For example, task, clocking, constrainted random, sequential assertion and so on.
About this point, maybe, we can select carefully to avoid complexity.
One more concern is scheduling semantics. Racing between variable set and get becomes problem, and native simulator #1287 may become more difficult. Instead of delay notation, clock based notation may be better.
One more concern is scheduling semantics. Racing between variable set and get becomes problem, and native simulator #1287 may become more difficult. Instead of delay notation, clock based notation may be better.
Could you give an example how that might look like (clock based test bench).
I don't have complete idea yet, the current image is like below:
#[test(half_adder)]
module test () {
#[clock(10, 10)]
var clk: clock;
#[reset(0, 5)]
var rst: reset;
var a: logic;
var b: logic;
initial {
@rst;
@clk;
a = 1;
b = 1;
@clk;
assert (c == 2);
a = 2;
b = 2;
}
}
#[clock(10, 10)] defines the clock duty cycle, and #[reset(0, 5)] defines a reset event, active high, with a length of 5?
@reset and @clk are event instances, so here first a reset, then a clock, then some assignments, followed by another clock event.
Is the idea that the clockevent performs a single transition or the period? In some cases you might have logic triggered by either flank so I assume its either high to low, or low to high, on each event.
I also assume events to be blocking.
Should there be something like assert (..., $display("...")); allowing to trace assertion violations. Or perhaps something more Verylish, if !assert (c ==2) { ... } assuming assert to return true if the assertion passes.
#[clock(10, 10)]defines the clock duty cycle, and#[reset(0, 5)]defines a reset event, active high, with a length of 5?
Yes. I intended it.
Unbalance duty is not necessary to handle, so more simplified syntax like #[clock(10)] may be better.
About reset, instead of the attribute, assignment in initial block may be better for flexibility.
Is the idea that the
clockevent performs a single transition or the period? In some cases you might have logic triggered by either flank so I assume its either high to low, or low to high, on each event.
To specify the event polarity, something like @(posedge clk) can be considered.
However, I don't know whether there are a case that negedge is necessary.
Should there be something like
assert (..., $display("...")); allowing to trace assertion violations. Or perhaps something more Verylish,if !assert (c ==2) { ... }assuming assert to return true if the assertion passes.
I agree it is necesarry to consider about assertion syntax.
I have another idea about native Veryl tests. The detailed information is here: https://zenn.dev/dalance/articles/d451090305688f (It is written in Japanese, please use a translator)
The summary is below:
- Introducing test syntax to Veryl causes language complexity
- Programming language based test (e.g. cocotb) is better from the viewpoint of flexibility, but learning cost of the additional language and ecosystem segmentation are problems
The third idea assumes Veryl native simulator #1287.
It introduces verification components written in programming language (probably Rust).
They are added to Veryl native simulator as plugin.
The example component clk_gen can be instantiated in Veryl's test like below:
inst u_clk: clk_gen (
clk,
);
initial {
a = 0;
u_clk.wait();
a = 1;
u_clk.wait();
}
By using function call style, syntax extension for test is not necessary.
Basic components like clk_gen, rst_gen, assert will be provided as standard plugins.
More complex plugins like below can be developed by users freely:
- AXI transactor
- constrainted random sequence generator
- complex assertion like SVA
Veryl users who uses standard or third-party plugins can write tests using Veryl only.