Write simple test for MultiPortQueue

... and comment out old CAM-based inflight table test.
This commit is contained in:
Hansung Kim
2023-03-27 15:21:01 -07:00
parent f07497638d
commit 23d8fa3be1
2 changed files with 127 additions and 125 deletions

View File

@@ -253,7 +253,7 @@ class CoalescingUnitImp(outer: CoalescingUnit, numLanes: Int) extends LazyModule
// Take [(off-1)*size:off*size] starting from MSB // Take [(off-1)*size:off*size] starting from MSB
c := (data >> (dataWidth - (o + 1) * size)) & sizeMask c := (data >> (dataWidth - (o + 1) * size)) & sizeMask
} }
chunks(offset) chunks(offset) // MUX
} }
// Un-coalesce responses back to individual lanes and queue them up // Un-coalesce responses back to individual lanes and queue them up

View File

@@ -2,30 +2,29 @@ import chisel3._
import chiseltest._ import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.flatspec.AnyFlatSpec
import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.MultiPortQueue
class MyModule extends Module { class MultiPortQueueUnitTest extends AnyFlatSpec with ChiselScalatestTester {
val io = IO(new Bundle { behavior of "MultiPortQueue"
val in = Input(UInt(16.W))
val out = Output(UInt(16.W))
})
io.out := RegNext(io.in) it should "serialize at dequeue end" in {
} test(new MultiPortQueue(UInt(4.W), 3, 1, 3, 6))
.withAnnotations(Seq(WriteVcdAnnotation)) { c =>
class BasicTest extends AnyFlatSpec with ChiselScalatestTester { c.io.enq(0).valid.poke(true.B)
// test class body here c.io.enq(0).bits.poke(11.U)
it should "do something" in { c.io.enq(1).valid.poke(true.B)
// test case body here c.io.enq(1).bits.poke(15.U)
test(new MyModule) { c => c.io.enq(2).valid.poke(true.B)
// test body here c.io.enq(2).bits.poke(7.U)
c.io.in.poke(0.U) c.io.deq(0).ready.poke(true.B)
c.clock.step() c.clock.step()
c.io.out.expect(0.U) // c.io.enq(0).valid.poke(false.B)
c.io.in.poke(42.U) // c.io.enq(1).valid.poke(false.B)
c.clock.step() for (_ <- 0 until 100) {
c.io.out.expect(42.U) c.clock.step()
println("Last output value :" + c.io.out.peek().litValue) }
} c.io.deq(0).valid.expect(false.B)
}
} }
} }
@@ -35,121 +34,124 @@ class CoalescingUnitTest extends AnyFlatSpec with ChiselScalatestTester {
val sourceWidth = 2 val sourceWidth = 2
val entries = 4 val entries = 4
val offsetBits = 4
val sizeBits = 2
val inflightCoalReqTableEntry = val inflightCoalReqTableEntry =
new InflightCoalReqTableEntry(numLanes, sourceWidth) new InflightCoalReqTableEntry(numLanes, sourceWidth, offsetBits, sizeBits)
it should "stop enqueueing when full" in { // it should "stop enqueueing when full" in {
test(new InflightCoalReqTable(numLanes, sourceWidth, entries)) { c => // test(new InflightCoalReqTable(numLanes, sourceWidth, entries)) { c =>
// fill up the table // // fill up the table
for (i <- 0 until entries) { // for (i <- 0 until entries) {
val sourceId = i // val sourceId = i
c.io.enq.ready.expect(true.B) // c.io.enq.ready.expect(true.B)
c.io.enq.valid.poke(true.B) // c.io.enq.valid.poke(true.B)
c.io.enq.bits.fromLane.poke(0.U) // c.io.enq.bits.fromLane.poke(0.U)
c.io.enq.bits.respSourceId.poke(sourceId.U) // c.io.enq.bits.respSourceId.poke(sourceId.U)
c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) } // c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
c.io.lookup.ready.poke(false.B) // c.io.lookup.ready.poke(false.B)
c.clock.step() // c.clock.step()
} // }
// now cannot enqueue any more // // now cannot enqueue any more
c.io.enq.ready.expect(false.B) // c.io.enq.ready.expect(false.B)
c.io.enq.valid.poke(true.B) // c.io.enq.valid.poke(true.B)
c.io.enq.bits.fromLane.poke(0.U) // c.io.enq.bits.fromLane.poke(0.U)
c.io.enq.bits.respSourceId.poke(0.U) // c.io.enq.bits.respSourceId.poke(0.U)
c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) } // c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
c.clock.step() // c.clock.step()
c.io.enq.ready.expect(false.B) // c.io.enq.ready.expect(false.B)
// try to lookup all existing entries // // try to lookup all existing entries
for (i <- 0 until entries) { // for (i <- 0 until entries) {
val sourceId = i // val sourceId = i
c.io.enq.valid.poke(false.B) // c.io.enq.valid.poke(false.B)
c.io.lookup.ready.poke(true.B) // c.io.lookup.ready.poke(true.B)
c.io.lookupSourceId.poke(sourceId) // c.io.lookupSourceId.poke(sourceId)
c.io.lookup.valid.expect(true.B) // c.io.lookup.valid.expect(true.B)
c.io.lookup.bits.expect(sourceId) // c.io.lookup.bits.expect(sourceId)
c.clock.step() // c.clock.step()
} // }
// now the table should be empty // // now the table should be empty
for (i <- 0 until entries) { // for (i <- 0 until entries) {
val sourceId = i // val sourceId = i
c.io.enq.valid.poke(false.B) // c.io.enq.valid.poke(false.B)
c.io.lookup.ready.poke(true.B) // c.io.lookup.ready.poke(true.B)
c.io.lookupSourceId.poke(sourceId) // c.io.lookupSourceId.poke(sourceId)
c.io.lookup.valid.expect(false.B) // c.io.lookup.valid.expect(false.B)
c.clock.step() // c.clock.step()
} // }
} // }
} // }
it should "lookup matching entry" in { // it should "lookup matching entry" in {
test(new InflightCoalReqTable(numLanes, sourceWidth, entries)) // test(new InflightCoalReqTable(numLanes, sourceWidth, entries))
.withAnnotations(Seq(WriteVcdAnnotation)) { c => // .withAnnotations(Seq(WriteVcdAnnotation)) { c =>
c.reset.poke(true.B) // c.reset.poke(true.B)
c.clock.step(10) // c.clock.step(10)
c.reset.poke(false.B) // c.reset.poke(false.B)
// enqueue one entry to not match at 0th index // // enqueue one entry to not match at 0th index
c.io.enq.ready.expect(true.B) // c.io.enq.ready.expect(true.B)
c.io.enq.valid.poke(true.B) // c.io.enq.valid.poke(true.B)
c.io.enq.bits.fromLane.poke(0.U) // c.io.enq.bits.fromLane.poke(0.U)
c.io.enq.bits.respSourceId.poke(0.U) // c.io.enq.bits.respSourceId.poke(0.U)
c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) } // c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
c.clock.step() // c.clock.step()
val targetSourceId = 1.U // val targetSourceId = 1.U
c.io.enq.ready.expect(true.B) // c.io.enq.ready.expect(true.B)
c.io.enq.valid.poke(true.B) // c.io.enq.valid.poke(true.B)
c.io.enq.bits.fromLane.poke(0.U) // c.io.enq.bits.fromLane.poke(0.U)
c.io.enq.bits.respSourceId.poke(targetSourceId) // c.io.enq.bits.respSourceId.poke(targetSourceId)
c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) } // c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
c.clock.step() // c.clock.step()
c.io.lookup.ready.poke(true.B) // c.io.lookup.ready.poke(true.B)
c.io.lookupSourceId.poke(targetSourceId) // c.io.lookupSourceId.poke(targetSourceId)
c.io.lookup.valid.expect(true.B) // c.io.lookup.valid.expect(true.B)
c.io.lookup.bits.expect(targetSourceId) // c.io.lookup.bits.expect(targetSourceId)
c.clock.step() // c.clock.step()
// test if matching entry dequeues after 1 cycle // // test if matching entry dequeues after 1 cycle
c.io.lookup.ready.poke(true.B) // c.io.lookup.ready.poke(true.B)
c.io.lookupSourceId.poke(targetSourceId) // c.io.lookupSourceId.poke(targetSourceId)
c.io.lookup.valid.expect(false.B) // c.io.lookup.valid.expect(false.B)
} // }
} // }
it should "handle lookup and enqueue at the same time" in { // it should "handle lookup and enqueue at the same time" in {
test(new InflightCoalReqTable(numLanes, sourceWidth, entries)) { c => // test(new InflightCoalReqTable(numLanes, sourceWidth, entries)) { c =>
// fill up the table // // fill up the table
val targetSourceId = 1.U // val targetSourceId = 1.U
c.io.enq.ready.expect(true.B) // c.io.enq.ready.expect(true.B)
c.io.enq.valid.poke(true.B) // c.io.enq.valid.poke(true.B)
c.io.enq.bits.fromLane.poke(0.U) // c.io.enq.bits.fromLane.poke(0.U)
c.io.enq.bits.respSourceId.poke(0.U) // c.io.enq.bits.respSourceId.poke(0.U)
c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) } // c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
c.clock.step() // c.clock.step()
c.io.enq.ready.expect(true.B) // c.io.enq.ready.expect(true.B)
c.io.enq.valid.poke(true.B) // c.io.enq.valid.poke(true.B)
c.io.enq.bits.fromLane.poke(0.U) // c.io.enq.bits.fromLane.poke(0.U)
c.io.enq.bits.respSourceId.poke(targetSourceId) // c.io.enq.bits.respSourceId.poke(targetSourceId)
c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) } // c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
c.clock.step() // c.clock.step()
// do both enqueue and lookup at the same cycle // // do both enqueue and lookup at the same cycle
val enqSourceId = 2.U // val enqSourceId = 2.U
c.io.enq.ready.expect(true.B) // c.io.enq.ready.expect(true.B)
c.io.enq.valid.poke(true.B) // c.io.enq.valid.poke(true.B)
c.io.enq.bits.fromLane.poke(0.U) // c.io.enq.bits.fromLane.poke(0.U)
c.io.enq.bits.respSourceId.poke(enqSourceId) // c.io.enq.bits.respSourceId.poke(enqSourceId)
c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) } // c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
c.io.lookup.ready.poke(true.B) // c.io.lookup.ready.poke(true.B)
c.io.lookupSourceId.poke(targetSourceId) // c.io.lookupSourceId.poke(targetSourceId)
c.clock.step() // c.clock.step()
} // }
} // }
} }