chipsalliance / firrtl

Flexible Intermediate Representation for RTL
https://www.chisel-lang.org/firrtl/
Apache License 2.0
727 stars 177 forks source link

Improve code generation for nested/multiple when statements #1320

Open aswaterman opened 4 years ago

aswaterman commented 4 years ago

Feature Description

When a register is updated by multiple nested when statements, the code generation starts to get rather expansive. Unfortunately, this hurts traditional Verilog line coverage metrics.

Here is an example, derived from rocket-chip:

  module M : 
    input clock : Clock
    input i1 : UInt<1>
    input i2 : UInt<1>
    input i3 : UInt<1>
    input i4 : UInt<1>
    input i5 : UInt<1>
    input i6 : UInt<1>
    input i7 : UInt<1>
    output z : UInt<1>
    reg r : UInt<1>, clock
    z <= r
    when i7 :
      when i4 :
        when i5 :
          r <= UInt<1>(1)
    when i6 :
      when i3 :
      else :
        when i2 :
          when i1 :
            r <= UInt<1>(0)
  always @(posedge clock) begin
    if (i6) begin
      if (i3) begin
        if (i7) begin
          if (i4) begin
            r <= _GEN_0;
          end
        end
      end else if (i2) begin
        if (i1) begin
          r <= 1'h0;
        end else if (i7) begin
          if (i4) begin
            r <= _GEN_0;
          end
        end
      end else if (i7) begin
        if (i4) begin
          r <= _GEN_0;
        end
      end
    end else if (i7) begin
      if (i4) begin
        r <= _GEN_0;
      end
    end
  end

The feature request is to emit something that looks like the original Firrtl, i.e., with 7 ifs instead of 12. (This might have to occur before the optimization that creates the bitwise-OR in _GEN_0.)

solomatnikov commented 4 years ago

Another example:

WCB Verilog

seldridge commented 4 years ago

Is this closed by https://github.com/freechipsproject/firrtl/pull/1727?

For the above circuit, current (FIRRTL 1.4.0-RC2) generates the following Verilog for the above module M example (randomization logic was manually removed):

module M(
  input   clock,
  input   i1,
  input   i2,
  input   i3,
  input   i4,
  input   i5,
  input   i6,
  input   i7,
  output  z
);
  reg  r;
  wire  _GEN_0 = i5 | r; // @[]
  wire  _GEN_1 = i4 ? _GEN_0 : r; // @[]
  wire  _GEN_2 = i7 ? _GEN_1 : r; // @[]
  assign z = r;
  always @(posedge clock) begin
    if (i6) begin
      if (i3) begin
        r <= _GEN_2;
      end else if (i2) begin
        if (i1) begin
          r <= 1'h0;
        end else begin
          r <= _GEN_2;
        end
      end else begin
        r <= _GEN_2;
      end
    end else begin
      r <= _GEN_2;
    end
  end
endmodule