Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIRRTL] "exprInEventControl" not working for big designs #4620

Closed
joonho3020 opened this issue Feb 3, 2023 · 1 comment · Fixed by #4625
Closed

[FIRRTL] "exprInEventControl" not working for big designs #4620

joonho3020 opened this issue Feb 3, 2023 · 1 comment · Fixed by #4625
Labels
bug Something isn't working ExportVerilog

Comments

@joonho3020
Copy link

Hi, while we was trying to compile CY designs using CIRCT & push it through tools (Genus), we found bugs in CIRCT that prevents us from doing this : async resets are being emitted in a way that synthesis tools like Genus do not like.
Specifically, we get something of the form:

 wire reset = ~_some_reset;
 always @(posedge clock or posedge reset)
 	if (~_some_reset)
 		...

even though we are using the exprInEventControl flag (related to ucb-bar/chipyard#1324)

Do you have any ideas on how we can fix this issue?

Here are the input files & commands to reproduce the issue.

firtool \
   --lowering-options=emittedLineLength=2048,noAlwaysComb,exprInEventControl,disallowPackedArrays,disallowLocalVariables,explicitBitcast,verifLabels,locationInfoStyle=wrapInAtSquareBracket \
  chipyard.TestHarness.TinyRocketConfig.sfc.fir
  • Problematic code is (120th line below the ChipTop module)
  wire        debug_reset_syncd = ~_debug_reset_syncd_debug_reset_sync_io_q;	// @[Periphery.scala:288:40, ShiftReg.scala:45:23]
  always @(posedge _system_auto_subsystem_cbus_fixedClockNode_out_clock or posedge debug_reset_syncd) begin	// @[ChipTop.scala:28:35, Periphery.scala:288:40]
    if (~_debug_reset_syncd_debug_reset_sync_io_q)	// @[ChipTop.scala:28:35, Periphery.scala:288:40, ShiftReg.scala:45:23]
      clock_en <= 1'h1;	// @[Periphery.scala:296:29]
    else	// @[ChipTop.scala:28:35]
      clock_en <= _dmactiveAck_dmactiveAck_io_q;	// @[Periphery.scala:296:29, ShiftReg.scala:45:23]
  end // always @(posedge, posedge)
@joonho3020 joonho3020 changed the title "exprInEventControl" not working for big designs [FIRTOOL] "exprInEventControl" not working for big designs Feb 3, 2023
@joonho3020 joonho3020 changed the title [FIRTOOL] "exprInEventControl" not working for big designs [FIRRTL] "exprInEventControl" not working for big designs Feb 3, 2023
@seldridge
Copy link
Member

Here's a minimal example:

circuit Foo:
  module Foo:
    input clock: Clock
    input rst_n: AsyncReset
    input d: UInt<1>
    output q: UInt<1>

    node rst = asAsyncReset(not(asUInt(rst_n)))

    reg r: UInt<1>, clock with: (reset => (rst, UInt<1>(0)))

    r <= d
    q <= r

Producing:

// Generated by CIRCT unknown git version
module Foo(
  input  clock,
         rst_n,
         d,
  output q
);

  reg  r;
  wire _GEN = ~rst_n;
  always @(posedge clock or posedge _GEN) begin
    if (~rst_n)
      r <= 1'h0;
    else
      r <= d;
  end // always @(posedge, posedge)
  assign q = r;
endmodule

And the MLIR right before emission:

module {
  hw.module @Foo(%clock: i1, %rst_n: i1, %d: i1) -> (q: i1) {
    %true = hw.constant true
    %r = sv.reg  : !hw.inout<i1>
    %0 = sv.read_inout %r : !hw.inout<i1>
    %1 = comb.xor bin %rst_n, %true : i1
    sv.always posedge %clock, posedge %1 {
      %true_0 = hw.constant true
      %2 = comb.xor bin %rst_n, %true_0 : i1
      sv.if %2 {
        %false = hw.constant false
        sv.passign %r, %false : i1
      } else {
        sv.passign %r, %d : i1
      }
    }
    hw.output %0 : i1
  }
}

Prepare for emission correctly mangles this so %1 won't be inlined. However, it looks like it should do the same thing for any usage of that in an async reset position.

The output after prepare for emission is the following showing the synthetic wire created for the reset in the always event list:

hw.module @Foo(%clock: i1, %rst_n: i1, %d: i1) -> (q: i1) {
  %true = hw.constant true
  %r = sv.reg  : !hw.inout<i1>
  %0 = comb.xor bin %rst_n, %true : i1
  %1 = sv.wire  : !hw.inout<i1>
  sv.assign %1, %0 : i1
  %2 = sv.read_inout %1 : !hw.inout<i1>
  sv.always posedge %clock, posedge %2 {
    %true_0 = hw.constant true
    %4 = comb.xor bin %rst_n, %true_0 : i1
    sv.if %4 {
      %false = hw.constant false
      sv.passign %r, %false : i1
    } else {
      sv.passign %r, %d : i1
    }
  }
  %3 = sv.read_inout %r : !hw.inout<i1>
  hw.output %3 : i1
}

@seldridge seldridge added bug Something isn't working ExportVerilog labels Feb 3, 2023
uenoku added a commit that referenced this issue Feb 6, 2023
This commit fixes bugs in spilling logic regarding expressions used in sensitivity list.

* PrettifyVerilog is changed to check lowering options so that CSEd expressions are not cloned into users when `exprInEventControl` is enabled.
* There was a duplicated logic in isExpressionUnableToInline and PrepareForEmission so the logic was unified into isExpressionUnableToInline.

Fix #4620
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working ExportVerilog
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants