Chisel3 REPL Vec 分配到模块中仅在 eval 之后有效

Chisel3 REPL Vec assignment into module only works after eval

如果我们运行下面的Chisel3代码

class Controller extends Module {

  val io = IO(new Bundle {
  })
  val sff = Module(new SFF)

  val frame: Vec[UInt] = Reg(Vec(ProcedureSpaceSize, Integer32Bit))
  for(i <- 0 until ProcedureSpaceSize)
    frame(i) := 99.U

  sff.io.inputDataVector := frame
}

class SFF extends Module {

  val io = IO(new Bundle {
    val inputDataVector: Vec[UInt] = Input(Vec(ProcedureSpaceSize, Integer32Bit))
  })

}

处于 REPL 调试模式。先做

reset;step

peek sff.io_inputDataVector_0;peek sff.io_inputDataVector_1;peek sff.io_inputDataVector_2

REPL returns

Error: exception Error: getValue(sff.io_inputDataVector_0) returns value not found
Error: exception Error: getValue(sff.io_inputDataVector_1) returns value not found
Error: exception Error: getValue(sff.io_inputDataVector_2) returns value not found

然后做

eval sff.io_inputDataVector_0

这将是成功的,产生

...
resolve dependencies
  evaluate     sff.io_inputDataVector_0 <= frame_0
  evaluated    sff.io_inputDataVector_0 <= 99.U<32>

然后再次执行上面的 peek

peek sff.io_inputDataVector_0;peek sff.io_inputDataVector_1;peek sff.io_inputDataVector_2;

这次,returns

peek sff.io_inputDataVector_0  99
peek sff.io_inputDataVector_1  99
peek sff.io_inputDataVector_2  99

哪个更值得期待

为什么REPL会这样?还是我错过了什么?谢谢!

*chisel-iotesters 是版本 1.4.2chiseltest 是版本 0.2.2。两者都应该是最新版本。

我认为您看到的问题是由于死代码消除,您所有的连线都被消除了。有几件事你应该尝试解决这个问题。

  • 确保你的电线有有意义的连接。最终不会影响输出的硬件很可能会被淘汰。在您的示例中,您没有任何驱动顶级输出的东西
  • 您可能需要您的电路使用这些寄存器计算一些东西。如果寄存器初始化为 99,则常量传播可能会消除它们。我不确定你想让电路做什么,所以很难给出具体的建议。

如果您完成上述操作,我认为 repl 将按预期工作。我对你使用的 repl 有疑问(有两个:firrtl-interpreter 和 treadle)我建议使用后者。它更现代并且得到更好的支持。它还有两个有用的命令

  • show lofirrtl 将向您显示降低的 firrtl,这就是您可以看到 chisel3 发出的高 firrtl 中的很多内容已更改的方式。
  • symbol . 显示电路中的所有符号(. 是匹配所有内容的正则表达式。

这是根据您的 frame Vec 驱动和输出的电路的随机编辑。该电路将生成 firrtl,它不会消除您要查看的电线。

class Controller extends Module {
  val io = IO(new Bundle {
    val out = Output(UInt(32.W))
  })
  val sff = Module(new SFF)

  val frame: Vec[UInt] = Reg(Vec(ProcedureSpaceSize, Integer32Bit))
  when(reset.asBool()) {
    for (i <- 0 until ProcedureSpaceSize) {
      frame(i) := 99.U
    }
  }
  frame.zipWithIndex.foreach { case (element, index) => element := element + index.U }
  sff.io.inputDataVector := frame
  io.out := sff.io.outputDataVector.reduce(_ + _)

}

class SFF extends Module {

  val io = IO(new Bundle {
    val inputDataVector: Vec[UInt] = Input(Vec(ProcedureSpaceSize, Integer32Bit))
    val outputDataVector: Vec[UInt] = Output(Vec(ProcedureSpaceSize, Integer32Bit))
  })

  io.outputDataVector <> io.inputDataVector
}

firrtl 解释器 REPL 不一定计算或存储未使用的 mux 分支上的值。这可能会导致上述问题,如

Error: exception Error: getValue(sff.io_inputDataVector_0) returns value not found.

eval 可用于强制对未使用的分支进行评估。 REPL 是一个实验性功能,还没有太多用处。

treadle 是更现代的凿子 scala-based 模拟器。它比解释器得到更好的支持并且更快。它有自己的 REPL,但没有 executeFirrtlRepl 等价物。

必须通过根目录中的./treadle.sh脚本从命令行运行。还可以 运行 sbt assembly 创建一个更快的启动 jar,它被放置在 utils/bin 中。这个 REPL 也没有被大量使用,但我对反馈感兴趣,这将使它更好、更容易使用。