Skip to content

Conversation

fzi-hielscher
Copy link
Contributor

Mark DPICallIntrinsicOps as over-defined in the FIRRTL IMConstProp pass to prevent connections to the call's result from being removed.

Running this Chisel 7 snippet through firtool

class DPITest extends Module {
  val out = IO(Output(Bool()))
  val bar = Wire(Bool())
  val foo = RawClockedNonVoidFunctionCall("foo", Bool())(this.clock, true.B, bar)
  bar := RawClockedNonVoidFunctionCall("bar", Bool())(this.clock, true.B, foo)
  out := bar
}

incorrectly produces

[...]
  always @(posedge clock) begin
    foo(1'bz, _foo_0); 
    bar(_GEN, _bar_0);  
    _GEN_0 <= _bar_0; 
  end // always @(posedge)
  assign out = 1'bz; 
endmodule

The DPI call intrinsics ale initialized as Unknown in the constant propagation lattice and due to their cyclic dependency, this never gets resolved. This eventually leads to the connection to the bar wire being removed IMConstProp.cpp:1091:

if (isDeletableWireOrRegOrNode(destOp) &&
                !isOverdefined(fieldRef)) {
              connect.erase();
              ++numErasedOp;
            }

Initializing the call results to Overdefined prevents this.

I'm not familiar with this pass, but the !isOverdefined(fieldRef) check before deleting a connection looks a bit too optimistic to me. Is it an invariant at this point that every value is known to be either constant or overdefined? If so, this should probably get an assert, right?

@fzi-hielscher fzi-hielscher added bug Something isn't working FIRRTL Involving the `firrtl` dialect labels May 23, 2025
Copy link
Member

@uenoku uenoku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@uenoku
Copy link
Member

uenoku commented May 24, 2025

I'm not familiar with this pass, but the !isOverdefined(fieldRef) check before deleting a connection looks a bit too optimistic to me. Is it an invariant at this point that every value is known to be either constant or overdefined? If so, this should probably get an assert, right?

I think that's correct. Registers are marked as overdefined so there should't be dependency cycle. Thank you for catching an issue for DPI.

@fzi-hielscher fzi-hielscher merged commit 8f2f237 into llvm:main May 24, 2025
5 checks passed
TaoBi22 pushed a commit to TaoBi22/circt that referenced this pull request Jul 17, 2025
Mark DPICallIntrinsicOps as over-defined in the FIRRTL IMConstProp pass to prevent connections to the call's result from being removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working FIRRTL Involving the `firrtl` dialect
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants