mem-ruby: start using txnid and DBID identifiers in CHI transactions (#288)

With this PR our CHI implementation starts making use of the txnid and
DBID identifiers.
Note: we were already making use of the txnId for DVM messages to convey
the DVM address. This is still the case.
In the future we should realign the DVM logic so that the txnId is
solely used as a transaction identifier.
This commit is contained in:
Giacomo Travaglini
2023-09-26 09:51:47 +01:00
committed by GitHub
9 changed files with 103 additions and 26 deletions

View File

@@ -63,6 +63,7 @@ action(AllocateTBE_Request, desc="") {
out_msg.usesTxnId := false;
out_msg.event := Event:SendRetryAck;
out_msg.retryDest := in_msg.requestor;
out_msg.txnId := in_msg.txnId;
retryQueue.emplace(in_msg.addr,false,in_msg.requestor);
}
}
@@ -145,6 +146,7 @@ action(AllocateTBE_SeqRequest, desc="") {
assert(in_msg.Prefetch == PrefetchBit:No);
out_msg.is_local_pf := false;
out_msg.is_remote_pf := false;
out_msg.txnId := max_outstanding_transactions;
if ((in_msg.Type == RubyRequestType:LD) ||
(in_msg.Type == RubyRequestType:IFETCH)) {
@@ -2133,6 +2135,16 @@ action(Receive_ReqResp_WUComp, desc="") {
}
}
action(Receive_ReqResp_CopyDBID, desc="Copy the rsp DBID into the TBE") {
if (tbe.expected_req_resp.receivedRespType(CHIResponseType:DBIDResp) == false &&
tbe.expected_req_resp.receivedRespType(CHIResponseType:CompDBIDResp) == false) {
error("Received unexpected message");
}
peek(rspInPort, CHIResponseMsg) {
tbe.txnId := in_msg.dbid;
}
}
action(Receive_SnpResp, desc="") {
assert(tbe.expected_snp_resp.hasExpected());
peek(rspInPort, CHIResponseMsg) {
@@ -2508,6 +2520,7 @@ action(Send_Data, desc="") {
enqueue(datOutPort, CHIDataMsg, data_latency) {
out_msg.addr := tbe.addr;
out_msg.type := tbe.snd_msgType;
out_msg.txnId := tbe.txnId;
int offset := tbe.snd_pendBytes.firstBitSet(true);
assert(offset < blockSize);
@@ -2554,6 +2567,9 @@ action(Send_CompI, desc="") {
out_msg.type := CHIResponseType:Comp_I;
out_msg.responder := machineID;
out_msg.Destination.add(tbe.requestor);
out_msg.Destination.add(tbe.requestor);
out_msg.txnId := tbe.txnId;
out_msg.dbid := tbe.txnId;
}
}
@@ -2564,6 +2580,8 @@ action(Send_CompUC, desc="") {
out_msg.type := CHIResponseType:Comp_UC;
out_msg.responder := machineID;
out_msg.Destination.add(tbe.requestor);
out_msg.txnId := tbe.txnId;
out_msg.dbid := tbe.txnId;
}
}
@@ -2574,6 +2592,8 @@ action(Send_CompUC_Stale, desc="") {
out_msg.type := CHIResponseType:Comp_UC;
out_msg.responder := machineID;
out_msg.Destination.add(tbe.requestor);
out_msg.txnId := tbe.txnId;
out_msg.dbid := tbe.txnId;
// We don't know if this is a stale clean unique or a bug, so flag the
// reponse so the requestor can make further checks
out_msg.stale := true;
@@ -2587,6 +2607,7 @@ action(Send_CompAck, desc="") {
out_msg.type := CHIResponseType:CompAck;
out_msg.responder := machineID;
out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr));
out_msg.txnId := tbe.txnId;
}
}
@@ -2597,6 +2618,7 @@ action(Send_CompI_Stale, desc="") {
out_msg.type := CHIResponseType:Comp_I;
out_msg.responder := machineID;
out_msg.Destination.add(tbe.requestor);
out_msg.dbid := tbe.txnId;
// We don't know if this is a stale writeback or a bug, so flag the
// reponse so the requestor can make further checks
out_msg.stale := true;
@@ -2610,6 +2632,8 @@ action(Send_CompDBIDResp, desc="") {
out_msg.type := CHIResponseType:CompDBIDResp;
out_msg.responder := machineID;
out_msg.Destination.add(tbe.requestor);
out_msg.txnId := tbe.txnId;
out_msg.dbid := tbe.txnId;
}
}
@@ -2620,6 +2644,8 @@ action(Send_CompDBIDResp_Stale, desc="") {
out_msg.type := CHIResponseType:CompDBIDResp;
out_msg.responder := machineID;
out_msg.Destination.add(tbe.requestor);
out_msg.txnId := tbe.txnId;
out_msg.dbid := tbe.txnId;
// We don't know if this is a stale writeback or a bug, so flag the
// reponse so the requestor can make further checks
out_msg.stale := true;
@@ -2633,6 +2659,7 @@ action(Send_DBIDResp, desc="") {
out_msg.type := CHIResponseType:DBIDResp;
out_msg.responder := machineID;
out_msg.Destination.add(tbe.requestor);
out_msg.dbid := tbe.txnId;
}
}
@@ -2667,6 +2694,7 @@ action(Send_RetryAck, desc="") {
out_msg.type := CHIResponseType:RetryAck;
out_msg.responder := machineID;
out_msg.Destination.add(in_msg.retryDest);
out_msg.txnId := in_msg.txnId;
}
}
}
@@ -3155,9 +3183,7 @@ action(Profile_OutgoingEnd_DatalessResp, desc="") {
action(TagArrayRead, desc="") {
assert(is_valid(tbe));
tbe.delayNextAction := curTick() + cyclesToTicks(
tagLatency((tbe.reqType == CHIRequestType:Load) ||
(tbe.reqType == CHIRequestType:Store) ||
(tbe.reqType == CHIRequestType:StoreLine)));
tagLatency(fromSequencer(tbe.reqType)));
}
action(TagArrayWrite, desc="") {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022 ARM Limited
* Copyright (c) 2021-2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -299,6 +299,12 @@ Cycles dataLatency() {
return cache.getDataLatency();
}
bool fromSequencer(CHIRequestType reqType) {
return reqType == CHIRequestType:Load ||
reqType == CHIRequestType:Store ||
reqType == CHIRequestType:StoreLine;
}
bool inCache(Addr addr) {
CacheEntry entry := getCacheEntry(makeLineAddress(addr));
// NOTE: we consider data for the addr to be in cache if it exists in local,
@@ -405,6 +411,12 @@ TBE allocateRequestTBE(Addr addr, CHIRequestMsg in_msg), return_by_pointer="yes"
TBE tbe := TBEs[addr];
initializeTBE(tbe, addr, storTBEs.addEntryToNewSlot());
if (fromSequencer(in_msg.type)) {
assert(in_msg.txnId == max_outstanding_transactions);
tbe.txnId := static_cast(Addr, "value", tbe.storSlot);
} else {
tbe.txnId := in_msg.txnId;
}
assert(tbe.is_snp_tbe == false);
assert(tbe.is_repl_tbe == false);
@@ -486,6 +498,7 @@ TBE allocateSnoopTBE(Addr addr, CHIRequestMsg in_msg), return_by_pointer="yes" {
tbe.requestor := in_msg.requestor;
tbe.fwdRequestor := in_msg.fwdRequestor;
tbe.reqType := in_msg.type;
tbe.txnId := in_msg.txnId;
tbe.snpNeedsData := in_msg.retToSrc;
@@ -538,6 +551,8 @@ TBE _allocateReplacementTBE(Addr addr, int storSlot), return_by_pointer="yes" {
tbe.accSize := blockSize;
tbe.requestor := machineID;
tbe.reqType := CHIRequestType:null;
// This is an internal event and should generate a new TxnId
tbe.txnId := static_cast(Addr, "value", storSlot);
tbe.use_DMT := false;
tbe.use_DCT := false;
@@ -624,6 +639,9 @@ void prepareRequest(TBE tbe, CHIRequestType type, CHIRequestMsg & out_msg) {
out_msg.seqReq := tbe.seqReq;
out_msg.is_local_pf := false;
out_msg.is_remote_pf := tbe.is_local_pf || tbe.is_remote_pf;
out_msg.txnId := tbe.txnId;
assert(tbe.txnId != static_cast(Addr, "value", -1));
}
void allowRequestRetry(TBE tbe, CHIRequestMsg & out_msg) {
@@ -780,12 +798,12 @@ bool upstreamHasShared(State state) {
}
void printTBEState(TBE tbe) {
DPRINTF(RubySlicc, "STATE: addr: %#x data present=%d valid=%d unique=%d dirty=%d mu_dirty=%d dir ownerV=%d ownerE=%d sharers=%d tobe_I=%d tobe_SC=%d doFill=%d pendAction=%s\n",
DPRINTF(RubySlicc, "STATE: addr: %#x data present=%d valid=%d unique=%d dirty=%d mu_dirty=%d dir ownerV=%d ownerE=%d sharers=%d tobe_I=%d tobe_SC=%d doFill=%d pendAction=%s txnId=%d\n",
tbe.addr, tbe.dataBlkValid.isFull(), tbe.dataValid, tbe.dataUnique,
tbe.dataDirty, tbe.dataMaybeDirtyUpstream, tbe.dir_ownerExists,
tbe.dir_ownerIsExcl,tbe.dir_sharers.count(),
tbe.dataToBeInvalid, tbe.dataToBeSharedClean,
tbe.doCacheFill, tbe.pendAction);
tbe.doCacheFill, tbe.pendAction, tbe.txnId);
DPRINTF(RubySlicc, "dataBlkValid = %s\n", tbe.dataBlkValid);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022 ARM Limited
* Copyright (c) 2021-2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -1212,8 +1212,7 @@ transition(BUSY_BLKD,
}
// waiting for WB or evict ack
transition(BUSY_INTR,
{CompDBIDResp,Comp_I}, BUSY_BLKD) {
transition(BUSY_INTR, Comp_I, BUSY_BLKD) {
Receive_ReqResp;
Profile_OutgoingEnd_DatalessResp;
Pop_RespInQueue;
@@ -1229,9 +1228,19 @@ transition(BUSY_INTR, Comp_UC, BUSY_BLKD) {
ProcessNextState;
}
// waiting for WB or evict ack
transition(BUSY_INTR, CompDBIDResp, BUSY_BLKD) {
Receive_ReqResp;
Receive_ReqResp_CopyDBID;
Profile_OutgoingEnd_DatalessResp;
Pop_RespInQueue;
ProcessNextState;
}
// alternative flow for WU with separate Comp
transition(BUSY_INTR, DBIDResp, BUSY_BLKD) {
Receive_ReqResp;
Receive_ReqResp_CopyDBID;
Receive_ReqResp_WUNeedComp;
Pop_RespInQueue;
ProcessNextState;

View File

@@ -81,6 +81,9 @@ machine(MachineType:Cache, "Cache coherency protocol") :
int sc_lock_multiplier_max := 256;
bool sc_lock_enabled;
// Maximum number of outstanding transactions from a single requester
Addr max_outstanding_transactions := 1024;
// Recycle latency on resource stalls
Cycles stall_recycle_lat := 1;
@@ -599,6 +602,7 @@ machine(MachineType:Cache, "Cache coherency protocol") :
Addr accAddr, desc="Access address for Load/Store/WriteUniquePtl; otherwisse == addr";
int accSize, desc="Access size for Load/Store/WriteUniquePtl; otherwisse == blockSize";
CHIRequestType reqType, desc="Request type that initiated this transaction";
Addr txnId, desc="Transaction ID. We default to -1 for debug purposes", default="-1";
MachineID requestor, desc="Requestor ID";
MachineID fwdRequestor, desc="Requestor to receive data on fwding snoops";
bool use_DMT, desc="Use DMT for this transaction";
@@ -785,6 +789,7 @@ machine(MachineType:Cache, "Cache coherency protocol") :
Event event;
MachineID retryDest;
bool usesTxnId;
Addr txnId;
bool functionalRead(Packet *pkt) { return false; }
bool functionalRead(Packet *pkt, WriteMask &mask) { return false; }

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021,2022 ARM Limited
* Copyright (c) 2021-2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -164,6 +164,7 @@ machine(MachineType:Memory, "Memory controller interface") :
int storSlot, desc="Slot in the storage tracker occupied by this entry";
Addr addr, desc="Line address for this TBE";
Addr accAddr, desc="Original access address. Set only for Write*Ptl";
Addr txnId, desc="Transaction ID";
int accSize, desc="Access size. Set only for Write*Ptl";
State state, desc="Current line state";
DataBlock dataBlk, desc="Transaction data";
@@ -503,6 +504,7 @@ machine(MachineType:Memory, "Memory controller interface") :
}
tbe.accAddr := in_msg.accAddr;
tbe.accSize := in_msg.accSize;
tbe.txnId := in_msg.txnId;
}
}
@@ -608,6 +610,7 @@ machine(MachineType:Memory, "Memory controller interface") :
assert(tbe.rxtxBytes < blockSize);
enqueue(datOutPort, CHIDataMsg, data_latency) {
out_msg.addr := tbe.addr;
out_msg.txnId := tbe.txnId;
if (tbe.useDataSepResp) {
out_msg.type := CHIDataType:DataSepResp_UC;
} else {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 ARM Limited
* Copyright (c) 2021, 2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -156,6 +156,7 @@ structure(CHIResponseMsg, desc="", interface="Message") {
bool stale, desc="Response to a stale request";
bool usesTxnId, desc="True if using a Transaction ID", default="false";
Addr txnId, desc="Transaction ID", default="0";
Addr dbid, desc="Data Buffer ID", default="0";
//NOTE: not in CHI and for debuging only
MessageSizeType MessageSize, default="MessageSizeType_Control";

View File

@@ -1,3 +1,15 @@
# Copyright (c) 2023 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
# Copyright (c) 2009 The Hewlett-Packard Development Company
# All rights reserved.
@@ -76,11 +88,14 @@ class InfixOperatorExprAST(ExprAST):
("int", "int", "int"),
("Cycles", "Cycles", "Cycles"),
("Tick", "Tick", "Tick"),
("Addr", "Addr", "Addr"),
("Cycles", "int", "Cycles"),
("Scalar", "int", "Scalar"),
("int", "bool", "int"),
("bool", "int", "int"),
("int", "Cycles", "Cycles"),
("Addr", "int", "Addr"),
("int", "Addr", "Addr"),
]
else:
self.error(f"No operator matched with {self.op}!")

View File

@@ -1,3 +1,15 @@
# Copyright (c) 2023 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2009 Advanced Micro Devices, Inc.
# All rights reserved.
#
@@ -42,22 +54,9 @@ class StaticCastAST(ExprAST):
actual_type, ecode = self.expr_ast.inline(True)
if self.type_modifier == "pointer":
code("static_cast<${{self.type_ast.type.c_ident}} *>($ecode)")
elif self.type_modifier == "value":
code("static_cast<${{self.type_ast.type.c_ident}} >($ecode)")
else:
code("static_cast<${{self.type_ast.type.c_ident}} &>($ecode)")
if not "interface" in self.type_ast.type:
self.expr_ast.error(
"static cast only premitted for those types "
"that implement inherit an interface"
)
# The interface type should match
if str(actual_type) != str(self.type_ast.type["interface"]):
self.expr_ast.error(
"static cast miss-match, type is '%s',"
"but inherited type is '%s'",
actual_type,
self.type_ast.type["interface"],
)
return self.type_ast.type

View File

@@ -64,6 +64,7 @@ python_class_map = {
"DMASequencer": "DMASequencer",
"RubyPrefetcher": "RubyPrefetcher",
"Cycles": "Cycles",
"Addr": "Addr",
}