fix(dcache): bankoffset及时更新

This commit is contained in:
Liphen 2023-12-28 20:16:51 +08:00
parent fa41d30146
commit 277c3d31ad
1 changed files with 60 additions and 59 deletions

View File

@ -74,8 +74,8 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
}) })
// * fsm * // // * fsm * //
val s_idle :: s_uncached :: s_writeback :: s_replace :: s_wait :: Nil = Enum(5) val s_idle :: s_uncached :: s_fence :: s_replace :: s_wait :: Nil = Enum(5)
val state = RegInit(s_idle) val state = RegInit(s_idle)
// ========================================================== // ==========================================================
// | tag | index | offset | // | tag | index | offset |
@ -107,10 +107,21 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
val dirty = RegInit(VecInit(Seq.fill(nindex)(VecInit(Seq.fill(nway)(false.B))))) val dirty = RegInit(VecInit(Seq.fill(nindex)(VecInit(Seq.fill(nway)(false.B)))))
val lru = RegInit(VecInit(Seq.fill(nindex)(false.B))) // TODO:支持更多路数目前只支持2路 val lru = RegInit(VecInit(Seq.fill(nindex)(false.B))) // TODO:支持更多路数目前只支持2路
val dirty_table = Wire(Vec(nindex, UInt(log2Ceil(nway).W)))
val dirty_index = Wire(UInt(indexWidth.W))
val dirty_way = dirty_table(dirty_index) // 用于指示哪个路的脏位为真
val writeback_index = RegInit(0.U(indexWidth.W))
for (i <- 0 until nindex) {
dirty_table(i) := PriorityEncoder(dirty(i))
}
dirty_index := PriorityEncoder(dirty_table.map(w => w =/= 0.U))
// 对于uncached段使用writeFifo进行写回 // 对于uncached段使用writeFifo进行写回
val writeFifo = Module(new Queue(new WriteBufferUnit(), writeFifoDepth)) val writeFifo = Module(new Queue(new WriteBufferUnit(), writeFifoDepth))
val writeFifo_axi_busy = RegInit(false.B) val writeFifo_axi_busy = RegInit(false.B)
val writeFifo_busy = (writeFifo.io.deq.valid || writeFifo_axi_busy) val writeFifo_busy = writeFifo.io.deq.valid // || writeFifo_axi_busy 应该不需要这个判断
writeFifo.io.enq.valid := false.B writeFifo.io.enq.valid := false.B
writeFifo.io.enq.bits := 0.U.asTypeOf(new WriteBufferUnit()) writeFifo.io.enq.bits := 0.U.asTypeOf(new WriteBufferUnit())
@ -141,7 +152,8 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
val tag_wdata = RegInit(0.U(tagWidth.W)) val tag_wdata = RegInit(0.U(tagWidth.W))
val data = Wire(Vec(nbank, Vec(nway, UInt(XLEN.W)))) val data = Wire(Vec(nbank, Vec(nway, UInt(XLEN.W))))
val tag = RegInit(VecInit(Seq.fill(nway)(0.U(tagWidth.W)))) // 使用寄存器类型才能防止idle时tag出现无法hit的错误
val tag = RegInit(VecInit(Seq.fill(nway)(0.U(tagWidth.W))))
val tag_compare_valid = Wire(Vec(nway, Bool())) val tag_compare_valid = Wire(Vec(nway, Bool()))
val cache_hit = tag_compare_valid.contains(true.B) val cache_hit = tag_compare_valid.contains(true.B)
@ -164,6 +176,7 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
io.cpu.rdata := Mux(state === s_wait, saved_rdata, data(bank_index)(select_way)) io.cpu.rdata := Mux(state === s_wait, saved_rdata, data(bank_index)(select_way))
// bank tagv ram // bank tagv ram
val tagRam = Seq.fill(nway)(Module(new LUTRam(nindex, tagWidth)))
for { i <- 0 until nway } { for { i <- 0 until nway } {
val bank = Seq.fill(nbank)(Module(new SimpleDualPortRam(nindex, AXI_DATA_WID, byteAddressable = true))) val bank = Seq.fill(nbank)(Module(new SimpleDualPortRam(nindex, AXI_DATA_WID, byteAddressable = true)))
for { j <- 0 until nbank } { for { j <- 0 until nbank } {
@ -176,13 +189,12 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
bank(j).io.wdata := replace_wdata bank(j).io.wdata := replace_wdata
bank(j).io.wstrb := replace_wstrb(j)(i) bank(j).io.wstrb := replace_wstrb(j)(i)
val tagRam = Module(new LUTRam(nindex, tagWidth)) tagRam(i).io.raddr := tag_rindex
tagRam.io.raddr := tag_rindex tag(i) := tagRam(i).io.rdata
tag(i) := tagRam.io.rdata
tagRam.io.wen := tag_wstrb(i) tagRam(i).io.wen := tag_wstrb(i)
tagRam.io.waddr := replace_index tagRam(i).io.waddr := replace_index
tagRam.io.wdata := tag_wdata tagRam(i).io.wdata := tag_wdata
tag_compare_valid(i) := tag(i) === io.cpu.tlb.ptag && valid(replace_index)(i) && io.cpu.tlb.translation_ok tag_compare_valid(i) := tag(i) === io.cpu.tlb.ptag && valid(replace_index)(i) && io.cpu.tlb.translation_ok
@ -219,7 +231,7 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
io.cpu.acc_err := acc_err io.cpu.acc_err := acc_err
// write buffer // write buffer
when(writeFifo_axi_busy) { // To implement SC memory ordering, when store buffer busy, axi is unseable. when(writeFifo_axi_busy) {
when(io.axi.aw.fire) { when(io.axi.aw.fire) {
awvalid := false.B awvalid := false.B
} }
@ -304,29 +316,29 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
} }
} }
}.elsewhen(io.cpu.fence) { }.elsewhen(io.cpu.fence) {
assert(false.B, "fence not implemented") // // fence.i 需要将所有脏位为true的行写回
// when(dirty(replace_index).contains(true.B)) { // when(dirty.asUInt.orR) {
// when(!writeFifo_busy) { // when(!writeFifo_busy) {
// state := s_writeback // state := s_fence
// write_offset := 0.U // 从第一块bank开始写回 // writeback_index := dirty_index // 从第一个脏行开始写回
// bank_woffset := 0.U // 从第一块bank开始写回
// // for axi write // // for axi write
// aw.addr := Cat(tag(dirty(replace_index)(1)), replace_index, 0.U(offsetWidth.W)) // tagRam.map(_.io.raddr := writeback_index)
// aw.len := cached_len.U // val writeback_tag = Mux(dirty_way === 0.U, tagRam(0).io.rdata, tagRam(1).io.rdata)
// aw.size := cached_size.U // aw.addr := Cat(writeback_tag, writeback_index, 0.U(offsetWidth.W))
// awvalid := true.B // aw.len := cached_len.U
// w.data := data(dirty(replace_index)(1))(bank_index) // aw.size := cached_size.U
// w.strb := ~0.U(AXI_STRB_WID.W) // awvalid := true.B
// w.last := false.B // w.data := data(writeback_index)(0)
// wvalid := true.B // w.strb := ~0.U(AXI_STRB_WID.W)
// w.last := false.B
// wvalid := true.B
// }
// }.otherwise {
// // 当所有脏位为fault时fence.i可以直接完成
// state := s_wait
// } // }
// }.otherwise {
// when(valid(replace_index).contains(true.B)) {
// valid(replace_index)(0) := false.B
// valid(replace_index)(1) := false.B
// }
// state := s_wait
// }
} }
} }
is(s_uncached) { is(s_uncached) {
@ -339,14 +351,7 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
state := s_wait state := s_wait
} }
} }
is(s_writeback) { is(s_fence) {
assert(false.B, "writeback not implemented")
// when(burst_cnt.value =/= (cached_len).U) {
// burst_cnt.inc()
// }
// read_ready_cnt := burst_cnt.value
// read_buffer(read_ready_cnt) := data(dirty(index)(1))
// when(io.axi.aw.fire) { // when(io.axi.aw.fire) {
// awvalid := false.B // awvalid := false.B
// } // }
@ -354,22 +359,17 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
// when(w.last) { // when(w.last) {
// wvalid := false.B // wvalid := false.B
// }.otherwise { // }.otherwise {
// w.data := Mux( // bank_woffset := bank_woffset + 1.U
// ((axi_cnt.value + 1.U) === read_ready_cnt), // w.data := bank_replication(bank_woffset)
// data(dirty(index)(1)), // when(bank_woffset + 1.U === (cached_len).U) {
// read_buffer(axi_cnt.value + 1.U)
// )
// axi_cnt.inc()
// when(axi_cnt.value + 1.U === (cached_len).U) {
// w.last := true.B // w.last := true.B
// } // }
// } // }
// } // }
// when(io.axi.b.valid) { // when(io.axi.b.valid) {
// dirty(index)(dirty(index)(1)) := false.B // // TODO: 增加此处的错误处理
// burst.valid := false.B // // acc_err := io.axi.b.bits.resp =/= RESP_OKEY.U
// acc_err := io.axi.b.bits.resp =/= RESP_OKEY.U // replace_dirty := false.B // 写回完成清除脏位
// state := s_idle
// } // }
} }
is(s_replace) { is(s_replace) {
@ -431,14 +431,15 @@ class DCache(cacheConfig: CacheConfig)(implicit config: CpuConfig) extends Modul
tag_wstrb(replace_way) := true.B tag_wstrb(replace_way) := true.B
tag_wdata := io.cpu.tlb.ptag tag_wdata := io.cpu.tlb.ptag
when(replace_dirty) { when(replace_dirty) {
aw.addr := Cat(tag(replace_way), replace_index, 0.U(offsetWidth.W)) aw.addr := Cat(tag(replace_way), replace_index, 0.U(offsetWidth.W))
aw.len := cached_len.U aw.len := cached_len.U
aw.size := cached_size.U aw.size := cached_size.U
awvalid := true.B awvalid := true.B
w.data := data(bank_woffset)(replace_way) w.data := data(bank_woffset)(replace_way)
w.strb := ~0.U(AXI_STRB_WID.W) w.strb := ~0.U(AXI_STRB_WID.W)
w.last := false.B w.last := false.B
wvalid := true.B wvalid := true.B
bank_woffset := bank_woffset + 1.U // TODO:这里应该需要更新offset
} }
} }
} }