Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add axi queue #789

Merged
merged 2 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 32 additions & 24 deletions rocketv/src/HellaCache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import chisel3.util.{
UIntToOH
}
import org.chipsalliance.amba.axi4.bundle.{
AR,
AW,
AXI4BundleParameter,
AXI4ChiselBundle,
AXI4ROIrrevocable,
Expand Down Expand Up @@ -521,6 +523,10 @@ class HellaCache(val parameter: HellaCacheParameter)
with InlineInstance
)

val awQueue: Queue[AW] = Module(new Queue(chiselTypeOf(io.loadStoreAXI.aw.bits), 1, flow = true))

val arQueue: Queue[AR] = Module(new Queue(chiselTypeOf(io.loadStoreAXI.ar.bits), 1, flow = true))

dataArb.io.in.tail.foreach(_.bits.wdata := dataArb.io.in.head.bits.wdata) // tie off write ports by default
dataArb.io.out.ready := true.B
metaArb.io.out.ready := clock_en_reg
Expand Down Expand Up @@ -868,7 +874,7 @@ class HellaCache(val parameter: HellaCacheParameter)
val s2_victim_dirty = s2_victim_state.state === 3.U
dontTouch(s2_victim_dirty)
val s2_update_meta = s2_hit_state.state =/= s2_new_hit_state.state
val s2_dont_nack_uncached = s2_valid_uncached_pending && io.loadStoreAXI.aw.ready
val s2_dont_nack_uncached = s2_valid_uncached_pending && awQueue.io.enq.ready
val s2_dont_nack_misc = s2_valid_masked && !s2_meta_error &&
(supports_flush.B && s2_cmd_flush_all && flushed && !flushing ||
supports_flush.B && s2_cmd_flush_line && !s2_hit ||
Expand Down Expand Up @@ -1041,29 +1047,31 @@ class HellaCache(val parameter: HellaCacheParameter)
val accessWillRead: Bool = !s2_uncached || !s2_write
// If no managers support atomics, assert fail if processor asks for them
assert(!(memAccessValid && s2_read && s2_write && s2_uncached))
io.loadStoreAXI.ar.valid := memAccessValid && accessWillRead
io.loadStoreAXI.ar.bits := DontCare
io.loadStoreAXI.ar.bits.burst := 1.U
io.loadStoreAXI.ar.bits.addr := Mux(
arQueue.io.enq.valid := memAccessValid && accessWillRead
arQueue.io.enq.bits := DontCare
arQueue.io.enq.bits.burst := 1.U
arQueue.io.enq.bits.addr := Mux(
s2_uncached,
access_address,
access_address >> parameter.lgCacheBlockBytes << parameter.lgCacheBlockBytes
)
io.loadStoreAXI.ar.bits.len := Mux(
arQueue.io.enq.bits.len := Mux(
s2_uncached,
0.U,
(parameter.cacheBlockBytes * 8 / parameter.loadStoreParameter.dataWidth - 1).U
)
io.loadStoreAXI.ar.bits.size := Mux(s2_uncached, a_size, parameter.lgCacheBlockBytes.U)
io.loadStoreAXI.ar.bits.id := Mux(s2_uncached, a_source, 0.U)

io.loadStoreAXI.aw.valid := memAccessValid && !accessWillRead
io.loadStoreAXI.aw.bits := DontCare
io.loadStoreAXI.aw.bits.id := Mux(s2_uncached, a_source, 0.U)
io.loadStoreAXI.aw.bits.burst := 1.U
io.loadStoreAXI.aw.bits.addr := access_address
io.loadStoreAXI.aw.bits.len := 0.U
io.loadStoreAXI.aw.bits.size := a_size
arQueue.io.enq.bits.size := Mux(s2_uncached, a_size, parameter.lgCacheBlockBytes.U)
arQueue.io.enq.bits.id := Mux(s2_uncached, a_source, 0.U)
io.loadStoreAXI.ar <> arQueue.io.deq

awQueue.io.enq.valid := memAccessValid && !accessWillRead
awQueue.io.enq.bits := DontCare
awQueue.io.enq.bits.id := Mux(s2_uncached, a_source, 0.U)
awQueue.io.enq.bits.burst := 1.U
awQueue.io.enq.bits.addr := access_address
awQueue.io.enq.bits.len := 0.U
awQueue.io.enq.bits.size := a_size
io.loadStoreAXI.aw <> awQueue.io.deq

val dataQueue: Queue[W] = Module(new Queue(chiselTypeOf(io.loadStoreAXI.w.bits), cacheDataBeats))
dataQueue.io.enq.valid := memAccessValid && !accessWillRead
Expand Down Expand Up @@ -1091,7 +1099,7 @@ class HellaCache(val parameter: HellaCacheParameter)

// Set pending bits for outstanding TileLink transaction
val a_sel = UIntToOH(a_source, maxUncachedInFlight + mmioOffset) >> mmioOffset
when(io.loadStoreAXI.ar.fire || io.loadStoreAXI.aw.fire) {
when(arQueue.io.enq.fire || awQueue.io.enq.fire) {
when(s2_uncached) {
(a_sel.asBools.zip(uncachedInFlight.zip(uncachedReqs))).foreach { case (s, (f, r)) =>
when(s) {
Expand Down Expand Up @@ -1310,11 +1318,11 @@ class HellaCache(val parameter: HellaCacheParameter)
val s2_release_last: Bool = RegEnable(s1_release_last, s1_release_data_valid && !releaseRejected)

when(awState) {
io.loadStoreAXI.aw.valid := true.B
io.loadStoreAXI.aw.bits.addr := releaseAddress >> parameter.lgCacheBlockBytes << parameter.lgCacheBlockBytes
io.loadStoreAXI.aw.bits.len := (parameter.cacheBlockBytes * 8 / parameter.loadStoreParameter.dataWidth - 1).U
io.loadStoreAXI.aw.bits.size := parameter.lgCacheBlockBytes.U
io.loadStoreAXI.aw.bits.id := (mmioOffset - 1).U
awQueue.io.enq.valid := true.B
awQueue.io.enq.bits.addr := releaseAddress >> parameter.lgCacheBlockBytes << parameter.lgCacheBlockBytes
awQueue.io.enq.bits.len := (parameter.cacheBlockBytes * 8 / parameter.loadStoreParameter.dataWidth - 1).U
awQueue.io.enq.bits.size := parameter.lgCacheBlockBytes.U
awQueue.io.enq.bits.id := (mmioOffset - 1).U
}

when(s2_release_data_valid) {
Expand Down Expand Up @@ -1342,7 +1350,7 @@ class HellaCache(val parameter: HellaCacheParameter)
}

when(awState) {
when(io.loadStoreAXI.aw.ready) {
when(awQueue.io.enq.ready) {
release_state := s_voluntary_writeback
release_ack_wait := true.B
release_ack_addr := releaseAddress
Expand Down Expand Up @@ -1502,7 +1510,7 @@ class HellaCache(val parameter: HellaCacheParameter)
}

// when(tl_out_a.fire && !s2_uncached) { flushed := false.B }
when(io.loadStoreAXI.aw.fire && !s2_uncached) { flushed := false.B }
when(awQueue.io.enq.fire && !s2_uncached) { flushed := false.B }
when(flushing) {
s1_victim_way := flushCounter >> log2Ceil(nSets)
when(s2_flush_valid) {
Expand Down
22 changes: 12 additions & 10 deletions rocketv/src/ICache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ class ICache(val parameter: ICacheParameter)
val s2_slaveValid = RegNext(s1_slaveValid, false.B)
val s2_slaveWriteValid = RegNext(s1_slaveWriteValid, false.B)
val s3_slaveValid = RegNext(false.B)
val arQueue = Module(new Queue(chiselTypeOf(io.instructionFetchAXI.ar.bits), 1, flow = true))

/** valid signal for CPU accessing cache in stage 0. */
val s0_valid = io.req.fire
Expand Down Expand Up @@ -304,7 +305,7 @@ class ICache(val parameter: ICacheParameter)

/** indicate [[tl_out]] is performing a refill. */
// val refill_fire = tl_out.a.fire && !send_hint
val refill_fire = io.instructionFetchAXI.ar.fire && !send_hint
val refill_fire = arQueue.io.enq.fire && !send_hint

/** register to indicate there is a outstanding hint. */
val hint_outstanding = RegInit(false.B)
Expand Down Expand Up @@ -771,13 +772,14 @@ class ICache(val parameter: ICacheParameter)
}
}

io.instructionFetchAXI.ar.valid := s2_request_refill
io.instructionFetchAXI.ar.bits := DontCare
io.instructionFetchAXI.ar.bits.id := 0.U
io.instructionFetchAXI.ar.bits.addr := (refill_paddr >> blockOffBits) << blockOffBits
io.instructionFetchAXI.ar.bits.size := log2Up(parameter.blockBytes).U
io.instructionFetchAXI.ar.bits.len := 0.U
io.instructionFetchAXI.ar.bits.burst := 1.U
arQueue.io.enq.valid := s2_request_refill
arQueue.io.enq.bits := DontCare
arQueue.io.enq.bits.id := 0.U
arQueue.io.enq.bits.addr := (refill_paddr >> blockOffBits) << blockOffBits
arQueue.io.enq.bits.size := log2Up(parameter.blockBytes).U
arQueue.io.enq.bits.len := 0.U
arQueue.io.enq.bits.burst := 1.U
io.instructionFetchAXI.ar <> arQueue.io.deq

// prefetch when next-line access does not cross a page
if (cacheParams.prefetch) {
Expand Down Expand Up @@ -832,7 +834,7 @@ class ICache(val parameter: ICacheParameter)
}
// Drive APROT information
// bufferable ## modifiable ## readalloc ## writealloc ## privileged ## secure ## fetch
io.instructionFetchAXI.ar.bits.user := true.B ## true.B ## io.s2_cacheable ## io.s2_cacheable ##
arQueue.io.enq.bits.user := true.B ## true.B ## io.s2_cacheable ## io.s2_cacheable ##
true.B ## true.B ## true.B
// tl_out.a.bits.user.lift(AMBAProt).foreach { x =>
// // Rocket caches all fetch requests, and it's difficult to differentiate privileged/unprivileged on
Expand All @@ -848,7 +850,7 @@ class ICache(val parameter: ICacheParameter)
// tl_out.b.ready := true.B
// tl_out.c.valid := false.B
// tl_out.e.valid := false.B
assert(!(io.instructionFetchAXI.ar.valid && addrMaybeInScratchpad(io.instructionFetchAXI.ar.bits.addr)))
assert(!(arQueue.io.enq.valid && addrMaybeInScratchpad(arQueue.io.enq.bits.addr)))

// if there is an outstanding refill, cannot flush I$.
when(!refill_valid) { invalidated := false.B }
Expand Down
28 changes: 15 additions & 13 deletions rocketv/src/RocketCore.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,17 @@ class FPUScoreboardProbe extends Bundle {
}

class RocketProbe(param: RocketParameter) extends Bundle {
val rfWen: Bool = Bool()
val rfWaddr: UInt = UInt(param.lgNXRegs.W)
val rfWdata: UInt = UInt(param.xLen.W)
val rfWen: Bool = Bool()
val rfWaddr: UInt = UInt(param.lgNXRegs.W)
val rfWdata: UInt = UInt(param.xLen.W)
// rocket is idle
val waitWen: Bool = new Bool()
val waitWaddr: UInt = UInt(param.lgNXRegs.W)
val isVector: Bool = Bool()
val idle: Bool = Bool()
val waitWen: Bool = new Bool()
val waitWaddr: UInt = UInt(param.lgNXRegs.W)
val isVectorCommit: Bool = Bool()
val isVectorWrite: Bool = Bool()
val idle: Bool = Bool()
// fpu score board
val fpuScoreboard: Option[FPUScoreboardProbe] = Option.when(param.usingFPU)(new FPUScoreboardProbe)
val fpuScoreboard: Option[FPUScoreboardProbe] = Option.when(param.usingFPU)(new FPUScoreboardProbe)
}

object RocketParameter {
Expand Down Expand Up @@ -1616,14 +1617,15 @@ class Rocket(val parameter: RocketParameter)
probeWire.rfWaddr := rfWaddr
probeWire.rfWdata := rfWdata

probeWire.waitWen := wbSetSboard && wbWen
probeWire.waitWaddr := wbWaddr
probeWire.waitWen := wbSetSboard && wbWen
probeWire.waitWaddr := wbWaddr
// vector commit || vector write rd
probeWire.isVector := io.t1.map { t1 =>
probeWire.isVectorCommit := io.t1.map { t1 =>
wbRegValid && wbRegDecodeOutput(parameter.decoderParameter.vector) &&
!wbRegDecodeOutput(parameter.decoderParameter.vectorCSR)
}.getOrElse(false.B) || t1RetireQueue.map(q => q.io.deq.fire).getOrElse(false.B)
probeWire.idle := vectorEmpty
}.getOrElse(false.B)
probeWire.isVectorWrite := t1RetireQueue.map(q => q.io.deq.fire).getOrElse(false.B)
probeWire.idle := vectorEmpty

probeWire.fpuScoreboard.foreach { case fpProbe =>
fpProbe.memSetScoreBoard := wbValid && wbDcacheMiss && wbRegDecodeOutput(parameter.decoderParameter.wfd)
Expand Down
6 changes: 3 additions & 3 deletions t1rocketemu/src/TestBench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,13 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil

// output the probes
// rocket reg write
when(rocketProbe.rfWen && !rocketProbe.isVector && rocketProbe.rfWaddr =/= 0.U && !(rocketProbe.waitWen && rocketProbe.waitWaddr =/= 0.U))(
when(rocketProbe.rfWen && !rocketProbe.isVectorWrite && rocketProbe.rfWaddr =/= 0.U && !(rocketProbe.waitWen && rocketProbe.waitWaddr =/= 0.U))(
printf(
cf"""{"event":"RegWrite","idx":${rocketProbe.rfWaddr},"data":"${rocketProbe.rfWdata}%x","cycle":${simulationTime}}\n"""
)
)

when(rocketProbe.waitWen && !rocketProbe.isVector && rocketProbe.waitWaddr =/= 0.U)(
when(rocketProbe.waitWen && !rocketProbe.isVectorCommit && rocketProbe.waitWaddr =/= 0.U)(
printf(
cf"""{"event":"RegWriteWait","idx":${rocketProbe.waitWaddr},"cycle":${simulationTime}}\n"""
)
Expand All @@ -210,7 +210,7 @@ class TestBench(generator: SerializableModuleGenerator[T1RocketTile, T1RocketTil
fpuParameter.fLen,
fpuParameter.minFLen
)))
val isVectorForLLWrite = RegNext(rocketProbe.isVector, false.B)
val isVectorForLLWrite = RegNext(rocketProbe.isVectorWrite, false.B)

fpToIEEE.io.clock := clock
fpToIEEE.io.reset := reset
Expand Down