llvm / llvm/circt

[SVExtractTestCode] Behavior w/ and w/o Dedup

Open
#4,229 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Verilog/SystemVerilog
Dominant language
C++
Stars
2.2k
Forks
524
Avg merge
3d 2h
Merged PRs (30d)
46

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`):

```verilog
// 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`):
```verilog
// 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)
);
```

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the two commands shown, `firtool Foo.fir -extract-test-code` and `firtool Foo.fir -dedup -extract-test-code`, using the embedded Foo circuit. Compare the generated Verilog and bindfile output to establish the expected behavior when one candidate module is dead in one path but live in another; the issue names no source file or test to begin from.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.