Skip to content

[FIRRTL] Constants not sunk for read probed values #9766

@seldridge

Description

@seldridge

Consider the following:

FIRRTL version 6.0.0
circuit Foo:
  public module Foo:
    input clock: Clock
    input reset: AsyncReset
    input d: UInt<1>
    output q: UInt<1>
    output probe: Probe<UInt<1>>

    node v = UInt<1>(0)
    define probe = probe(v)

    regreset r1: UInt<1>, clock, reset, v
    connect r1, d
    connect q, r1

This is currently compiling (firtool Foo.fir -disable-all-randomization) to:

// Generated by CIRCT firtool-1.141.0-24-gcfe6182a6
module Foo(
  input  clock,
         reset,
         d,
  output q
);

  wire _GEN = 1'h0;
  reg  r1;
  always @(posedge clock or posedge reset) begin
    if (reset)
      r1 <= _GEN;
    else
      r1 <= d;
  end // always @(posedge, posedge)
  `ifdef ENABLE_INITIAL_REG_
    `ifdef FIRRTL_BEFORE_INITIAL
      `FIRRTL_BEFORE_INITIAL
    `endif // FIRRTL_BEFORE_INITIAL
    initial begin
      if (reset)
        r1 = _GEN;
    end // initial
    `ifdef FIRRTL_AFTER_INITIAL
      `FIRRTL_AFTER_INITIAL
    `endif // FIRRTL_AFTER_INITIAL
  `endif // ENABLE_INITIAL_REG_
  assign q = r1;
endmodule


// ----- 8< ----- FILE "ref_Foo.sv" ----- 8< -----

// Generated by CIRCT firtool-1.141.0-24-gcfe6182a6
`define ref_Foo_probe _GEN

After #9657, this goes through some variations inside the pipeline. IMCP will split the constant. Canonicalize will CSE the constant back. Eventually LowerXMR will set a symbol on the node and that will lock in this emission pattern.

This would be better to not do as some tools like to think of this as an "asynchronous load" reset. It's totally legal and fine, but tools are, sadly, dumb.

Acceptable emission is:

module Foo(
  input  clock,
         reset,
         d,
  output q
);

  wire _GEN = 1'h0;
  reg  r1;
  always @(posedge clock or posedge reset) begin
    if (reset)
      r1 <= 1'h0;
    else
      r1 <= d;
  end // always @(posedge, posedge)
  `ifdef ENABLE_INITIAL_REG_
    `ifdef FIRRTL_BEFORE_INITIAL
      `FIRRTL_BEFORE_INITIAL
    `endif // FIRRTL_BEFORE_INITIAL
    initial begin
      if (reset)
        r1 = 1'h0;
    end // initial
    `ifdef FIRRTL_AFTER_INITIAL
      `FIRRTL_AFTER_INITIAL
    `endif // FIRRTL_AFTER_INITIAL
  `endif // ENABLE_INITIAL_REG_
  assign q = r1;
endmodule

// ----- 8< ----- FILE "ref_Foo.sv" ----- 8< -----

// Generated by CIRCT firtool-1.141.0-24-gcfe6182a6
`define ref_Foo_probe _GEN

Ideal emission is:

module Foo(
  input  clock,
         reset,
         d,
  output q
);

  reg  r1;
  always @(posedge clock or posedge reset) begin
    if (reset)
      r1 <= 1'h0;
    else
      r1 <= d;
  end // always @(posedge, posedge)
  `ifdef ENABLE_INITIAL_REG_
    `ifdef FIRRTL_BEFORE_INITIAL
      `FIRRTL_BEFORE_INITIAL
    `endif // FIRRTL_BEFORE_INITIAL
    initial begin
      if (reset)
        r1 = 1'h0;
    end // initial
    `ifdef FIRRTL_AFTER_INITIAL
      `FIRRTL_AFTER_INITIAL
    `endif // FIRRTL_AFTER_INITIAL
  `endif // ENABLE_INITIAL_REG_
  assign q = r1;
endmodule

// ----- 8< ----- FILE "ref_Foo.sv" ----- 8< -----

// Generated by CIRCT firtool-1.141.0-24-gcfe6182a6
`define ref_Foo_probe 1'h0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions