From 2090b8703ec27c81b129f7d2bd009902a79a72e1 Mon Sep 17 00:00:00 2001 From: Hansung Kim Date: Tue, 25 Apr 2023 17:16:28 -0700 Subject: [PATCH] Rename params --- src/main/scala/tilelink/Coalescing.scala | 173 ++++++++++++----------- 1 file changed, 87 insertions(+), 86 deletions(-) diff --git a/src/main/scala/tilelink/Coalescing.scala b/src/main/scala/tilelink/Coalescing.scala index 258c97a..ad9007e 100644 --- a/src/main/scala/tilelink/Coalescing.scala +++ b/src/main/scala/tilelink/Coalescing.scala @@ -36,39 +36,40 @@ object DefaultInFlightTableSizeEnum extends InFlightTableSizeEnum { } case class CoalescerConfig( - NUM_LANES: Int, // number of lanes (or threads) in a warp - MAX_SIZE: Int, // maximum burst size (64 bytes) - QUEUE_DEPTH: Int, // request window per lane - WAIT_TIMEOUT: Int, // max cycles to wait before forced fifo dequeue, per lane - ADDR_WIDTH: Int, // assume <= 32 - DATA_BUS_SIZE: Int, // memory-side downstream TileLink data bus size - // this has to be at least larger than the word size for - // the coalescer to perform well - // WATERMARK = 2, // minimum buffer occupancy to start coalescing - WORD_SIZE: Int, // 32-bit system - WORD_WIDTH: Int, // log(WORD_SIZE) - NUM_OLD_IDS: Int, // num of outstanding requests per lane, from processor - NUM_NEW_IDS: Int, // num of outstanding coalesced requests - RESP_QUEUE_DEPTH: Int, // depth of the response fifo queues - COAL_SIZES: Seq[Int], + numLanes: Int, // number of lanes (or threads) in a warp + maxSize: Int, // maximum burst size (64 bytes) + queueDepth: Int, // request window per lane + waitTimeout: Int, // max cycles to wait before forced fifo dequeue, per lane + addressWidth: Int, // assume <= 32 + dataBusWidth: Int, // memory-side downstream TileLink data bus size + // this has to be at least larger than the word size for + // the coalescer to perform well + // watermark = 2, // minimum buffer occupancy to start coalescing + wordSizeInBytes: Int, // 32-bit system + wordWidth: Int, // log(WORD_SIZE) + numOldSrcIds: Int, // num of outstanding requests per lane, from processor + numNewSrcIds: Int, // num of outstanding coalesced requests + respQueueDepth: Int, // depth of the response fifo queues + coalSizes: Seq[Int], // list of coalescer sizes to try in the MonoCoalescers + // must be power of 2's sizeEnum: InFlightTableSizeEnum ) object defaultConfig extends CoalescerConfig( - NUM_LANES = 32, + numLanes = 32, // TODO: bigger size - MAX_SIZE = 3, - QUEUE_DEPTH = 1, - WAIT_TIMEOUT = 8, - ADDR_WIDTH = 24, - DATA_BUS_SIZE = 3, // 2^3=8 bytes, 64 bit bus - // WATERMARK = 2, - WORD_SIZE = 4, - WORD_WIDTH = 2, - NUM_OLD_IDS = 16, - NUM_NEW_IDS = 4, - RESP_QUEUE_DEPTH = 4, - COAL_SIZES = Seq(3), + maxSize = 3, + queueDepth = 1, + waitTimeout = 8, + addressWidth = 24, + dataBusWidth = 3, // 2^3=8 bytes, 64 bit bus + // watermark = 2, + wordSizeInBytes = 4, + wordWidth = 2, + numOldSrcIds = 16, + numNewSrcIds = 4, + respQueueDepth = 4, + coalSizes = Seq(3), sizeEnum = DefaultInFlightTableSizeEnum ) @@ -80,7 +81,7 @@ class CoalescingUnit(config: CoalescerConfig)(implicit p: Parameters) extends La // Number of maximum in-flight coalesced requests. The upper bound of this // value would be the sourceId range of a single lane. - val numInflightCoalRequests = config.NUM_NEW_IDS + val numInflightCoalRequests = config.numNewSrcIds // Master node that actually generates coalesced requests. protected val coalParam = Seq( @@ -245,20 +246,20 @@ class CoalShiftQueue[T <: Data]( class MonoCoalescer(coalSize: Int, windowT: CoalShiftQueue[ReqQueueEntry], config: CoalescerConfig) extends Module { val io = IO(new Bundle { - val window = Input(Vec(config.NUM_LANES, windowT.io.cloneType)) + val window = Input(Vec(config.numLanes, windowT.io.cloneType)) val results = Output(new Bundle { - val leaderIdx = Output(UInt(log2Ceil(config.NUM_LANES).W)) - val baseAddr = Output(UInt(config.ADDR_WIDTH.W)) - val matchOH = Output(Vec(config.NUM_LANES, UInt(config.QUEUE_DEPTH.W))) - val matchCount = Output(UInt(log2Ceil(config.NUM_LANES * config.QUEUE_DEPTH).W)) - val coverageHits = Output(UInt((1 << config.MAX_SIZE).W)) + val leaderIdx = Output(UInt(log2Ceil(config.numLanes).W)) + val baseAddr = Output(UInt(config.addressWidth.W)) + val matchOH = Output(Vec(config.numLanes, UInt(config.queueDepth.W))) + val matchCount = Output(UInt(log2Ceil(config.numLanes * config.queueDepth).W)) + val coverageHits = Output(UInt((1 << config.maxSize).W)) }) }) io := DontCare val size = coalSize - val mask = (((1 << config.ADDR_WIDTH) - 1) - ((1 << size) - 1)).U + val mask = (((1 << config.addressWidth) - 1) - ((1 << size) - 1)).U def canMatch(req0: ReqQueueEntry, req0v: Bool, req1: ReqQueueEntry, req1v: Bool): Bool = { (req0.op === req1.op) && @@ -313,9 +314,9 @@ class MonoCoalescer(coalSize: Int, windowT: CoalShiftQueue[ReqQueueEntry], val chosenMatchCount = VecInit(matchCounts)(chosenLeaderIdx) // coverage calculation - def getOffsetSlice(addr: UInt) = addr(size - 1, config.WORD_WIDTH) + def getOffsetSlice(addr: UInt) = addr(size - 1, config.wordWidth) val offsets = io.window.map(_.elts).flatMap(_.map(req => getOffsetSlice(req.address))) - val hits = Seq.tabulate(1 << (size - config.WORD_WIDTH)) { target => + val hits = Seq.tabulate(1 << (size - config.wordWidth)) { target => offsets.map(_ === target.U).reduce(_ || _) } @@ -331,17 +332,17 @@ class MultiCoalescer(windowT: CoalShiftQueue[ReqQueueEntry], coalReqT: ReqQueueE config: CoalescerConfig) extends Module { val io = IO(new Bundle { - val window = Input(Vec(config.NUM_LANES, windowT.io.cloneType)) + val window = Input(Vec(config.numLanes, windowT.io.cloneType)) val outReq = DecoupledIO(coalReqT.cloneType) - val invalidate = Output(Valid(Vec(config.NUM_LANES, UInt(config.QUEUE_DEPTH.W)))) + val invalidate = Output(Valid(Vec(config.numLanes, UInt(config.queueDepth.W)))) }) - val coalescers = config.COAL_SIZES.map(size => Module(new MonoCoalescer(size, windowT, config))) + val coalescers = config.coalSizes.map(size => Module(new MonoCoalescer(size, windowT, config))) coalescers.foreach(_.io.window := io.window) def normalize(x: Seq[UInt]): Seq[UInt] = { - x.zip(config.COAL_SIZES).map { case (hits, size) => - (hits << (config.MAX_SIZE - size).U).asUInt + x.zip(config.coalSizes).map { case (hits, size) => + (hits << (config.maxSize - size).U).asUInt } } @@ -356,10 +357,10 @@ class MultiCoalescer(windowT: CoalShiftQueue[ReqQueueEntry], coalReqT: ReqQueueE val normalizedMatches = normalize(coalescers.map(_.io.results.matchCount)) val normalizedHits = normalize(coalescers.map(_.io.results.coverageHits)) - val chosenIdx = Wire(UInt(log2Ceil(config.COAL_SIZES.size).W)) + val chosenIdx = Wire(UInt(log2Ceil(config.coalSizes.size).W)) val chosenValid = Wire(Bool()) // minimum 25% coverage - val minCoverage = 1.max(1 << (config.MAX_SIZE - 4)) + val minCoverage = 1.max(1 << (config.maxSize - 4)) when (normalizedHits.map(_ > minCoverage.U).reduce(_ || _)) { chosenIdx := argMax(normalizedHits) chosenValid := true.B @@ -380,21 +381,21 @@ class MultiCoalescer(windowT: CoalShiftQueue[ReqQueueEntry], coalReqT: ReqQueueE val flatMatches = chosenBundle.matchOH.flatMap(_.asBools) // check for word alignment in addresses - assert(io.window.flatMap(_.elts.map(req => req.address(config.WORD_WIDTH - 1, 0) === 0.U)).reduce(_ || _), + assert(io.window.flatMap(_.elts.map(req => req.address(config.wordWidth - 1, 0) === 0.U)).reduce(_ || _), "one or more addresses used for coalescing is not word-aligned") // note: this is word-level coalescing. if finer granularity is needed, need to modify code - val numWords = (1.U << (chosenSize - config.WORD_WIDTH.U)).asUInt - val maxWords = 1 << (config.MAX_SIZE - config.WORD_WIDTH) - val addrMask = Wire(UInt(config.MAX_SIZE.W)) + val numWords = (1.U << (chosenSize - config.wordWidth.U)).asUInt + val maxWords = 1 << (config.maxSize - config.wordWidth) + val addrMask = Wire(UInt(config.maxSize.W)) addrMask := (1.U << chosenSize).asUInt - 1.U - val data = Wire(Vec(maxWords, UInt((config.WORD_SIZE * 8).W))) - val mask = Wire(Vec(maxWords, UInt(config.WORD_SIZE.W))) + val data = Wire(Vec(maxWords, UInt((config.wordSizeInBytes * 8).W))) + val mask = Wire(Vec(maxWords, UInt(config.wordSizeInBytes.W))) for (i <- 0 until maxWords) { val sel = flatReqs.zip(flatMatches).map { case (req, m) => - m && ((req.address(config.MAX_SIZE - 1, 0) & addrMask) === i.U) + m && ((req.address(config.maxSize - 1, 0) & addrMask) === i.U) } // TODO: SW uses priority encoder, not sure about behavior of MuxCase data(i) := MuxCase(DontCare, flatReqs.zip(sel).map { case (req, s) => @@ -408,7 +409,7 @@ class MultiCoalescer(windowT: CoalShiftQueue[ReqQueueEntry], coalReqT: ReqQueueE ) } - val sourceGen = Module(new ReqSourceGen(log2Ceil(config.NUM_NEW_IDS))) + val sourceGen = Module(new ReqSourceGen(log2Ceil(config.numNewSrcIds))) sourceGen.io.gen := io.outReq.fire // use up a source ID only when request is created io.outReq.bits.source := sourceGen.io.id.bits @@ -431,19 +432,19 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends // Make sure IdentityNode is connected to an upstream node, not just the // coalescer TL master node assert(outer.node.in.length >= 2) - assert(outer.node.in(1)._1.params.sourceBits == log2Ceil(config.NUM_OLD_IDS), + assert(outer.node.in(1)._1.params.sourceBits == log2Ceil(config.numOldSrcIds), s"old source id bits TL param (${outer.node.in(1)._1.params.sourceBits}) mismatch with config") - assert(outer.node.in(1)._1.params.addressBits == config.ADDR_WIDTH, + assert(outer.node.in(1)._1.params.addressBits == config.addressWidth, s"address width TL param (${outer.node.in(1)._1.params.addressBits}) mismatch with config") val sourceWidth = outer.node.in(1)._1.params.sourceBits // note we are using word size. assuming all coalescer inputs are word sized - val reqQueueEntryT = new ReqQueueEntry(sourceWidth, config.WORD_WIDTH, config.ADDR_WIDTH, config.WORD_SIZE) - val reqQueues = Seq.tabulate(config.NUM_LANES) { _ => - Module(new CoalShiftQueue(reqQueueEntryT, config.QUEUE_DEPTH)) + val reqQueueEntryT = new ReqQueueEntry(sourceWidth, config.wordWidth, config.addressWidth, config.wordSizeInBytes) + val reqQueues = Seq.tabulate(config.numLanes) { _ => + Module(new CoalShiftQueue(reqQueueEntryT, config.queueDepth)) } - val coalReqT = new ReqQueueEntry(sourceWidth, log2Ceil(config.MAX_SIZE), config.ADDR_WIDTH, config.MAX_SIZE) + val coalReqT = new ReqQueueEntry(sourceWidth, log2Ceil(config.maxSize), config.addressWidth, config.maxSize) val coalescer = Module(new MultiCoalescer(reqQueues.head, coalReqT, config)) coalescer.io.window := reqQueues.map(_.io) @@ -511,10 +512,10 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends // The maximum number of requests from a single lane that can go into a // coalesced request. Upper bound is min(DEPTH, 2**sourceWidth). - val numPerLaneReqs = config.QUEUE_DEPTH + val numPerLaneReqs = config.queueDepth - val respQueueEntryT = new RespQueueEntry(sourceWidth, log2Ceil(config.MAX_SIZE), config.MAX_SIZE) - val respQueues = Seq.tabulate(config.NUM_LANES) { _ => + val respQueueEntryT = new RespQueueEntry(sourceWidth, log2Ceil(config.maxSize), config.maxSize) + val respQueues = Seq.tabulate(config.numLanes) { _ => Module( new MultiPortQueue( respQueueEntryT, @@ -533,7 +534,7 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends // make queue block up in the middle of the simulation. Ideally there // should be a more logical way to set this, or we should handle // response queue blocking. - config.RESP_QUEUE_DEPTH + config.respQueueDepth ) ) } @@ -621,7 +622,7 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends // but the width of the size enum val newEntry = Wire( new InflightCoalReqTableEntry( - config.NUM_LANES, + config.numLanes, numPerLaneReqs, sourceWidth, offsetBits, @@ -638,9 +639,9 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends // to assert that MAX_SIZE is <= DATA_BUS_SIZE because we do not support // multi-beat writes currently assert( - tlCoal.params.dataBits == (1 << config.DATA_BUS_SIZE) * 8, + tlCoal.params.dataBits == (1 << config.dataBusWidth) * 8, s"tlCoal param dataBits (${tlCoal.params.dataBits}) mismatch coalescer constant" - + s" (${(1 << config.DATA_BUS_SIZE) * 8})" + + s" (${(1 << config.dataBusWidth) * 8})" ) val origReqs = reqQueues.map(q => q.io.queue.deq.bits) newEntry.lanes.foreach { l => @@ -648,7 +649,7 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends // TODO: this part needs the actual coalescing logic to work r.valid := false.B r.source := origReqs(i).source - r.offset := (origReqs(i).address % (1 << config.MAX_SIZE).U) >> config.WORD_WIDTH + r.offset := (origReqs(i).address % (1 << config.maxSize).U) >> config.wordWidth r.sizeEnum := config.sizeEnum.logSizeToEnum(origReqs(i).size) } } @@ -701,8 +702,8 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends // // FIXME: overlaps with RespQueueEntry. Trait-ify class CoalescedResponseBundle(config: CoalescerConfig) extends Bundle { - val source = UInt(log2Ceil(config.NUM_NEW_IDS).W) - val data = UInt((8 * (1 << config.MAX_SIZE)).W) + val source = UInt(log2Ceil(config.numNewSrcIds).W) + val data = UInt((8 * (1 << config.maxSize)).W) } class UncoalescingUnit(config: CoalescerConfig) extends Module { @@ -721,11 +722,11 @@ class UncoalescingUnit(config: CoalescerConfig) extends Module { val coalResp = Flipped(Decoupled(new CoalescedResponseBundle(config))) val uncoalResps = Output( Vec( - config.NUM_LANES, + config.numLanes, Vec( - config.QUEUE_DEPTH, + config.queueDepth, ValidIO( - new RespQueueEntry(log2Ceil(config.NUM_OLD_IDS), config.WORD_WIDTH, config.WORD_SIZE) + new RespQueueEntry(log2Ceil(config.numOldSrcIds), config.wordWidth, config.wordSizeInBytes) ) ) ) @@ -808,15 +809,15 @@ class InflightCoalReqTable(config: CoalescerConfig) extends Module { val offsetBits = 4 // FIXME hardcoded val sizeBits = 2 // FIXME hardcoded val entryT = new InflightCoalReqTableEntry( - config.NUM_LANES, - config.QUEUE_DEPTH, - log2Ceil(config.NUM_OLD_IDS), - config.MAX_SIZE, + config.numLanes, + config.queueDepth, + log2Ceil(config.numOldSrcIds), + config.maxSize, config.sizeEnum ) - val entries = config.NUM_NEW_IDS - val sourceWidth = log2Ceil(config.NUM_OLD_IDS) + val entries = config.numNewSrcIds + val sourceWidth = log2Ceil(config.numOldSrcIds) val io = IO(new Bundle { val enq = Flipped(Decoupled(entryT)) @@ -930,7 +931,7 @@ class MemTraceDriver(config: CoalescerConfig, filename: String)(implicit p: Parameters ) extends LazyModule { // Create N client nodes together - val laneNodes = Seq.tabulate(config.NUM_LANES) { i => + val laneNodes = Seq.tabulate(config.numLanes) { i => val clientParam = Seq( TLMasterParameters.v1( name = "MemTraceDriver" + i.toString, @@ -972,7 +973,7 @@ class TraceLine extends Bundle with HasTraceLine { class MemTraceDriverImp(outer: MemTraceDriver, config: CoalescerConfig, traceFile: String) extends LazyModuleImp(outer) with UnitTestModule { - val sim = Module(new SimMemTrace(traceFile, config.NUM_LANES)) + val sim = Module(new SimMemTrace(traceFile, config.numLanes)) sim.io.clock := clock sim.io.reset := reset.asBool sim.io.trace_read.ready := true.B @@ -980,7 +981,7 @@ class MemTraceDriverImp(outer: MemTraceDriver, config: CoalescerConfig, traceFil // Split output of SimMemTrace, which is flattened across all lanes, // back to each lane's. - val laneReqs = Wire(Vec(config.NUM_LANES, new TraceLine)) + val laneReqs = Wire(Vec(config.numLanes, new TraceLine)) val addrW = laneReqs(0).address.getWidth val sizeW = laneReqs(0).size.getWidth val dataW = laneReqs(0).data.getWidth @@ -1013,17 +1014,17 @@ class MemTraceDriverImp(outer: MemTraceDriver, config: CoalescerConfig, traceFil // the trace driver to act so as well. // That means if req.size is smaller than word size, we need to pad data // with zeros to generate a word-size request, and set mask accordingly. - val offsetInWord = req.address % config.WORD_SIZE.U - val subword = req.size < log2Ceil(config.WORD_SIZE).U + val offsetInWord = req.address % config.wordSizeInBytes.U + val subword = req.size < log2Ceil(config.wordSizeInBytes).U // `mask` is currently unused - val mask = Wire(UInt(config.WORD_SIZE.W)) - val wordData = Wire(UInt((config.WORD_SIZE * 8 * 2).W)) + val mask = Wire(UInt(config.wordSizeInBytes.W)) + val wordData = Wire(UInt((config.wordSizeInBytes * 8 * 2).W)) val sizeInBytes = Wire(UInt((sizeW + 1).W)) sizeInBytes := (1.U) << req.size mask := Mux(subword, (~((~0.U(64.W)) << sizeInBytes)) << offsetInWord, ~0.U) wordData := Mux(subword, req.data << (offsetInWord * 8.U), req.data) - val wordAlignedAddress = req.address & ~((1 << log2Ceil(config.WORD_SIZE)) - 1).U(addrW.W) + val wordAlignedAddress = req.address & ~((1 << log2Ceil(config.wordSizeInBytes)) - 1).U(addrW.W) val wordAlignedSize = Mux(subword, 2.U, req.size) // when(req.valid && subword) {