Gemmini测试test文件chisel源码详解(三)

PipelineTest.scala

源码

package gemmini

import chisel3._
import chisel3.iotesters.{ChiselFlatSpec, PeekPokeTester}

class PipelineTester(c: Pipeline[SInt]) extends PeekPokeTester(c) {
  var max_cycles = 100000
  // rnd.setSeed(0L)

  val n_inputs = 100
  val inputs = Seq.fill(n_inputs)(rnd.nextInt())
  // val inputs = (1 to n_inputs).toSeq

  var input_cnt = 0
  var output_cnt = 0

  while (output_cnt < n_inputs && max_cycles > 0) {
    val input_valid = input_cnt < n_inputs && rnd.nextBoolean()
    val output_ready = rnd.nextBoolean()

    poke(c.io.in.valid, input_valid)
    poke(c.io.out.ready, output_ready)

    if (input_cnt < n_inputs) {
      poke(c.io.in.bits, inputs(input_cnt))
    }

    val input_ready = peek(c.io.in.ready) != 0
    val output_valid = peek(c.io.out.valid) != 0

    val input_fire = input_valid && input_ready
    val output_fire = output_valid && output_ready

    if (input_fire) {
      input_cnt += 1
    }

    if (output_fire) {
      assert(inputs(output_cnt) == peek(c.io.out.bits),
        s"Expected: ${inputs(output_cnt)}\nActual: ${peek(c.io.out.bits)}")
      output_cnt += 1
    }

    step(1)
    max_cycles -= 1
  }

  assert(max_cycles > 0, "ran out of max_cycles")
}

class PipelineUnitTest extends ChiselFlatSpec {
  val testerArgs = Array(
    "--backend-name", "treadle",
    // "--generate-vcd-output", "on",
    "--target-dir", "test_run_dir/pipeline"
  )

  behavior of "Pipeline"
  it should "work" in {
    chisel3.iotesters.Driver.execute(testerArgs, () => new Pipeline(SInt(32.W), 10)()) {
      c => new PipelineTester(c)
    } should be (true)
  }

  it should "work with one element" in {
    chisel3.iotesters.Driver.execute(testerArgs, () => new Pipeline(SInt(32.W), 1)()) {
      c => new PipelineTester(c)
    } should be (true)
  }

  it should "work with no elements" in {
    chisel3.iotesters.Driver.execute(testerArgs, () => new Pipeline(SInt(32.W), 0)()) {
      c => new PipelineTester(c)
    } should be (true)
  }
}

 这段代码是用来测试流水线的

  • PipelineTester 类是一个继承自 PeekPokeTester 的测试器类,它接受一个 Pipeline[SInt] 类型的参数 c,并在其构造函数中定义了一些变量和方法。

    • max_cycles 是一个整数变量,它表示最大的执行周期数,用于限制测试的时间。
    • n_inputs 是一个整数变量,它表示要输入的数据数量,初始值为 100。
    • inputs 是一个序列变量,它存储了 n_inputs 个随机生成的整数作为输入数据。
    • input_cnt 和 output_cnt 是两个整数变量,它们分别表示已输入和已输出的数据数量,初始值为 0。
    • while 循环是测试的主要逻辑,它在 output_cnt 小于 n_inputs 并且 max_cycles 大于 0 的条件下执行。循环中包含以下步骤:
      • 随机决定是否可以输入新的数据,并将结果赋值给 input_valid 变量,然后将其 poke 给 c.io.in.valid 输入端口。
      • 随机决定是否可以接收输出的数据,并将结果赋值给 output_ready 变量,然后将其 poke 给 c.io.out.ready 输入端口。
      • 如果 input_cnt 小于 n_inputs,则从 inputs 中取出对应位置的数据,并将其 poke 给 c.io.in.bits 输入端口。
      • 从 c.io.in.ready 和 c.io.out.valid 输出端口读取 input_ready 和 output_valid 的值,并判断是否发生了 input_fire 和 output_fire 事件,即输入或输出端口同时有效和就绪。
      • 如果发生了 input_fire 事件,则将 input_cnt 增加 1。
      • 如果发生了 output_fire 事件,则从 c.io.out.bits 输出端口读取输出的数据,并断言它与 inputs 中对应位置的数据相等,表示流水线没有改变数据的值。然后将 output_cnt 增加 1。
      • 调用 step(1) 方法执行一个时钟周期,并将 max_cycles 减 1。
    • 在 while 循环结束后,断言 max_cycles 大于 0,表示测试没有超时。
  • PipelineUnitTest 类是一个继承自 ChiselFlatSpec 的单元测试类,它定义了一些变量和方法。

    • testerArgs 是一个字符串数组,它存储了一些测试参数,如后端名称、目标目录等。
    • behavior of “Pipeline” 是一个字符串字面量,它表示要测试的类名。
    • it should “work” 是一个方法,它表示要测试的功能。方法中包含以下步骤:
      • 调用 chisel3.iotesters.Driver.execute 方法,传入 testerArgs 和一个匿名函数,该函数返回一个新建的 Pipeline 对象,其参数为 SInt(32.W) 和 10。这表示流水线接收和发送 32 位有符号整数,并且内部可以缓存 10 个数据。
      • 在 execute 方法的第二个参数中,传入一个匿名函数,该函数接受一个 Pipeline 类型的参数 c,并返回一个新建的 PipelineTester 对象,其参数为 c。
      • 在 execute 方法的返回值上调用 should be (true) 方法,断言测试结果为 true。
    • it should “work with one element” 是另一个方法,它表示要测试另一种情况。方法中包含类似的步骤,只是在创建 Pipeline 对象时将内部缓存数量改为 1。
    • it should “work with no elements” 是再一个方法,它表示要测试另一种情况。方法中包含类似的步骤,只是在创建 Pipeline 对象时将内部缓存数量改为 0。

