Skip to content

[SVExtractTestCode] Behavior w/ and w/o Dedup #4229

Open
@seldridge

Description

The more aggressive test code extraction may have surprising behavior when a module that is a candidate for aggressive extraction is dead in one code path, but not dead in another.

Consider:

circuit Foo:
  module Baz:
    input clock: Clock
    input reset: UInt<1>
    input a: UInt<1>
    output b: UInt<1>

    b <= a

    assert(clock, eq(a, UInt<1>(0)), reset, "a != 0")

  module Bar:
    input clock: Clock
    input reset: UInt<1>
    input a: UInt<1>
    output b: UInt<1>

    b <= a

    assert(clock, eq(a, UInt<1>(0)), reset, "a != 0")

  module Foo:
    input clock: Clock
    input reset: UInt<1>
    input a: UInt<1>
    output b: UInt<1>

    inst bar of Bar
    bar.clock <= clock
    bar.reset <= reset
    bar.a <= a

    inst baz of Baz
    baz.clock <= clock
    baz.reset <= reset
    baz.a <= a
    b <= baz.b

When running without dedup (firtool Foo.fir -extract-test-code):

// Generated by CIRCT unknown git version
// VCS coverage exclude_file
module Baz_assert(
  input a,
        reset,
        clock);

  always @(posedge clock) begin
    if (reset)
      assert(~a) else $error("a != 0");
  end // always @(posedge)
endmodule

module Baz(
  input  clock,
         reset,
         a,
  output b);

  /* This instance is elsewhere emitted as a bind statement.
    Baz_assert Baz_assert (
      .a     (a),
      .reset (reset),
      .clock (clock)
    );
  */
  assign b = a;
endmodule

// VCS coverage exclude_file
module Bar_assert(
  input a,
        reset,
        clock);

  always @(posedge clock) begin
    if (reset)
      assert(~a) else $error("a != 0");
  end // always @(posedge)
endmodule

module Foo(
  input  clock,
         reset,
         a,
  output b);

  /* This instance is elsewhere emitted as a bind statement.
    Bar_assert Bar_assert (
      .a     (a),
      .reset (reset),
      .clock (clock)
    );
  */
  Baz baz (
    .clock (clock),
    .reset (reset),
    .a     (a),
    .b     (b)
  );
endmodule


// ----- 8< ----- FILE "bindfile" ----- 8< -----

bind Baz Baz_assert Baz_assert (
  .a     (a),
  .reset (reset),
  .clock (clock)
);
bind Foo Bar_assert Bar_assert (
  .a     (a),
  .reset (reset),
  .clock (clock)
);

When running with dedup (firtool Foo.fir -dedup -extract-test-code):

// Generated by CIRCT unknown git version
// VCS coverage exclude_file
module Bar_assert(
  input a,
        reset,
        clock);

  always @(posedge clock) begin
    if (reset)
      assert(~a) else $error("a != 0");
  end // always @(posedge)
endmodule

module Bar(
  input  clock,
         reset,
         a,
  output b);

  /* This instance is elsewhere emitted as a bind statement.
    Bar_assert Bar_assert (
      .a     (a),
      .reset (reset),
      .clock (clock)
    );
  */
  assign b = a;
endmodule

module Foo(
  input  clock,
         reset,
         a,
  output b);

  wire _bar_b;
  Bar bar (
    .clock (clock),
    .reset (reset),
    .a     (a),
    .b     (_bar_b)
  );
  Bar baz (
    .clock (clock),
    .reset (reset),
    .a     (a),
    .b     (b)
  );
endmodule


// ----- 8< ----- FILE "bindfile" ----- 8< -----

bind Bar Bar_assert Bar_assert (
  .a     (a),
  .reset (reset),
  .clock (clock)
);

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