/* * Copyright (c) 2021 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // All CHI request and response types match the name style in the standard doc. // For a description of a specific message type, refer to the Arm's AMBA 5 // CHI specification (issue D): // https://static.docs.arm.com/ihi0050/d/ // IHI0050D_amba_5_chi_architecture_spec.pdf enumeration(CHIRequestType, desc="") { // Incoming requests generated by the sequencer Load; Store; StoreLine; // CHI request types ReadShared; ReadNotSharedDirty; ReadUnique; ReadOnce; CleanUnique; Evict; WriteBackFull; WriteCleanFull; WriteEvictFull; WriteUniquePtl; WriteUniqueFull; SnpSharedFwd; SnpNotSharedDirtyFwd; SnpUniqueFwd; SnpOnceFwd; SnpOnce; SnpShared; SnpUnique; SnpCleanInvalid; WriteNoSnpPtl; WriteNoSnp; ReadNoSnp; ReadNoSnpSep; null; } structure(CHIRequestMsg, desc="", interface="Message") { Addr addr, desc="Request line address"; Addr accAddr, desc="Original access address. Set for Write*Ptl and requests from the sequencer"; int accSize, desc="Access size. Set for Write*Ptl and requests from the sequencer"; CHIRequestType type, desc="Request type"; MachineID requestor, desc="Requestor ID"; MachineID fwdRequestor, desc="Where to send data for DMT/DCT requests"; bool dataToFwdRequestor, desc="Data has to be forwarded to fwdRequestor"; bool retToSrc, desc="Affects whether or not a snoop resp returns data"; bool allowRetry, desc="This request can be retried"; NetDest Destination, desc="Message destination"; RequestPtr seqReq, default="nullptr", desc="Pointer to original request from CPU/sequencer (nullptr if not valid)"; bool isSeqReqValid, default="false", desc="Set if seqReq is valid (not nullptr)"; bool is_local_pf, desc="Request generated by a local prefetcher"; bool is_remote_pf, desc="Request generated a prefetcher in another cache"; MessageSizeType MessageSize, default="MessageSizeType_Control"; // No data for functional access bool functionalRead(Packet *pkt) { return false; } bool functionalRead(Packet *pkt, WriteMask &mask) { return false; } bool functionalWrite(Packet *pkt) { return false; } } enumeration(CHIResponseType, desc="...") { // CHI response types Comp_I; Comp_UC; Comp_SC; CompAck; CompDBIDResp; DBIDResp; Comp; ReadReceipt; RespSepData; SnpResp_I; SnpResp_I_Fwded_UC; SnpResp_I_Fwded_UD_PD; SnpResp_SC; SnpResp_SC_Fwded_SC; SnpResp_SC_Fwded_SD_PD; SnpResp_UC_Fwded_I; SnpResp_UD_Fwded_I; SnpResp_SC_Fwded_I; SnpResp_SD_Fwded_I; RetryAck; PCrdGrant; null; } structure(CHIResponseMsg, desc="", interface="Message") { Addr addr, desc="Line address"; CHIResponseType type, desc="Response type"; MachineID responder, desc="Responder ID"; NetDest Destination, desc="Response destination"; bool stale, desc="Response to a stale request"; //NOTE: not in CHI and for debuging only MessageSizeType MessageSize, default="MessageSizeType_Control"; // No data for functional access bool functionalRead(Packet *pkt) { return false; } bool functionalRead(Packet *pkt, WriteMask &mask) { return false; } bool functionalWrite(Packet *pkt) { return false; } } enumeration(CHIDataType, desc="...") { // CHI data response types CompData_I; CompData_UC; CompData_SC; CompData_UD_PD; CompData_SD_PD; DataSepResp_UC; CBWrData_UC; CBWrData_SC; CBWrData_UD_PD; CBWrData_SD_PD; CBWrData_I; NCBWrData; SnpRespData_I; SnpRespData_I_PD; SnpRespData_SC; SnpRespData_SC_PD; SnpRespData_SD; SnpRespData_UC; SnpRespData_UD; SnpRespData_SC_Fwded_SC; SnpRespData_SC_Fwded_SD_PD; SnpRespData_SC_PD_Fwded_SC; SnpRespData_I_Fwded_SD_PD; SnpRespData_I_PD_Fwded_SC; SnpRespData_I_Fwded_SC; null; } structure(CHIDataMsg, desc="", interface="Message") { Addr addr, desc="Line address"; CHIDataType type, desc="Response type"; MachineID responder, desc="Responder ID"; NetDest Destination, desc="Response destination"; DataBlock dataBlk, desc="Line data"; WriteMask bitMask, desc="Which bytes in the data block are valid"; MessageSizeType MessageSize, default="MessageSizeType_Data"; bool functionalRead(Packet *pkt) { if(bitMask.isFull()) { return testAndRead(addr, dataBlk, pkt); } else { return false; } } bool functionalRead(Packet *pkt, WriteMask &mask) { // read if bitmask has bytes not in mask or if data is dirty bool is_dirty := (type == CHIDataType:CompData_UD_PD) || (type == CHIDataType:CompData_SD_PD) || (type == CHIDataType:CBWrData_UD_PD) || (type == CHIDataType:CBWrData_SD_PD) || (type == CHIDataType:NCBWrData) || (type == CHIDataType:SnpRespData_I_PD) || (type == CHIDataType:SnpRespData_SC_PD) || (type == CHIDataType:SnpRespData_SD) || (type == CHIDataType:SnpRespData_UD) || (type == CHIDataType:SnpRespData_SC_Fwded_SD_PD) || (type == CHIDataType:SnpRespData_SC_PD_Fwded_SC) || (type == CHIDataType:SnpRespData_I_Fwded_SD_PD) || (type == CHIDataType:SnpRespData_I_PD_Fwded_SC); assert(bitMask.isEmpty() == false); WriteMask test_mask := mask; test_mask.orMask(bitMask); if ((mask.cmpMask(test_mask) == false) || is_dirty) { if (testAndReadMask(addr, dataBlk, bitMask, pkt)) { mask.orMask(bitMask); return true; } } return false; } bool functionalWrite(Packet *pkt) { return testAndWrite(addr, dataBlk, pkt); } }