2

我有一个像这样的模块......

class ApbSplitter (clients : List[ApbRange]) extends MultiIOModule {
  val nApb = clients.length

  val apb   = IO(Vec(nApb, new ApbChannel()))
  val apb_m = IO(Flipped(new ApbChannel))
  ...

我想做的是向 Vec 的每个元素提出建议名称,这样就可以代替前缀 asapb_0_ apb_1_等等......这是我为每个元素提供的任何内容。

我可以apb.suggestName,但这只会影响前导前缀,并且数组索引仍然存在。做apb(idx).suggestName("blah")编译但没有效果。

有什么办法可以做到这一点?

4

3 回答 3

2

通过消除 Vec 并创建 IO 列表来实现这一点

case class ApbRange (name: String, loAddr : Int, hiAddr : Int)

class ApbSplitter (clients : List[ApbRange]) extends MultiIOModule {
  val apb = clients.map({x => IO(new ApbChannel).suggestName(x.name)})
  val apb_m = IO(Flipped(new ApbChannel))
  ...

不确定这是否是规范的,但似乎可以解决问题。

于 2021-05-04T19:25:41.843 回答
0

我猜你的新 apbChannel 有一堆输入输出信号或电线。因此,如果您的 apbChannel 有(比如说)val ip = Input(Bool())您可以这样做,而不是 apb(idx).suggestNameapb(idx).ip.suggestName("blah")

于 2021-05-04T17:38:41.483 回答
0

用布赖恩的其他帖子回答这个问题,并记住他自己对这个帖子的回答。这将是一个很长的答案,因为它涉及到 Chisel API 中的几个缺陷,这些缺陷正在改进但在当前版本中肯定是相关的(截至 2021 年 8 月 12 日的 v3.4.3)。

Brian 的回答是正确的,如果您想命名需要使用 aSeq而不是 a的各个字段Vec。这样做的原因是,从 Chisel 的角度来看,an IOof typeVec是具有聚合类型的单个端口,而 theSeq只是一系列不相关的端口。这Seq是一个 Scala 构造(而Vec来自 Chisel),所以 Chisel 本身并不知道Seq.

那么问题是你需要一个Vec做动态索引。您可以在需要进行动态索引时使用从您VecInit的动态索引创建:WireSeq

例如

class MyModule(names: Seq[String]) extends RawModule {
  val enq = names.map(n => IO(Flipped(Decoupled(UInt(8.W)))).suggestName(n))
  val idx = IO(Input(UInt(log2Ceil(names.size).W)))
  val deq = IO(Decoupled(UInt(8.W)))
 
  // enqWire connects all fields of enq
  val enqWire = VecInit(enq)
  // Need to make sure backpressure is always driven
  enqWire.foreach(_.ready := false.B)
  deq <> enqWire(idx)
}

只要deq它本身是一个端口,这将起作用。如果是 Wire则它将不起作用,因为它是可交换运算符,因此在连接 2 条双向线时会模棱两可。如需更详细的说明,请参阅此 PR 评论deq<>

如果出于某种原因deq需要,您可以使用一个将Vecs作为端口的辅助模块:Wire

例如

class InnerHelper(n: Int) extends RawModule {
  val enq = IO(Flipped(Vec(n, Decoupled(UInt(8.W)))))
  val idx = IO(Input(UInt(log2Ceil(n).W)))
  val jdx = IO(Input(UInt(log2Ceil(n).W)))
  val deq = IO(Vec(n, Decoupled(UInt(8.W))))
  
  // backpressure defaults
  enq.foreach(_.ready := false.B)
  deq.foreach { x =>
    x.valid := false.B
    x.bits := DontCare
  }
  
  deq(jdx) <> enq(idx)
}

class MyModule(names: Seq[String]) extends RawModule {
  val enq = names.map(n => IO(Flipped(Decoupled(UInt(8.W)))).suggestName(n))
  val idx = IO(Input(UInt(log2Ceil(names.size).W)))
  val jdx = IO(Input(UInt(log2Ceil(names.size).W)))
  val deq = names.map(n => IO(Decoupled(UInt(8.W))).suggestName(s"${n}_out"))
  
  val helper = Module(new InnerHelper(names.size))
  helper.enq <> enq
  helper.idx := idx
  helper.jdx := jdx
  helper.deq <> deq
}

这有点痛苦,但它至少解决了歧义。我们可以构建其他实用程序——例如,InnerHelper我们可以创建一个实用程序方法来创建一个模块,以便动态索引 a 的返回值Seq是一个新子模块的端口,而不是为每个案例定制一个实用程序,但它是一个有点棘手。

好消息是,一种更好的方法即将到来—— Ch​​isel 3.5 中的DataView应该可以将a视为Seqa Vec(而不是必须使用VecInitwhich 创建 a Wire),这使得更容易避免这种Wire <>连接歧义问题。我也希望要么“修复” <>Wires,要么提供一个新的非可交换运算符:<>,但尚未开发。

于 2021-08-12T19:00:06.037 回答