使用 UInt 在 Seq 中获取一个项目

Get an item in Seq using UInt

我正在尝试写入高速缓存,因此我创建了一个 Seq 类型的 Mem 因为我正在尝试访问一组高速缓存中的所有元素同时.

val metaMem = Seq.fill(nWays) (Mem((nSets), new MetaData))

然后我想要如下所示的索引:

   metaMem(way).write(set, MD)

但是,因为我的代码中way是UInt,而seq只接受Int进行索引,所以会导致编译错误。 有人对如何解决这个问题有什么建议吗? 非常感谢

通常要使用 UInt 中的动态值访问硬件元素,您必须使用 Vec。在这种情况下,最简单的方法是使用 VecInit 创建一个 Vec,给定一个序列,定义 Vec 并连接你的元素。

但是 内存不是数据的子类(正如Vec/VecInit 所要求的)。 这是一个非常简单的示例,它创建了一个内存库并提供 read/write 对它们的访问。

/** Simulate a VecLike bank of memories
  */
class MemBank(val banks: Int, val bankDepth: Int) extends MultiIOModule {
  val bank = IO(Input(UInt(16.W)))
  val address = IO(Input(UInt(16.W)))
  val isRead = IO(Input(Bool()))
  val inputValue = IO(Input(UInt(32.W)))
  val outputValue = IO(Output(UInt(32.W)))

  val mems = Seq.fill(banks) { Mem(bankDepth, UInt(32.W)) }

  outputValue := DontCare

  when(isRead) {
    (0 until banks).foldLeft(when(false.B) {}) {
      case (whenContext, bankIndex) =>
        whenContext.elsewhen(bank === bankIndex.U) {
          outputValue := mems(bankIndex)(address)
        }
    }
  }.otherwise {
    (0 until banks).foldLeft(when(false.B) {}) {
      case (whenContext, bankIndex) =>
        whenContext.elsewhen(bank === bankIndex.U) {
          mems(bankIndex)(address) := inputValue
        }
    }
  }
}

这是一个单元测试,可以演示如何使用这个模块

class MemBankTest extends FreeSpec with ChiselScalatestTester {

  "MemBankSimulation should work" in {
    test(new MemBank(banks = 3, bankDepth = 3)) { dut =>
      // write values into memory
      dut.isRead.poke(false.B)
      for (bank <- 0 until dut.banks) {
        for (address <- 0 until dut.bankDepth) {
          dut.clock.step()
          dut.bank.poke(bank.U)
          dut.address.poke(address.U)
          dut.inputValue.poke((bank * 1000 + address).U)
        }
      }

      // read values out of memory banks
      dut.isRead.poke(true.B)
      for (bank <- 0 until dut.banks) {
        for (address <- 0 until dut.bankDepth) {
          dut.clock.step()
          dut.bank.poke(bank.U)
          dut.address.poke(address.U)
          println(f"Bank $bank%3d at address $address%3d contains ${dut.outputValue.peek().litValue()}%6d")
        }
      }
    }
  }
}

还有很多其他方法可以做到这一点,我鼓励您查看其他 chisel 项目,例如 rocket-chip 以了解如何处理多个内存。 看看这种方法是如何工作的还是很高兴的。它创建了 MemSeq,但它使用 foldLeft(一种非常有用的方法)创建了一组 Muxes,即 select 您感兴趣的银行。有两个并行使用这个来分别控制读写。 我希望这会有所帮助,这是一个很好但很难回答的问题。