表达式 _GEN_7 用作 FEMALE 但只能用作 MALE

Expression _GEN_7 is used as a FEMALE but can only be used as a MALE

我正在尝试为 firrtl 编写一个 Scala 转换,在某些时候,我有一堆电线应该连接到输入端口。因为电线的数量可能很多,我不想将每根电线都连接到一个端口,而是将所有电线连接在一起并使用一个宽度更大的端口。

我正在使用 seqCat 函数:

 val seq_cat = seqCat(wires.map(x=>WRef(x.name,port.tpe,WireKind,BIGENDER))) 

然后我接上猫的输出,就是几只猫组成的表达式:

val connect_pin = Connect(NoInfo, seq_cat, WRef(port.name, port.tpe, PortKind, BIGENDER))

因为connect_pin的表达式比较复杂:

Connect(,DoPrim(cat,List(WRef(_GEN_0,UIntType(IntWidth(3)),WireKind,BIGENDER), DoPrim(cat,ArrayBuffer(WRef(_GEN_1,UIntType(IntWidth(3)),WireKind,BIGENDER), WRef(_GEN_2,UIntType(IntWidth(3)),WireKind,BIGENDER)),List(),UIntType(UnknownWidth))),List(),UIntType(UnknownWidth)),WRef(faultPin,UIntType(IntWidth(3)),PortKind,BIGENDER))

我尝试使用 Chisel Bootcamp 上提供的 Splitter 函数将其拆分为更简单的节点,splitter 的输出是预期的:

Block(ArrayBuffer(DefNode(,_GEN_6,DoPrim(cat,ArrayBuffer(WRef(_GEN_1,UIntType(IntWidth(3)),WireKind,BIGENDER), WRef(_GEN_2,UIntType(IntWidth(3)),WireKind,BIGENDER)),List(),UIntType(UnknownWidth))), DefNode(,_GEN_7,DoPrim(cat,List(WRef(_GEN_0,UIntType(IntWidth(3)),WireKind,BIGENDER), WRef(_GEN_6,UIntType(UnknownWidth),ExpKind,UNKNOWNGENDER)),List(),UIntType(UnknownWidth))), Connect(,WRef(_GEN_7,UIntType(UnknownWidth),ExpKind,UNKNOWNGENDER),WRef(faultPin,UIntType(IntWidth(3)),PortKind,BIGENDER))))

当我 运行 转换时,出现 运行 时间错误:

======== Starting Transform CheckGenders$ ========
[error] (run-main-0) firrtl.passes.CheckGenders$WrongGender:  @[:Top_adder_muxed.fir@22.2]: [module Top_adder]  Expression _GEN_7 is used as a FEMALE but can only be used as a MALE.
[error] firrtl.passes.CheckGenders$WrongGender:  @[:Top_adder_muxed.fir@22.2]: [module Top_adder]  Expression _GEN_7 is used as a FEMALE but can only be used as a MALE.
[error]     at firrtl.passes.CheckGenders$.firrtl$passes$CheckGenders$$check_gender(Checks.scala:511)
[error]     at firrtl.passes.CheckGenders$.firrtl$passes$CheckGenders$$check_genders_s(Checks.scala:542)
[error]     at firrtl.passes.CheckGenders$$anonfun$firrtl$passes$CheckGenders$$check_genders_s.apply(Checks.scala:558)
[error]     at firrtl.passes.CheckGenders$$anonfun$firrtl$passes$CheckGenders$$check_genders_s.apply(Checks.scala:558) ``` ``` 

我不明白为什么会出现这个错误,它只是一根线,应该连接到输入端口。事实上,这根电线是猫的输出,它并不能使它成为 MALE,因为只是将一些电线放在一起,猫操作员不会合成任何驱动电线的驱动程序。

如果你对此有任何提示,我在这个错误上被困了几天。

问题是原始操作(DoPrims)的输出是MALE(新术语中的SourceFlow,基本上是只读值)。虽然概念上将连线连接在一起并不一定意味着它是只读的,但在 FIRRTL 的语义中确实如此。这在 FIRRTL Spec 的第 8 节中有描述:"The flow of all other expressions are source"。

所以这给我们留下了一个问题,即如何完成将单个端口连接到多条线。您可以使用多个连接来执行此操作。这是代码的草图,当然,这取决于您的具体类型:

// Assuming 3-bit wires and UInt port as suggested by the code in the question
val portRef = WRef(port) // same as val portRef = WRef(port.name, port.tpe, PortKind, UNKNOWNGENDER)
val cons = wires.zipWithIndex.map { case (wire, idx) =>
  val msb = (idx * 3) - 1
  val lsb = msb - 2
  val rhs = DoPrim(PrimOps.Bits, Seq(portRef), Seq(msb, lsb), UIntType(IntWidth(3)))
  val lhs = WRef(wire) // same as WRef(wire.name, wire.tpe, WireKind, UNKNOWNGENDER)
  Connect(NoInfo, lhs, rhs)
}

所有这些逻辑都可以包含在一个可重用的实用程序函数中,这可能非常有用,当然这样的实用程序需要适用于其他类型(不仅仅是 UInts)。