Write simple test for MultiPortQueue
... and comment out old CAM-based inflight table test.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user