Scala 期权影响

Scala Option Impact

我在使用 scala .getorElse 命令时遇到问题。我想一直生成 AVec,但我只希望在 elemA >= 50 时生成 AVecBVec,最后,我希望在 [=16] 时生成所有这些=].我试过 .get 但没有成功,下面你可以看到 .getorElse.

的实现

任何关于如何正确实施的建议将不胜感激。谢谢!

 val AVec = Reg(Vec(10, Valid(Vec(10, UInt(8.W)))))

 val BVec = if(elemA >= 50){
   Some(Reg(Vec(11, Valid(Vec(11, UInt(8.W))))))
 } else {
   None
 }

 val CVec = if(elemA >= 100){
   Some(Reg(Vec(12, Valid(Vec(12, UInt(8.W))))))
 } else {
   None
 }


 when(io.elemB.fire()){
   when(io.elemC === 0.U){
     AVec.map{_.valid := false.B}
   }.elsewhen(io.elemC === 1.U){
     AVec.map{_.valid := false.B}
     BVec.getOrElse(AVec).map{_.valid := false.B}
   }.otherwise{
     AVec.map{_.valid := false.B}
     BVec.getOrElse(AVec).map{_.valid := false.B}
     CVec.getOrElse(CVec).map{_.valid := false.B} //<------Issues coming here
   }
 }

考虑到您的写作风格,为什么不呢?

CVec.getOrElse(AVec).map{_.valid := false.B}

话虽如此,Option 有更多惯用的方法。我建议在 Scala 中查看一些关于 Option 的教程,例如。 https://www.baeldung.com/scala/option-type

特别是,您并不总是需要“获取”Option。将 Option 视为具有零个或一个元素的 ListArray。就像您可以 mapforeach a List(或您在这里做的 chisel3 Vec)一样,您可以 mapforeach一个 Option。考虑以下因素:

 when(io.elemB.fire()){
   when(io.elemC === 0.U){
     // Note that I used () instead of {}, this is a stylistic choice
     // Generally you use {} only when there are multiple Statements in the anonymous function
     // If this doesn't make sense to you yet, just ignore it, it's fine to use {} :)
     AVec.map(_.valid := false.B)
   }.elsewhen(io.elemC === 1.U){
     AVec.map(_.valid := false.B)
     BVec.foreach(_.map(_.valid := false.B))
   }.otherwise{
     AVec.map(_.valid := false.B)
     BVec.foreach(_.map(_.valid := false.B))
     CVec.foreach(_.map(_.valid := false.B))
   }

就像 AVec.map(f)f 应用于 Vec 的每个元素一样,BVec.foreach(g)g 应用于 BVec 的内容,如果它是 Some,否则什么都不做。这是 2 层函数嵌套深度,当您不熟悉 Chisel/Scala 时可能看起来有点陌生,但这是表达它的常用方式。

或者,您可以测试选项并使用 .get,这对于函数式编程的新手(即大多数 Chisel 新手)来说通常更熟悉:

 when(io.elemB.fire()){
   when(io.elemC === 0.U){
     AVec.map(_.valid := false.B)
   }.elsewhen(io.elemC === 1.U){
     AVec.map(_.valid := false.B)
     if (BVec.isDefined) {
       BVec.get.map(_.valid := false.B)
     }
   }.otherwise{
     AVec.map(_.valid := false.B)
     if (BVec.isDefined) {
       BVec.get.map(_.valid := false.B)
     }
     if (CVec.isDefined) {
       CVec.get.map(_.valid := false.B)
     }
   }

如果这看起来有点冗长(你必须写两次 CVec),那就是 foreach 的目的。这个“如果定义,做 .get 并做某事”字面意思是 Option.foreachimplementation