为什么 DspContext 不能像 withNumAddPipes 这样工作?

Why doesn't the DspContext work such as withNumAddPipes?

最近在研究DspContext,在dsptools中输入类。我只是根据教程运行一个测试代码。它展示了如何将管道添加到数学运算中。但是我发现这个例子没有按预期工作。 这是示例代码:

class SimpleDspIo[T <: Data:RealBits](gen: T) extends Bundle {
  val x = Input(gen.cloneType)
  val y = Input(gen.cloneType)
  val z = Output(gen.cloneType)
  override def cloneType: this.type = new SimpleDspIo(gen).asInstanceOf[this.type]
}

class SimpleDspModule[T <: Data:RealBits](gen: T, val addPipes: Int) extends Module {
  val io = IO(new SimpleDspIo(gen))

  DspContext.withNumAddPipes(addPipes) { 
    io.z := io.x + io.y
  }
} 

及其测试程序:

class SimpleDspModuleTester[T <: Data:RealBits](c: SimpleDspModule[T]) extends DspTester(c) {
  val x = Seq(-1.1, -0.4, 0.4, 1.1)
  val z = x map (2 * _)
  for (i <- 0 until (x.length + c.addPipes)) {
    val in = x(i % x.length)

    poke(c.io.x, in)

    updatableDspVerbose.withValue(false) {
      poke(c.io.y, in)
    }

    step(1)

    peek(c.io.z)
  }
}

class SimpleDspModuleSpec extends FlatSpec with Matchers {

  val testOptions = new DspTesterOptionsManager {
    dspTesterOptions = DspTesterOptions(
        fixTolLSBs = 1,
        isVerbose = true)

    commonOptions = commonOptions.copy(targetDirName = "test_run_dir/simple_dsp_fix")
  }

  behavior of "simple dsp module"

  it should "properly add fixed point types" in {
    dsptools.Driver.execute(() => new SimpleDspModule(FixedPoint(16.W, 12.BP), addPipes = 3), testOptions) { c =>
      new SimpleDspModuleTester(c)
    } should be (true)
  }

当我运行它时,终端显示:

[info] [0.001] SEED 1560341324819
[info] [0.005]   POKE SimpleDspModule.io_x <- -1.1, Q3.12
[info] [0.005] STEP 1x -> 1
[info] [0.006]   PEEK SimpleDspModule.io_z -> -2.2001953125, Q3.12
[info] [0.006]   POKE SimpleDspModule.io_x <- -0.4, Q3.12
[info] [0.006] STEP 1x -> 2
[info] [0.006]   PEEK SimpleDspModule.io_z -> -0.7998046875, Q3.12
[info] [0.006]   POKE SimpleDspModule.io_x <- 0.4, Q3.12
[info] [0.007] STEP 1x -> 3
[info] [0.007]   PEEK SimpleDspModule.io_z -> 0.7998046875, Q3.12
[info] [0.007]   POKE SimpleDspModule.io_x <- 1.1, Q3.12
[info] [0.007] STEP 1x -> 4
[info] [0.007]   PEEK SimpleDspModule.io_z -> 2.2001953125, Q3.12
[info] [0.007]   POKE SimpleDspModule.io_x <- -1.1, Q3.12
[info] [0.007] STEP 1x -> 5
[info] [0.007]   PEEK SimpleDspModule.io_z -> -2.2001953125, Q3.12
[info] [0.008]   POKE SimpleDspModule.io_x <- -0.4, Q3.12
[info] [0.008] STEP 1x -> 6
[info] [0.008]   PEEK SimpleDspModule.io_z -> -0.7998046875, Q3.12
[info] [0.008]   POKE SimpleDspModule.io_x <- 0.4, Q3.12
[info] [0.008] STEP 1x -> 7
[info] [0.008]   PEEK SimpleDspModule.io_z -> 0.7998046875, Q3.12

输出是立即生成的,而不是正确延迟的。更进一步,我发现正确的方法是调用函数plusContext。就像这样:

class SimpleDspIo extends Bundle {
  val x = Input(FixedPoint(16.W, 12.BP))
  val y = Input(FixedPoint(16.W, 12.BP))
  val z = Output(FixedPoint(16.W, 12.BP))
}

class SimpleDspModule(val addPipes: Int) extends Module {
  val io = IO(new SimpleDspIo)

  DspContext.withNumAddPipes(addPipes) { 
    io.z := FixedPointRealImpl.plusContext(io.x, io.y)
  }
}

现在,它按预期工作:

[info] [0.000] SEED 1560343025741
[info] [0.004]   POKE SimpleDspModule.io_x <- -1.1, Q3.12
[info] [0.005] STEP 1x -> 1
[info] [0.005]   PEEK SimpleDspModule.io_z -> 0.0, Q3.12
[info] [0.005]   POKE SimpleDspModule.io_x <- -0.4, Q3.12
[info] [0.005] STEP 1x -> 2
[info] [0.006]   PEEK SimpleDspModule.io_z -> 0.0, Q3.12
[info] [0.006]   POKE SimpleDspModule.io_x <- 0.4, Q3.12
[info] [0.006] STEP 1x -> 3
[info] [0.006]   PEEK SimpleDspModule.io_z -> -2.2001953125, Q3.12
[info] [0.006]   POKE SimpleDspModule.io_x <- 1.1, Q3.12
[info] [0.006] STEP 1x -> 4
[info] [0.006]   PEEK SimpleDspModule.io_z -> -0.7998046875, Q3.12
[info] [0.006]   POKE SimpleDspModule.io_x <- -1.1, Q3.12
[info] [0.007] STEP 1x -> 5
[info] [0.007]   PEEK SimpleDspModule.io_z -> 0.7998046875, Q3.12
[info] [0.007]   POKE SimpleDspModule.io_x <- -0.4, Q3.12
[info] [0.007] STEP 1x -> 6
[info] [0.007]   PEEK SimpleDspModule.io_z -> 2.2001953125, Q3.12
[info] [0.007]   POKE SimpleDspModule.io_x <- 0.4, Q3.12
[info] [0.007] STEP 1x -> 7
[info] [0.007]   PEEK SimpleDspModule.io_z -> -2.2001953125, Q3.12

没有明确的方法可以将“+”转换为 "plusContext"(和其他函数)。 dsptools 是否未完成?

在旧版本的 dsptools 中,您的原始代码会按预期工作。但是,+ 行为取决于是否存在类型类的隐式,这常常令人困惑。如果我没记错的话,对您的导入进行看似无害的更改可能会极大地改变您的电路行为。

我们最终做出的决定是,如果凿子类型具有运算符,则类型类永远不应更改该行为。如果要使用使用上下文的运算符版本(流水线、舍入等),则必须使用单独的运算符,这些运算符都以 context_ 作为前缀。 a + ba context_+ b 不能混淆。

我仍然不完全满意 context_ 作为前缀。也许我们应该为这些运算符添加一些 shorthand,但我认为在这种情况下清晰比简洁更重要。