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 meta = getMetadataType
|
||||||
val valid = Bool()
|
val valid = Bool()
|
||||||
}
|
}
|
||||||
// valid: in use, invalid: available
|
val occupancyTable = Mem(numSourceId, Bool()/* true: in use, false: free */)
|
||||||
// val occupancyTable = Mem(numSourceId, Valid(UInt(sourceWidth.W)))
|
// Due to a potential chisel/CIRCT bug, storing both meta and valid in a
|
||||||
val occupancyTable = Mem(numSourceId, row)
|
// 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) {
|
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 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
|
io.id.bits := lowestFree
|
||||||
when(io.gen && io.id.valid /* fire */ ) {
|
when(io.gen && io.id.valid /* fire */ ) {
|
||||||
// handle reclaim at the same cycle, e.g. for 0-latency D channel response
|
// handle reclaim at the same cycle, e.g. for 0-latency D channel response
|
||||||
when (!io.reclaim.valid || io.reclaim.bits =/= io.id.bits) {
|
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) {
|
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?
|
// @perf: would this require multiple write ports?
|
||||||
// NOTE: this does not seem sufficient to handle same-cycle gen-reclaim on
|
// NOTE: this does not seem sufficient to handle same-cycle gen-reclaim on
|
||||||
// its own
|
// its own
|
||||||
occupancyTable(io.reclaim.bits).valid := false.B // mark freed
|
occupancyTable(io.reclaim.bits) := false.B // mark freed
|
||||||
}
|
}
|
||||||
io.peek := {
|
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) {
|
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
|
// Make sure the outgoing edge of this passthrough has enough sourceIds
|
||||||
// that encompasses the core-side incoming edge's. This is an unfortunate
|
// that encompasses the core-side incoming edge's. This is an unfortunate
|
||||||
// hack due to not doing proper param negotiations across disconnected
|
// hack due to incomplete param negotiations across disconnected Diplomacy
|
||||||
// Diplomacy graphs.
|
// graphs.
|
||||||
// println(s"${upstream.params.sourceBits} <= ${downstream.params.sourceBits}")
|
// println(s"${upstream.params.sourceBits} <= ${downstream.params.sourceBits}")
|
||||||
require(upstream.params.sourceBits <= downstream.params.sourceBits,
|
require(upstream.params.sourceBits <= downstream.params.sourceBits,
|
||||||
"mem-side source of L1 cache truncates core-side source! " +
|
"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.
|
// its MSHR and therefore doesn't allocate a new tag id for write requests.
|
||||||
// We use a separate source ID allocator to solve this.
|
// We use a separate source ID allocator to solve this.
|
||||||
val sourceGen = Module(
|
val sourceGen = Module(
|
||||||
new NewSourceGenerator(
|
new SourceGenerator(
|
||||||
log2Ceil(config.memSideSourceIds),
|
log2Ceil(config.memSideSourceIds),
|
||||||
metadata = Some(UInt(32.W)),
|
metadata = Some(UInt(32.W)),
|
||||||
ignoreInUse = false
|
ignoreInUse = false
|
||||||
@@ -556,7 +556,8 @@ class NewSourceGenerator[T <: Data](
|
|||||||
when(reset.asBool) {
|
when(reset.asBool) {
|
||||||
(0 until numSourceId).foreach { i =>
|
(0 until numSourceId).foreach { i =>
|
||||||
occupancyTable(i).id.valid := false.B
|
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)
|
val frees = (0 until numSourceId).map(!occupancyTable(_).id.valid)
|
||||||
|
|||||||
Reference in New Issue
Block a user