Fix truncation bug in matchCount

This commit is contained in:
Hansung Kim
2023-04-27 20:24:15 -07:00
parent 84ac332637
commit ba2bc3020b
2 changed files with 49 additions and 50 deletions

View File

@@ -253,7 +253,7 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry],
val matchOH = Output(Vec(config.numLanes, UInt(config.queueDepth.W))) val matchOH = Output(Vec(config.numLanes, UInt(config.queueDepth.W)))
// number of entries matched with this leader lane's head. // number of entries matched with this leader lane's head.
// maximum is numLanes * queueDepth // maximum is numLanes * queueDepth
val matchCount = Output(UInt(log2Ceil(config.numLanes * config.queueDepth).W)) val matchCount = Output(UInt(log2Ceil(config.numLanes * config.queueDepth + 1).W))
val coverageHits = Output(UInt((1 << config.maxSize).W)) val coverageHits = Output(UInt((1 << config.maxSize).W))
}) })
}) })
@@ -307,7 +307,9 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry],
} }
// TODO: potentially expensive: popcount & adder // TODO: potentially expensive: popcount & adder
val matchCounts = matchTablePerLane.map(leader => leader.map(PopCount(_)).reduce(_ +& _)) val matchCounts = matchTablePerLane.map(table =>
table.map(PopCount(_)) // sum up each column
.reduce(_ +& _))
val canCoalesce = matchCounts.map(_ > 1.U) val canCoalesce = matchCounts.map(_ > 1.U)
// TODO: potentially expensive // TODO: potentially expensive
@@ -330,10 +332,10 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry],
// 2-D table flattened to 1-D // 2-D table flattened to 1-D
val offsets = io.window.map(_.elts).flatMap(_.map(req => getOffsetSlice(req.address))) val offsets = io.window.map(_.elts).flatMap(_.map(req => getOffsetSlice(req.address)))
val valids = io.window.map(_.mask).flatMap(_.asBools) val valids = io.window.map(_.mask).flatMap(_.asBools)
// indicates whether each word in the coalesced chunk is accessed by any of the
// queue entries. e.g. if [ 1 1 1 1 ], all of the four words in the coalesced
// data has been accessed and we've reached 100% utilization.
val hits = Seq.tabulate(1 << (size - config.wordWidth)) { target => val hits = Seq.tabulate(1 << (size - config.wordWidth)) { target =>
// count if any of the queue entries accesses the given offset word of the
// coalesced chunk; if 1 for all offsets, we've reached 100% utilization
// of the coalesced data words
(offsets zip valids).map { case (offset, valid) => valid && (offset === target.U) }.reduce(_ || _) (offsets zip valids).map { case (offset, valid) => valid && (offset === target.U) }.reduce(_ || _)
} }
@@ -348,6 +350,7 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry],
printf("%d ", m) printf("%d ", m)
} }
printf("]\n") printf("]\n")
printf("chosenMatchCount = %d\n", chosenMatchCount)
printf("hits = [ ") printf("hits = [ ")
hits.foreach { m => hits.foreach { m =>
@@ -410,9 +413,11 @@ class MultiCoalescer(windowT: CoalShiftQueue[ReqQueueEntry], coalReqT: ReqQueueE
when (normalizedHits.map(_ > minCoverage.U).reduce(_ || _)) { when (normalizedHits.map(_ > minCoverage.U).reduce(_ || _)) {
chosenSizeIdx := argMax(normalizedHits) chosenSizeIdx := argMax(normalizedHits)
chosenValid := true.B chosenValid := true.B
printf("coalescing success by coverage policy\n")
}.elsewhen(normalizedMatches.map(_ > 1.U).reduce(_ || _)) { }.elsewhen(normalizedMatches.map(_ > 1.U).reduce(_ || _)) {
chosenSizeIdx := argMax(normalizedMatches) chosenSizeIdx := argMax(normalizedMatches)
chosenValid := true.B chosenValid := true.B
printf("coalescing success by matches policy\n")
}.otherwise { }.otherwise {
chosenSizeIdx := DontCare chosenSizeIdx := DontCare
chosenValid := false.B chosenValid := false.B
@@ -460,9 +465,6 @@ class MultiCoalescer(windowT: CoalShiftQueue[ReqQueueEntry], coalReqT: ReqQueueE
sourceGen.io.gen := io.outReq.fire // use up a source ID only when request is created sourceGen.io.gen := io.outReq.fire // use up a source ID only when request is created
val coalesceValid = chosenValid && sourceGen.io.id.valid val coalesceValid = chosenValid && sourceGen.io.id.valid
when (coalesceValid) {
printf("coalescing success!\n")
}
io.outReq.bits.source := sourceGen.io.id.bits io.outReq.bits.source := sourceGen.io.id.bits
io.outReq.bits.mask := mask.asUInt io.outReq.bits.mask := mask.asUInt

View File

@@ -96,6 +96,23 @@ class DummyCoalescingUnitTBImp(outer: DummyCoalescingUnitTB) extends LazyModuleI
// val coalMasterNode = coal.coalescerNode.makeIOs() // val coalMasterNode = coal.coalescerNode.makeIOs()
} }
object testConfig extends CoalescerConfig(
numLanes = 4,
maxSize = 3,
queueDepth = 1,
waitTimeout = 8,
addressWidth = 24,
dataBusWidth = 5,
// watermark = 2,
wordSizeInBytes = 4,
wordWidth = 2,
numOldSrcIds = 16,
numNewSrcIds = 4,
respQueueDepth = 4,
coalLogSizes = Seq(3),
sizeEnum = DefaultInFlightTableSizeEnum
)
class CoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester { class CoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester {
behavior of "multi- and mono-coalescers" behavior of "multi- and mono-coalescers"
@@ -140,33 +157,33 @@ class CoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester {
} }
} }
it should "coalesce fully consecutive accesses at size 4, only once" in { // it should "coalesce fully consecutive accesses at size 4, only once" in {
test(makeTb().module) // test(makeTb().module)
.withAnnotations(Seq(VcsBackendAnnotation, WriteFsdbAnnotation)) // .withAnnotations(Seq(VcsBackendAnnotation, WriteFsdbAnnotation))
{ c => // { c =>
println(s"coalIO length = ${c.coalIOs(0).length}") // println(s"coalIO length = ${c.coalIOs(0).length}")
val nodes = c.coalIOs.map(_.head) // val nodes = c.coalIOs.map(_.head)
// val nodes = c.cpuNodesImp.map(_.out.head._1) // // val nodes = c.cpuNodesImp.map(_.out.head._1)
// val nodes = c.coal.node.in.map(_._1) // // val nodes = c.coal.node.in.map(_._1)
// val nodes = c.mitmNodesImp.map(_.in.head._1) // // val nodes = c.mitmNodesImp.map(_.in.head._1)
// always ready to take coalesced requests // // always ready to take coalesced requests
// c.coalMasterNode.head.a.ready.poke(true.B) // // c.coalMasterNode.head.a.ready.poke(true.B)
// c.coal.module.coalescer.io.outReq.ready.poke(true.B) // // c.coal.module.coalescer.io.outReq.ready.poke(true.B)
pokeA(nodes, idx = 0, op = 1, size = 2, source = 0, addr = 0x10, mask = 0xf, data = 0x1111) // pokeA(nodes, idx = 0, op = 1, size = 2, source = 0, addr = 0x10, mask = 0xf, data = 0x1111)
pokeA(nodes, idx = 1, op = 1, size = 2, source = 0, addr = 0x14, mask = 0xf, data = 0x2222) // pokeA(nodes, idx = 1, op = 1, size = 2, source = 0, addr = 0x14, mask = 0xf, data = 0x2222)
pokeA(nodes, idx = 2, op = 1, size = 2, source = 0, addr = 0x18, mask = 0xf, data = 0x3333) // pokeA(nodes, idx = 2, op = 1, size = 2, source = 0, addr = 0x18, mask = 0xf, data = 0x3333)
pokeA(nodes, idx = 3, op = 1, size = 2, source = 0, addr = 0x1c, mask = 0xf, data = 0x4444) // pokeA(nodes, idx = 3, op = 1, size = 2, source = 0, addr = 0x1c, mask = 0xf, data = 0x4444)
c.clock.step() // c.clock.step()
unsetA(nodes) // unsetA(nodes)
c.clock.step() // c.clock.step()
c.clock.step() // c.clock.step()
} // }
} // }
it should "coalesce identical addresses (stride of 0)" in { it should "coalesce identical addresses (stride of 0)" in {
test(makeTb().module) test(makeTb().module)
@@ -186,8 +203,6 @@ class CoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester {
c.clock.step() c.clock.step()
c.clock.step() c.clock.step()
nodes(0).a.ready.expect(true.B)
} }
} }
@@ -426,24 +441,6 @@ class CoalShiftQueueTest extends AnyFlatSpec with ChiselScalatestTester {
} }
} }
object testConfig
extends CoalescerConfig(
maxSize = 5,
queueDepth = 2,
waitTimeout = 8,
addressWidth = 24,
dataBusWidth = 5,
numLanes = 4,
// watermark = 2,
wordSizeInBytes = 4,
wordWidth = 2,
numOldSrcIds = 16,
numNewSrcIds = 4,
respQueueDepth = 4,
coalLogSizes = Seq(4, 5),
sizeEnum = DefaultInFlightTableSizeEnum
)
class UncoalescingUnitTest extends AnyFlatSpec with ChiselScalatestTester { class UncoalescingUnitTest extends AnyFlatSpec with ChiselScalatestTester {
behavior of "uncoalescer" behavior of "uncoalescer"
val numLanes = 4 val numLanes = 4