From 4f5d4b9bafc111526520a88e4bfcd2a22ec17b1a Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 19 Dec 2023 11:12:50 +0000 Subject: [PATCH] mem-ruby: Implement WriteUniqueZero CHI transaction (#692) The WriteUniqueZero is an immediate write to a Snoopable address region that does not require any data transfer (cacheline is zeroed) Change-Id: Ia8c9b40e08a3b7d613f0b62ce0ac4b0547860871 Reviewed-by: Tiago Muck Signed-off-by: Giacomo Travaglini --- .../ruby/protocol/chi/CHI-cache-actions.sm | 24 ++++++++++++ src/mem/ruby/protocol/chi/CHI-cache-funcs.sm | 3 ++ .../protocol/chi/CHI-cache-transitions.sm | 37 ++++++++++++++++++- src/mem/ruby/protocol/chi/CHI-cache.sm | 4 +- src/mem/ruby/protocol/chi/CHI-msg.sm | 1 + 5 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index a79bee6e0a..74acce2e87 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -927,6 +927,25 @@ action(Initiate_StoreUpgrade, desc="") { tbe.actions.push(Event:TagArrayWrite); } +action(Initiate_WriteUnique_Zero, desc="") { + assert(is_HN); + tbe.dataUnique := true; + if (tbe.dir_sharers.count() > 0) { + tbe.actions.push(Event:SendSnpCleanInvalid); + } + tbe.actions.push(Event:WriteZero); + if (comp_wu) { + tbe.actions.push(Event:SendDBIDResp_WUZ); + tbe.actions.pushNB(Event:WriteFEPipe); + tbe.actions.pushNB(Event:SendComp_WU); + } else { + tbe.actions.push(Event:SendCompDBIDResp); + tbe.actions.pushNB(Event:WriteFEPipe); + } + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:TagArrayWrite); +} + action(Initiate_WriteUnique_LocalWrite, desc="") { // auto-upgrade if hn but state was not unique assert(is_HN || tbe.dataUnique); @@ -1955,6 +1974,11 @@ action(ExpectComp, desc="") { tbe.expected_req_resp.addExpectedCount(1); } +action(WriteZero, desc="") { + tbe.dataBlkValid.fillMask(); + tbe.dataBlk.clear(); +} + action(Receive_ReqDataResp, desc="") { assert(is_valid(tbe)); assert(tbe.expected_req_resp.hasExpected()); diff --git a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm index d96364dcc9..fbafda61cd 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm @@ -1194,6 +1194,7 @@ bool isWriteReqType(CHIRequestType type) { type == CHIRequestType:StoreLine || type == CHIRequestType:WriteUniquePtl || type == CHIRequestType:WriteUniqueFull || + type == CHIRequestType:WriteUniqueZero || type == CHIRequestType:ReadUnique) { return true; } @@ -1262,6 +1263,8 @@ Event reqToEvent(CHIRequestType type, bool is_prefetch) { } else { return Event:WriteUnique; // all WriteUnique handled the same when ~PoC } + } else if (type == CHIRequestType:WriteUniqueZero) { + return Event:WriteUniqueZero; } else if (type == CHIRequestType:StashOnceShared) { return Event:StashOnceShared; } else if (type == CHIRequestType:StashOnceUnique) { diff --git a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm index 7dc6d3b948..31b5b0914a 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm @@ -351,6 +351,28 @@ transition({I, SC, UC, SD, UD, RU, RSC, RSD, RUSD, RUSC, ProcessNextState; } +// WriteUniqueZero cacheline not present +transition({I,RU,RSC,RSD,RUSD,RUSC}, + WriteUniqueZero, + BUSY_BLKD) { + Initiate_Request; + Initiate_WriteUnique_Zero; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +// WriteUniqueZero cacheline available +transition({SC,UC,SD,UD,SC_RSC,UC_RSC,SD_RSC,UD_RSC,UC_RU,UD_RU,UD_RSD,SD_RSD}, + WriteUniqueZero, + BUSY_BLKD) { + Initiate_Request; + Initiate_WriteUnique_Zero; + Profile_Hit; + Pop_ReqRdyQueue; + ProcessNextState; +} + // WriteUniquePtl transition({UD,UD_RSD,UD_RSC,UC,UC_RSC}, @@ -856,7 +878,8 @@ transition({BUSY_BLKD,BUSY_INTR}, WriteCleanFull, WriteCleanFull_Stale, Evict, Evict_Stale, WriteUnique,WriteUniquePtl_PoC, - WriteUniqueFull_PoC,WriteUniqueFull_PoC_Alloc + WriteUniqueFull_PoC,WriteUniqueFull_PoC_Alloc, + WriteUniqueZero, AtomicReturn,AtomicReturn_PoC, AtomicNoReturn,AtomicNoReturn_PoC, StashOnceShared,StashOnceUnique}) { @@ -1212,6 +1235,12 @@ transition(BUSY_BLKD, SendCompDBIDResp_WU) { ProcessNextState_ClearPending; } +transition(BUSY_BLKD, SendDBIDResp_WUZ) { + Pop_TriggerQueue; + Send_DBIDResp; + ProcessNextState_ClearPending; +} + transition(BUSY_BLKD, SendDBIDResp_WU) { Pop_TriggerQueue; ExpectNCBWrData; @@ -1480,6 +1509,12 @@ transition(BUSY_BLKD, TX_Data) { ProcessNextState_ClearPending; } +transition(BUSY_INTR, WriteZero) { + Pop_TriggerQueue; + WriteZero; + ProcessNextState_ClearPending; +} + // Finalization transition transition({BUSY_BLKD,BUSY_INTR}, Final, *) { diff --git a/src/mem/ruby/protocol/chi/CHI-cache.sm b/src/mem/ruby/protocol/chi/CHI-cache.sm index c7d1b02819..a5c75b167b 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache.sm @@ -321,6 +321,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : WriteUniquePtl_PoC, desc="", in_trans="yes"; WriteUniqueFull_PoC, desc="", in_trans="yes"; WriteUniqueFull_PoC_Alloc, desc="", in_trans="yes"; + WriteUniqueZero, desc="", in_trans="yes"; AtomicReturn, desc="", in_trans="yes"; AtomicNoReturn, desc="", in_trans="yes"; AtomicReturn_PoC, desc="", in_trans="yes"; @@ -482,6 +483,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : SendCompDBIDResp_WU, desc="Ack WU with CompDBIDResp and set expected data"; SendDBIDResp_WU, desc="Ack WU with DBIDResp and set expected data"; SendComp_WU, desc="Ack WU completion"; + SendDBIDResp_WUZ, desc="Ack WUZ with DBIDResp and set expected data"; // Send an atomic request downstream. SendAtomicReturn, out_trans="yes", desc="Send atomic request with return"; @@ -496,7 +498,6 @@ machine(MachineType:Cache, "Cache coherency protocol") : SendDBIDResp_ANR, desc="Ack ANR with DBIDResp and set expected data"; SendComp_ANR, desc="Ack ANR completion"; - // Dataless requests SendEvict, out_trans="yes", desc="Send a Evict"; SendCompIResp, desc="Ack Evict with Comp_I"; @@ -552,6 +553,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : FinishCleanUnique, desc="Sends acks and perform any writeback after a CleanUnique"; FinishCopyBack_Stale, desc="Check if a Evict needs to be sent"; ActionStalledOnHazard, desc="Stall a trigger action because until finish handling snoop hazard"; + WriteZero, desc="Stall a trigger action because until finish handling snoop hazard"; // This is triggered once a transaction doesn't have // any queued action and is not expecting responses/data. The transaction diff --git a/src/mem/ruby/protocol/chi/CHI-msg.sm b/src/mem/ruby/protocol/chi/CHI-msg.sm index 18f7ee4c21..eacd29a4b3 100644 --- a/src/mem/ruby/protocol/chi/CHI-msg.sm +++ b/src/mem/ruby/protocol/chi/CHI-msg.sm @@ -67,6 +67,7 @@ enumeration(CHIRequestType, desc="") { WriteEvictFull; WriteUniquePtl; WriteUniqueFull; + WriteUniqueZero; AtomicReturn; AtomicNoReturn;