您可以使用 Scala FIRRTL 编译器的“替换顺序记忆”传递来黑盒记忆。这正是 Rocket Chip 正在发生的事情。
请注意,这仅限于仅在内存具有单个读取端口和单个写入端口并且读取延迟为 1 和写入延迟为 1 时才有效。
例如,考虑以下 1r1w(一读一写)SyncReadMem:
import chisel3._
class Foo extends MultiIOModule {
val read = IO(new Bundle {
val en = Input(Bool())
val addr = Input(UInt(8.W))
val data = Output(UInt(1.W))
})
val write = IO(new Bundle{
val en = Input(Bool())
val addr = Input(UInt(8.W))
val data = Input(UInt(1.W))
})
val bar = SyncReadMem(256, UInt(1.W))
read.data := bar.read(read.addr, read.en)
when (write.en) {
bar.write(write.addr, write.data)
}
}
如果您通过运行替换顺序内存传递的请求来编译它:
(new ChiselStage)
.emitVerilog(new Foo, Array("--repl-seq-mem", "-c:Foo:-o:Foo.mem.conf"))
这里使用的参数是-c:<circuit>,其中<circuit> 是您要运行的电路的名称,-o:<mem-conf-file> 是要生成的文件的名称,该文件将包含信息(例如,名称、宽度和深度)被黑盒化的记忆。
你最终会在一个名为 bar_ext 的新模块 bar 中获得内存黑盒:
module bar(
input [7:0] R0_addr,
input R0_en,
input R0_clk,
output R0_data,
input [7:0] W0_addr,
input W0_en,
input W0_clk,
input W0_data
);
wire [7:0] bar_ext_R0_addr;
wire bar_ext_R0_en;
wire bar_ext_R0_clk;
wire bar_ext_R0_data;
wire [7:0] bar_ext_W0_addr;
wire bar_ext_W0_en;
wire bar_ext_W0_clk;
wire bar_ext_W0_data;
bar_ext bar_ext (
.R0_addr(bar_ext_R0_addr),
.R0_en(bar_ext_R0_en),
.R0_clk(bar_ext_R0_clk),
.R0_data(bar_ext_R0_data),
.W0_addr(bar_ext_W0_addr),
.W0_en(bar_ext_W0_en),
.W0_clk(bar_ext_W0_clk),
.W0_data(bar_ext_W0_data)
);
assign bar_ext_R0_clk = R0_clk;
assign bar_ext_R0_en = R0_en;
assign bar_ext_R0_addr = R0_addr;
assign R0_data = bar_ext_R0_data;
assign bar_ext_W0_clk = W0_clk;
assign bar_ext_W0_en = W0_en;
assign bar_ext_W0_addr = W0_addr;
assign bar_ext_W0_data = W0_data;
endmodule
然后,您可以运行内存编译器来使用内存配置文件中的信息并删除输出以代替 bar_ext。