Closed wbouillo closed 3 years ago
There are a couple of things at play here. Moore itself never emits a reg
instruction directly, since SystemVerilog itself has no register construct. The reg
keyword is just an alias for logic
, and always_ff
is just an always
process with a few additional warnings enabled. The thing responsible for converting the always_ff
processes to reg
is the desequentialization transformation in LLHD.
However, in trying to throw together an example for you I realized that the transformation chain currently has a bug in LLHD. Thanks for pointing me at that :+1:. Here's an example that should work, but doesn't:
// reg.sv
module foo (input clk, d, output q);
always_ff @(posedge clk) q <= d;
endmodule
Compiling this with moore reg.sv -e foo > reg.llhd
yields:
; reg.llhd
proc %foo.always_ff.31.0 (i1$ %clk, i1$ %d) -> (i1$ %q) {
init:
%clk.prb = prb i1$ %clk
wait %check, %clk
check:
%clk.prb1 = prb i1$ %clk
%0 = const i1 0
%1 = eq i1 %clk.prb, %0
%2 = neq i1 %clk.prb1, %0
%posedge = and i1 %1, %2
br %posedge, %init, %event
event:
%3 = const time 0s 1d
%d.prb = prb i1$ %d
drv i1$ %q, %d.prb, %3
br %init
}
entity @foo (i1$ %clk, i1$ %d) -> (i1$ %q) {
inst %foo.always_ff.31.0 (i1$ %clk, i1$ %d) -> (i1$ %q)
}
At this point llhd-opt reg.llhd -l
should actually pick this up and map to a reg
, but it produces an error and generates:
proc %foo.always_ff.31.0 (i1$ %clk, i1$ %d) -> (i1$ %q) {
init:
%clk.prb = prb i1$ %clk
%0 = const i1 0
%1 = eq i1 %clk.prb, %0
%2 = const time 0s 1d
wait %check, %clk
check:
%d.prb = prb i1$ %d
%clk.prb1 = prb i1$ %clk
%3 = neq i1 %clk.prb1, %0
%posedge = and i1 %1, %3
drv i1$ %q if %posedge, %d.prb, %2
br %posedge, %init, %event
event:
%d.prb = prb i1$ %d ; <--- this should have been removed (it's inserted in check)
br %init
}
If you remove the offending line and run it through llhd-opt
again, you get what you are looking for:
entity %foo.always_ff.31.0 (i1$ %clk, i1$ %d) -> (i1$ %q) {
%d.prb = prb i1$ %d
%0 = prb i1$ %clk
reg i1$ %q, [%d.prb, rise %0] ; <--- voila!
}
entity @foo (i1$ %clk, i1$ %d) -> (i1$ %q) {
inst %foo.always_ff.31.0 (i1$ %clk, i1$ %d) -> (i1$ %q)
}
This is likely a bug in the Common Subexpression Elimination code of LLHD, which leaves the prb i1$ %d
inserted in two places -- and an issue in the verifier not asserting that the instruction is not inserted twice.
At a later stage (once the LLHD transformation become more mature), Moore will run these transformations automatically on the output (unless you specify -O0
).
Will be fixed by https://github.com/fabianschuiki/llhd/issues/145.
Has been fixed as part of llhd v0.14.3.
In my examples of using moore to generate LLHD, I can't successfully generate the reg primitive. I expected a SystemVerilog reg to generate a LLHD reg, but that did not happen for me. Can someone provide an example of an HDL that will generate a reg primitive via moore?