当我定义IO时,如何创建向量向量

时间:2017-11-06 00:40:19

标签: chisel

我试图为我的IO定义Vector of Vector,但是我从凿子中得到错误说:

vec element 'Vec(chisel3.util.DecoupledIO@2b57)' must be hardware, not a bare Chisel type

我写的代码如下:

//Module's argument
   ,val ArgsOut: Array[Int]
...
...

val Args = for (i <- 0 until ArgsOut.length) yield {
      val arg = Vec(ArgsOut(i), Decoupled(UInt()))
      arg
 }

 val outputArg = Vec(Args)

4 个答案:

答案 0 :(得分:4)

需要考虑的一些事项

  1. IO端口,即IO Bundle的成员,必须是凿子硬件构造,Args是scala Vector类型,它需要是凿子Vec
  2. Vec的所有元素必须大小相同,这主要是因为需要能够索引Vec的元素。你将Args的每个元素都作为Vec,其长度由ArgsOut的一些元素决定。 Vec(n,type)不会
    1. 真的是要有一个2D Vec(Vec(解耦IO的?)
  3. 您在解耦中的UInt的宽度未知。严格来说这不是错误,因为Firrtl可以在大多数情况下推断出宽度。但同样,对于要求Vec的元素长度相同,这可能是一个问题。应谨慎使用IO中的推断宽度。
  4. 我能够像IOBundle那样构建

      val io = IO(new Bundle {
        val args = Vec(ArgsOut.length, Vec(ArgsOut(0), Decoupled(UInt(18.W))))
        val outputArg = Flipped(args)
      })
    

    哪个编译但可能不是你想到的。我能够使用

    连接io
    io.outputArg <> io.args
    

    如果这似乎不适合您的用例,我需要了解您打算如何使用这些字段,我们应该能够弄清楚如何连接它们。

答案 1 :(得分:3)

以下是如何使用Record的子类来管理不同长度的Vector虚拟数组的说明。这个例子适合我。它与您的示例不完全相同。但我认为它让事情变得更加清晰。这是针对您不需要通过UInt访问Vecs的用例,而是用于何时需要匹配异构混合的Vector。

import chisel3._
import chisel3.iotesters.PeekPokeTester
import org.scalatest.{FreeSpec, Matchers}

import scala.collection.immutable.ListMap

final class VariableBundle(elts: (String, Vec[UInt])*) extends Record {
  val elements = ListMap(elts map { case (field, elt) => field -> elt.chiselCloneType }: _*)
  def apply(elt: String): Vec[UInt] = elements(elt)
  override def cloneType = (new VecVecBundle(elements.toList: _*)).asInstanceOf[this.type]
}

class SeqIO(val sizes: Array[Int]) extends Module {
  val io = IO(new VariableBundle(Seq.tabulate(sizes.length) { i =>
        s"vec_in_$i" -> Input(Vec(sizes(i), UInt(8.W)))
      } ++
      Seq.tabulate(sizes.length) { i =>
        s"vec_out_$i" -> Output(Vec(sizes(i), UInt(8.W)))
      }:_*
    )
  )

  for(i <- sizes.indices) {
    io(s"vec_out_$i") := io(s"vec_in_$i")
  }
}

class SeqIOTester(c: SeqIO) extends PeekPokeTester(c) {
  for(i <- c.sizes.indices) {
    for(j <- 0 until c.sizes(i)) {
      poke(c.io(s"vec_in_$i")(j), j)
    }
  }

  step(1)

  for(i <- c.sizes.indices) {
    for(j <- 0 until c.sizes(i)) {
      expect(c.io(s"vec_out_$i")(j), j)
    }
  }

}

class SeqIOSpec extends FreeSpec with Matchers {
  "illustrate how to build bundles that have vecs wrapping different sized vecs" in {
    iotesters.Driver.execute(Array.empty[String], () => new SeqIO(Array(1, 2, 3, 4))) { c =>
      new SeqIOTester(c)
    } should be (true)
  }
}

答案 2 :(得分:0)

让我写下实际代码:

class LoopLatch(val NumInputs: Int,
                val ArgsOut: Array[Int],
                val ID: Int)
               (implicit val p: Parameters) extends Module with CoreParams with UniformPrintfs {

  val io = IO(new Bundle {
    val inputArg = Vec(NumInputs, Flipped(Decoupled(new DataBundle())))

    val Args = Vec(for (i <- 0 until ArgsOut.length) yield {
      val arg = Vec(ArgsOut(i), Decoupled(new DataBundle()))
      arg
    })

DataBundle()是一种自定义数据类型,我已将其定义在单独的文件中。我真正想做的是。我想将数组传递给模块,如ArgsOut,然后构建Databundle向量的向量,每个后续向量都有自己的Databundle数,它来自输入数组。

答案 3 :(得分:0)

loopLatch模块是我设计的其他模块LiveInNode的包装器。实际上,LoopLatch模块只有这个元素的向量,然后为它提供一个IO。 这是实际的代码:

class LoopStart(val NumInputs: Int,
            val ArgsOut: Array[Int],
            val ID: Int)
           (implicit val p: Parameters) extends Module with CoreParams with UniformPrintfs {

  val io = IO(new Bundle {
    val inputArg = Vec(NumInputs, Flipped(Decoupled(new DataBundle())))
    val Args = Vec(ArgsOut.length, Vec(ArgsOut(0), Decoupled(new DataBundle())))


    val Out = new VecVecBundle(
      Seq("inputArg" -> Vec(NumInputs, Flipped(Decoupled(new DataBundle())))) ++
        (ArgsOut.indices).map { i =>
          val arg = Vec(ArgsOut(i), Decoupled(new DataBundle()))
          s"Args_$i" -> arg
        }:_*
    )

    val pSignal = Vec(NumInputs, Flipped(Decoupled(Bool())))

    val Finish = Vec(NumInputs, Flipped(Decoupled(new ControlBundle())))

  }
  )

  val Args = for (i <- 0 until NumInputs) yield {
    val arg = Module(new LiveInNode(NumOuts = 1, ID = i))
    arg
  }

  //Iterating over each loopelement and connect them to the IO
  for (i <- 0 until NumInputs) {
    Args(i).io.InData <> io.inputArg(i)
    Args(i).io.Finish <> io.Finish(i)
    Args(i).io.pred <> io.pSignal(i)
  }

  for (i <- 0 until ArgsOut.length) {
      io.Out("Args_0") <> Args(i).io.Out
  }

}