llvm / llvm/circt

[FIRRTL][HW] Feature Request to emit FIRRTL Memories Inline

Open
#5,681 4 comments 0 reactions 0 assignees View on GitHub
FIRRTL good first issue HW
Dominant language
C++
Stars
2.2k
Forks
524
Avg merge
3d 2h
Merged PRs (30d)
46

Description

FIRRTL memories that do not go through the `--repl-seq-mem` path to replace them with blackboxes always produce a wrapper module around the memory. However, this can result in poorer performance for Vivado tooling for designs which rely on Vivado optimizations to optimize certain memory-to-memory paths.

For more information, see the discussion here: https://matrix.to/#/!jSbgpvvpsPbLpsLZOC:matrix.org/$NRsJEcgzZH0ghUHWnRG00OIqkHOLIIutn9WShxiNK6E?via=matrix.org&via=gitter.im&via=austin-harris.com

Add an option that enables inline emission of memories.

#### Example

Input FIRRTL:
```
FIRRTL version 3.0.0
circuit Foo:
module Foo:
input r: {addr: UInt<3>, en: UInt<1>, clk: Clock, flip data: UInt<32>}
input w: {addr: UInt<3>, en: UInt<1>, clk: Clock, data: UInt<32>, mask: UInt<1>}

mem memory :
data-type => UInt<32>
depth => 8
read-latency => 1
write-latency => 1
reader => r
writer => w
read-under-write => undefined

connect memory.r, r
connect memory.w, w
```

Current output Verilog:

```verilog
module memory_8x32(
input [2:0] R0_addr,
input R0_en,
R0_clk,
input [2:0] W0_addr,
input W0_en,
W0_clk,
input [31:0] W0_data,
output [31:0] R0_data
);

reg [31:0] Memory[0:7];
reg _GEN;
reg [2:0] _GEN_0;
always @(posedge R0_clk) begin
_GEN <= R0_en;
_GEN_0 <= R0_addr;
end // always @(posedge)
always @(posedge W0_clk) begin
if (W0_en)
Memory[W0_addr] <= W0_data;
end // always @(posedge)
assign R0_data = _GEN ? Memory[_GEN_0] : 32'bx;
endmodule

module Foo(
input [2:0] r_addr,
input r_en,
r_clk,
input [2:0] w_addr,
input w_en,
w_clk,
input [31:0] w_data,
input w_mask,
output [31:0] r_data
);

memory_8x32 memory_ext (
.R0_addr (r_addr),
.R0_en (r_en),
.R0_clk (r_clk),
.W0_addr (w_addr),
.W0_en (w_en & w_mask),
.W0_clk (w_clk),
.W0_data (w_data),
.R0_data (r_data)
);
endmodule
```

Desired output Verilog:

```verilog
module Foo(
input [2:0] r_addr,
input r_en,
r_clk,
input [2:0] w_addr,
input w_en,
w_clk,
input [31:0] w_data,
input w_mask,
output [31:0] r_data
);

reg [31:0] Memory[0:7];
reg _GEN;
reg [2:0] _GEN_0;
always @(posedge r_clk) begin
_GEN <= r_en;
_GEN_0 <= r_addr;
end // always @(posedge)
always @(posedge w_clk) begin
if (w_en)
Memory[w_addr] <= w_data;
end // always @(posedge)
assign r_data = _GEN ? Memory[_GEN_0] : 32'bx;

endmodule
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Begin with the FIRRTL memory emission path that produces the wrapper shown in the current Verilog, then compare it with the desired inline output. Define the new option around inline memory emission and verify that this example no longer adds the memory_8x32 module. The issue names no source file or test, so locating the relevant emitter and adding coverage is part of the work.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Feature
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.