Merge branch 'graphics' of https://github.com/hansungk/rocket-chip into graphics
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -180,12 +180,12 @@ class DummyCoalescingUnitTBImp(outer: DummyCoalescingUnitTB) extends LazyModuleI
|
|||||||
)
|
)
|
||||||
|
|
||||||
val reqQueueEnqReady = peekIn(0).asInstanceOf[Seq[Bool]].map(x => IO(x.cloneType))
|
val reqQueueEnqReady = peekIn(0).asInstanceOf[Seq[Bool]].map(x => IO(x.cloneType))
|
||||||
val reqQueueEnqBits = peekIn(1).asInstanceOf[Seq[ReqQueueEntry]].map(x => IO(x.cloneType))
|
val reqQueueEnqBits = peekIn(1).asInstanceOf[Seq[Request]].map(x => IO(x.cloneType))
|
||||||
val reqQueueEnqValid = peekIn(2).asInstanceOf[Seq[Bool]].map(x => IO(x.cloneType))
|
val reqQueueEnqValid = peekIn(2).asInstanceOf[Seq[Bool]].map(x => IO(x.cloneType))
|
||||||
val reqQueueDeqBits = peekIn(3).asInstanceOf[Seq[ReqQueueEntry]].map(x => IO(Output(x.cloneType)))
|
val reqQueueDeqBits = peekIn(3).asInstanceOf[Seq[Request]].map(x => IO(Output(x.cloneType)))
|
||||||
val reqQueueDeqValid = peekIn(4).asInstanceOf[Seq[Bool]].map(x => IO(Output(x.cloneType)))
|
val reqQueueDeqValid = peekIn(4).asInstanceOf[Seq[Bool]].map(x => IO(Output(x.cloneType)))
|
||||||
val coalReqReady = IO(Output(peekIn(5).asInstanceOf[Bool].cloneType))
|
val coalReqReady = IO(Output(peekIn(5).asInstanceOf[Bool].cloneType))
|
||||||
val coalReqBits = IO(Output(peekIn(6).asInstanceOf[ReqQueueEntry].cloneType))
|
val coalReqBits = IO(Output(peekIn(6).asInstanceOf[Request].cloneType))
|
||||||
val coalReqValid = IO(Output(peekIn(7).asInstanceOf[Bool].cloneType))
|
val coalReqValid = IO(Output(peekIn(7).asInstanceOf[Bool].cloneType))
|
||||||
val coalInvalidate = IO(Output(peekIn(8).asInstanceOf[Valid[Vec[UInt]]].cloneType))
|
val coalInvalidate = IO(Output(peekIn(8).asInstanceOf[Valid[Vec[UInt]]].cloneType))
|
||||||
|
|
||||||
@@ -759,67 +759,70 @@ class CoalShiftQueueTest extends AnyFlatSpec with ChiselScalatestTester {
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
object uncoalescerTestConfig extends CoalescerConfig(
|
|
||||||
enable = true,
|
|
||||||
numLanes = 4,
|
|
||||||
queueDepth = 2,
|
|
||||||
waitTimeout = 8,
|
|
||||||
addressWidth = 24,
|
|
||||||
dataBusWidth = 5,
|
|
||||||
// watermark = 2,
|
|
||||||
wordSizeInBytes = 4,
|
|
||||||
numOldSrcIds = 16,
|
|
||||||
numNewSrcIds = 4,
|
|
||||||
respQueueDepth = 4,
|
|
||||||
coalLogSizes = Seq(4),
|
|
||||||
sizeEnum = DefaultInFlightTableSizeEnum,
|
|
||||||
numCoalReqs = 1,
|
|
||||||
numArbiterOutputPorts = 4,
|
|
||||||
bankStrideInBytes = 64,
|
|
||||||
)
|
|
||||||
|
|
||||||
class UncoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester {
|
class UncoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester {
|
||||||
behavior of "uncoalescer"
|
behavior of "uncoalescer"
|
||||||
val numLanes = 4
|
object uncoalescerTestConfig extends CoalescerConfig(
|
||||||
val numPerLaneReqs = 2
|
enable = true,
|
||||||
val sourceWidth = 2
|
numLanes = 4,
|
||||||
val sizeWidth = 2
|
queueDepth = 2,
|
||||||
// 16B coalescing size
|
waitTimeout = 8,
|
||||||
val coalDataWidth = 128
|
addressWidth = 24,
|
||||||
val numInflightCoalRequests = 4
|
dataBusWidth = 4, // 128 bit data bus
|
||||||
|
wordSizeInBytes = 4,
|
||||||
|
numOldSrcIds = 16,
|
||||||
|
numNewSrcIds = 4,
|
||||||
|
respQueueDepth = 4,
|
||||||
|
coalLogSizes = Seq(4),
|
||||||
|
sizeEnum = DefaultInFlightTableSizeEnum,
|
||||||
|
numCoalReqs = 1,
|
||||||
|
numArbiterOutputPorts = 4,
|
||||||
|
bankStrideInBytes = 64,
|
||||||
|
)
|
||||||
|
|
||||||
|
val config = uncoalescerTestConfig
|
||||||
|
|
||||||
|
val nonCoalReqT = new NonCoalescedRequest(config)
|
||||||
|
val coalReqT = new CoalescedRequest(config)
|
||||||
|
|
||||||
it should "work in general case" in {
|
it should "work in general case" in {
|
||||||
test(new Uncoalescer(uncoalescerTestConfig))
|
test(new Uncoalescer(config, nonCoalReqT, coalReqT))
|
||||||
// vcs helps with simulation time, but sometimes errors with
|
// vcs helps with simulation time, but sometimes errors with
|
||||||
// "mutation occurred during iteration" java error
|
// "mutation occurred during iteration" java error
|
||||||
// .withAnnotations(Seq(VcsBackendAnnotation))
|
// .withAnnotations(Seq(VcsBackendAnnotation))
|
||||||
{ c =>
|
{ c =>
|
||||||
|
// 4 lanes, queue depth 2
|
||||||
|
c.io.windowElts(0)(0).op.poke(0.U)
|
||||||
|
c.io.windowElts(0)(0).source.poke(1.U)
|
||||||
|
c.io.windowElts(0)(0).address.poke(0x4.U)
|
||||||
|
c.io.windowElts(0)(0).size.poke(2.U)
|
||||||
|
c.io.windowElts(0)(1).op.poke(0.U)
|
||||||
|
c.io.windowElts(0)(1).source.poke(2.U)
|
||||||
|
c.io.windowElts(0)(1).address.poke(0x4.U) // two reqs from one lane
|
||||||
|
c.io.windowElts(0)(1).size.poke(2.U)
|
||||||
|
c.io.windowElts(2)(0).op.poke(0.U)
|
||||||
|
c.io.windowElts(2)(0).source.poke(2.U)
|
||||||
|
c.io.windowElts(2)(0).address.poke(0x8.U)
|
||||||
|
c.io.windowElts(2)(0).size.poke(2.U)
|
||||||
|
c.io.windowElts(2)(1).op.poke(0.U)
|
||||||
|
c.io.windowElts(2)(1).source.poke(2.U)
|
||||||
|
c.io.windowElts(2)(1).address.poke(0xc.U)
|
||||||
|
c.io.windowElts(2)(1).size.poke(2.U)
|
||||||
|
// indicate lane 0 and 2 are used for coalescing
|
||||||
|
c.io.invalidate.valid.poke(true.B)
|
||||||
|
c.io.invalidate.bits(0).poke(0x3.U) // 2'b11 for depth=2
|
||||||
|
c.io.invalidate.bits(1).poke(0x0.U)
|
||||||
|
c.io.invalidate.bits(2).poke(0x3.U)
|
||||||
|
c.io.invalidate.bits(3).poke(0x0.U)
|
||||||
|
|
||||||
val sourceId = 0.U
|
val sourceId = 0.U
|
||||||
val four = c.io.newEntry.sizeEnumT.FOUR
|
c.io.coalReq.valid.poke(true.B)
|
||||||
c.io.coalReqValid.poke(true.B)
|
c.io.coalReq.bits.source.poke(sourceId)
|
||||||
c.io.newEntry.source.poke(sourceId)
|
c.io.coalReq.ready.expect(true.B)
|
||||||
c.io.newEntry.lanes(0).reqs(0).valid.poke(true.B)
|
|
||||||
c.io.newEntry.lanes(0).reqs(0).source.poke(1.U)
|
|
||||||
c.io.newEntry.lanes(0).reqs(0).offset.poke(1.U)
|
|
||||||
c.io.newEntry.lanes(0).reqs(0).sizeEnum.poke(four)
|
|
||||||
c.io.newEntry.lanes(0).reqs(1).valid.poke(true.B)
|
|
||||||
c.io.newEntry.lanes(0).reqs(1).source.poke(2.U)
|
|
||||||
c.io.newEntry.lanes(0).reqs(1).offset.poke(1.U) // same offset to different lanes
|
|
||||||
c.io.newEntry.lanes(0).reqs(1).sizeEnum.poke(four)
|
|
||||||
c.io.newEntry.lanes(1).reqs(0).valid.poke(false.B)
|
|
||||||
c.io.newEntry.lanes(2).reqs(0).valid.poke(true.B)
|
|
||||||
c.io.newEntry.lanes(2).reqs(0).source.poke(2.U)
|
|
||||||
c.io.newEntry.lanes(2).reqs(0).offset.poke(2.U)
|
|
||||||
c.io.newEntry.lanes(2).reqs(0).sizeEnum.poke(four)
|
|
||||||
c.io.newEntry.lanes(2).reqs(1).valid.poke(true.B)
|
|
||||||
c.io.newEntry.lanes(2).reqs(1).source.poke(2.U)
|
|
||||||
c.io.newEntry.lanes(2).reqs(1).offset.poke(3.U)
|
|
||||||
c.io.newEntry.lanes(2).reqs(1).sizeEnum.poke(four)
|
|
||||||
c.io.newEntry.lanes(3).reqs(0).valid.poke(false.B)
|
|
||||||
|
|
||||||
c.clock.step()
|
c.clock.step()
|
||||||
|
|
||||||
c.io.coalReqValid.poke(false.B)
|
c.io.coalReq.valid.poke(false.B)
|
||||||
|
c.io.invalidate.valid.poke(false.B)
|
||||||
|
|
||||||
c.clock.step()
|
c.clock.step()
|
||||||
|
|
||||||
@@ -848,37 +851,42 @@ class UncoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it should "uncoalesce when coalesced to the same word offset" in {
|
it should "uncoalesce when coalesced to the same word offset" in {
|
||||||
test(new Uncoalescer(uncoalescerTestConfig))
|
test(new Uncoalescer(config, nonCoalReqT, coalReqT))
|
||||||
// .withAnnotations(Seq(VcsBackendAnnotation))
|
// .withAnnotations(Seq(VcsBackendAnnotation))
|
||||||
{ c =>
|
{ c =>
|
||||||
|
// 4 lanes, queue depth 2
|
||||||
|
c.io.windowElts(0)(0).op.poke(0.U)
|
||||||
|
c.io.windowElts(0)(0).source.poke(0.U)
|
||||||
|
c.io.windowElts(0)(0).address.poke(0x4.U)
|
||||||
|
c.io.windowElts(0)(0).size.poke(2.U)
|
||||||
|
c.io.windowElts(1)(0).op.poke(0.U)
|
||||||
|
c.io.windowElts(1)(0).source.poke(1.U)
|
||||||
|
c.io.windowElts(1)(0).address.poke(0x4.U) // two reqs from one lane
|
||||||
|
c.io.windowElts(1)(0).size.poke(2.U)
|
||||||
|
c.io.windowElts(2)(0).op.poke(0.U)
|
||||||
|
c.io.windowElts(2)(0).source.poke(2.U)
|
||||||
|
c.io.windowElts(2)(0).address.poke(0x4.U)
|
||||||
|
c.io.windowElts(2)(0).size.poke(2.U)
|
||||||
|
c.io.windowElts(3)(0).op.poke(0.U)
|
||||||
|
c.io.windowElts(3)(0).source.poke(3.U)
|
||||||
|
c.io.windowElts(3)(0).address.poke(0x4.U)
|
||||||
|
c.io.windowElts(3)(0).size.poke(2.U)
|
||||||
|
// indicate lanes used for coalescing
|
||||||
|
c.io.invalidate.valid.poke(true.B)
|
||||||
|
c.io.invalidate.bits(0).poke(0x1.U) // 2'b01 for enabling head
|
||||||
|
c.io.invalidate.bits(1).poke(0x1.U)
|
||||||
|
c.io.invalidate.bits(2).poke(0x1.U)
|
||||||
|
c.io.invalidate.bits(3).poke(0x1.U)
|
||||||
|
|
||||||
val sourceId = 0.U
|
val sourceId = 0.U
|
||||||
val four = c.io.newEntry.sizeEnumT.FOUR
|
c.io.coalReq.valid.poke(true.B)
|
||||||
c.io.coalReqValid.poke(true.B)
|
c.io.coalReq.bits.source.poke(sourceId)
|
||||||
c.io.newEntry.source.poke(sourceId)
|
c.io.coalReq.ready.expect(true.B)
|
||||||
c.io.newEntry.lanes(0).reqs(0).valid.poke(true.B)
|
|
||||||
c.io.newEntry.lanes(0).reqs(0).source.poke(0.U)
|
|
||||||
c.io.newEntry.lanes(0).reqs(0).offset.poke(1.U)
|
|
||||||
c.io.newEntry.lanes(0).reqs(0).sizeEnum.poke(four)
|
|
||||||
c.io.newEntry.lanes(0).reqs(1).valid.poke(false.B)
|
|
||||||
c.io.newEntry.lanes(1).reqs(0).valid.poke(true.B)
|
|
||||||
c.io.newEntry.lanes(1).reqs(0).source.poke(1.U)
|
|
||||||
c.io.newEntry.lanes(1).reqs(0).offset.poke(1.U)
|
|
||||||
c.io.newEntry.lanes(1).reqs(0).sizeEnum.poke(four)
|
|
||||||
c.io.newEntry.lanes(1).reqs(1).valid.poke(false.B)
|
|
||||||
c.io.newEntry.lanes(2).reqs(0).valid.poke(true.B)
|
|
||||||
c.io.newEntry.lanes(2).reqs(0).source.poke(2.U)
|
|
||||||
c.io.newEntry.lanes(2).reqs(0).offset.poke(1.U)
|
|
||||||
c.io.newEntry.lanes(2).reqs(0).sizeEnum.poke(four)
|
|
||||||
c.io.newEntry.lanes(2).reqs(1).valid.poke(false.B)
|
|
||||||
c.io.newEntry.lanes(3).reqs(0).valid.poke(true.B)
|
|
||||||
c.io.newEntry.lanes(3).reqs(0).source.poke(3.U)
|
|
||||||
c.io.newEntry.lanes(3).reqs(0).offset.poke(1.U)
|
|
||||||
c.io.newEntry.lanes(3).reqs(0).sizeEnum.poke(four)
|
|
||||||
c.io.newEntry.lanes(3).reqs(1).valid.poke(false.B)
|
|
||||||
|
|
||||||
c.clock.step()
|
c.clock.step()
|
||||||
|
|
||||||
c.io.coalReqValid.poke(false.B)
|
c.io.coalReq.valid.poke(false.B)
|
||||||
|
c.io.invalidate.valid.poke(false.B)
|
||||||
|
|
||||||
c.clock.step()
|
c.clock.step()
|
||||||
|
|
||||||
@@ -908,138 +916,3 @@ class UncoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoalInflightTableUnitTest extends AnyFlatSpec with ChiselScalatestTester {
|
|
||||||
behavior of "inflight coalesced request table"
|
|
||||||
val numLanes = 4
|
|
||||||
val numPerLaneReqs = 2
|
|
||||||
val sourceWidth = 2
|
|
||||||
val entries = 4
|
|
||||||
|
|
||||||
val offsetBits = 4
|
|
||||||
val sizeBits = 2
|
|
||||||
|
|
||||||
val inflightCoalReqTableEntry =
|
|
||||||
new InflightCoalReqTableEntry(
|
|
||||||
numLanes,
|
|
||||||
numPerLaneReqs,
|
|
||||||
sourceWidth,
|
|
||||||
offsetBits,
|
|
||||||
testConfig.sizeEnum
|
|
||||||
)
|
|
||||||
|
|
||||||
// it should "stop enqueueing when full" in {
|
|
||||||
// test(new InflightCoalReqTable(numLanes, sourceWidth, entries)) { c =>
|
|
||||||
// // fill up the table
|
|
||||||
// for (i <- 0 until entries) {
|
|
||||||
// val sourceId = i
|
|
||||||
// c.io.enq.ready.expect(true.B)
|
|
||||||
// c.io.enq.valid.poke(true.B)
|
|
||||||
// c.io.enq.bits.fromLane.poke(0.U)
|
|
||||||
// c.io.enq.bits.respSourceId.poke(sourceId.U)
|
|
||||||
// c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
|
|
||||||
// c.io.lookup.ready.poke(false.B)
|
|
||||||
// c.clock.step()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // now cannot enqueue any more
|
|
||||||
// c.io.enq.ready.expect(false.B)
|
|
||||||
// c.io.enq.valid.poke(true.B)
|
|
||||||
// c.io.enq.bits.fromLane.poke(0.U)
|
|
||||||
// c.io.enq.bits.respSourceId.poke(0.U)
|
|
||||||
// c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
|
|
||||||
|
|
||||||
// c.clock.step()
|
|
||||||
// c.io.enq.ready.expect(false.B)
|
|
||||||
|
|
||||||
// // try to lookup all existing entries
|
|
||||||
// for (i <- 0 until entries) {
|
|
||||||
// val sourceId = i
|
|
||||||
// c.io.enq.valid.poke(false.B)
|
|
||||||
// c.io.lookup.ready.poke(true.B)
|
|
||||||
// c.io.lookupSourceId.poke(sourceId)
|
|
||||||
// c.io.lookup.valid.expect(true.B)
|
|
||||||
// c.io.lookup.bits.expect(sourceId)
|
|
||||||
// c.clock.step()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // now the table should be empty
|
|
||||||
// for (i <- 0 until entries) {
|
|
||||||
// val sourceId = i
|
|
||||||
// c.io.enq.valid.poke(false.B)
|
|
||||||
// c.io.lookup.ready.poke(true.B)
|
|
||||||
// c.io.lookupSourceId.poke(sourceId)
|
|
||||||
// c.io.lookup.valid.expect(false.B)
|
|
||||||
// c.clock.step()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// it should "lookup matching entry" in {
|
|
||||||
// test(new InflightCoalReqTable(numLanes, sourceWidth, entries))
|
|
||||||
// .withAnnotations(Seq(WriteVcdAnnotation)) { c =>
|
|
||||||
// c.reset.poke(true.B)
|
|
||||||
// c.clock.step(10)
|
|
||||||
// c.reset.poke(false.B)
|
|
||||||
|
|
||||||
// // enqueue one entry to not match at 0th index
|
|
||||||
// c.io.enq.ready.expect(true.B)
|
|
||||||
// c.io.enq.valid.poke(true.B)
|
|
||||||
// c.io.enq.bits.fromLane.poke(0.U)
|
|
||||||
// c.io.enq.bits.respSourceId.poke(0.U)
|
|
||||||
// c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
|
|
||||||
|
|
||||||
// c.clock.step()
|
|
||||||
|
|
||||||
// val targetSourceId = 1.U
|
|
||||||
// c.io.enq.ready.expect(true.B)
|
|
||||||
// c.io.enq.valid.poke(true.B)
|
|
||||||
// c.io.enq.bits.fromLane.poke(0.U)
|
|
||||||
// c.io.enq.bits.respSourceId.poke(targetSourceId)
|
|
||||||
// c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
|
|
||||||
|
|
||||||
// c.clock.step()
|
|
||||||
|
|
||||||
// c.io.lookup.ready.poke(true.B)
|
|
||||||
// c.io.lookupSourceId.poke(targetSourceId)
|
|
||||||
// c.io.lookup.valid.expect(true.B)
|
|
||||||
// c.io.lookup.bits.expect(targetSourceId)
|
|
||||||
|
|
||||||
// c.clock.step()
|
|
||||||
|
|
||||||
// // test if matching entry dequeues after 1 cycle
|
|
||||||
// c.io.lookup.ready.poke(true.B)
|
|
||||||
// c.io.lookupSourceId.poke(targetSourceId)
|
|
||||||
// c.io.lookup.valid.expect(false.B)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// it should "handle lookup and enqueue at the same time" in {
|
|
||||||
// test(new InflightCoalReqTable(numLanes, sourceWidth, entries)) { c =>
|
|
||||||
// // fill up the table
|
|
||||||
// val targetSourceId = 1.U
|
|
||||||
// c.io.enq.ready.expect(true.B)
|
|
||||||
// c.io.enq.valid.poke(true.B)
|
|
||||||
// c.io.enq.bits.fromLane.poke(0.U)
|
|
||||||
// c.io.enq.bits.respSourceId.poke(0.U)
|
|
||||||
// c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
|
|
||||||
// c.clock.step()
|
|
||||||
// c.io.enq.ready.expect(true.B)
|
|
||||||
// c.io.enq.valid.poke(true.B)
|
|
||||||
// c.io.enq.bits.fromLane.poke(0.U)
|
|
||||||
// c.io.enq.bits.respSourceId.poke(targetSourceId)
|
|
||||||
// c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
|
|
||||||
// c.clock.step()
|
|
||||||
|
|
||||||
// // do both enqueue and lookup at the same cycle
|
|
||||||
// val enqSourceId = 2.U
|
|
||||||
// c.io.enq.ready.expect(true.B)
|
|
||||||
// c.io.enq.valid.poke(true.B)
|
|
||||||
// c.io.enq.bits.fromLane.poke(0.U)
|
|
||||||
// c.io.enq.bits.respSourceId.poke(enqSourceId)
|
|
||||||
// c.io.enq.bits.reqSourceIds.foreach { id => id.poke(0.U) }
|
|
||||||
// c.io.lookup.ready.poke(true.B)
|
|
||||||
// c.io.lookupSourceId.poke(targetSourceId)
|
|
||||||
|
|
||||||
// c.clock.step()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user