最近,我一直在研究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是否未完成?
答案 0 :(得分:2)
在较早版本的dsptools中,您的原始代码将按预期工作。但是,使+
的行为取决于是否存在类型类的隐含对象,这常常令人困惑。如果我没记错的话,看似无害的进口更改可能会极大地改变电路的行为。
我们最终做出的决定是,如果凿子类型具有运算符,则类型类永远都不应更改该行为。如果要使用使用上下文的运算符版本(流水线,舍入等),则必须使用单独的运算符,所有运算符都以context_
作为前缀。 a + b
和a context_+ b
不能混淆。
我仍然对context_
作为前缀不完全满意。也许我们应该为这些运算符添加一些速记,但是在这种情况下,我认为清晰度比简洁更重要。