llvm / llvm/circt

[PrepareForEmission] Incorrect emission of blocking assignments with disallowLocalVariables

Open
#4,367 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
2.2k
Forks
524
Avg merge
3d 2h
Merged PRs (30d)
46

Description

Currently PrepareForEmission hoist expressions if `disallowLocalVariables` exists but it has been broken.
```mlir
module attributes {circt.loweringOptions = "disallowLocalVariables"} {
hw.module @Foo(%fd: i32) -> () {
%r1 = sv.reg : !hw.inout
sv.initial {
%1 = sv.verbatim.expr "`RANDOM" : () -> i4
sv.bpassign %r1, %1 : i4
%read = sv.read_inout %r1: !hw.inout
%2 = comb.add %read, %read: i4
%3 = comb.extract %2 from 0 : (i4) -> i2
sv.fwrite %fd, "%d"(%3) : i2
}
}
}
```

Current output is broken. `r1 + r1` must be spilled to a register.
```verilog
module Foo( // foo.mlir:3:3
input [31:0] fd);

reg [3:0] r1; // foo.mlir:4:12
wire [3:0] _GEN = r1 + r1; // foo.mlir:8:16, :9:13
initial begin // foo.mlir:5:6
r1 = `RANDOM; // foo.mlir:6:13, :7:8
$fwrite(fd, "%d", _GEN[1:0]); // foo.mlir:9:13, :10:13, :11:8
end // initial
endmodule

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the issue with the provided MLIR example and inspect PrepareForEmission's handling of disallowLocalVariables and blocking assignments. Trace why the r1 + r1 expression is emitted as a wire, then verify that the expression is spilled to a register and that the generated Verilog matches the intended behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.