diff --git a/src/main/scala/bus/tilelink/TileLink.scala b/src/main/scala/bus/tilelink/TileLink.scala index 82b4f8e63a26942cced026eea724ecf9e16f23f4..f26e9fe2380970b733c3ffecf76917d76bb3fc1e 100644 --- a/src/main/scala/bus/tilelink/TileLink.scala +++ b/src/main/scala/bus/tilelink/TileLink.scala @@ -188,6 +188,9 @@ class TLBundleA(override val params: TLParameters) extends TLAddrChannel val mask = UInt((params.dataBits/8).W) val data = UInt(params.dataBits.W) val corrupt = Bool() + + def dump = printf(s"$channelName opcode: %x param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n", + opcode, param, size, source, address, mask, data, corrupt) } class TLBundleB(override val params: TLParameters) extends TLAddrChannel @@ -201,6 +204,8 @@ class TLBundleB(override val params: TLParameters) extends TLAddrChannel val mask = UInt((params.dataBits/8).W) val data = UInt(params.dataBits.W) val corrupt = Bool() + def dump = printf(s"$channelName opcode: %x param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n", + opcode, param, size, source, address, mask, data, corrupt) } class TLBundleC(override val params: TLParameters) extends TLAddrChannel @@ -213,6 +218,8 @@ class TLBundleC(override val params: TLParameters) extends TLAddrChannel val address = UInt(params.addressBits.W) val data = UInt(params.dataBits.W) val corrupt = Bool() + def dump = printf(s"$channelName opcode: %x param: %x size: %x source: %d address: %x data: %x corrupt: %b\n", + opcode, param, size, source, address, data, corrupt) } class TLBundleD(override val params: TLParameters) extends TLDataChannel @@ -226,18 +233,31 @@ class TLBundleD(override val params: TLParameters) extends TLDataChannel val denied = Bool() val data = UInt(params.dataBits.W) val corrupt = Bool() + def dump = printf(s"$channelName opcode: %x param: %x size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n", + opcode, param, size, source, sink, denied, data, corrupt) } class TLBundleE(override val params: TLParameters) extends TLChannel { val channelName = "'E' channel" val sink = UInt(params.sinkBits.W) + def dump = printf(s"$channelName sink: %d\n", sink) } // TL-UL and TL-UC class TLUnCached(val params: TLParameters) extends Bundle { val a = Decoupled(new TLBundleA(params)) val d = Flipped(Decoupled(new TLBundleD(params))) + def dump(cond: Bool) = { + when (cond) { + when (a.fire()) { + a.bits.dump + } + when (d.fire()) { + d.bits.dump + } + } + } } // TL-C @@ -245,6 +265,20 @@ class TLCached(override val params: TLParameters) extends TLUnCached(params) { val b = Flipped(Decoupled(new TLBundleB(params))) val c = Decoupled(new TLBundleC(params)) val e = Decoupled(new TLBundleE(params)) + override def dump(cond: Bool) = { + super.dump(cond) + when (cond) { + when (b.fire()) { + b.bits.dump + } + when (c.fire()) { + c.bits.dump + } + when (e.fire()) { + e.bits.dump + } + } + } } object TLUnCached diff --git a/src/main/scala/xiangshan/mem/cache/L1Cache.scala b/src/main/scala/xiangshan/mem/cache/L1Cache.scala index f962b5c697998d09fa2d7c4a4c779adec67c1a93..85544b0675dee8fa26fc7136fb33806b726f007d 100644 --- a/src/main/scala/xiangshan/mem/cache/L1Cache.scala +++ b/src/main/scala/xiangshan/mem/cache/L1Cache.scala @@ -5,7 +5,7 @@ package xiangshan.mem.cache import chisel3._ import chisel3.util._ -import xiangshan.HasXSParameter +import xiangshan.{HasXSParameter, XSModule, XSBundle} import xiangshan.mem.MemoryOpConstants // this file contains common building blocks that can be shared by ICache and DCache @@ -45,8 +45,8 @@ trait HasL1CacheParameters extends HasXSParameter def refillCycles = cacheDataBeats } -abstract class L1CacheModule extends Module +abstract class L1CacheModule extends XSModule with HasL1CacheParameters -abstract class L1CacheBundle extends Bundle +abstract class L1CacheBundle extends XSBundle with HasL1CacheParameters diff --git a/src/main/scala/xiangshan/mem/cache/dcache.scala b/src/main/scala/xiangshan/mem/cache/dcache.scala index 4d6f072039843f81d8f064002b1ed2cf8afdd7ad..a79c68a894450e7123aef70bc6a9c87de3e1730f 100644 --- a/src/main/scala/xiangshan/mem/cache/dcache.scala +++ b/src/main/scala/xiangshan/mem/cache/dcache.scala @@ -5,6 +5,7 @@ import chisel3.util._ import chisel3.util.experimental.BoringUtils import xiangshan.mem.{DCacheReq, DCacheResp, LSUDMemIO} +import xiangshan.utils.XSDebug import bus.tilelink._ import _root_.utils.{Code, RandomReplacement, Transpose} @@ -72,10 +73,10 @@ trait HasDCacheParameters extends HasL1CacheParameters { require(pgIdxBits >= untagBits, s"page aliasing problem: pgIdxBits($pgIdxBits) < untagBits($untagBits)") } -abstract class DCacheModule extends Module +abstract class DCacheModule extends L1CacheModule with HasDCacheParameters -abstract class DCacheBundle extends Bundle +abstract class DCacheBundle extends L1CacheBundle with HasDCacheParameters // basic building blocks for L1 DCache @@ -407,6 +408,24 @@ class DCache extends DCacheModule // ------- // Pipeline + def dump_pipeline_reqs(pipeline_stage_name: String, valid: Vec[Bool], + reqs: Vec[DCacheReq], s0_type: UInt) = { + (0 until memWidth) map { w => + XSDebug(s"$pipeline_stage_name") + XSDebug("channel %d: valid: %b ", w.U, valid(w)) + when (valid(w)) { + when (s0_type === t_replay) { + XSDebug("type: reply ") + } .elsewhen (s0_type === t_lsu) { + XSDebug("type: reply ") + } .otherwise { + XSDebug("type: unknown ") + } + XSDebug("cmd: %x addr: %x data: %x mask: %x meta: %x\n", + reqs(w).cmd, reqs(w).addr, reqs(w).data, reqs(w).mask, reqs(w).meta) + } + } + } // stage 0 val s0_valid = Mux(io.lsu.req.fire(), VecInit(io.lsu.req.bits.map(_.valid)), @@ -416,6 +435,9 @@ class DCache extends DCacheModule replay_req) val s0_type = Mux(io.lsu.req.fire(), t_lsu, t_replay) + dump_pipeline_reqs("DCache s0", s0_valid, s0_req, s0_type) + + // Does this request need to send a response or nack // for successfully executed load/stores, we send a resp // for all other failures(bank conflict, blocked by mshr, in write back) @@ -437,6 +459,8 @@ class DCache extends DCacheModule // For replays, the metadata isn't written yet val s1_replay_way_en = RegNext(mshrs.io.replay.bits.way_en) + dump_pipeline_reqs("DCache s1", s1_valid, s1_req, s1_type) + // tag check def wayMap[T <: Data](f: Int => T) = VecInit((0 until nWays).map(f)) val s1_tag_eq_way = widthMap(i => wayMap((w: Int) => meta(i).io.resp(w).tag === (s1_addr(i) >> untagBits)).asUInt) @@ -451,6 +475,8 @@ class DCache extends DCacheModule val s2_valid = widthMap(w => RegNext(s1_valid(w), init = false.B)) + dump_pipeline_reqs("DCache s2", s2_valid, s2_req, s2_type) + val s2_tag_match_way = RegNext(s1_tag_match_way) val s2_tag_match = s2_tag_match_way.map(_.orR) val s2_hit_state = widthMap(i => Mux1H(s2_tag_match_way(i), wayMap((w: Int) => RegNext(meta(i).io.resp(w).coh)))) diff --git a/src/main/scala/xiangshan/mem/cache/mshrs.scala b/src/main/scala/xiangshan/mem/cache/mshrs.scala index 52b4738629d35774e8d5826ad1176b0f2f713419..75824c323afeddb76138cbe2d815c73baef484ad 100644 --- a/src/main/scala/xiangshan/mem/cache/mshrs.scala +++ b/src/main/scala/xiangshan/mem/cache/mshrs.scala @@ -10,6 +10,7 @@ import chisel3._ import chisel3.util._ import xiangshan.mem.DCacheReq +import xiangshan.utils.XSDebug import bus.tilelink._ class DCacheReqInternal extends DCacheReq @@ -380,4 +381,49 @@ class MSHRFile extends DCacheModule sdq_val := sdq_val & ~(UIntToOH(replay_arb.io.out.bits.sdq_id) & Fill(cfg.nSDQ, free_sdq)) | PriorityEncoderOH(~sdq_val(cfg.nSDQ-1,0)) & Fill(cfg.nSDQ, sdq_enq) } + + // print all input/output requests for debug purpose + + // print req + XSDebug(req.fire(), "cmd: %x addr: %x data: %x mask: %x meta: %x tag_match: %b old_coh: %d old_tag: %x way_en: %x\n", + req.bits.cmd, req.bits.addr, req.bits.data, req.bits.mask, req.bits.meta, + req.bits.tag_match, req.bits.old_meta.coh.state, req.bits.old_meta.tag, req.bits.way_en) + + // block hit + (0 until memWidth) map { w => + XSDebug(io.req(w).valid && io.block_hit(w), "channel %d req block hit\n", w.U) + } + + // print refill + XSDebug(io.refill.fire(), "addr %x data: %x wmask: %x way_en: %x\n", + io.refill.bits.addr, io.refill.bits.data, + io.refill.bits.wmask, io.refill.bits.way_en) + + // print meta_write + XSDebug(io.meta_write.fire(), "idx %x way_en: %x old_tag: %x new_coh: %d new_tag: %x\n", + io.meta_write.bits.idx, io.meta_write.bits.way_en, + io.meta_write.bits.data.coh.state, io.meta_write.bits.data.tag, + io.meta_write.bits.tag) + + // print replay + XSDebug(io.replay.fire(), "cmd: %x addr: %x data: %x mask: %x meta: %x tag_match: %b old_coh: %d old_tag: %x way_en: %x\n", + io.replay.bits.cmd, io.replay.bits.addr, io.replay.bits.data, io.replay.bits.mask, io.replay.bits.meta, + io.replay.bits.tag_match, io.replay.bits.old_meta.coh.state, io.replay.bits.old_meta.tag, io.replay.bits.way_en) + + // print wb_req + XSDebug(io.wb_req.fire(), "idx %x tag: %x source: %d param: %x way_en: %x voluntary: %b\n", + io.wb_req.bits.idx, io.wb_req.bits.tag, + io.wb_req.bits.source, io.wb_req.bits.param, + io.wb_req.bits.way_en, io.wb_req.bits.voluntary) + + // print tilelink messages + when (XSDebug.trigger && io.mem_acquire.fire()) { + io.mem_acquire.bits.dump + } + when (XSDebug.trigger && io.mem_grant.fire()) { + io.mem_grant.bits.dump + } + when (XSDebug.trigger && io.mem_finish.fire()) { + io.mem_finish.bits.dump + } } diff --git a/src/main/scala/xiangshan/utils/LogUtils.scala b/src/main/scala/xiangshan/utils/LogUtils.scala index 33cdec3415db05b5ecea8f6cc840b06b2a02a12b..f864c054d14b0e59444f56f269b4bc96b5767ba7 100644 --- a/src/main/scala/xiangshan/utils/LogUtils.scala +++ b/src/main/scala/xiangshan/utils/LogUtils.scala @@ -55,6 +55,12 @@ sealed abstract class LogHelper(val logLevel: XSLogLevel) extends HasXSParameter apply(prefix, cond, Printable.pack(fmt, data:_*)) def apply(prefix: Boolean, cond: Bool, pable: Printable)(implicit name: String): Any = XSLog(logLevel)(prefix, cond, pable) + + // trigger log or not + // used when user what to fine-control their printf output + def trigger: Bool = { + logLevel.id.U >= XSLog.xsLogLevel && XSLog.displayLog + } } object XSDebug extends LogHelper(XSLogLevel.DEBUG) diff --git a/src/test/scala/xiangshan/backend/exu/DCacheTest.scala b/src/test/scala/xiangshan/backend/exu/DCacheTest.scala index 88da43035fa702e268e90fa55fa2c703ae4bd1e9..3bac92159b57736eac4d75dada7a631201e4f1c4 100644 --- a/src/test/scala/xiangshan/backend/exu/DCacheTest.scala +++ b/src/test/scala/xiangshan/backend/exu/DCacheTest.scala @@ -4,10 +4,12 @@ import org.scalatest._ import scala.collection.mutable.{Map, Queue} import chisel3._ +import chisel3.util.experimental.BoringUtils import chisel3.experimental.BundleLiterals._ import chiseltest._ import xiangshan.XSModule +import xiangshan.utils.XSLogLevel import xiangshan.mem.{LSUDMemIO, MemoryOpConstants} import xiangshan.mem.cache.DCache import bus.tilelink.NaiveTLToAXI4 @@ -19,12 +21,23 @@ class DCacheDut extends XSModule { }) val dcache = Module(new DCache) - val mem = Module(new AXI4RAM(memByte = 128 * 1024 * 1024, useBlackBox = true)) + val mem = Module(new AXI4RAM(memByte = 128 * 1024 * 1024, useBlackBox = false)) val tlToAXI = Module(new NaiveTLToAXI4(l1BusParams)) dcache.io.lsu <> io.in dcache.io.bus <> tlToAXI.io.in tlToAXI.io.out <> mem.in + + + // log control + val log_begin, log_end, log_level = Wire(UInt(64.W)) + log_begin := 0.U + log_end := 0xfffffff.U + log_level := XSLogLevel.DEBUG.id.U + + BoringUtils.addSource(log_begin, "DISPLAY_LOG_START") + BoringUtils.addSource(log_end, "DISPLAY_LOG_END") + BoringUtils.addSource(log_level, "DISPLAY_LOG_LEVEL") }