注释版

package gemmini

import chisel3._
import chisel3.iotesters.{ChiselFlatSpec, PeekPokeTester}
//测试流水线
class PipelineTester(c: Pipeline[SInt]) extends PeekPokeTester(c) {
//周期
  var max_cycles = 100000
  // rnd.setSeed(0L)
//要输入的数据数量
  val n_inputs = 100
//序列变量,存储了 n_inputs 个随机生成的整数作为输入数据。
  val inputs = Seq.fill(n_inputs)(rnd.nextInt())
  // val inputs = (1 to n_inputs).toSeq
//分别表示已输入和已输出的数据数量,初始值为 0
  var input_cnt = 0
  var output_cnt = 0
//输出数量小于总的序列变量个数且还有时间时进入循环
  while (output_cnt < n_inputs && max_cycles > 0) {
//随机决定是否可以输入新的数据,将其 poke 给 c.io.in.valid 输入端口
    val input_valid = input_cnt < n_inputs && rnd.nextBoolean()
//随机决定是否可以输出的数据是否准备完毕,将其 poke 给 c.io.out.ready 输入端口。
    val output_ready = rnd.nextBoolean()

    poke(c.io.in.valid, input_valid)
    poke(c.io.out.ready, output_ready)
//当前循环迭代小于输入数量,则从 inputs 中取出对应位置的数据,并将其 poke 给 c.io.in.bits 输入端口。
    if (input_cnt < n_inputs) {
      poke(c.io.in.bits, inputs(input_cnt))
    }
//使用 peek 函数读取模块的输入和输出端口的就绪和有效信号,并计算输入和输出是否满足触发条件
    val input_ready = peek(c.io.in.ready) != 0
    val output_valid = peek(c.io.out.valid) != 0

    val input_fire = input_valid && input_ready
    val output_fire = output_valid && output_ready
//在触发条件满足的情况下,更新输入和输出的计数器,并通过断言验证输出是否与预期值相符。
    if (input_fire) {
      input_cnt += 1
    }

    if (output_fire) {
      assert(inputs(output_cnt) == peek(c.io.out.bits),
        s"Expected: ${inputs(output_cnt)}\nActual: ${peek(c.io.out.bits)}")
      output_cnt += 1
    }
//通过 step 函数进行时间步进,并将 max_cycles 减少1,用于控制测试的最大周期数。循环直到输出计数器达到输入数量或者达到最大周期数的限制。
    step(1)
    max_cycles -= 1
  }

  assert(max_cycles > 0, "ran out of max_cycles")
}

class PipelineUnitTest extends ChiselFlatSpec {
  val testerArgs = Array(
    "--backend-name", "treadle",
    // "--generate-vcd-output", "on",
    "--target-dir", "test_run_dir/pipeline"
  )

  behavior of "Pipeline"
  it should "work" in {
    chisel3.iotesters.Driver.execute(testerArgs, () => new Pipeline(SInt(32.W), 10)()) {
      c => new PipelineTester(c)
    } should be (true)
  }

  it should "work with one element" in {
    chisel3.iotesters.Driver.execute(testerArgs, () => new Pipeline(SInt(32.W), 1)()) {
      c => new PipelineTester(c)
    } should be (true)
  }

  it should "work with no elements" in {
    chisel3.iotesters.Driver.execute(testerArgs, () => new Pipeline(SInt(32.W), 0)()) {
      c => new PipelineTester(c)
    } should be (true)
  }
}

你可能感兴趣的:(计算机体系结构学习笔记,risc-v,scala,体系结构,系统安全)