diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index e52bb01e83..42e07eb46b 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -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="") { diff --git a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm index f990c0b3b5..4d8c35053c 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm @@ -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); } diff --git a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm index 4c93988afd..cb9ffa567a 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm @@ -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; diff --git a/src/mem/ruby/protocol/chi/CHI-cache.sm b/src/mem/ruby/protocol/chi/CHI-cache.sm index 568b39c223..e40989df47 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache.sm @@ -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; } diff --git a/src/mem/ruby/protocol/chi/CHI-mem.sm b/src/mem/ruby/protocol/chi/CHI-mem.sm index 1e34d234c2..46f57456a5 100644 --- a/src/mem/ruby/protocol/chi/CHI-mem.sm +++ b/src/mem/ruby/protocol/chi/CHI-mem.sm @@ -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 { diff --git a/src/mem/ruby/protocol/chi/CHI-msg.sm b/src/mem/ruby/protocol/chi/CHI-msg.sm index 63648a5920..f3c2d66363 100644 --- a/src/mem/ruby/protocol/chi/CHI-msg.sm +++ b/src/mem/ruby/protocol/chi/CHI-msg.sm @@ -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"; diff --git a/src/mem/slicc/ast/OperatorExprAST.py b/src/mem/slicc/ast/OperatorExprAST.py index 714b553101..cc1e7a2fb4 100644 --- a/src/mem/slicc/ast/OperatorExprAST.py +++ b/src/mem/slicc/ast/OperatorExprAST.py @@ -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}!") diff --git a/src/mem/slicc/ast/StaticCastAST.py b/src/mem/slicc/ast/StaticCastAST.py index 178285202b..b6b70efcb5 100644 --- a/src/mem/slicc/ast/StaticCastAST.py +++ b/src/mem/slicc/ast/StaticCastAST.py @@ -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 diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 039202a321..20ab096a63 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -64,6 +64,7 @@ python_class_map = { "DMASequencer": "DMASequencer", "RubyPrefetcher": "RubyPrefetcher", "Cycles": "Cycles", + "Addr": "Addr", }