Compare commits

...

14 Commits

Author SHA1 Message Date
cz4e 910771157b
Merge d8433a5a73 into 1e7e38e249 2025-04-22 10:05:12 +08:00
Anzo 1e7e38e249
chore(Parameters): remove the incorrect parameter description (#4391)
EMU Test / Changes Detection (push) Waiting to run Details
EMU Test / Generate Verilog (push) Blocked by required conditions Details
EMU Test / EMU - Basics (push) Blocked by required conditions Details
EMU Test / EMU - CHI (push) Blocked by required conditions Details
EMU Test / EMU - Performance (push) Blocked by required conditions Details
EMU Test / EMU - MC (push) Blocked by required conditions Details
EMU Test / SIMV - Basics (push) Blocked by required conditions Details
EMU Test / Upload Artifacts (push) Blocked by required conditions Details
EMU Test / Check Submodules (push) Blocked by required conditions Details
EMU Test / Check Format (push) Blocked by required conditions Details
This is a misrepresentation; currently, there is only one item in the fofbuffer.
2025-04-22 10:04:43 +08:00
NewPaulWalker f9ed852fb2
fix(xiselect): set the minimum range for xiselect (#4594)
The miselect register implements at least enough bits to support all
implemented miselect values.
The siselect register will support the value range 0..0xFFF at a
minimum.
The vsiselect register will support the value range 0..0xFFF at a
minimum.
2025-04-22 09:52:44 +08:00
cz4e 99a48a761c
timing(LoadQueueUncache): adjust s1 enq and s2 enq valid generate logic (#4603)
EMU Test / Changes Detection (push) Waiting to run Details
EMU Test / Generate Verilog (push) Blocked by required conditions Details
EMU Test / EMU - Basics (push) Blocked by required conditions Details
EMU Test / EMU - CHI (push) Blocked by required conditions Details
EMU Test / EMU - Performance (push) Blocked by required conditions Details
EMU Test / EMU - MC (push) Blocked by required conditions Details
EMU Test / SIMV - Basics (push) Blocked by required conditions Details
EMU Test / Upload Artifacts (push) Blocked by required conditions Details
EMU Test / Check Submodules (push) Blocked by required conditions Details
EMU Test / Check Format (push) Blocked by required conditions Details
2025-04-22 00:42:41 +08:00
Anzo cd450e3243
submodule(ready-to-run): bump nemu and spike ref in ready-to-run (#4604) 2025-04-22 00:42:07 +08:00
Zhaoyang You 51ad03b0f6
fix(rename): fix Csrr format (#4605) 2025-04-22 00:40:40 +08:00
zhaohong1988 d7dd2491d4
submodule(ChiselAIA): bump ChiselAIA (#4595) 2025-04-22 00:37:45 +08:00
xu_zh be3685ffd1
chore(scalastyle): disable space-around-operator checks (#4567) 2025-04-22 00:37:04 +08:00
Guanghui Cheng b5c820f608
fix(top): enable cpuclock when debug halt req (#4583) 2025-04-22 00:36:20 +08:00
sfencevma d8433a5a73 refactor(MainPipe): add an assert 2025-04-21 06:29:41 +08:00
sfencevma 8b1bb7c7b7 fix(MainPipe): fix `s2_grow_perm_fail` conditoin 2025-04-21 06:27:57 +08:00
sfencevma b2d426dd3c fix(MainPipe): fix `BtoT_ways_for_set` to use `PopCount` 2025-04-21 06:26:13 +08:00
sfencevma baec321003 fix(MainPipe): fix `BtoT_ways_for_set` threshold 2025-04-21 06:25:32 +08:00
sfencevma 2373f296dd fix(DCache): fix DCache replacement when multi ways `BtoT`
* t0: dcache has a tag (e.g. 0x90054), but cacheline sbuffer without write permission has a write request with the tag
* t1: sbuffer writes dcache, which will cause dcache miss because there is no write request, thus sending a miss request
with the tag
* t2: when other miss request refill to mainpipe, it needs to be replaced, and the algorithm replacement always chooses
the way with tag=0x90054, At the same time, mainpipe will compare tag=0 with missqueue. there is a request with tag=0x90054
 in missqueue, causing missqueue refill failure and resend.
* t3: In BtoT's sbuffer write request, l2 did not send grantData, resulting in the refill not being completed, which led to
tag=0x90054 request will not refill to dcache, and probe 0x90054 will be blocked

How to fix:
* when a request need to grow permssion, it will query missqueue, if missqueue has set hit and permssion is BtoT,
mainpipe will set grow_perm_fail, and replay.
* when a request with grow_perm_fail is true, it will use random replacer instead of plru replacer
2025-04-21 06:15:42 +08:00
15 changed files with 115 additions and 43 deletions

@ -1 +1 @@
Subproject commit 6608dc16ec944800d39200e2fad5924d0968b42b
Subproject commit eacee874c515eadfe197cd6b66a52799c30332c1

@ -1 +1 @@
Subproject commit c22a4b2e81d97680380c38cb1ccc7cc2028f01fa
Subproject commit 2b60fc5edf50f519a4310dc41620e9a204b4aacb

View File

@ -71,38 +71,38 @@
<!-- always add a space after `//` or `/*` before comments -->
<check enabled="true" class="org.scalastyle.scalariform.SpaceAfterCommentStartChecker" level="warning"/>
<!-- check space around operators, ref: https://github.com/scala-ide/scalariform/blob/master/scalariform/src/main/scala/scalariform/lexer/Tokens.scala -->
<check enabled="true" class="org.scalastyle.scalariform.DisallowSpaceAfterTokenChecker" level="warning">
<check enabled="false" class="org.scalastyle.scalariform.DisallowSpaceAfterTokenChecker" level="warning">
<parameters>
<!-- (, ~, ! -->
<parameter name="tokens">LPAREN, TILDE, EXCLAMATION</parameter>
</parameters>
</check>
<check enabled="true" class="org.scalastyle.scalariform.DisallowSpaceBeforeTokenChecker" level="warning">
<check enabled="false" class="org.scalastyle.scalariform.DisallowSpaceBeforeTokenChecker" level="warning">
<parameters>
<!-- :, ,, ) -->
<parameter name="tokens">COLON, COMMA, RPAREN</parameter>
</parameters>
</check>
<check enabled="true" class="org.scalastyle.scalariform.EnsureSingleSpaceAfterTokenChecker" level="warning">
<check enabled="false" class="org.scalastyle.scalariform.EnsureSingleSpaceAfterTokenChecker" level="warning">
<parameters>
<!-- if, match, case, for, while, =>, <-, {, <:, <%:, >:, +, -, *, |, = -->
<parameter name="tokens">IF, MATCH, CASE, FOR, WHILE, ARROW, LARROW, LBRACE, SUBTYPE, VIEWBOUND, SUPERTYPE, PLUS, MINUS, STAR, PIPE, EQUAL</parameter>
</parameters>
</check>
<check enabled="true" class="org.scalastyle.scalariform.EnsureSingleSpaceBeforeTokenChecker" level="warning">
<check enabled="false" class="org.scalastyle.scalariform.EnsureSingleSpaceBeforeTokenChecker" level="warning">
<parameters>
<!-- =>, <-, }, <:, <%, >:, +, -, *, |, = -->
<parameter name="tokens">ARROW, LARROW, RBRACE, SUBTYPE, VIEWBOUND, SUPERTYPE, PLUS, MINUS, STAR, PIPE, EQUAL</parameter>
</parameters>
</check>
<check enabled="true" class="org.scalastyle.file.RegexChecker" level="warning">
<check enabled="false" class="org.scalastyle.file.RegexChecker" level="warning">
<parameters>
<!-- :=, :<=, :>=, :<>=, :#=, <>, ===, =/=, <<, >>, <=, >= -->
<parameter name="regex"><![CDATA[[^ ](:<?#?>?=|<>|=[=/]=|<<|>>|[<>]=)]]></parameter>
</parameters>
<customMessage>No space before operators</customMessage>
</check>
<check enabled="true" class="org.scalastyle.file.RegexChecker" level="warning">
<check enabled="false" class="org.scalastyle.file.RegexChecker" level="warning">
<parameters>
<!-- :=, :<=, :>=, :<>=, :#=, <>, ===, =/=, <<, >>, <=, >= -->
<parameter name="regex"><![CDATA[(:<?#?>?=|<>|=[=/]=|<<|>>|[<>]=)[^ \n]]]></parameter>

View File

@ -71,43 +71,43 @@
<!-- always add a space after `//` or `/*` before comments -->
<check enabled="true" class="org.scalastyle.scalariform.SpaceAfterCommentStartChecker" level="warning"/>
<!-- check space around operators, ref: https://github.com/scala-ide/scalariform/blob/master/scalariform/src/main/scala/scalariform/lexer/Tokens.scala -->
<check enabled="true" class="org.scalastyle.scalariform.DisallowSpaceAfterTokenChecker" level="warning">
<check enabled="false" class="org.scalastyle.scalariform.DisallowSpaceAfterTokenChecker" level="warning">
<parameters>
<!-- (, ~, ! -->
<parameter name="tokens">LPAREN, TILDE, EXCLAMATION</parameter>
</parameters>
</check>
<check enabled="true" class="org.scalastyle.scalariform.DisallowSpaceBeforeTokenChecker" level="warning">
<check enabled="false" class="org.scalastyle.scalariform.DisallowSpaceBeforeTokenChecker" level="warning">
<parameters>
<!-- :, ,, ) -->
<parameter name="tokens">COLON, COMMA, RPAREN</parameter>
</parameters>
</check>
<check enabled="true" class="org.scalastyle.scalariform.EnsureSingleSpaceAfterTokenChecker" level="warning">
<check enabled="false" class="org.scalastyle.scalariform.EnsureSingleSpaceAfterTokenChecker" level="warning">
<parameters>
<!-- if, match, case, for, while, =>, <-, {, <:, <%:, >:, +, -, *, |, = -->
<parameter name="tokens">IF, MATCH, CASE, FOR, WHILE, ARROW, LARROW, LBRACE, SUBTYPE, VIEWBOUND, SUPERTYPE, PLUS, MINUS, STAR, PIPE, EQUAL</parameter>
</parameters>
</check>
<check enabled="true" class="org.scalastyle.scalariform.EnsureSingleSpaceBeforeTokenChecker" level="warning">
<check enabled="false" class="org.scalastyle.scalariform.EnsureSingleSpaceBeforeTokenChecker" level="warning">
<parameters>
<!-- =>, <-, }, <:, <%, >:, +, -, *, |, = -->
<parameter name="tokens">ARROW, LARROW, RBRACE, SUBTYPE, VIEWBOUND, SUPERTYPE, PLUS, MINUS, STAR, PIPE, EQUAL</parameter>
</parameters>
</check>
<check enabled="true" class="org.scalastyle.file.RegexChecker" level="warning">
<check enabled="false" class="org.scalastyle.file.RegexChecker" level="warning">
<parameters>
<!-- :=, :<=, :>=, :<>=, :#=, <>, ===, =/=, <<, >>, <=, >= -->
<parameter name="regex"><![CDATA[[^ ](:<?#?>?=|<>|=[=/]=|<<|>>|[<>]=)]]></parameter>
</parameters>
<customMessage>No space before operators</customMessage>
</check>
<check enabled="true" class="org.scalastyle.file.RegexChecker" level="warning">
<check enabled="false" class="org.scalastyle.file.RegexChecker" level="warning">
<parameters>
<!-- :=, :<=, :>=, :<>=, :#=, <>, ===, =/=, <<, >>, <=, >= -->
<parameter name="regex"><![CDATA[(:<?#?>?=|<>|=[=/]=|<<|>>|[<>]=)[^ ]]]></parameter>
<parameter name="regex"><![CDATA[(:<?#?>?=|<>|=[=/]=|<<|>>|[<>]=)[^ \n]]]></parameter>
</parameters>
<customMessage>No space after operators</customMessage>
<customMessage>No space or newline after operators</customMessage>
</check>
<!-- ===== imports ===== -->
@ -158,7 +158,7 @@
<!-- pure lower cases for package names -->
<check enabled="true" class="org.scalastyle.scalariform.PackageNamesChecker" level="warning">
<parameters>
<parameter name="regex">^[a-z]*$</parameter>
<parameter name="regex">^[a-z0-9]*$</parameter>
</parameters>
</check>

View File

@ -222,8 +222,9 @@ class XSNoCTop()(implicit p: Parameters) extends BaseXSSoc with HasSoCParameter
val seip = plic.last(0)
val nmi_31 = nmi.head(0)
val nmi_43 = nmi.head(1)
val debugIntr = debug.head(0)
val msi_info_vld = core_with_l2.module.io.msiInfo.valid
val intSrc = Cat(msip, mtip, meip, seip, nmi_31, nmi_43, msi_info_vld)
val intSrc = Cat(msip, mtip, meip, seip, nmi_31, nmi_43, debugIntr, msi_info_vld)
/*
* CPU Low Power State:

View File

@ -233,8 +233,6 @@ case class XSCoreParameters
VLUopWritebackWidth: Int = 2,
VSUopWritebackWidth: Int = 1,
VSegmentBufferSize: Int = 8,
VFOFBufferSize: Int = 8,
VLFOFWritebackWidth: Int = 1,
// ==============================
UncacheBufferSize: Int = 4,
EnableLoadToLoadForward: Boolean = false,
@ -813,7 +811,6 @@ trait HasXSParameter {
def VLUopWritebackWidth = coreParams.VLUopWritebackWidth
def VSUopWritebackWidth = coreParams.VSUopWritebackWidth
def VSegmentBufferSize = coreParams.VSegmentBufferSize
def VFOFBufferSize = coreParams.VFOFBufferSize
def UncacheBufferSize = coreParams.UncacheBufferSize
def UncacheBufferIndexWidth = log2Up(UncacheBufferSize)
def EnableLoadToLoadForward = coreParams.EnableLoadToLoadForward

View File

@ -204,11 +204,11 @@ class ISelectField(final val maxValue: Int, reserved: Seq[Range]) extends CSREnu
}
object VSISelectField extends ISelectField(
0x1FF,
0xFFF,
reserved = Seq(
Range.inclusive(0x000, 0x02F),
Range.inclusive(0x040, 0x06F),
Range.inclusive(0x100, 0x1FF),
Range.inclusive(0x100, 0xFFF),
),
)
@ -221,15 +221,16 @@ object MISelectField extends ISelectField(
)
object SISelectField extends ISelectField(
maxValue = 0xFF,
maxValue = 0xFFF,
reserved = Seq(
Range.inclusive(0x00, 0x2F),
Range.inclusive(0x40, 0x6F),
Range.inclusive(0x000, 0x02F),
Range.inclusive(0x040, 0x06F),
Range.inclusive(0x100, 0xFFF),
),
)
class VSISelectBundle extends CSRBundle {
val ALL = VSISelectField(log2Up(0x1FF), 0, null).withReset(0.U)
val ALL = VSISelectField(log2Up(0xFFF), 0, null).withReset(0.U)
}
class MISelectBundle extends CSRBundle {
@ -237,7 +238,7 @@ class MISelectBundle extends CSRBundle {
}
class SISelectBundle extends CSRBundle {
val ALL = SISelectField(log2Up(0xFF), 0, null).withReset(0.U)
val ALL = SISelectField(log2Up(0xFFF), 0, null).withReset(0.U)
}
class TopIBundle extends CSRBundle {

View File

@ -206,8 +206,8 @@ class Rename(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHe
private val inst = Wire(Vec(RenameWidth, new XSInstBitFields))
private val isCsr = Wire(Vec(RenameWidth, Bool()))
private val isCsrr = Wire(Vec(RenameWidth, Bool()))
private val isWaitForwardCsrr = Wire(Vec(RenameWidth, Bool()))
private val isBlockBackwardCsrr = Wire(Vec(RenameWidth, Bool()))
private val isNotWaitForwardCsrr = Wire(Vec(RenameWidth, Bool()))
private val isNotBlockBackwardCsrr = Wire(Vec(RenameWidth, Bool()))
private val fuType = uops.map(_.fuType)
private val fuOpType = uops.map(_.fuOpType)
private val vtype = uops.map(_.vpu.vtype)
@ -291,9 +291,9 @@ class Rename(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHe
inst(i) := uops(i).instr.asTypeOf(new XSInstBitFields)
isCsr(i) := inst(i).OPCODE5Bit === OPCODE5Bit.SYSTEM && inst(i).FUNCT3(1, 0) =/= 0.U
isCsrr(i) := isCsr(i) && inst(i).FUNCT3 === BitPat("b?1?") && inst(i).RS1 === 0.U
isWaitForwardCsrr(i) := isCsrr(i) && LookupTreeDefault(
isNotWaitForwardCsrr(i) := isCsrr(i) && LookupTreeDefault(
inst(i).CSRIDX, true.B, CSROoORead.waitForwardInOrderCsrReadList.map(_.U -> false.B))
isBlockBackwardCsrr(i) := isCsrr(i) && LookupTreeDefault(
isNotBlockBackwardCsrr(i) := isCsrr(i) && LookupTreeDefault(
inst(i).CSRIDX, true.B, CSROoORead.blockBackwardInOrderCsrReadList.map(_.U -> false.B))
/*
@ -303,8 +303,8 @@ class Rename(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHe
*
* Signal "isCsrr" contains not only "CSRR", but also other CSR instructions that do not require writing to CSR.
*/
uops(i).waitForward := io.in(i).bits.waitForward && !isWaitForwardCsrr(i)
uops(i).blockBackward := io.in(i).bits.blockBackward && !isBlockBackwardCsrr(i)
uops(i).waitForward := io.in(i).bits.waitForward && !isNotWaitForwardCsrr(i)
uops(i).blockBackward := io.in(i).bits.blockBackward && !isNotBlockBackwardCsrr(i)
// update cf according to ssit result
uops(i).storeSetHit := io.ssit(i).valid

View File

@ -394,6 +394,7 @@ class DCacheLineReq(implicit p: Parameters) extends DCacheBundle
val data = UInt((cfg.blockBytes * 8).W)
val mask = UInt(cfg.blockBytes.W)
val id = UInt(reqIdWidth.W)
val grow_perm_fail = Bool()
def dump(cond: Bool) = {
XSDebug(cond, "DCacheLineReq: cmd: %x addr: %x data: %x mask: %x id: %d\n",
cmd, addr, data, mask, id)
@ -484,6 +485,7 @@ class DCacheLineResp(implicit p: Parameters) extends DCacheBundle
// cache req nacked, replay it later
val replay = Bool()
val id = UInt(reqIdWidth.W)
val grow_perm_fail = Bool()
def dump(cond: Bool) = {
XSDebug(cond, "DCacheLineResp: data: %x id: %d miss: %b replay: %b\n",
data, id, miss, replay)
@ -589,6 +591,7 @@ class MainPipeResp(implicit p: Parameters) extends DCacheBundle {
val ack_miss_queue = Bool()
val id = UInt(reqIdWidth.W)
val grow_perm_fail = Bool()
def isAMO: Bool = source === AMO_SOURCE.U
def isStore: Bool = source === STORE_SOURCE.U
@ -1516,6 +1519,8 @@ class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParame
bus.e <> missQueue.io.mem_finish
missQueue.io.probe_addr := bus.b.bits.address
missQueue.io.replace_addr := mainPipe.io.replace_addr
missQueue.io.grow_perm_addr := mainPipe.io.grow_perm_addr
missQueue.io.BtoT_ways_for_set <> mainPipe.io.BtoT_ways_for_set
missQueue.io.main_pipe_resp.valid := RegNext(mainPipe.io.atomic_resp.valid)
missQueue.io.main_pipe_resp.bits := RegEnable(mainPipe.io.atomic_resp.bits, mainPipe.io.atomic_resp.valid)

View File

@ -73,6 +73,8 @@ class MainPipeReq(implicit p: Parameters) extends DCacheBundle {
val id = UInt(reqIdWidth.W)
val grow_perm_fail = Bool()
def isLoad: Bool = source === LOAD_SOURCE.U
def isStore: Bool = source === STORE_SOURCE.U
def isAMO: Bool = source === AMO_SOURCE.U
@ -95,6 +97,7 @@ class MainPipeReq(implicit p: Parameters) extends DCacheBundle {
req.replace := false.B
req.error := false.B
req.id := store.id
req.grow_perm_fail := store.grow_perm_fail
req
}
}
@ -173,6 +176,9 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
// find the way to be replaced
val replace_way = new ReplacementWayReqIO
val grow_perm_addr = Output(UInt(PAddrBits.W))
val BtoT_ways_for_set = Input(UInt(nWays.W))
// writeback addr to be replaced
val replace_addr = ValidIO(UInt(PAddrBits.W))
val replace_block = Input(Bool())
@ -359,13 +365,15 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
XSPerfAccumulate("replace_unused_prefetch", s1_req.replace && isFromL1Prefetch(s1_extra_meta.prefetch) && !s1_extra_meta.access) // may not be accurate
// replacement policy
val alt_replacer = ReplacementPolicy.fromString("random", nWays)
val s1_invalid_vec = wayMap(w => !meta_resp(w).asTypeOf(new Meta).coh.isValid())
val s1_have_invalid_way = s1_invalid_vec.asUInt.orR
val s1_invalid_way_en = ParallelPriorityMux(s1_invalid_vec.zipWithIndex.map(x => x._1 -> UIntToOH(x._2.U(nWays.W))))
val s1_mux_repl_way = Mux(s1_req.grow_perm_fail, alt_replacer.way, io.replace_way.way)
val s1_repl_way_en = WireInit(0.U(nWays.W))
s1_repl_way_en := Mux(
GatedValidRegNext(s0_fire),
UIntToOH(io.replace_way.way),
UIntToOH(s1_mux_repl_way),
RegEnable(s1_repl_way_en, s1_valid)
)
val s1_repl_tag = ParallelMux(s1_repl_way_en.asBools, (0 until nWays).map(w => tag_resp(w)))
@ -373,7 +381,7 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
val s1_repl_pf = ParallelMux(s1_repl_way_en.asBools, (0 until nWays).map(w => io.extra_meta_resp(w).prefetch))
val s1_repl_way_raw = WireInit(0.U(log2Up(nWays).W))
s1_repl_way_raw := Mux(GatedValidRegNext(s0_fire), io.replace_way.way, RegEnable(s1_repl_way_raw, s1_valid))
s1_repl_way_raw := Mux(GatedValidRegNext(s0_fire), s1_mux_repl_way, RegEnable(s1_repl_way_raw, s1_valid))
val s1_need_replacement = s1_req.miss && !s1_tag_match
val s1_need_eviction = s1_req.miss && !s1_tag_match && s1_repl_coh.state =/= ClientStates.Nothing
@ -389,9 +397,10 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
XSPerfAccumulate("store_has_invalid_way_but_select_valid_way", io.replace_way.set.valid && wayMap(w => !meta_resp(w).asTypeOf(new Meta).coh.isValid()).asUInt.orR && s1_need_replacement && s1_repl_coh.isValid())
XSPerfAccumulate("store_using_replacement", io.replace_way.set.valid && s1_need_replacement)
val s1_has_permission = s1_hit_coh.onAccess(s1_req.cmd)._1
val (s1_has_permission, s1_shrink_perm, _) = s1_hit_coh.onAccess(s1_req.cmd)
val s1_hit = s1_tag_match && s1_has_permission
val s1_pregen_can_go_to_mq = !s1_req.replace && !s1_req.probe && !s1_req.miss && (s1_req.isStore || s1_req.isAMO && s1_req.cmd =/= M_XSC) && !s1_hit
val s1_store_or_amo = !s1_req.replace && !s1_req.probe && !s1_req.miss && (s1_req.isStore || s1_req.isAMO && s1_req.cmd =/= M_XSC)
val s1_pregen_can_go_to_mq = s1_store_or_amo && !s1_hit
// s2: select data, return resp if this is a store miss
val s2_valid = RegInit(false.B)
@ -399,8 +408,9 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
val s2_tag_errors = RegEnable(s1_tag_errors, s1_fire)
val s2_tag_match = RegEnable(s1_tag_match, s1_fire)
val s2_tag_match_way = RegEnable(s1_real_tag_match_way, s1_fire)
val s2_tag_ecc_match_way = RegEnable(s1_tag_ecc_match_way, s1_fire)
val s2_hit_coh = RegEnable(s1_hit_coh, s1_fire)
val (s2_has_permission, _, s2_new_hit_coh) = s2_hit_coh.onAccess(s2_req.cmd)
val (s2_has_permission, s2_shrink_perm, s2_new_hit_coh) = s2_hit_coh.onAccess(s2_req.cmd)
val s2_repl_tag = RegEnable(s1_repl_tag, s1_fire)
val s2_repl_coh = RegEnable(s1_repl_coh, s1_fire)
@ -436,6 +446,14 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
s2_s0_set_conlict := s2_valid && s0_idx === s2_idx
s2_s0_set_conlict_store := s2_valid && store_idx === s2_idx
// Grow permission fail
// Only in case BtoT will both cache and missqueue be occupied
val s2_grow_perm = s2_shrink_perm === BtoT && !s2_has_permission
val s2_grow_perm_fail = PopCount(io.BtoT_ways_for_set) > (nWays-2).U && s2_grow_perm
XSError(s2_valid && s2_grow_perm && io.BtoT_ways_for_set.andR,
"BtoT grow permission, but all ways are BtoT\n"
)
// For a store req, it either hits and goes to s3, or miss and enter miss queue immediately
val s2_req_miss_without_data = Mux(s2_valid, s2_req.miss && !io.refill_info.valid, false.B)
val s2_can_go_to_mq_replay = (s2_req_miss_without_data && RegEnable(s2_req_miss_without_data && !io.mainpipe_info.s2_replay_to_mq, false.B, s2_valid)) || io.replace_block // miss_req in s2 but refill data is invalid, can block 1 cycle
@ -802,21 +820,25 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
miss_req.cancel := false.B
miss_req.pc := DontCare
miss_req.full_overwrite := s2_req.isStore && s2_req.store_mask.andR
miss_req.isBtoT := s2_grow_perm
miss_req.occupy_way := s2_tag_ecc_match_way
io.wbq_conflict_check.valid := s2_valid && s2_can_go_to_mq
io.wbq_conflict_check.bits := s2_req.addr
io.store_replay_resp.valid := s2_valid && s2_can_go_to_mq && replay && s2_req.isStore
io.store_replay_resp.valid := s2_valid && (s2_can_go_to_mq && replay || s2_grow_perm_fail) && s2_req.isStore
io.store_replay_resp.bits.data := DontCare
io.store_replay_resp.bits.miss := true.B
io.store_replay_resp.bits.replay := true.B
io.store_replay_resp.bits.id := s2_req.id
io.store_replay_resp.bits.grow_perm_fail := s2_grow_perm_fail
io.store_hit_resp.valid := s3_valid && (s3_store_can_go || (s3_miss_can_go && s3_req.isStore))
io.store_hit_resp.bits.data := DontCare
io.store_hit_resp.bits.miss := false.B
io.store_hit_resp.bits.replay := false.B
io.store_hit_resp.bits.id := s3_req.id
io.store_hit_resp.bits.grow_perm_fail := false.B
val atomic_hit_resp = Wire(new MainPipeResp)
atomic_hit_resp.source := s3_req.source
@ -827,6 +849,7 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
atomic_hit_resp.replay := false.B
atomic_hit_resp.ack_miss_queue := s3_req.miss
atomic_hit_resp.id := lrsc_valid
atomic_hit_resp.grow_perm_fail := false.B
val atomic_replay_resp = Wire(new MainPipeResp)
atomic_replay_resp.source := s2_req.source
atomic_replay_resp.data := DontCare
@ -836,8 +859,9 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
atomic_replay_resp.replay := true.B
atomic_replay_resp.ack_miss_queue := false.B
atomic_replay_resp.id := DontCare
atomic_replay_resp.grow_perm_fail := s2_grow_perm_fail
val atomic_replay_resp_valid = s2_valid && s2_can_go_to_mq && replay && s2_req.isAMO
val atomic_replay_resp_valid = s2_valid && (s2_can_go_to_mq && replay || s2_grow_perm_fail) && s2_req.isAMO
val atomic_hit_resp_valid = s3_valid && (s3_amo_can_go || s3_miss_can_go && s3_req.isAMO)
io.atomic_resp.valid := atomic_replay_resp_valid || atomic_hit_resp_valid
@ -898,6 +922,8 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents w
io.replace_addr.valid := s2_valid && s2_need_eviction
io.replace_addr.bits := get_block_addr(Cat(s2_tag, get_untag(s2_req.vaddr)))
io.grow_perm_addr := get_block_addr(s2_req.addr)
assert(!RegNext(io.tag_write.valid && !io.tag_write_intend))
io.data_write.valid := s3_valid && s3_update_data_cango && update_data

View File

@ -65,6 +65,17 @@ class MissReqWoStoreData(implicit p: Parameters) extends DCacheBundle {
val req_coh = new ClientMetadata
val id = UInt(reqIdWidth.W)
/**
* isBtoT is used to mark whether the current request requires BtoT permission.
* If so, other requests for BtoT in the same set are blocked. Otherwise,
* they are not blocked.
*/
val isBtoT = Bool()
/**
* The way isBtoT requests to occupy
*/
val occupy_way = UInt(log2Up(nWays).W)
// For now, miss queue entry req is actually valid when req.valid && !cancel
// * req.valid is fast to generate
// * cancel is slow to generate, it will not be used until the last moment
@ -271,6 +282,10 @@ class MissReqPipeRegBundle(edge: TLEdgeOut)(implicit p: Parameters) extends DCac
def block_match(release_addr: UInt): Bool = {
reg_valid() && get_block(req.addr) === get_block(release_addr)
}
def grow_perm_set_match(grow_perm_addr: UInt): Bool = {
reg_valid() && get_idx(req.addr) === get_idx(grow_perm_addr)
}
}
class CMOUnit(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule {
@ -379,6 +394,7 @@ class MissEntry(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DC
val refill_info = ValidIO(new MissQueueRefillInfo)
val block_addr = ValidIO(UInt(PAddrBits.W))
val occupy_way = Output(UInt(nWays.W))
val req_addr = ValidIO(UInt(PAddrBits.W))
@ -501,8 +517,10 @@ class MissEntry(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DC
req_valid := true.B
req := miss_req_pipe_reg_bits.toMissReqWoStoreData()
req_primary_fire := miss_req_pipe_reg_bits.toMissReqWoStoreData()
req.isBtoT := DontCare
req.occupy_way := Mux(miss_req_pipe_reg_bits.isBtoT, 0.U, miss_req_pipe_reg_bits.occupy_way)
req.addr := get_block_addr(miss_req_pipe_reg_bits.addr)
req_primary_fire := miss_req_pipe_reg_bits.toMissReqWoStoreData()
//only load miss need keyword
isKeyword := Mux(miss_req_pipe_reg_bits.isFromLoad, miss_req_pipe_reg_bits.vaddr(5).asBool,false.B)
@ -553,6 +571,8 @@ class MissEntry(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DC
when (miss_req_pipe_reg_bits.isFromStore) {
req := miss_req_pipe_reg_bits
req.isBtoT := DontCare
req.occupy_way := Mux(miss_req_pipe_reg_bits.isBtoT, 0.U, miss_req_pipe_reg_bits.occupy_way)
req.addr := get_block_addr(miss_req_pipe_reg_bits.addr)
req_store_mask := miss_req_pipe_reg_bits.store_mask
for (i <- 0 until blockRows) {
@ -818,6 +838,7 @@ class MissEntry(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DC
io.main_pipe_req.bits.id := req.id
io.main_pipe_req.bits.pf_source := req.pf_source
io.main_pipe_req.bits.access := access
io.main_pipe_req.bits.grow_perm_fail := false.B
io.block_addr.valid := req_valid && w_grantlast
io.block_addr.bits := req.addr
@ -825,6 +846,8 @@ class MissEntry(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DC
io.req_addr.valid := req_valid
io.req_addr.bits := req.addr
io.occupy_way := req.occupy_way
io.refill_info.valid := req_valid && w_grantlast
io.refill_info.bits.store_data := refill_and_store_data.asUInt
io.refill_info.bits.store_mask := ~0.U(blockBytes.W)
@ -928,6 +951,10 @@ class MissQueue(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DC
val replace_addr = Flipped(ValidIO(UInt(PAddrBits.W)))
val replace_block = Output(Bool())
// block all way for set to BtoT
val grow_perm_addr = Flipped(UInt(PAddrBits.W))
val BtoT_ways_for_set = Output(UInt(nWays.W))
// req blocked by wbq
val wbq_block_miss_req = Input(Bool())
@ -1150,6 +1177,11 @@ class MissQueue(edge: TLEdgeOut, reqNum: Int)(implicit p: Parameters) extends DC
io.probe_block := Cat(probe_block_vec).orR
io.replace_block := io.replace_addr.valid && Cat(entries.map(e => e.io.req_addr.valid && e.io.req_addr.bits === io.replace_addr.bits) ++ Seq(miss_req_pipe_reg.block_match(io.replace_addr.bits))).orR
val grow_perm_set_hit = entries.map(e => e.io.req_addr.valid && get_idx(e.io.req_addr.bits) === get_idx(io.grow_perm_addr)) ++
Seq(miss_req_pipe_reg.grow_perm_set_match(io.grow_perm_addr))
io.BtoT_ways_for_set := grow_perm_set_hit.zip(entries).map {
case (hit, e) => Fill(nWays, hit) & e.io.occupy_way
}.reduce(_|_)
io.full := ~Cat(entries.map(_.io.primary_ready)).andR

View File

@ -105,6 +105,7 @@ class ProbeEntry(implicit p: Parameters) extends DCacheModule {
pipe_req.probe_need_data := req.needData
pipe_req.error := false.B
pipe_req.id := io.id
pipe_req.grow_perm_fail := false.B
when (io.pipe_req.fire) {
state := s_wait_resp

View File

@ -300,7 +300,7 @@ class LoadQueue(implicit p: Parameters) extends XSModule
for ((buff, w) <- uncacheBuffer.io.req.zipWithIndex) {
// from load_s3
val ldinBits = io.ldu.ldin(w).bits
buff.valid := io.ldu.ldin(w).valid && (ldinBits.nc || ldinBits.mmio) && !ldinBits.rep_info.need_rep && !ldinBits.nc_with_data
buff.valid := io.ldu.ldin(w).valid && !ldinBits.nc_with_data
buff.bits := ldinBits
}

View File

@ -80,6 +80,7 @@ class AtomicsUnit(implicit p: Parameters) extends XSModule
// `pdest2` is used to record the pdest of the second uop
val pdest1, pdest2 = Reg(UInt(PhyRegIdxWidth.W))
val pdest1Valid, pdest2Valid = RegInit(false.B)
val grow_perm_fail = RegInit(false.B)
/**
* The # of std uops that an atomic instruction require:
* (1) For AMOs (except AMOCAS) and LR/SC, 1 std uop is wanted: X(rs2) with uopIdx = 0
@ -140,6 +141,7 @@ class AtomicsUnit(implicit p: Parameters) extends XSModule
rs1 := io.in.bits.src_rs1
state := s_tlb_and_flush_sbuffer_req
have_sent_first_tlb_req := false.B
grow_perm_fail := false.B
}
}
@ -358,6 +360,9 @@ class AtomicsUnit(implicit p: Parameters) extends XSModule
when (io.dcache.resp.bits.miss) {
when (io.dcache.resp.bits.replay) {
state := s_cache_req
grow_perm_fail := true.B
} .otherwise {
grow_perm_fail := false.B
}
}.otherwise {
dcache_resp_data := io.dcache.resp.bits.data

View File

@ -220,6 +220,7 @@ class Sbuffer(implicit p: Parameters)
val stateVec = RegInit(VecInit(Seq.fill(StoreBufferSize)(0.U.asTypeOf(new SbufferEntryState))))
val cohCount = RegInit(VecInit(Seq.fill(StoreBufferSize)(0.U(EvictCountBits.W))))
val missqReplayCount = RegInit(VecInit(Seq.fill(StoreBufferSize)(0.U(MissqReplayCountBits.W))))
val grow_perm_fail = RegInit(VecInit(Seq.fill(StoreBufferSize)(false.B)))
val sbuffer_out_s0_fire = Wire(Bool())
@ -437,6 +438,7 @@ class Sbuffer(implicit p: Parameters)
// missqReplayCount(insertIdx) := 0.U
ptag(entryIdx) := reqptag
vtag(entryIdx) := reqvtag // update vtag if a new sbuffer line is allocated
grow_perm_fail(entryIdx) := false.B
}
})
}
@ -691,6 +693,7 @@ class Sbuffer(implicit p: Parameters)
io.dcache.req.bits.data := data(sbuffer_out_s1_evictionIdx).asUInt
io.dcache.req.bits.mask := mask(sbuffer_out_s1_evictionIdx).asUInt
io.dcache.req.bits.id := sbuffer_out_s1_evictionIdx
io.dcache.req.bits.grow_perm_fail := grow_perm_fail(sbuffer_out_s1_evictionIdx)
XSDebug(sbuffer_out_s1_fire,
p"send buf [$sbuffer_out_s1_evictionIdx] to Dcache, req fire\n"
@ -741,6 +744,7 @@ class Sbuffer(implicit p: Parameters)
when (io.dcache.replay_resp.fire) {
missqReplayCount(replay_resp_id) := 0.U
stateVec(replay_resp_id).w_timeout := true.B
grow_perm_fail(replay_resp_id) := io.dcache.replay_resp.bits.grow_perm_fail
// waiting for timeout
assert(io.dcache.replay_resp.bits.replay)
assert(stateVec(replay_resp_id).state_inflight === true.B)