summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrendan Sweeney2019-01-25 13:39:35 -0800
committeredwardcwang2019-02-01 12:31:46 -0800
commit30fd36855210409cd63dd06f5f8b67f95f679c70 (patch)
tree8fc6c862814231de68c0d29c63df3e27f2b2bf9b /src
parent5509cdd4c8332c53151e10ba5bdbe0684af1c05b (diff)
Queue Tests
Diffstat (limited to 'src')
-rw-r--r--src/test/scala/chiselTests/QueueSpec.scala237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/test/scala/chiselTests/QueueSpec.scala b/src/test/scala/chiselTests/QueueSpec.scala
new file mode 100644
index 00000000..3f723ecf
--- /dev/null
+++ b/src/test/scala/chiselTests/QueueSpec.scala
@@ -0,0 +1,237 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import org.scalatest._
+import org.scalatest.prop._
+import org.scalacheck._
+
+import chisel3._
+import chisel3.testers.BasicTester
+import chisel3.util._
+
+class ThingsPassThroughTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int) extends BasicTester {
+ val q = Module(new Queue(UInt(bitWidth.W), queueDepth))
+ val elems = VecInit(elements.map {
+ _.asUInt()
+ })
+ val inCnt = Counter(elements.length + 1)
+ val outCnt = Counter(elements.length + 1)
+
+ q.io.enq.valid := (inCnt.value < elements.length.U)
+ q.io.deq.ready := LFSR16()(tap)
+
+ q.io.enq.bits := elems(inCnt.value)
+ when(q.io.enq.fire()) {
+ inCnt.inc()
+ }
+ when(q.io.deq.fire()) {
+ //ensure that what comes otu is what comes in
+ assert(elems(outCnt.value) === q.io.deq.bits)
+ outCnt.inc()
+ }
+ when(outCnt.value === elements.length.U) {
+ stop()
+ }
+}
+
+class QueueReasonableReadyValid(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int) extends BasicTester {
+ val q = Module(new Queue(UInt(bitWidth.W), queueDepth))
+ val elems = VecInit(elements.map {
+ _.asUInt()
+ })
+ val inCnt = Counter(elements.length + 1)
+ val outCnt = Counter(elements.length + 1)
+
+ q.io.enq.valid := (inCnt.value < elements.length.U)
+ //Queue should be full or ready
+ assert(q.io.enq.ready || q.io.count === queueDepth.U)
+
+ q.io.deq.ready := LFSR16()(tap)
+ //Queue should be empty or valid
+ assert(q.io.deq.valid || q.io.count === 0.U)
+
+ q.io.enq.bits := elems(inCnt.value)
+ when(q.io.enq.fire()) {
+ inCnt.inc()
+ }
+ when(q.io.deq.fire()) {
+ outCnt.inc()
+ }
+ when(outCnt.value === elements.length.U) {
+ stop()
+ }
+}
+
+class CountIsCorrectTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int) extends BasicTester {
+ val q = Module(new Queue(UInt(bitWidth.W), queueDepth))
+ val elems = VecInit(elements.map {
+ _.asUInt(bitWidth.W)
+ })
+ val inCnt = Counter(elements.length + 1)
+ val outCnt = Counter(elements.length + 1)
+
+ q.io.enq.valid := (inCnt.value < elements.length.U)
+ q.io.deq.ready := LFSR16()(tap)
+
+ q.io.enq.bits := elems(inCnt.value)
+ when(q.io.enq.fire()) {
+ inCnt.inc()
+ assert(q.io.count === (inCnt.value - outCnt.value))
+ }
+ when(q.io.deq.fire()) {
+ outCnt.inc()
+ assert(q.io.count === (inCnt.value - outCnt.value))
+ }
+ //assert(q.io.count === (inCnt.value - outCnt.value))
+
+ when(outCnt.value === elements.length.U) {
+ stop()
+ }
+}
+
+class QueueSinglePipeTester(elements: Seq[Int], bitWidth: Int, tap: Int) extends BasicTester {
+ val q = Module(new Queue(UInt(bitWidth.W), 1, pipe = true))
+ val elems = VecInit(elements.map {
+ _.asUInt(bitWidth.W)
+ })
+ val inCnt = Counter(elements.length + 1)
+ val outCnt = Counter(elements.length + 1)
+
+ q.io.enq.valid := (inCnt.value < elements.length.U)
+ q.io.deq.ready := LFSR16()(tap)
+
+ assert(q.io.enq.ready || (q.io.count === 1.U && !q.io.deq.ready))
+
+ q.io.enq.bits := elems(inCnt.value)
+ when(q.io.enq.fire()) {
+ inCnt.inc()
+ }
+ when(q.io.deq.fire()) {
+ outCnt.inc()
+ }
+
+ when(outCnt.value === elements.length.U) {
+ stop()
+ }
+}
+
+class QueuePipeTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int) extends BasicTester {
+ val q = Module(new Queue(UInt(bitWidth.W), queueDepth, pipe = true))
+ val elems = VecInit(elements.map {
+ _.asUInt(bitWidth.W)
+ })
+ val inCnt = Counter(elements.length + 1)
+ val outCnt = Counter(elements.length + 1)
+
+ q.io.enq.valid := (inCnt.value < elements.length.U)
+ q.io.deq.ready := LFSR16()(tap)
+
+ assert(q.io.enq.ready || (q.io.count === queueDepth.U && !q.io.deq.ready))
+
+ q.io.enq.bits := elems(inCnt.value)
+ when(q.io.enq.fire()) {
+ inCnt.inc()
+ }
+ when(q.io.deq.fire()) {
+ outCnt.inc()
+ }
+
+ when(outCnt.value === elements.length.U) {
+ stop()
+ }
+}
+
+class QueueFlowTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int) extends BasicTester {
+ val q = Module(new Queue(UInt(bitWidth.W), queueDepth, flow = true))
+ val elems = VecInit(elements.map {
+ _.asUInt()
+ })
+ val inCnt = Counter(elements.length + 1)
+ val outCnt = Counter(elements.length + 1)
+
+ q.io.enq.valid := (inCnt.value < elements.length.U)
+ //Queue should be full or ready
+ assert(q.io.enq.ready || q.io.count === queueDepth.U)
+
+ q.io.deq.ready := LFSR16()(tap)
+ //Queue should be empty or valid
+ assert(q.io.deq.valid || (q.io.count === 0.U && !q.io.enq.fire()))
+
+ q.io.enq.bits := elems(inCnt.value)
+ when(q.io.enq.fire()) {
+ inCnt.inc()
+ }
+ when(q.io.deq.fire()) {
+ outCnt.inc()
+ }
+ when(outCnt.value === elements.length.U) {
+ stop()
+ }
+}
+
+class QueueSpec extends ChiselPropSpec {
+ // Disable shrinking on error.
+ implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty)
+ implicit val noShrinkInt = Shrink[Int](_ => Stream.empty)
+
+ property("Queue should have things pass through") {
+ forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15)) { (depth, se, tap) =>
+ whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) {
+ assertTesterPasses {
+ new ThingsPassThroughTester(se._2, depth, se._1, tap)
+ }
+ }
+ }
+ }
+
+ property("Queue should have reasonable ready/valid") {
+ forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15)) { (depth, se, tap) =>
+ whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) {
+ assertTesterPasses {
+ new QueueReasonableReadyValid(se._2, depth, se._1, tap)
+ }
+ }
+ }
+ }
+
+ property("Queue should have correct count") {
+ forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15)) { (depth, se, tap) =>
+ whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) {
+ assertTesterPasses {
+ new CountIsCorrectTester(se._2, depth, se._1, tap)
+ }
+ }
+ }
+ }
+
+ property("Queue pipe should work for 1-element queues") {
+ forAll(safeUIntN(20), Gen.choose(0, 15)) { (se, tap) =>
+ whenever(se._1 >= 1 && se._2.nonEmpty) {
+ assertTesterPasses {
+ new QueueSinglePipeTester(se._2, se._1, tap)
+ }
+ }
+ }
+ }
+
+ property("Queue pipe should work for more general queues") {
+ forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15)) { (depth, se, tap) =>
+ whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) {
+ assertTesterPasses {
+ new QueuePipeTester(se._2, depth, se._1, tap)
+ }
+ }
+ }
+ }
+
+ property("Queue flow should work") {
+ forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15)) { (depth, se, tap) =>
+ whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) {
+ assertTesterPasses {
+ new QueueFlowTester(se._2, depth, se._1, tap)
+ }
+ }
+ }
+ }
+}