在FIRRTL中更新内存元素的"部分"的惯用方法是什么?当更新缓存中一行的一个条目时,就会出现这种情



在FIRRTL中写一个寄存器文件很简单:创建一个机器单词的内存并读写它们。

然而,当写入缓存时,它是不同的:您通常有一个缓存行,而在写入时,只想更新行的部分,缓存行的单个元素。

在FIRRTL中做这件事的惯用方法是什么?(请不要指出我在凿子火箭实现,因为我发现凿子是完全不可读的。)

我能想到至少两种方法:

(1)使内存包含Vector或Bundle,然后选择内存元素的成员,如下所示:

cmem mem1 : {x:SInt<64>,y:SInt<64>}[4]
infer mport temp_x_mem1 = mem1[i].x, clock
temp_x_mem1 <= foo

(2)执行一些read-modify-write操作,如下所示:

cmem mem1 : {x:SInt<64>,y:SInt<64>}[4]
infer mport temp_x_mem1 = mem1[i], clock
bar <= temp_x_mem1
bar.x <= foo
infer mport temp_x_mem1_B = mem1[i], clock
temp_x_mem1_B <= bar

我从另一种格式生成我的FIRRTL,我没有计划这样做,所以当我生成内存时,唯一直接的方法是读取或写入整个内存元素,而不是其中的一部分。因此,方法(1)是困难的,但方法(2)是直接的。如果所有代码都发生在同一模块中,那么FIRRTL优化器或随后的Verilog优化器的某些层是否会使方式(2)与方式(1)一样有效地工作?

最简单的方法是使用FIRRTL内存结构(mem)而完全避免chrirtl (cmem/smem)。前者为您提供内存上的显式掩码端口。这就使您能够描述您想要的掩码写入。FIRRTL内存结构没有Chisel API,但听起来你正在使用其他东西,所以这可能不是问题。

方法(1)将不起作用,因为您不能使用部件选择来描述内存端口。(infer mport temp_x_mem1 = mem1[i].x, clock是非法的。)方法(2)是有效的,但是你要付出周期惩罚。

还有第三种惯用的方法,它涉及到以这样一种方式描述内存,即FIRRTL编译器将推断出掩码。这是通过保护when语句后面的写操作来实现的,该语句包含enable:

circuit Foo:
module Foo:
input clock: Clock
input i: UInt<2>
input mask: {x: UInt<1>, y: UInt<1>}
input data: {x: SInt<64>, y: SInt<64>}
cmem mem1 : {x:SInt<64>,y:SInt<64>}[4]
infer mport temp_x_mem1 = mem1[i], clock
when eq(mask.x, UInt<1>(1)):
temp_x_mem1.x <= data.x
when eq(mask.y, UInt<1>(1)):
temp_x_mem1.y <= data.y

基于scala的FIRRTL编译器或基于mlr的FIRRTL编译器将推断when条件作为掩码。

基于mlr的FIRRTL编译器输出:

circuit Foo :
module Foo :
input clock : Clock
input i : UInt<2>
input mask : { x : UInt<1>, y : UInt<1> }
input data : { x : SInt<64>, y : SInt<64> }
mem mem1 : 
data-type => { x : SInt<64>, y : SInt<64> }
depth => 4
read-latency => 0
write-latency => 1
writer => temp_x_mem1
read-under-write => undefined
mem1.temp_x_mem1.addr is invalid 
mem1.temp_x_mem1.en <= UInt<1>(0) 
mem1.temp_x_mem1.clk is invalid 
mem1.temp_x_mem1.data is invalid 
mem1.temp_x_mem1.mask is invalid 
mem1.temp_x_mem1.addr <= i
mem1.temp_x_mem1.en <= UInt<1>(1) 
mem1.temp_x_mem1.clk <= clock 
mem1.temp_x_mem1.mask.x <= UInt<1>(0) 
mem1.temp_x_mem1.mask.y <= UInt<1>(0) 
when eq(mask.x, UInt<1>(1)) : 
mem1.temp_x_mem1.mask.x <= UInt<1>(1) 
mem1.temp_x_mem1.data.x <= data.x 
when eq(mask.y, UInt<1>(1)) : 
mem1.temp_x_mem1.mask.y <= UInt<1>(1) 
mem1.temp_x_mem1.data.y <= data.y 

最新更新