Commit 5a1f9945 authored by Jens Korinth's avatar Jens Korinth
Browse files

DecoupledDataSource module

* testing utility: provides fixed data via Decoupled
* configurable with/without wrap-around
* unit tests
parents
*.log
*.jou
.Xil
/target/
/project/
/test/
/ip/
scalaVersion := "2.11.7"
libraryDependencies += "edu.berkeley.cs" %% "chisel" % "latest.release"
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.6" %"test"
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.5.4"
run in Compile <<= run in Compile map { (file) =>
"packaging/package.py ip/VgaTimingController.json" !
}
import Chisel._
/**
* Interface for DecoupledDataSource.
**/
class DecoupledDataSourceIO[T <: Data](gen: T) extends Bundle {
val out = Decoupled(gen.cloneType)
}
/**
* Data source providing fixed data via Decoupled interface.
* Provides the data given via Decoupled handshakes; if repeat
* is true, data is wrapped around.
* @param gen Type.
* @param size Total number of elements.
* @param data Function providing data for each index
* @param repeat If true, will always have data via wrap-around,
otherwise valid will go low after data was
consumed.
**/
class DecoupledDataSource[T <: Data](gen: T, val size : Int, data: (Int) => T, val repeat: Boolean = true) extends Module {
val ds = for (i <- 0 until size) yield data(i) // evaluate data to array
val io = new DecoupledDataSourceIO(gen) // interface
val i = Reg(UInt(width = log2Up(if (repeat) size else size + 1))) // index
val rom = Vec.tabulate(size)(n => ds(n)) // ROM with data
io.out.bits := rom(i) // current index data
io.out.valid := i < UInt(size) // valid until exceeded
when (reset) {
i := UInt(0)
}
.otherwise {
if (repeat)
when (io.out.ready && io.out.valid) { i := Mux(i < UInt(size - 1), i + UInt(1), UInt(0)) }
else
when (io.out.ready && io.out.valid && i < UInt(size)) { i := i + UInt(1) }
}
}
import Chisel._
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import org.junit.Assert._
/**
* Tester class for DecoupledDataSource.
* Automatically exhausts the internal data of the instance, checks that
* each dequeued output matches the expected value. Also checks whether
* or not the module wraps correctly (in case repeat is true).
**/
class DecoupledDataSource_OutputCheck[T <: UInt](m: DecoupledDataSource[T]) extends Tester(m, false) {
import scala.util.Properties.{lineSeparator => NL}
poke(m.io.out.ready, true)
var errors: List[String] = List()
var i = 0
while (peek(m.io.out.valid) > 0 && i <= m.size) {
if (i >= m.size) {
if (! m.repeat)
errors = "repeat is false, but index (%d) exceeds size(%d)".format(i, m.size) :: errors
} else {
if (peek(m.io.out.bits) != peek(m.ds(i))) {
errors = "output #%d: expected %d, found %d".format(i, peek(m.ds(i)), peek(m.io.out.bits)) :: errors
} else {
// wait for random time up to 10 cycles
val wait = (scala.math.random * 10).toInt
poke(m.io.out.ready, false)
step(wait)
poke(m.io.out.ready, true)
}
}
i += 1
step(1)
}
assertTrue (("all elements should match, errors: " :: errors).mkString(NL), errors.length == 0)
}
class DecoupledDataSourceSuite extends JUnitSuite {
/** Performs randomized tests with random data of random size. **/
@Test def checkRandomOutputs {
for (i <- 0 until 1) {
val cnt = Seq(1, (scala.math.random * 10000).toInt).max
val width = Seq(1, (scala.math.random * 64).toInt).max
val repeat = scala.math.random > 0.5
println("testing cnt = %d, width = %d, repeat = %b ...".format(cnt, width, repeat))
chiselMainTest(Array("--genHarness", "--backend", "c", "--vcd", "--targetDir", "test", "--compile", "--test"),
() => Module(new DecoupledDataSource(UInt(width = width), cnt, i => UInt((scala.math.random * scala.math.pow(2, width)).toInt), repeat)))
{ m => new DecoupledDataSource_OutputCheck(m) }
}
}
/** Performs test for 8bit wide sequential data with repeat. **/
@Test def checkSequentialOutputsWithRepeat {
chiselMainTest(Array("--genHarness", "--backend", "c", "--vcd", "--targetDir", "test", "--compile", "--test"),
() => Module(new DecoupledDataSource(UInt(width = 8), 256, i => UInt(i), true)))
{ m => new DecoupledDataSource_OutputCheck(m) }
}
/** Performs test for 8bit wide sequential data without repeat. **/
@Test def checkSequentialOutputsWithoutRepeat {
chiselMainTest(Array("--genHarness", "--backend", "c", "--vcd", "--targetDir", "test", "--compile", "--test"),
() => Module(new DecoupledDataSource(UInt(width = 8), 256, i => UInt(i), false)))
{ m => new DecoupledDataSource_OutputCheck(m) }
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment