Fix possible CIRCT bug on SourceGenerator
When migrated to amd3 (possibly wiht newer CIRCT version), a new bug
shows up where storing both meta and valid into a single table doesn't
work, since writing meta writes {1'b0, meta} to the whole row of the
table overwriting the valid bit. Work this around by creating separate
tables for the meta and valid bits.
While at it, remove use of outdated NewSourceGenerator in VortexBank.
This commit is contained in:
@@ -332,24 +332,27 @@ class SourceGenerator[T <: Data](
|
||||
val meta = getMetadataType
|
||||
val valid = Bool()
|
||||
}
|
||||
// valid: in use, invalid: available
|
||||
// val occupancyTable = Mem(numSourceId, Valid(UInt(sourceWidth.W)))
|
||||
val occupancyTable = Mem(numSourceId, row)
|
||||
val occupancyTable = Mem(numSourceId, Bool()/* true: in use, false: free */)
|
||||
// Due to a potential chisel/CIRCT bug, storing both meta and valid in a
|
||||
// single table doesn't work; writing meta writes {1'b0, meta} to the whole
|
||||
// row of the table, overwriting the valid bit. Workaround by creating
|
||||
// separate tables for meta and valid.
|
||||
val metadataTable = Mem(numSourceId, getMetadataType)
|
||||
when(reset.asBool) {
|
||||
(0 until numSourceId).foreach { occupancyTable(_).valid := false.B }
|
||||
(0 until numSourceId).foreach { occupancyTable(_) := false.B }
|
||||
}
|
||||
val frees = (0 until numSourceId).map(!occupancyTable(_).valid)
|
||||
val frees = (0 until numSourceId).map(!occupancyTable(_))
|
||||
val lowestFree = PriorityEncoder(frees)
|
||||
val lowestFreeRow = occupancyTable(lowestFree)
|
||||
val lowestFreeValid = occupancyTable(lowestFree)
|
||||
|
||||
io.id.valid := (if (ignoreInUse) true.B else !lowestFreeRow.valid)
|
||||
io.id.valid := (if (ignoreInUse) true.B else !lowestFreeValid)
|
||||
io.id.bits := lowestFree
|
||||
when(io.gen && io.id.valid /* fire */ ) {
|
||||
// handle reclaim at the same cycle, e.g. for 0-latency D channel response
|
||||
when (!io.reclaim.valid || io.reclaim.bits =/= io.id.bits) {
|
||||
occupancyTable(io.id.bits).valid := true.B // mark in use
|
||||
occupancyTable(io.id.bits) := true.B // mark in use
|
||||
if (metadata.isDefined) {
|
||||
occupancyTable(io.id.bits).meta := io.meta
|
||||
metadataTable(io.id.bits) := io.meta
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,10 +360,10 @@ class SourceGenerator[T <: Data](
|
||||
// @perf: would this require multiple write ports?
|
||||
// NOTE: this does not seem sufficient to handle same-cycle gen-reclaim on
|
||||
// its own
|
||||
occupancyTable(io.reclaim.bits).valid := false.B // mark freed
|
||||
occupancyTable(io.reclaim.bits) := false.B // mark freed
|
||||
}
|
||||
io.peek := {
|
||||
if (metadata.isDefined) occupancyTable(io.reclaim.bits).meta else 0.U
|
||||
if (metadata.isDefined) metadataTable(io.reclaim.bits) else 0.U
|
||||
}
|
||||
|
||||
when(io.gen && io.id.valid) {
|
||||
|
||||
@@ -124,8 +124,8 @@ class VortexBankPassThrough(config: VortexL1Config)(implicit p: Parameters)
|
||||
|
||||
// Make sure the outgoing edge of this passthrough has enough sourceIds
|
||||
// that encompasses the core-side incoming edge's. This is an unfortunate
|
||||
// hack due to not doing proper param negotiations across disconnected
|
||||
// Diplomacy graphs.
|
||||
// hack due to incomplete param negotiations across disconnected Diplomacy
|
||||
// graphs.
|
||||
// println(s"${upstream.params.sourceBits} <= ${downstream.params.sourceBits}")
|
||||
require(upstream.params.sourceBits <= downstream.params.sourceBits,
|
||||
"mem-side source of L1 cache truncates core-side source! " +
|
||||
@@ -344,7 +344,7 @@ class VortexBankImp(
|
||||
// its MSHR and therefore doesn't allocate a new tag id for write requests.
|
||||
// We use a separate source ID allocator to solve this.
|
||||
val sourceGen = Module(
|
||||
new NewSourceGenerator(
|
||||
new SourceGenerator(
|
||||
log2Ceil(config.memSideSourceIds),
|
||||
metadata = Some(UInt(32.W)),
|
||||
ignoreInUse = false
|
||||
@@ -556,7 +556,8 @@ class NewSourceGenerator[T <: Data](
|
||||
when(reset.asBool) {
|
||||
(0 until numSourceId).foreach { i =>
|
||||
occupancyTable(i).id.valid := false.B
|
||||
occupancyTable(i).age := 0.U // Reset age during reset
|
||||
occupancyTable(i).meta := 0.U
|
||||
occupancyTable(i).age := 0.U
|
||||
}
|
||||
}
|
||||
val frees = (0 until numSourceId).map(!occupancyTable(_).id.valid)
|
||||
|
||||
Reference in New Issue
Block a user