Uncoalesce using table size enum

This commit is contained in:
Hansung Kim
2023-04-23 14:42:10 -07:00
parent ccf9b95fb5
commit 8cee61a591
2 changed files with 36 additions and 26 deletions

View File

@@ -11,17 +11,24 @@ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.MultiPortQueue import freechips.rocketchip.util.MultiPortQueue
import freechips.rocketchip.unittest._ import freechips.rocketchip.unittest._
object InFlightTableSizeEnum extends ChiselEnum { trait InFlightTableSizeEnum extends ChiselEnum {
val INVALID: Type
val FOUR: Type
def logSizeToEnum(x: UInt): Type
def enumToLogSize(x: Type): UInt
}
object DefaultInFlightTableSizeEnum extends InFlightTableSizeEnum {
val INVALID = Value(0.U) val INVALID = Value(0.U)
val FOUR = Value(1.U) val FOUR = Value(1.U)
def log2Enum(x: UInt): Type = { def logSizeToEnum(x: UInt): Type = {
MuxCase(INVALID, Seq( MuxCase(INVALID, Seq(
(x === 2.U) -> FOUR (x === 2.U) -> FOUR
)) ))
} }
def enum2log(x: Type): UInt = { def enumToLogSize(x: Type): UInt = {
MuxCase(0.U, Seq( MuxCase(0.U, Seq(
(x === FOUR) -> 2.U (x === FOUR) -> 2.U
)) ))
@@ -41,7 +48,7 @@ case class CoalescerConfig(
NUM_OLD_IDS: Int, // num of outstanding requests per lane, from processor NUM_OLD_IDS: Int, // num of outstanding requests per lane, from processor
NUM_NEW_IDS: Int, // num of outstanding coalesced requests NUM_NEW_IDS: Int, // num of outstanding coalesced requests
COAL_SIZES: Seq[Int], COAL_SIZES: Seq[Int],
SizeEnum: ChiselEnum SizeEnum: InFlightTableSizeEnum
) )
object defaultConfig extends CoalescerConfig( object defaultConfig extends CoalescerConfig(
@@ -58,7 +65,7 @@ object defaultConfig extends CoalescerConfig(
NUM_OLD_IDS = 16, // num of outstanding requests per lane, from processor NUM_OLD_IDS = 16, // num of outstanding requests per lane, from processor
NUM_NEW_IDS = 4, // num of outstanding coalesced requests NUM_NEW_IDS = 4, // num of outstanding coalesced requests
COAL_SIZES = Seq(3), COAL_SIZES = Seq(3),
SizeEnum = InFlightTableSizeEnum SizeEnum = DefaultInFlightTableSizeEnum
) )
class CoalescingUnit(config: CoalescerConfig)(implicit p: Parameters) extends LazyModule { class CoalescingUnit(config: CoalescerConfig)(implicit p: Parameters) extends LazyModule {
@@ -436,7 +443,7 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends
dontTouch(tlOut.d) dontTouch(tlOut.d)
} }
// Construct new entry for the inflight table // Construct new entry for the inflight table
// FIXME: don't instantiate inflight table entry type here. It leaks the table's impl // FIXME: don't instantiate inflight table entry type here. It leaks the table's impl
// detail to the coalescer // detail to the coalescer
@@ -446,13 +453,13 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends
// this also reduces top level clutter. // this also reduces top level clutter.
val offsetBits = 4 // FIXME hardcoded val offsetBits = 4 // FIXME hardcoded
val sizeBits = log2Ceil(config.MAX_SIZE) // FIXME This is should be not the TL size bits
// but the width of the size enum // but the width of the size enum
val newEntry = Wire( val newEntry = Wire(
new InflightCoalReqTableEntry(config.NUM_LANES, numPerLaneReqs, sourceWidth, offsetBits, sizeBits) new InflightCoalReqTableEntry(config.NUM_LANES, numPerLaneReqs, sourceWidth, offsetBits,
config.SizeEnum)
) )
println(s"=========== table sourceWidth: ${sourceWidth}") println(s"=========== table sourceWidth: ${sourceWidth}")
println(s"=========== table sizeBits: ${sizeBits}") // println(s"=========== table sizeEnumBits: ${newEntry.sizeEnumBits}")
newEntry.source := coalescer.io.out_req.bits.source newEntry.source := coalescer.io.out_req.bits.source
// TODO: richard to write table fill logic // TODO: richard to write table fill logic
@@ -465,7 +472,7 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends
r.valid := false.B r.valid := false.B
r.source := origReqs(i).source 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.MAX_SIZE).U) >> config.WORD_WIDTH
r.size := origReqs(i).size r.sizeEnum := config.SizeEnum.logSizeToEnum(origReqs(i).size)
} }
} }
newEntry.lanes(0).reqs(0).valid := true.B newEntry.lanes(0).reqs(0).valid := true.B
@@ -562,12 +569,15 @@ class UncoalescingUnit(config: CoalescerConfig) extends Module {
// Un-coalescing logic // Un-coalescing logic
// //
def getCoalescedDataChunk(data: UInt, dataWidth: Int, offset: UInt, logSize: UInt): UInt = { def getCoalescedDataChunk(data: UInt, dataWidth: Int, offset: UInt, logSize: UInt): UInt = {
assert(logSize === 2.U, "currently only supporting 4-byte accesses. TODO")
// sizeInBits should be simulation-only construct
val sizeInBits = (1.U << logSize) << 3.U val sizeInBits = (1.U << logSize) << 3.U
assert( assert(
(dataWidth > 0).B && (dataWidth.U % sizeInBits === 0.U), (dataWidth > 0).B && (dataWidth.U % sizeInBits === 0.U),
s"coalesced data width ($dataWidth) not evenly divisible by core req size ($sizeInBits)" s"coalesced data width ($dataWidth) not evenly divisible by core req size ($sizeInBits)"
) )
assert(logSize === 2.U, "currently only supporting 4-byte accesses. TODO")
val numChunks = dataWidth / 32 val numChunks = dataWidth / 32
val chunks = Wire(Vec(numChunks, UInt(32.W))) val chunks = Wire(Vec(numChunks, UInt(32.W)))
val offsets = (0 until numChunks) val offsets = (0 until numChunks)
@@ -594,9 +604,14 @@ class UncoalescingUnit(config: CoalescerConfig) extends Module {
when(inflightTable.io.lookup.valid) { when(inflightTable.io.lookup.valid) {
ioOldReq.valid := oldReq.valid ioOldReq.valid := oldReq.valid
ioOldReq.bits.source := oldReq.source ioOldReq.bits.source := oldReq.source
ioOldReq.bits.size := oldReq.size // FIXME: this is janky. We can't use config.SizeEnum.enumToLogSize for
// some reason because type checker complains that config.SizeEnum.Type
// is different from found.sizeEnumType.type
// val logSize = config.SizeEnum.enumToLogSize(oldReq.sizeEnum)
val logSize = found.sizeEnumType.enumToLogSize(oldReq.sizeEnum)
ioOldReq.bits.size := logSize
ioOldReq.bits.data := ioOldReq.bits.data :=
getCoalescedDataChunk(io.coalResp.bits.data, io.coalResp.bits.data.getWidth, oldReq.offset, oldReq.size) getCoalescedDataChunk(io.coalResp.bits.data, io.coalResp.bits.data.getWidth, oldReq.offset, logSize)
} }
} }
} }
@@ -611,7 +626,7 @@ class InflightCoalReqTable(config: CoalescerConfig) extends Module {
val offsetBits = 4 // FIXME hardcoded val offsetBits = 4 // FIXME hardcoded
val sizeBits = 2 // FIXME hardcoded val sizeBits = 2 // FIXME hardcoded
val entryT = new InflightCoalReqTableEntry(config.NUM_LANES, config.DEPTH, val entryT = new InflightCoalReqTableEntry(config.NUM_LANES, config.DEPTH,
log2Ceil(config.NUM_OLD_IDS), config.MAX_SIZE, config.SizeEnum.getWidth) log2Ceil(config.NUM_OLD_IDS), config.MAX_SIZE, config.SizeEnum)
val entries = config.NUM_NEW_IDS val entries = config.NUM_NEW_IDS
val sourceWidth = log2Ceil(config.NUM_OLD_IDS) val sourceWidth = log2Ceil(config.NUM_OLD_IDS)
@@ -640,7 +655,7 @@ class InflightCoalReqTable(config: CoalescerConfig) extends Module {
r.valid := false.B r.valid := false.B
r.source := 0.U r.source := 0.U
r.offset := 0.U r.offset := 0.U
r.size := 0.U r.sizeEnum := config.SizeEnum.INVALID
} }
} }
} }
@@ -688,14 +703,14 @@ class InflightCoalReqTableEntry(
val numPerLaneReqs: Int, val numPerLaneReqs: Int,
val sourceWidth: Int, val sourceWidth: Int,
val offsetBits: Int, val offsetBits: Int,
val sizeBits: Int val sizeEnumType: InFlightTableSizeEnum
) extends Bundle { ) extends Bundle {
class PerCoreReq extends Bundle { class PerCoreReq extends Bundle {
val valid = Bool() val valid = Bool()
// FIXME: oldId and newId shares the same width // FIXME: oldId and newId shares the same width
val source = UInt(sourceWidth.W) val source = UInt(sourceWidth.W)
val offset = UInt(offsetBits.W) val offset = UInt(offsetBits.W)
val size = UInt(sizeBits.W) val sizeEnum = sizeEnumType()
} }
class PerLane extends Bundle { class PerLane extends Bundle {
val reqs = Vec(numPerLaneReqs, new PerCoreReq) val reqs = Vec(numPerLaneReqs, new PerCoreReq)

View File

@@ -264,13 +264,8 @@ class UncoalescingUnitTest extends AnyFlatSpec with ChiselScalatestTester {
val coalDataWidth = 128 val coalDataWidth = 128
val numInflightCoalRequests = 4 val numInflightCoalRequests = 4
val hey = new TLBundleParameters(64, 64, 64, 64, 64)
it should "work" in { it should "work" in {
test( test(new UncoalescingUnit(defaultConfig))
new UncoalescingUnit(
defaultConfig,
)
)
// 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))
@@ -301,10 +296,10 @@ class UncoalescingUnitTest extends AnyFlatSpec with ChiselScalatestTester {
c.clock.step() c.clock.step()
c.io.coalRespValid.poke(true.B) c.io.coalResp.valid.poke(true.B)
c.io.coalRespSrcId.poke(sourceId) c.io.coalResp.bits.source.poke(sourceId)
val lit = (BigInt(0x0123456789abcdefL) << 64) | BigInt(0x5ca1ab1edeadbeefL) val lit = (BigInt(0x0123456789abcdefL) << 64) | BigInt(0x5ca1ab1edeadbeefL)
c.io.coalRespData.poke(lit.U) c.io.coalResp.bits.data.poke(lit.U)
// table lookup is combinational at the same cycle // table lookup is combinational at the same cycle
c.io.uncoalResps(0)(0).valid.expect(true.B) c.io.uncoalResps(0)(0).valid.expect(true.B)