Reputation: 73
Recently, I have been studying DspContext and type classes in dsptools. I just ran a test code according to the tutorial. It shows how to add pipelines to mathematical operations. But I found this example didn't work as expected. Here is the code of example:
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
}
}
And its test program:
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)
}
When I ran it, the terminal displayed:
[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
The output was generated instantly rather than was delayed correctly. Going a step further, I find the right way is to call function plusContext. Just like this:
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)
}
}
Now, it works as expected:
[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
There is no explicit way to convert "+" into "plusContext"(and other functions). Is the dsptools uncompleted?
Upvotes: 1
Views: 60
Reputation: 36
In older versions of dsptools, your original code would have worked as you expected it to. However, it was often confusing to have +
behavior depend on if an implicit for the typeclass is present. If I recall correctly, seemingly innocuous changes to your imports could dramatically change your circuit's behavior.
The decision we ended up making was that if a chisel type has an operator, the typeclass should not change that behavior ever. If you want to use versions of the operators that use the context (pipelining, rounding, etc.), you have to use separate operators that all have context_
as a prefix. a + b
and a context_+ b
can't be confused.
I'm still not entirely satisfied with context_
as a prefix. Maybe we should add some shorthand for these operators, but I think clarity is more important than brevity in this instance.
Upvotes: 2