diff --git a/src/main/scala/tilelink/Coalescing.scala b/src/main/scala/tilelink/Coalescing.scala index deeb403..cf8c330 100644 --- a/src/main/scala/tilelink/Coalescing.scala +++ b/src/main/scala/tilelink/Coalescing.scala @@ -253,7 +253,7 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry], val matchOH = Output(Vec(config.numLanes, UInt(config.queueDepth.W))) // number of entries matched with this leader lane's head. // 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)) }) }) @@ -307,7 +307,9 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry], } // 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) // TODO: potentially expensive @@ -330,10 +332,10 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry], // 2-D table flattened to 1-D val offsets = io.window.map(_.elts).flatMap(_.map(req => getOffsetSlice(req.address))) 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 => - // 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(_ || _) } @@ -348,6 +350,7 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry], printf("%d ", m) } printf("]\n") + printf("chosenMatchCount = %d\n", chosenMatchCount) printf("hits = [ ") hits.foreach { m => @@ -410,9 +413,11 @@ class MultiCoalescer(windowT: CoalShiftQueue[ReqQueueEntry], coalReqT: ReqQueueE when (normalizedHits.map(_ > minCoverage.U).reduce(_ || _)) { chosenSizeIdx := argMax(normalizedHits) chosenValid := true.B + printf("coalescing success by coverage policy\n") }.elsewhen(normalizedMatches.map(_ > 1.U).reduce(_ || _)) { chosenSizeIdx := argMax(normalizedMatches) chosenValid := true.B + printf("coalescing success by matches policy\n") }.otherwise { chosenSizeIdx := DontCare 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 val coalesceValid = chosenValid && sourceGen.io.id.valid - when (coalesceValid) { - printf("coalescing success!\n") - } io.outReq.bits.source := sourceGen.io.id.bits io.outReq.bits.mask := mask.asUInt diff --git a/src/test/scala/coalescing/CoalescingUnitTest.scala b/src/test/scala/coalescing/CoalescingUnitTest.scala index c31e97c..0e79ef1 100644 --- a/src/test/scala/coalescing/CoalescingUnitTest.scala +++ b/src/test/scala/coalescing/CoalescingUnitTest.scala @@ -96,6 +96,23 @@ class DummyCoalescingUnitTBImp(outer: DummyCoalescingUnitTB) extends LazyModuleI // 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 { 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 { - test(makeTb().module) - .withAnnotations(Seq(VcsBackendAnnotation, WriteFsdbAnnotation)) - { c => - println(s"coalIO length = ${c.coalIOs(0).length}") - val nodes = c.coalIOs.map(_.head) -// val nodes = c.cpuNodesImp.map(_.out.head._1) -// val nodes = c.coal.node.in.map(_._1) -// val nodes = c.mitmNodesImp.map(_.in.head._1) + // it should "coalesce fully consecutive accesses at size 4, only once" in { + // test(makeTb().module) + // .withAnnotations(Seq(VcsBackendAnnotation, WriteFsdbAnnotation)) + // { c => + // println(s"coalIO length = ${c.coalIOs(0).length}") + // val nodes = c.coalIOs.map(_.head) +// // val nodes = c.cpuNodesImp.map(_.out.head._1) +// // val nodes = c.coal.node.in.map(_._1) +// // val nodes = c.mitmNodesImp.map(_.in.head._1) - // always ready to take coalesced requests -// c.coalMasterNode.head.a.ready.poke(true.B) -// c.coal.module.coalescer.io.outReq.ready.poke(true.B) + // // always ready to take coalesced requests +// // c.coalMasterNode.head.a.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 = 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 = 3, op = 1, size = 2, source = 0, addr = 0x1c, mask = 0xf, data = 0x4444) + // 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 = 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) - 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 { test(makeTb().module) @@ -186,8 +203,6 @@ class CoalescerUnitTest extends AnyFlatSpec with ChiselScalatestTester { 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 { behavior of "uncoalescer" val numLanes = 4