[FIRRTL] Differences due to IMCP
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 2.2k
- Forks
- 524
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 46
Description
This is a small collection of tests regarding the differences between our constant prop.
There are tons of possible tests to write here, so this isn't exhaustive. There are some things that are broken in `IMCP` but are properly optimized by `RemoveInvalids` before IMCP can break it. In particular, any register with a reset should be equivalent to a reset-less register with a mux, although currently IMCP handles them differently:
```scala
reg r0 : UInt<8>, clock with :
reset => (reset, UInt<8>(3))
```
Is equivalent to:
```scala
reg r0 : UInt<8>, clock with :
reset => (UInt<1>(0), r0)
r0 <= mux(reset, UInt<8>(3), r0)
```
---
Input:
```scala
circuit Test:
module Test:
input clock : Clock
input reset : UInt<1>
output o : UInt<8>
wire w : UInt<8>
reg r : UInt<8>, clock with :
reset => (reset, mux(reset, UInt<8>(3), w))
w <= r
o <= r
```
MFC:
```verilog
module Test(
input clock,
reset,
output [7:0] o);
wire [7:0] _GEN;
wire [7:0] w;
reg [7:0] r;
assign w = _GEN;
assign _GEN = r;
always @(posedge clock) begin
if (reset)
r <= reset ? 8'h3 : w;
else
r <= r;
end // always @(posedge)
assign o = w;
endmodule
```
SFC:
```verilog
module Test(
input clock,
input reset,
output [7:0] o
);
assign o = 8'h3;
endmodule
```
---
Input:
```scala
circuit Test:
module Test:
input clock : Clock
input reset : UInt<1>
output o : UInt<8>
reg r : UInt<8>, clock with :
reset => (UInt<1>(0), r)
r <= or(UInt<8>(8), r)
o <= r
```
MFC:
```verilog
module Test(
input clock,
reset,
output [7:0] o);
assign o = 8'h8;
endmodule
```
SFC:
```verilog
module Test(
input clock,
input reset,
output [7:0] o
);
reg [7:0] r;
assign o = r;
always @(posedge clock) begin
r <= 8'h8 | r;
end
endmodule
```
---
Input:
```scala
circuit Test:
module Test:
input clock : Clock
input reset : UInt<1>
output o : UInt<8>
reg r0 : UInt<8>, clock with :
reset => (UInt<1>(0), r0)
reg r1 : UInt<8>, clock with :
reset => (reset, r0)
r1 <= UInt<8>(3)
o <= r1
```
MFC:
```verilog
module Test(
input clock,
reset,
output [7:0] o);
assign o = 8'h3;
endmodule
```
SFC:
```verilog
module Test(
input clock,
input reset,
output [7:0] o
);
reg [7:0] r1;
assign o = r1;
always @(posedge clock) begin
if (reset) begin
r1 <= 8'h0;
end else begin
r1 <= 8'h3;
end
end
endmodule
```
---
Input:
```scala
; Each register should be initialized to a "unique" constant. We can't optimize
; either register away here. We can't make the assumption that `r0 == r1` and
; remove the registers here.
circuit Test:
module Test:
input clock : Clock
input reset : UInt<1>
output o0 : UInt<8>
output o1 : UInt<8>
reg r0 : UInt<8>, clock with :
reset => (UInt<1>(0), r0)
reg r1 : UInt<8>, clock with :
reset => (UInt<1>(0), r1)
r0 <= mux(reset, UInt<8>(3), r1)
r1 <= mux(reset, UInt<8>(3), r0)
o0 <= r0
o1 <= r1
```
MFC:
```verilog
module Test(
input clock,
reset,
output [7:0] o0,
o1);
assign o0 = 8'h3;
assign o1 = 8'h3;
endmodule
```
SFC:
```verilog
module Test(
input clock,
input reset,
output [7:0] o0,
output [7:0] o1
);
reg [7:0] r0;
reg [7:0] r1;
assign o0 = r0;
assign o1 = r1;
always @(posedge clock) begin
if (reset) begin
r0 <= 8'h3;
end else begin
r0 <= r1;
end
if (reset) begin
r1 <= 8'h3;
end else begin
r1 <= r0;
end
end
endmodule
```
---
Input:
```scala
; A register's initial state should *not* propogate across module boundaries.
circuit Test:
module Test:
input clock : Clock
input reset : UInt<1>
output o : UInt<8>
inst child of Child
child.clock <= clock
child.reset <= reset
; Connect the child register to itself.
child.value <= child.o
o <= child.o
; CHECK-LABEL: module Child
module Child:
input clock : Clock
input reset : UInt<1>
input value: UInt<8>
output o : UInt<8>
reg r : UInt<8>, clock with :
reset => (reset, UInt<8>(3))
; Connect the register to itself across a module boundary.
r <= value
o <= r
```
MFC:
```verilog
module Test(
input clock,
reset,
output [7:0] o);
Child child ();
assign o = 8'h3;
endmodule
module Child();
endmodule
```
SFC:
```verilog
module Test(
input clock,
input reset,
output [7:0] o
);
wire child_clock;
wire child_reset;
wire [7:0] child_value;
wire [7:0] child_o;
Child child (
.clock(child_clock),
.reset(child_reset),
.value(child_value),
.o(child_o)
);
assign o = child_o;
assign child_clock = clock;
assign child_reset = reset;
assign child_value = child_o;
endmodule
module Child(
input clock,
input reset,
input [7:0] value,
output [7:0] o
);
reg [7:0] r;
assign o = r;
always @(posedge clock) begin
if (reset) begin
r <= 8'h3;
end else begin
r <= value;
end
end
endmodule
```
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the FIRRTL IMCP and RemoveInvalids passes and their existing test suite. Use the supplied FIRRTL inputs and MFC/SFC outputs to add coverage for the listed register, reset, module-boundary, and constant-propagation cases; done means the tests record the intended differences without incorrect optimization.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100