packet.hh revision 11199:929fd978ab4e
14679Sgblack@eecs.umich.edu/*
24679Sgblack@eecs.umich.edu * Copyright (c) 2012-2015 ARM Limited
34679Sgblack@eecs.umich.edu * All rights reserved
44679Sgblack@eecs.umich.edu *
57087Snate@binkert.org * The license below extends only to copyright in the software and shall
67087Snate@binkert.org * not be construed as granting a license to any other intellectual
77087Snate@binkert.org * property including but not limited to intellectual property relating
87087Snate@binkert.org * to a hardware implementation of the functionality of the software
97087Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated
117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
127087Snate@binkert.org * modified or unmodified, in source code or in binary form.
134679Sgblack@eecs.umich.edu *
147087Snate@binkert.org * Copyright (c) 2006 The Regents of The University of Michigan
157087Snate@binkert.org * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
167087Snate@binkert.org * All rights reserved.
177087Snate@binkert.org *
187087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
197087Snate@binkert.org * modification, are permitted provided that the following conditions are
207087Snate@binkert.org * met: redistributions of source code must retain the above copyright
217087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
224679Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
237087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
244679Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
254679Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
264679Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
274679Sgblack@eecs.umich.edu * this software without specific prior written permission.
284679Sgblack@eecs.umich.edu *
294679Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
304679Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
314679Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
324679Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
334679Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
344679Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
354679Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
364679Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
374679Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
384679Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
394679Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
404679Sgblack@eecs.umich.edu *
414679Sgblack@eecs.umich.edu * Authors: Ron Dreslinski
424679Sgblack@eecs.umich.edu *          Steve Reinhardt
434679Sgblack@eecs.umich.edu *          Ali Saidi
445727Sgblack@eecs.umich.edu *          Andreas Hansson
455912Sgblack@eecs.umich.edu */
464679Sgblack@eecs.umich.edu
474679Sgblack@eecs.umich.edu/**
484679Sgblack@eecs.umich.edu * @file
496622Snate@binkert.org * Declaration of the Packet class.
506622Snate@binkert.org */
515912Sgblack@eecs.umich.edu
525965Sgblack@eecs.umich.edu#ifndef __MEM_PACKET_HH__
536132Sgblack@eecs.umich.edu#define __MEM_PACKET_HH__
546132Sgblack@eecs.umich.edu
555912Sgblack@eecs.umich.edu#include <bitset>
565912Sgblack@eecs.umich.edu#include <cassert>
574679Sgblack@eecs.umich.edu#include <list>
584679Sgblack@eecs.umich.edu
594679Sgblack@eecs.umich.edu#include "base/cast.hh"
604679Sgblack@eecs.umich.edu#include "base/compiler.hh"
614679Sgblack@eecs.umich.edu#include "base/flags.hh"
624679Sgblack@eecs.umich.edu#include "base/misc.hh"
634679Sgblack@eecs.umich.edu#include "base/printable.hh"
644679Sgblack@eecs.umich.edu#include "base/types.hh"
654679Sgblack@eecs.umich.edu#include "mem/request.hh"
664679Sgblack@eecs.umich.edu#include "sim/core.hh"
674679Sgblack@eecs.umich.edu
684679Sgblack@eecs.umich.educlass Packet;
694679Sgblack@eecs.umich.edutypedef Packet *PacketPtr;
704679Sgblack@eecs.umich.edutypedef uint8_t* PacketDataPtr;
715912Sgblack@eecs.umich.edutypedef std::list<PacketPtr> PacketList;
724804Sgblack@eecs.umich.edu
734679Sgblack@eecs.umich.educlass MemCmd
744679Sgblack@eecs.umich.edu{
754679Sgblack@eecs.umich.edu    friend class Packet;
764679Sgblack@eecs.umich.edu
774679Sgblack@eecs.umich.edu  public:
786345Sgblack@eecs.umich.edu    /**
796345Sgblack@eecs.umich.edu     * List of all commands associated with a packet.
806345Sgblack@eecs.umich.edu     */
814679Sgblack@eecs.umich.edu    enum Command
825912Sgblack@eecs.umich.edu    {
834679Sgblack@eecs.umich.edu        InvalidCmd,
844679Sgblack@eecs.umich.edu        ReadReq,
854679Sgblack@eecs.umich.edu        ReadResp,
866345Sgblack@eecs.umich.edu        ReadRespWithInvalidate,
876345Sgblack@eecs.umich.edu        WriteReq,
886345Sgblack@eecs.umich.edu        WriteResp,
895912Sgblack@eecs.umich.edu        WritebackDirty,
906345Sgblack@eecs.umich.edu        WritebackClean,
914804Sgblack@eecs.umich.edu        CleanEvict,
926345Sgblack@eecs.umich.edu        SoftPFReq,
934804Sgblack@eecs.umich.edu        HardPFReq,
944804Sgblack@eecs.umich.edu        SoftPFResp,
954804Sgblack@eecs.umich.edu        HardPFResp,
964804Sgblack@eecs.umich.edu        WriteLineReq,
974679Sgblack@eecs.umich.edu        UpgradeReq,
984679Sgblack@eecs.umich.edu        SCUpgradeReq,           // Special "weak" upgrade for StoreCond
994679Sgblack@eecs.umich.edu        UpgradeResp,
1004767Sgblack@eecs.umich.edu        SCUpgradeFailReq,       // Failed SCUpgradeReq in MSHR (never sent)
1014767Sgblack@eecs.umich.edu        UpgradeFailResp,        // Valid for SCUpgradeReq only
1024767Sgblack@eecs.umich.edu        ReadExReq,
1034767Sgblack@eecs.umich.edu        ReadExResp,
1044767Sgblack@eecs.umich.edu        ReadCleanReq,
1055002Sgblack@eecs.umich.edu        ReadSharedReq,
1064767Sgblack@eecs.umich.edu        LoadLockedReq,
1074767Sgblack@eecs.umich.edu        StoreCondReq,
1085002Sgblack@eecs.umich.edu        StoreCondFailReq,       // Failed StoreCondReq in MSHR (never sent)
1094767Sgblack@eecs.umich.edu        StoreCondResp,
1104767Sgblack@eecs.umich.edu        SwapReq,
1115002Sgblack@eecs.umich.edu        SwapResp,
1124767Sgblack@eecs.umich.edu        MessageReq,
1134767Sgblack@eecs.umich.edu        MessageResp,
1145002Sgblack@eecs.umich.edu        ReleaseReq,
1154767Sgblack@eecs.umich.edu        ReleaseResp,
1164767Sgblack@eecs.umich.edu        AcquireReq,
1175002Sgblack@eecs.umich.edu        AcquireResp,
1184767Sgblack@eecs.umich.edu        // Error responses
1194767Sgblack@eecs.umich.edu        // @TODO these should be classified as responses rather than
1205002Sgblack@eecs.umich.edu        // requests; coding them as requests initially for backwards
1214767Sgblack@eecs.umich.edu        // compatibility
1224767Sgblack@eecs.umich.edu        InvalidDestError,  // packet dest field invalid
1234767Sgblack@eecs.umich.edu        BadAddressError,   // memory address invalid
1244767Sgblack@eecs.umich.edu        FunctionalReadError, // unable to fulfill functional read
1254767Sgblack@eecs.umich.edu        FunctionalWriteError, // unable to fulfill functional write
1264767Sgblack@eecs.umich.edu        // Fake simulator-only commands
1274767Sgblack@eecs.umich.edu        PrintReq,       // Print state matching address
1284767Sgblack@eecs.umich.edu        FlushReq,      //request for a cache flush
1295002Sgblack@eecs.umich.edu        InvalidateReq,   // request for address to be invalidated
1304767Sgblack@eecs.umich.edu        InvalidateResp,
1314767Sgblack@eecs.umich.edu        NUM_MEM_CMDS
1325002Sgblack@eecs.umich.edu    };
1334767Sgblack@eecs.umich.edu
1344767Sgblack@eecs.umich.edu  private:
1355002Sgblack@eecs.umich.edu    /**
1364767Sgblack@eecs.umich.edu     * List of command attributes.
1374767Sgblack@eecs.umich.edu     */
1385002Sgblack@eecs.umich.edu    enum Attribute
1394767Sgblack@eecs.umich.edu    {
1404767Sgblack@eecs.umich.edu        IsRead,         //!< Data flows from responder to requester
1415002Sgblack@eecs.umich.edu        IsWrite,        //!< Data flows from requester to responder
1424767Sgblack@eecs.umich.edu        IsUpgrade,
1434767Sgblack@eecs.umich.edu        IsInvalidate,
1445002Sgblack@eecs.umich.edu        NeedsExclusive, //!< Requires exclusive copy to complete in-cache
1454767Sgblack@eecs.umich.edu        IsRequest,      //!< Issued by requester
1464767Sgblack@eecs.umich.edu        IsResponse,     //!< Issue by responder
1474767Sgblack@eecs.umich.edu        NeedsResponse,  //!< Requester needs response from target
1485727Sgblack@eecs.umich.edu        IsEviction,
1495727Sgblack@eecs.umich.edu        IsSWPrefetch,
1505727Sgblack@eecs.umich.edu        IsHWPrefetch,
1515727Sgblack@eecs.umich.edu        IsLlsc,         //!< Alpha/MIPS LL or SC access
1525727Sgblack@eecs.umich.edu        HasData,        //!< There is an associated payload
1535727Sgblack@eecs.umich.edu        IsError,        //!< Error response
1545727Sgblack@eecs.umich.edu        IsPrint,        //!< Print state matching address (for debugging)
1555727Sgblack@eecs.umich.edu        IsFlush,        //!< Flush the address from caches
1565727Sgblack@eecs.umich.edu        NUM_COMMAND_ATTRIBUTES
1575727Sgblack@eecs.umich.edu    };
1585727Sgblack@eecs.umich.edu
1595727Sgblack@eecs.umich.edu    /**
1605727Sgblack@eecs.umich.edu     * Structure that defines attributes and other data associated
1615727Sgblack@eecs.umich.edu     * with a Command.
1625727Sgblack@eecs.umich.edu     */
1635727Sgblack@eecs.umich.edu    struct CommandInfo
1645727Sgblack@eecs.umich.edu    {
1655727Sgblack@eecs.umich.edu        /// Set of attribute flags.
1665727Sgblack@eecs.umich.edu        const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
1674679Sgblack@eecs.umich.edu        /// Corresponding response for requests; InvalidCmd if no
1684679Sgblack@eecs.umich.edu        /// response is applicable.
1694679Sgblack@eecs.umich.edu        const Command response;
1704679Sgblack@eecs.umich.edu        /// String representation (for printing)
171        const std::string str;
172    };
173
174    /// Array to map Command enum to associated info.
175    static const CommandInfo commandInfo[];
176
177  private:
178
179    Command cmd;
180
181    bool
182    testCmdAttrib(MemCmd::Attribute attrib) const
183    {
184        return commandInfo[cmd].attributes[attrib] != 0;
185    }
186
187  public:
188
189    bool isRead() const            { return testCmdAttrib(IsRead); }
190    bool isWrite() const           { return testCmdAttrib(IsWrite); }
191    bool isUpgrade() const         { return testCmdAttrib(IsUpgrade); }
192    bool isRequest() const         { return testCmdAttrib(IsRequest); }
193    bool isResponse() const        { return testCmdAttrib(IsResponse); }
194    bool needsExclusive() const    { return testCmdAttrib(NeedsExclusive); }
195    bool needsResponse() const     { return testCmdAttrib(NeedsResponse); }
196    bool isInvalidate() const      { return testCmdAttrib(IsInvalidate); }
197    bool isEviction() const        { return testCmdAttrib(IsEviction); }
198
199    /**
200     * A writeback is an eviction that carries data.
201     */
202    bool isWriteback() const       { return testCmdAttrib(IsEviction) &&
203                                            testCmdAttrib(HasData); }
204
205    /**
206     * Check if this particular packet type carries payload data. Note
207     * that this does not reflect if the data pointer of the packet is
208     * valid or not.
209     */
210    bool hasData() const        { return testCmdAttrib(HasData); }
211    bool isLLSC() const         { return testCmdAttrib(IsLlsc); }
212    bool isSWPrefetch() const   { return testCmdAttrib(IsSWPrefetch); }
213    bool isHWPrefetch() const   { return testCmdAttrib(IsHWPrefetch); }
214    bool isPrefetch() const     { return testCmdAttrib(IsSWPrefetch) ||
215                                         testCmdAttrib(IsHWPrefetch); }
216    bool isError() const        { return testCmdAttrib(IsError); }
217    bool isPrint() const        { return testCmdAttrib(IsPrint); }
218    bool isFlush() const        { return testCmdAttrib(IsFlush); }
219
220    const Command
221    responseCommand() const
222    {
223        return commandInfo[cmd].response;
224    }
225
226    /// Return the string to a cmd given by idx.
227    const std::string &toString() const { return commandInfo[cmd].str; }
228    int toInt() const { return (int)cmd; }
229
230    MemCmd(Command _cmd) : cmd(_cmd) { }
231    MemCmd(int _cmd) : cmd((Command)_cmd) { }
232    MemCmd() : cmd(InvalidCmd) { }
233
234    bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
235    bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
236};
237
238/**
239 * A Packet is used to encapsulate a transfer between two objects in
240 * the memory system (e.g., the L1 and L2 cache).  (In contrast, a
241 * single Request travels all the way from the requester to the
242 * ultimate destination and back, possibly being conveyed by several
243 * different Packets along the way.)
244 */
245class Packet : public Printable
246{
247  public:
248    typedef uint32_t FlagsType;
249    typedef ::Flags<FlagsType> Flags;
250
251  private:
252
253    enum : FlagsType {
254        // Flags to transfer across when copying a packet
255        COPY_FLAGS             = 0x0000000F,
256
257        SHARED                 = 0x00000001,
258        // Special control flags
259        /// Special timing-mode atomic snoop for multi-level coherence.
260        EXPRESS_SNOOP          = 0x00000002,
261        /// Does supplier have exclusive copy?
262        /// Useful for multi-level coherence.
263        SUPPLY_EXCLUSIVE       = 0x00000004,
264        // Snoop response flags
265        MEM_INHIBIT            = 0x00000008,
266
267        /// Are the 'addr' and 'size' fields valid?
268        VALID_ADDR             = 0x00000100,
269        VALID_SIZE             = 0x00000200,
270
271        /// Is the data pointer set to a value that shouldn't be freed
272        /// when the packet is destroyed?
273        STATIC_DATA            = 0x00001000,
274        /// The data pointer points to a value that should be freed when
275        /// the packet is destroyed. The pointer is assumed to be pointing
276        /// to an array, and delete [] is consequently called
277        DYNAMIC_DATA           = 0x00002000,
278
279        /// suppress the error if this packet encounters a functional
280        /// access failure.
281        SUPPRESS_FUNC_ERROR    = 0x00008000,
282
283        // Signal block present to squash prefetch and cache evict packets
284        // through express snoop flag
285        BLOCK_CACHED          = 0x00010000
286    };
287
288    Flags flags;
289
290  public:
291    typedef MemCmd::Command Command;
292
293    /// The command field of the packet.
294    MemCmd cmd;
295
296    /// A pointer to the original request.
297    const RequestPtr req;
298
299  private:
300   /**
301    * A pointer to the data being transfered.  It can be differnt
302    * sizes at each level of the heirarchy so it belongs in the
303    * packet, not request. This may or may not be populated when a
304    * responder recieves the packet. If not populated it memory should
305    * be allocated.
306    */
307    PacketDataPtr data;
308
309    /// The address of the request.  This address could be virtual or
310    /// physical, depending on the system configuration.
311    Addr addr;
312
313    /// True if the request targets the secure memory space.
314    bool _isSecure;
315
316    /// The size of the request or transfer.
317    unsigned size;
318
319    /**
320     * Track the bytes found that satisfy a functional read.
321     */
322    std::vector<bool> bytesValid;
323
324  public:
325
326    /**
327     * The extra delay from seeing the packet until the header is
328     * transmitted. This delay is used to communicate the crossbar
329     * forwarding latency to the neighbouring object (e.g. a cache)
330     * that actually makes the packet wait. As the delay is relative,
331     * a 32-bit unsigned should be sufficient.
332     */
333    uint32_t headerDelay;
334
335    /**
336     * Keep track of the extra delay incurred by snooping upwards
337     * before sending a request down the memory system. This is used
338     * by the coherent crossbar to account for the additional request
339     * delay.
340     */
341    uint32_t snoopDelay;
342
343    /**
344     * The extra pipelining delay from seeing the packet until the end of
345     * payload is transmitted by the component that provided it (if
346     * any). This includes the header delay. Similar to the header
347     * delay, this is used to make up for the fact that the
348     * crossbar does not make the packet wait. As the delay is
349     * relative, a 32-bit unsigned should be sufficient.
350     */
351    uint32_t payloadDelay;
352
353    /**
354     * A virtual base opaque structure used to hold state associated
355     * with the packet (e.g., an MSHR), specific to a MemObject that
356     * sees the packet. A pointer to this state is returned in the
357     * packet's response so that the MemObject in question can quickly
358     * look up the state needed to process it. A specific subclass
359     * would be derived from this to carry state specific to a
360     * particular sending device.
361     *
362     * As multiple MemObjects may add their SenderState throughout the
363     * memory system, the SenderStates create a stack, where a
364     * MemObject can add a new Senderstate, as long as the
365     * predecessing SenderState is restored when the response comes
366     * back. For this reason, the predecessor should always be
367     * populated with the current SenderState of a packet before
368     * modifying the senderState field in the request packet.
369     */
370    struct SenderState
371    {
372        SenderState* predecessor;
373        SenderState() : predecessor(NULL) {}
374        virtual ~SenderState() {}
375    };
376
377    /**
378     * Object used to maintain state of a PrintReq.  The senderState
379     * field of a PrintReq should always be of this type.
380     */
381    class PrintReqState : public SenderState
382    {
383      private:
384        /**
385         * An entry in the label stack.
386         */
387        struct LabelStackEntry
388        {
389            const std::string label;
390            std::string *prefix;
391            bool labelPrinted;
392            LabelStackEntry(const std::string &_label, std::string *_prefix);
393        };
394
395        typedef std::list<LabelStackEntry> LabelStack;
396        LabelStack labelStack;
397
398        std::string *curPrefixPtr;
399
400      public:
401        std::ostream &os;
402        const int verbosity;
403
404        PrintReqState(std::ostream &os, int verbosity = 0);
405        ~PrintReqState();
406
407        /**
408         * Returns the current line prefix.
409         */
410        const std::string &curPrefix() { return *curPrefixPtr; }
411
412        /**
413         * Push a label onto the label stack, and prepend the given
414         * prefix string onto the current prefix.  Labels will only be
415         * printed if an object within the label's scope is printed.
416         */
417        void pushLabel(const std::string &lbl,
418                       const std::string &prefix = "  ");
419
420        /**
421         * Pop a label off the label stack.
422         */
423        void popLabel();
424
425        /**
426         * Print all of the pending unprinted labels on the
427         * stack. Called by printObj(), so normally not called by
428         * users unless bypassing printObj().
429         */
430        void printLabels();
431
432        /**
433         * Print a Printable object to os, because it matched the
434         * address on a PrintReq.
435         */
436        void printObj(Printable *obj);
437    };
438
439    /**
440     * This packet's sender state.  Devices should use dynamic_cast<>
441     * to cast to the state appropriate to the sender.  The intent of
442     * this variable is to allow a device to attach extra information
443     * to a request. A response packet must return the sender state
444     * that was attached to the original request (even if a new packet
445     * is created).
446     */
447    SenderState *senderState;
448
449    /**
450     * Push a new sender state to the packet and make the current
451     * sender state the predecessor of the new one. This should be
452     * prefered over direct manipulation of the senderState member
453     * variable.
454     *
455     * @param sender_state SenderState to push at the top of the stack
456     */
457    void pushSenderState(SenderState *sender_state);
458
459    /**
460     * Pop the top of the state stack and return a pointer to it. This
461     * assumes the current sender state is not NULL. This should be
462     * preferred over direct manipulation of the senderState member
463     * variable.
464     *
465     * @return The current top of the stack
466     */
467    SenderState *popSenderState();
468
469    /**
470     * Go through the sender state stack and return the first instance
471     * that is of type T (as determined by a dynamic_cast). If there
472     * is no sender state of type T, NULL is returned.
473     *
474     * @return The topmost state of type T
475     */
476    template <typename T>
477    T * findNextSenderState() const
478    {
479        T *t = NULL;
480        SenderState* sender_state = senderState;
481        while (t == NULL && sender_state != NULL) {
482            t = dynamic_cast<T*>(sender_state);
483            sender_state = sender_state->predecessor;
484        }
485        return t;
486    }
487
488    /// Return the string name of the cmd field (for debugging and
489    /// tracing).
490    const std::string &cmdString() const { return cmd.toString(); }
491
492    /// Return the index of this command.
493    inline int cmdToIndex() const { return cmd.toInt(); }
494
495    bool isRead() const              { return cmd.isRead(); }
496    bool isWrite() const             { return cmd.isWrite(); }
497    bool isUpgrade()  const          { return cmd.isUpgrade(); }
498    bool isRequest() const           { return cmd.isRequest(); }
499    bool isResponse() const          { return cmd.isResponse(); }
500    bool needsExclusive() const      { return cmd.needsExclusive(); }
501    bool needsResponse() const       { return cmd.needsResponse(); }
502    bool isInvalidate() const        { return cmd.isInvalidate(); }
503    bool isEviction() const          { return cmd.isEviction(); }
504    bool isWriteback() const         { return cmd.isWriteback(); }
505    bool hasData() const             { return cmd.hasData(); }
506    bool isLLSC() const              { return cmd.isLLSC(); }
507    bool isError() const             { return cmd.isError(); }
508    bool isPrint() const             { return cmd.isPrint(); }
509    bool isFlush() const             { return cmd.isFlush(); }
510
511    // Snoop flags
512    void assertMemInhibit()
513    {
514        assert(isRequest());
515        assert(!flags.isSet(MEM_INHIBIT));
516        flags.set(MEM_INHIBIT);
517    }
518    bool memInhibitAsserted() const { return flags.isSet(MEM_INHIBIT); }
519    void assertShared()             { flags.set(SHARED); }
520    bool sharedAsserted() const     { return flags.isSet(SHARED); }
521
522    // Special control flags
523    void setExpressSnoop()          { flags.set(EXPRESS_SNOOP); }
524    bool isExpressSnoop() const     { return flags.isSet(EXPRESS_SNOOP); }
525    void setSupplyExclusive()       { flags.set(SUPPLY_EXCLUSIVE); }
526    bool isSupplyExclusive() const  { return flags.isSet(SUPPLY_EXCLUSIVE); }
527    void setSuppressFuncError()     { flags.set(SUPPRESS_FUNC_ERROR); }
528    bool suppressFuncError() const  { return flags.isSet(SUPPRESS_FUNC_ERROR); }
529    void setBlockCached()          { flags.set(BLOCK_CACHED); }
530    bool isBlockCached() const     { return flags.isSet(BLOCK_CACHED); }
531    void clearBlockCached()        { flags.clear(BLOCK_CACHED); }
532
533    // Network error conditions... encapsulate them as methods since
534    // their encoding keeps changing (from result field to command
535    // field, etc.)
536    void
537    setBadAddress()
538    {
539        assert(isResponse());
540        cmd = MemCmd::BadAddressError;
541    }
542
543    void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
544
545    Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
546    /**
547     * Update the address of this packet mid-transaction. This is used
548     * by the address mapper to change an already set address to a new
549     * one based on the system configuration. It is intended to remap
550     * an existing address, so it asserts that the current address is
551     * valid.
552     */
553    void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; }
554
555    unsigned getSize() const  { assert(flags.isSet(VALID_SIZE)); return size; }
556
557    Addr getOffset(unsigned int blk_size) const
558    {
559        return getAddr() & Addr(blk_size - 1);
560    }
561
562    Addr getBlockAddr(unsigned int blk_size) const
563    {
564        return getAddr() & ~(Addr(blk_size - 1));
565    }
566
567    bool isSecure() const
568    {
569        assert(flags.isSet(VALID_ADDR));
570        return _isSecure;
571    }
572
573    /**
574     * It has been determined that the SC packet should successfully update
575     * memory. Therefore, convert this SC packet to a normal write.
576     */
577    void
578    convertScToWrite()
579    {
580        assert(isLLSC());
581        assert(isWrite());
582        cmd = MemCmd::WriteReq;
583    }
584
585    /**
586     * When ruby is in use, Ruby will monitor the cache line and the
587     * phys memory should treat LL ops as normal reads.
588     */
589    void
590    convertLlToRead()
591    {
592        assert(isLLSC());
593        assert(isRead());
594        cmd = MemCmd::ReadReq;
595    }
596
597    /**
598     * Constructor. Note that a Request object must be constructed
599     * first, but the Requests's physical address and size fields need
600     * not be valid. The command must be supplied.
601     */
602    Packet(const RequestPtr _req, MemCmd _cmd)
603        :  cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
604           size(0), headerDelay(0), snoopDelay(0), payloadDelay(0),
605           senderState(NULL)
606    {
607        if (req->hasPaddr()) {
608            addr = req->getPaddr();
609            flags.set(VALID_ADDR);
610            _isSecure = req->isSecure();
611        }
612        if (req->hasSize()) {
613            size = req->getSize();
614            flags.set(VALID_SIZE);
615        }
616    }
617
618    /**
619     * Alternate constructor if you are trying to create a packet with
620     * a request that is for a whole block, not the address from the
621     * req.  this allows for overriding the size/addr of the req.
622     */
623    Packet(const RequestPtr _req, MemCmd _cmd, int _blkSize)
624        :  cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
625           headerDelay(0), snoopDelay(0), payloadDelay(0),
626           senderState(NULL)
627    {
628        if (req->hasPaddr()) {
629            addr = req->getPaddr() & ~(_blkSize - 1);
630            flags.set(VALID_ADDR);
631            _isSecure = req->isSecure();
632        }
633        size = _blkSize;
634        flags.set(VALID_SIZE);
635    }
636
637    /**
638     * Alternate constructor for copying a packet.  Copy all fields
639     * *except* if the original packet's data was dynamic, don't copy
640     * that, as we can't guarantee that the new packet's lifetime is
641     * less than that of the original packet.  In this case the new
642     * packet should allocate its own data.
643     */
644    Packet(const PacketPtr pkt, bool clear_flags, bool alloc_data)
645        :  cmd(pkt->cmd), req(pkt->req),
646           data(nullptr),
647           addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
648           bytesValid(pkt->bytesValid),
649           headerDelay(pkt->headerDelay),
650           snoopDelay(0),
651           payloadDelay(pkt->payloadDelay),
652           senderState(pkt->senderState)
653    {
654        if (!clear_flags)
655            flags.set(pkt->flags & COPY_FLAGS);
656
657        flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
658
659        // should we allocate space for data, or not, the express
660        // snoops do not need to carry any data as they only serve to
661        // co-ordinate state changes
662        if (alloc_data) {
663            // even if asked to allocate data, if the original packet
664            // holds static data, then the sender will not be doing
665            // any memcpy on receiving the response, thus we simply
666            // carry the pointer forward
667            if (pkt->flags.isSet(STATIC_DATA)) {
668                data = pkt->data;
669                flags.set(STATIC_DATA);
670            } else {
671                allocate();
672            }
673        }
674    }
675
676    /**
677     * Generate the appropriate read MemCmd based on the Request flags.
678     */
679    static MemCmd
680    makeReadCmd(const RequestPtr req)
681    {
682        if (req->isLLSC())
683            return MemCmd::LoadLockedReq;
684        else if (req->isPrefetch())
685            return MemCmd::SoftPFReq;
686        else
687            return MemCmd::ReadReq;
688    }
689
690    /**
691     * Generate the appropriate write MemCmd based on the Request flags.
692     */
693    static MemCmd
694    makeWriteCmd(const RequestPtr req)
695    {
696        if (req->isLLSC())
697            return MemCmd::StoreCondReq;
698        else if (req->isSwap())
699            return MemCmd::SwapReq;
700        else
701            return MemCmd::WriteReq;
702    }
703
704    /**
705     * Constructor-like methods that return Packets based on Request objects.
706     * Fine-tune the MemCmd type if it's not a vanilla read or write.
707     */
708    static PacketPtr
709    createRead(const RequestPtr req)
710    {
711        return new Packet(req, makeReadCmd(req));
712    }
713
714    static PacketPtr
715    createWrite(const RequestPtr req)
716    {
717        return new Packet(req, makeWriteCmd(req));
718    }
719
720    /**
721     * clean up packet variables
722     */
723    ~Packet()
724    {
725        // Delete the request object if this is a request packet which
726        // does not need a response, because the requester will not get
727        // a chance. If the request packet needs a response then the
728        // request will be deleted on receipt of the response
729        // packet. We also make sure to never delete the request for
730        // express snoops, even for cases when responses are not
731        // needed (CleanEvict and Writeback), since the snoop packet
732        // re-uses the same request.
733        if (req && isRequest() && !needsResponse() &&
734            !isExpressSnoop()) {
735            delete req;
736        }
737        deleteData();
738    }
739
740    /**
741     * Take a request packet and modify it in place to be suitable for
742     * returning as a response to that request.
743     */
744    void
745    makeResponse()
746    {
747        assert(needsResponse());
748        assert(isRequest());
749        cmd = cmd.responseCommand();
750
751        // responses are never express, even if the snoop that
752        // triggered them was
753        flags.clear(EXPRESS_SNOOP);
754    }
755
756    void
757    makeAtomicResponse()
758    {
759        makeResponse();
760    }
761
762    void
763    makeTimingResponse()
764    {
765        makeResponse();
766    }
767
768    void
769    setFunctionalResponseStatus(bool success)
770    {
771        if (!success) {
772            if (isWrite()) {
773                cmd = MemCmd::FunctionalWriteError;
774            } else {
775                cmd = MemCmd::FunctionalReadError;
776            }
777        }
778    }
779
780    void
781    setSize(unsigned size)
782    {
783        assert(!flags.isSet(VALID_SIZE));
784
785        this->size = size;
786        flags.set(VALID_SIZE);
787    }
788
789
790  public:
791    /**
792     * @{
793     * @name Data accessor mehtods
794     */
795
796    /**
797     * Set the data pointer to the following value that should not be
798     * freed. Static data allows us to do a single memcpy even if
799     * multiple packets are required to get from source to destination
800     * and back. In essence the pointer is set calling dataStatic on
801     * the original packet, and whenever this packet is copied and
802     * forwarded the same pointer is passed on. When a packet
803     * eventually reaches the destination holding the data, it is
804     * copied once into the location originally set. On the way back
805     * to the source, no copies are necessary.
806     */
807    template <typename T>
808    void
809    dataStatic(T *p)
810    {
811        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
812        data = (PacketDataPtr)p;
813        flags.set(STATIC_DATA);
814    }
815
816    /**
817     * Set the data pointer to the following value that should not be
818     * freed. This version of the function allows the pointer passed
819     * to us to be const. To avoid issues down the line we cast the
820     * constness away, the alternative would be to keep both a const
821     * and non-const data pointer and cleverly choose between
822     * them. Note that this is only allowed for static data.
823     */
824    template <typename T>
825    void
826    dataStaticConst(const T *p)
827    {
828        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
829        data = const_cast<PacketDataPtr>(p);
830        flags.set(STATIC_DATA);
831    }
832
833    /**
834     * Set the data pointer to a value that should have delete []
835     * called on it. Dynamic data is local to this packet, and as the
836     * packet travels from source to destination, forwarded packets
837     * will allocate their own data. When a packet reaches the final
838     * destination it will populate the dynamic data of that specific
839     * packet, and on the way back towards the source, memcpy will be
840     * invoked in every step where a new packet was created e.g. in
841     * the caches. Ultimately when the response reaches the source a
842     * final memcpy is needed to extract the data from the packet
843     * before it is deallocated.
844     */
845    template <typename T>
846    void
847    dataDynamic(T *p)
848    {
849        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
850        data = (PacketDataPtr)p;
851        flags.set(DYNAMIC_DATA);
852    }
853
854    /**
855     * get a pointer to the data ptr.
856     */
857    template <typename T>
858    T*
859    getPtr()
860    {
861        assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
862        return (T*)data;
863    }
864
865    template <typename T>
866    const T*
867    getConstPtr() const
868    {
869        assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
870        return (const T*)data;
871    }
872
873    /**
874     * Get the data in the packet byte swapped from big endian to
875     * host endian.
876     */
877    template <typename T>
878    T getBE() const;
879
880    /**
881     * Get the data in the packet byte swapped from little endian to
882     * host endian.
883     */
884    template <typename T>
885    T getLE() const;
886
887    /**
888     * Get the data in the packet byte swapped from the specified
889     * endianness.
890     */
891    template <typename T>
892    T get(ByteOrder endian) const;
893
894    /**
895     * Get the data in the packet byte swapped from guest to host
896     * endian.
897     */
898    template <typename T>
899    T get() const;
900
901    /** Set the value in the data pointer to v as big endian. */
902    template <typename T>
903    void setBE(T v);
904
905    /** Set the value in the data pointer to v as little endian. */
906    template <typename T>
907    void setLE(T v);
908
909    /**
910     * Set the value in the data pointer to v using the specified
911     * endianness.
912     */
913    template <typename T>
914    void set(T v, ByteOrder endian);
915
916    /** Set the value in the data pointer to v as guest endian. */
917    template <typename T>
918    void set(T v);
919
920    /**
921     * Copy data into the packet from the provided pointer.
922     */
923    void
924    setData(const uint8_t *p)
925    {
926        // we should never be copying data onto itself, which means we
927        // must idenfity packets with static data, as they carry the
928        // same pointer from source to destination and back
929        assert(p != getPtr<uint8_t>() || flags.isSet(STATIC_DATA));
930
931        if (p != getPtr<uint8_t>())
932            // for packet with allocated dynamic data, we copy data from
933            // one to the other, e.g. a forwarded response to a response
934            std::memcpy(getPtr<uint8_t>(), p, getSize());
935    }
936
937    /**
938     * Copy data into the packet from the provided block pointer,
939     * which is aligned to the given block size.
940     */
941    void
942    setDataFromBlock(const uint8_t *blk_data, int blkSize)
943    {
944        setData(blk_data + getOffset(blkSize));
945    }
946
947    /**
948     * Copy data from the packet to the provided block pointer, which
949     * is aligned to the given block size.
950     */
951    void
952    writeData(uint8_t *p) const
953    {
954        std::memcpy(p, getConstPtr<uint8_t>(), getSize());
955    }
956
957    /**
958     * Copy data from the packet to the memory at the provided pointer.
959     */
960    void
961    writeDataToBlock(uint8_t *blk_data, int blkSize) const
962    {
963        writeData(blk_data + getOffset(blkSize));
964    }
965
966    /**
967     * delete the data pointed to in the data pointer. Ok to call to
968     * matter how data was allocted.
969     */
970    void
971    deleteData()
972    {
973        if (flags.isSet(DYNAMIC_DATA))
974            delete [] data;
975
976        flags.clear(STATIC_DATA|DYNAMIC_DATA);
977        data = NULL;
978    }
979
980    /** Allocate memory for the packet. */
981    void
982    allocate()
983    {
984        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
985        flags.set(DYNAMIC_DATA);
986        data = new uint8_t[getSize()];
987    }
988
989    /** @} */
990
991  private: // Private data accessor methods
992    /** Get the data in the packet without byte swapping. */
993    template <typename T>
994    T getRaw() const;
995
996    /** Set the value in the data pointer to v without byte swapping. */
997    template <typename T>
998    void setRaw(T v);
999
1000  public:
1001    /**
1002     * Check a functional request against a memory value stored in
1003     * another packet (i.e. an in-transit request or
1004     * response). Returns true if the current packet is a read, and
1005     * the other packet provides the data, which is then copied to the
1006     * current packet. If the current packet is a write, and the other
1007     * packet intersects this one, then we update the data
1008     * accordingly.
1009     */
1010    bool
1011    checkFunctional(PacketPtr other)
1012    {
1013        // all packets that are carrying a payload should have a valid
1014        // data pointer
1015        return checkFunctional(other, other->getAddr(), other->isSecure(),
1016                               other->getSize(),
1017                               other->hasData() ?
1018                               other->getPtr<uint8_t>() : NULL);
1019    }
1020
1021    /**
1022     * Does the request need to check for cached copies of the same block
1023     * in the memory hierarchy above.
1024     **/
1025    bool
1026    mustCheckAbove() const
1027    {
1028        return cmd == MemCmd::HardPFReq || isEviction();
1029    }
1030
1031    /**
1032     * Is this packet a clean eviction, including both actual clean
1033     * evict packets, but also clean writebacks.
1034     */
1035    bool
1036    isCleanEviction() const
1037    {
1038        return cmd == MemCmd::CleanEvict || cmd == MemCmd::WritebackClean;
1039    }
1040
1041    /**
1042     * Check a functional request against a memory value represented
1043     * by a base/size pair and an associated data array. If the
1044     * current packet is a read, it may be satisfied by the memory
1045     * value. If the current packet is a write, it may update the
1046     * memory value.
1047     */
1048    bool
1049    checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
1050                    uint8_t *_data);
1051
1052    /**
1053     * Push label for PrintReq (safe to call unconditionally).
1054     */
1055    void
1056    pushLabel(const std::string &lbl)
1057    {
1058        if (isPrint())
1059            safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
1060    }
1061
1062    /**
1063     * Pop label for PrintReq (safe to call unconditionally).
1064     */
1065    void
1066    popLabel()
1067    {
1068        if (isPrint())
1069            safe_cast<PrintReqState*>(senderState)->popLabel();
1070    }
1071
1072    void print(std::ostream &o, int verbosity = 0,
1073               const std::string &prefix = "") const;
1074
1075    /**
1076     * A no-args wrapper of print(std::ostream...)
1077     * meant to be invoked from DPRINTFs
1078     * avoiding string overheads in fast mode
1079     * @return string with the request's type and start<->end addresses
1080     */
1081    std::string print() const;
1082};
1083
1084#endif //__MEM_PACKET_HH
1085