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

TransposerUnitTest.scala

package gemmini

import chisel3._
import chisel3.iotesters.{ChiselFlatSpec, PeekPokeTester}
import gemmini.TestUtils.{Matrix, consecutive, identity, rand}

// TODO: replace Transposer type parameter with wildcard (with LUB of Data)
class TransposerTester[+C <: Transposer[UInt]](c: C, mats: Seq[Matrix[Int]], dim: Int)
extends PeekPokeTesterC {
val rowsToPush = mats.flatten
val expectedCols = mats.map(_.transpose).flatten
val actualCols = collection.mutable.Buffer.empty[Seq[Int]]
val timeout = 1000
var cycles = 0

def checkTimeout() = {
if (cycles > timeout) {
println("TIMING OUT")
finish
throw new Exception("TIMING OUT")
}
}

reset()
poke(c.io.outCol.ready, 1)

rowsToPush.foreach { row =>
checkTimeout()
poke(c.io.inRow.valid, 1)
row.zipWithIndex.foreach { case(elem, i) =>
poke(c.io.inRow.bits(i), elem)
}
if (peek(c.io.inRow.ready) == 1) {
if (peek(c.io.outCol.valid) == 1) {
actualCols += peek(c.io.outCol.bits).map(.intValue)
}
step(1)
cycles += 1
}
else {
while(peek(c.io.inRow.ready) != 1) {
if (peek(c.io.outCol.valid) == 1) {
actualCols += peek(c.io.outCol.bits).map(.intValue)
}
step(1)
cycles += 1
checkTimeout()
}
step(1)
cycles += 1
}
}

poke(c.io.inRow.valid, 0)
while(peek(c.io.outCol.valid) != 0) {
actualCols += peek(c.io.outCol.bits).map(_.intValue)
step(1)
cycles += 1
checkTimeout()
}

assert(expectedCols == actualCols)
}

class TransposerUnitTest extends ChiselFlatSpec {
val testerArgs = Array(
"--backend-name", "treadle",
"--generate-vcd-output", "on",
"--target-dir", "test_run_dir/transposer",
"--top-name"
)
val dim = 4
behavior of "NaiveTransposer"
it should "transpose one matrix" in {
chisel3.iotesters.Driver.execute(testerArgs :+ "naive_transposer", () => new NaiveTransposer(dim, UInt(8.W))) {
c => new TransposerTester(c, Seq(identity(dim), rand(dim, 255), consecutive(dim)), dim)
} should be (true)
}

behavior of "PipelinedTransposer"
it should "transpose one matrix" in {
chisel3.iotesters.Driver.execute(testerArgs :+ "pipe_transposer", () => new PipelinedTransposer(dim, UInt(8.W))) {
c => new TransposerTester(c, Seq(consecutive(dim), consecutive(dim), consecutive(dim), consecutive(dim), rand(dim, 255)), dim)
} should be (true)
}
}
package gemmini

import chisel3._
import chisel3.iotesters.{ChiselFlatSpec, PeekPokeTester}
import gemmini.TestUtils.{Matrix, consecutive, identity, rand}

// TODO: replace Transposer type parameter with wildcard (with LUB of Data)
//NaiveTransposer是一种简单的转置器实现,它采用了基本的行列交换算法来实现矩阵转置
//PipelinedTransposer是一种优化的转置器实现,它采用了流水线技术来提高转置操作的效率
//使用不同类型和规模的输入矩阵,测试了NaiveTransposer和PipelinedTransposer模块的转置功能
class TransposerTester[+C <: Transposer[UInt]](c: C, mats: Seq[Matrix[Int]], dim: Int)
  extends PeekPokeTester[C](c) {
//将一组矩阵序列展平
  val rowsToPush = mats.flatten
//将该组矩阵的转置展平
  val expectedCols = mats.map(_.transpose).flatten
//创建一个可变缓冲区,用于存储实际生成的数据  
  val actualCols = collection.mutable.Buffer.empty[Seq[Int]]
  val timeout = 1000//时间限制
  var cycles = 0//记录进行了多少个周期
//超时抛出异常
  def checkTimeout() = {
    if (cycles > timeout) {
      println("TIMING OUT")
      finish
      throw new Exception("TIMING OUT")
    }
  }
//复位,重新接受数据
  reset()
  poke(c.io.outCol.ready, 1)
//遍历row中的每个元素,并将元素的值elem放入c.io.inRow.bits的对应位置
  rowsToPush.foreach { row =>
    checkTimeout()
    poke(c.io.inRow.valid, 1)
    row.zipWithIndex.foreach { case(elem, i) =>
      poke(c.io.inRow.bits(i), elem)
    }
//检查输出列是否有效如果有效,则将输出列的位值转换为Int并添加到actualCols中。然后调用step函数进行一次时钟周期的仿真,增加cycles计数器的值。
    if (peek(c.io.inRow.ready) == 1) {
      if (peek(c.io.outCol.valid) == 1) {
        actualCols += peek(c.io.outCol.bits).map(_.intValue)
      }
      step(1)
      cycles += 1
    }
//输入行不就绪,则进入一个while循环,直到输入行就绪为止
    else {
      while(peek(c.io.inRow.ready) != 1) {
        if (peek(c.io.outCol.valid) == 1) {
          actualCols += peek(c.io.outCol.bits).map(_.intValue)
        }
        step(1)
        cycles += 1
        checkTimeout()
      }
      step(1)
      cycles += 1
    }
  }
//所有行都被处理完毕后,将输入行端口的有效性设置为0,然后进入一个while循环,直到输出列端口的valid为0,即等待最后一个输出数据被处理完毕
//(确保在整个流水线中的所有数据都被正确处理和传输)
  poke(c.io.inRow.valid, 0)
  while(peek(c.io.outCol.valid) != 0) {
    actualCols += peek(c.io.outCol.bits).map(_.intValue)
    step(1)
    cycles += 1
    checkTimeout()
  }
//比较期望的列数据和实际的列数据是否相等。
  assert(expectedCols == actualCols)
}

class TransposerUnitTest extends ChiselFlatSpec {
  val testerArgs = Array(
    "--backend-name", "treadle",//指定后端,模拟器
    "--generate-vcd-output", "on",//打开波形生成
    "--target-dir", "test_run_dir/transposer",//输出文件
    "--top-name"//顶层模块名称
  )
  val dim = 4
  behavior of "NaiveTransposer"
  it should "transpose one matrix" in {
    chisel3.iotesters.Driver.execute(testerArgs :+ "naive_transposer", () => new NaiveTransposer(dim, UInt(8.W))) {
      c => new TransposerTester(c, Seq(identity(dim), rand(dim, 255), consecutive(dim)), dim)
    } should be (true)
  }

  behavior of "PipelinedTransposer"
  it should "transpose one matrix" in {
    chisel3.iotesters.Driver.execute(testerArgs :+ "pipe_transposer", () => new PipelinedTransposer(dim, UInt(8.W))) {
      c => new TransposerTester(c, Seq(consecutive(dim), consecutive(dim), consecutive(dim), consecutive(dim), rand(dim, 255)), dim)
    } should be (true)
  }
}

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