【问题标题】:It would be nice to have Vec[Mem] in Chisel在 Chisel 中有 Vec[Mem] 会很好
【发布时间】:2013-10-29 13:18:20
【问题描述】:

如果 Vec[Mem] 用于表示集合关联缓存,那就太好了。

很遗憾,Chisel 不支持 Vec[Mem] 构造:

val tag_ram2    = Vec.fill(num_ways) {Mem(new TagType(), num_sets , seqRead = true )}

确实:

inferred type arguments [Chisel.Mem[cache.TagType]] do not conform to method fill's type     parameter bounds [T <: Chisel.Data]
[error] Error occurred in an application involving default arguments.
[error]     val tag_ram2    = Vec.fill(num_ways) {Mem(new TagType(), num_sets , seqRead = true )}
[error]                               ^
[error] /home/asamoilov/work/projects/my-chisel/Cache.scala:139: type mismatch;
[error]  found   : Chisel.Mem[cache.TagType]
[error]  required: T
[error] Error occurred in an application involving default arguments.
[error]     val tag_ram2    = Vec.fill(num_ways) {Mem(new TagType(), num_sets , seqRead = true )}

但是一个简单的解决方法可以正常工作:

val tag_ram2    = Array.fill(num_ways) {Mem(new TagType(), num_sets , seqRead = true )}
[...]
    is (read_tag) {

        set_idx := req_idx % UInt(num_sets) // FIXME
        for (way_no <- 0 until num_ways) {
            tag_read_vec(way_no) := tag_ram2(way_no)(set_idx)
        }
        controller_state := compare_tag
    }

以及用于编写标签(在某些 when(...) 子句下的原因)

            for (way_no <- 0 until num_ways) {
                when (UInt(way_no) === way_idx) {
                    printf("writing to way %d set %d tag %x\n", way_idx, set_idx, tag_write.toBits)
                    tag_ram2(way_no)(set_idx) := tag_write
                }
            }

意见,改进拟议方案的建议? 谢谢!

【问题讨论】:

  • 功能请求更有可能在 (github.com/ucb-bar/chisel/issues) 或 (groups.google.com/forum/#!forum/chisel-users) 上被看到和响应。我所做的是设置一个 for 循环,并在 for 循环中匿名定义每个银行。对于内存银行,我发现它比尝试使用有效的二维数组非常好(甚至可能更好?)。
  • 你说得对——这实际上是一个二维数组,用于保存 n_ways X n_sets 个标签和数据。我可以看看你的内存银行实现吗?我是 Chisel 的新手,正在寻找最好的 Chisel 风格指南。谢谢!
  • 好的,在 github 上的代码中找到了 2-bank 内存实现:github.com/ucb-bar/riscv-sodor/blob/master/src/rv32_3stage/…
  • 是的,不过我并不为此感到骄傲。我明确命名了每家银行——因此与只有两家银行有关。那是因为我必须匹配一个奇怪的用例,其中外部主机-目标接口 (HTIF) 需要读/写暂存器,这是在 16 字节块中完成的,而处理器通常是 8 字节块(我变得懒惰并且不想处理写入掩码和移位/屏蔽读取数据,因此内存的每一“行”都是一个字宽)。所以处理器读/写 1 个 bank,HTIF 可以在一个周期内跨两个 bank 读/写。

标签: scala hardware hdl digital-logic chisel


【解决方案1】:

对于标签数组,请尝试使用宽度为 (n_tag_sz*n_ways) 的一维位向量。在缓存访问中,无论如何您都读出了整行,并且您希望将其存储在尽可能密集的地方。像这样:

val tag_array = Mem(Bits(width = tagbits*n_ways), n_sets, seqRead = true)  

这里是 i-cache 内存组的 psuedo-code 的 sn-p,它涵盖了 ifgen、ic_access 和 ic_response 的 3 个周期(s0、s1、s2):

val s1_tag_match = Vec.fill(n_ways){Bool()}
val s2_tag_hit = Vec.fill(n_ways){Bool()}
val s2_dout = Vec.fill(n_ways){Reg(Bits())}

for (i <- 0 until n_ways) 
{
   // notice each cycle of refill gets its own line
   val data_array = Mem(Bits(width = n_code_width), n_sets*REFILL_CYCLES, seqRead = true)
   val s1_raddr = Reg(UInt())
   // refill
   when (io.mem.resp.valid && repl_way === UInt(i)) 
   {
      data_array(Cat(s2_idx,rf_cnt)) := io.mem.resp.bits.data
   }
   // read enable
   .elsewhen (s0_valid) 
   {
      s1_raddr := s0_raddr
   }

   // read
   when (s1_valid && s1_tag_match(i) && ready) 
   { 
      s2_dout(i) := data_array(s1_raddr) 
   }
 }

 io.resp.bits.data := Mux1H(s2_tag_hit, s2_dout)

【讨论】:

  • 感谢推荐!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
  • 2016-05-14
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
相关资源
最近更新 更多