Consider the case for a parameterizable LSFR module.
class LSFR[T <: Bundle](gen: T = UInt(4.W)) extends Module { val io = IO(new Bundle { val rand = Output(gen) }) val width = gen.getWidth val regLFSR = Reg(UInt(width.W), init = UInt(0)) when(true.B) { regLFSR := Cat(regLFSR(0) ^ regLFSR(1), regLFSR(width - 1, 1)) } io.rand := gen.fromBits(regLFSR) }
Below I show a test containing two examples. First using PokeTester and the second using PeekPokeTester. See if you can spot the difference ...
class LSFRPeekPokeTester[T <: Bundle](gen: T, c: LSFR[T]) extends PeekPokeTester(c) { println("peekpoke test") } class LSFRSpec extends ChiselFlatSpec with PokeTester { behavior of "LSFR" it should "elaborate with peek test" in { val options = new TesterOptionsManager options.setTargetDirName("test_run_dir/LSFRSpec") test(new LSFR(new DDRCommand), testerBackend = FirrtlInterpreterBackend, options = options) { (t, c) => { println("poke test") } } } it should "elaborate with peekpoke test" in { Driver(() => new LSFR(new DDRCommand)) { c => new LSFRPeekPokeTester(new DDRCommand, c) } } }
In the PokeTester case, the first argument to test is new LSFR(new DDRCommand). For PeekPokeTester, you pass a function to generate the module () => new LSFR(new DDRCommand). Not immediately obvious. Now, look at the function prototypes for PokeTester and PeekPokeTester respectively ...
// PokeTester source def test[T <: Module](dutGen: => T, testerBackend: TesterBackend, options: TesterOptionsManager)(block: (InnerTester, T) => Unit) { //[..] // PeekPokeTester source def apply[T <: Module]( dutGen: () => T, backendType: String = "firrtl", verbose: Boolean = false, testerSeed: Long = System.currentTimeMillis())( testerGen: T => PeekPokeTester[T]): Boolean = { //[..]
The definition of dutGen is different.
Wise to keep in mind that PokeTester is under iotesters.experimental.
No comments:
Post a Comment