如何使用ScalaBlackBox编写累加器?

时间:2019-06-07 13:05:56

标签: chisel

我想为dsptools创建一些类似DspReal的新数字类型,例如DspPosit和DspQuire。 DspPosit基于posit,我有一些Java代码,而DspQuire基于quire,后者是posit的一种累加器。因为我现在只想模拟,所以我为它们的操作编写了许多ScalaBlackBox,例如DspReal。但是,我发现ScalaBlackBox无法构造顺序逻辑。例如,查询累加器的当前输出取决于其输入和最后一个输出。但是ScalaBlackBox无法获取输出值。另外,步骤(n)也影响输出。因为累加器将在每个时钟周期读取其输入。

我发现了踏板的一些系统问题。首先,ScalaBlackBox,twoOp和oneOp等功能将被多次调用。我不知道为什么其次,step(n)是PeekPokeTester的功能,ScalaBlackBox无法访问它。第三,我尝试读取当前输出,但系统给出了错误。

trait DspBlackBlackBoxImpl extends BlackBoxImplementation with ScalaBlackBox

abstract class DspQuireAccumulator extends DspBlackBlackBoxImpl {

  lazy val accValue = Quire32() // initial value

  /**
    * sub-classes must implement this two argument function
    *
    * @param posit  accumulate element
    * @return       quire operation result
    */
  def accOp(posit: Posit32): Unit

  def outputDependencies(outputName: String): Seq[(String)] = {
    outputName match {
      case "out" => Seq("in") // Seq("out", "in") gives errors
      case _ => Seq.empty
    }
  }

  def cycle(): Unit = {}

  def execute(inputValues: Seq[Concrete], tpe: Type, outputName: String): Concrete = {
    val arg1 :: _ = inputValues
    val positArg = Posit32(arg1.value)
    accOp(positArg)
    val result = quire32ToBigInt(accValue)
    ConcreteSInt(result, DspQuire.underlyingWidth, arg1.poisoned).asUInt
  }

  def getOutput(inputValues: Seq[BigInt], tpe: Type, outputName: String): BigInt = {
    val arg1 :: _ = inputValues
    val positArg = Posit32(arg1)
    accOp(positArg)
    quire32ToBigInt(accValue)
  }
}
class DspQuireAddAcc(val name: String) extends DspQuireAccumulator {
  def accOp(posit: Posit32): Unit = accValue += posit
}
class QuireBlackboxAccOperand extends BlackBox {
  val io = IO(new Bundle() {
    val in = Input(UInt(DspPosit.underlyingWidth.W))
    val out = Output(UInt(DspQuire.underlyingWidth.W))
  })
}

class BBQAddAcc extends QuireBlackboxAccOperand

class TreadleDspQuireFactory extends ScalaBlackBoxFactory {
  def createInstance(instanceName: String, blackBoxName: String): Option[ScalaBlackBox] = {
    blackBoxName match {
      case "BBQAddAcc" => Some(add(new DspQuireAddAcc(instanceName)))
...

accOp将被调用多次。因此,如果我要累加List(1、2、3),结果可能是0 +1 +1 +1 2 2 ... 并且peek函数将再次调用accOp,这也让我感到困惑。

1 个答案:

答案 0 :(得分:2)

我相信您目前的大多数问题是由两种不同的方法混合引起的。我认为您不应该使用BlackBoxImplmentation,因为它是firrtl-interpreter中使用的较旧方案。只需使用ScalaBlackBox并实现wiki页面Black Boxes and Treadle中所述和TreadleTest BlackBoxWithState中所示的方法即可。

不要使用outputDependencies,而是使用getDependencies指定输入和输出之间的任何依赖关系。每当更改输入IO时,就会调用inputChanged。因此,在这种方法中,您要记录或更新黑匣子的内部状态。 clockChange会在时钟改变时被调用,并会提供转换信息,因此您可以决定随后会发生什么。只要您不需要使用getOutput,Treadle就会调用outputDependencies,因为您不会使用lambda,因此您可以忽略输入,而仅根据内部状态提供输出值。

我仍在这里尝试复制您的代码的运行版本,但是如果您可以尝试上面的建议并让我知道如何进行,这将是我一点时间将其组合在一起的方法。我有兴趣使Treadle的此功能更好,更易于使用,因此感谢所有反馈。