packet.hh revision 10412:6400a2ab4e22
1/*
2 * Copyright (c) 2012-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2006 The Regents of The University of Michigan
15 * Copyright (c) 2010 Advanced Micro Devices, Inc.
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Ron Dreslinski
42 *          Steve Reinhardt
43 *          Ali Saidi
44 *          Andreas Hansson
45 */
46
47/**
48 * @file
49 * Declaration of the Packet class.
50 */
51
52#ifndef __MEM_PACKET_HH__
53#define __MEM_PACKET_HH__
54
55#include <bitset>
56#include <cassert>
57#include <list>
58
59#include "base/cast.hh"
60#include "base/compiler.hh"
61#include "base/flags.hh"
62#include "base/misc.hh"
63#include "base/printable.hh"
64#include "base/types.hh"
65#include "mem/request.hh"
66#include "sim/core.hh"
67
68class Packet;
69typedef Packet *PacketPtr;
70typedef uint8_t* PacketDataPtr;
71typedef std::list<PacketPtr> PacketList;
72
73class MemCmd
74{
75    friend class Packet;
76
77  public:
78    /**
79     * List of all commands associated with a packet.
80     */
81    enum Command
82    {
83        InvalidCmd,
84        ReadReq,
85        ReadResp,
86        ReadRespWithInvalidate,
87        WriteReq,
88        WriteResp,
89        Writeback,
90        SoftPFReq,
91        HardPFReq,
92        SoftPFResp,
93        HardPFResp,
94        WriteInvalidateReq,
95        WriteInvalidateResp,
96        UpgradeReq,
97        SCUpgradeReq,           // Special "weak" upgrade for StoreCond
98        UpgradeResp,
99        SCUpgradeFailReq,       // Failed SCUpgradeReq in MSHR (never sent)
100        UpgradeFailResp,        // Valid for SCUpgradeReq only
101        ReadExReq,
102        ReadExResp,
103        LoadLockedReq,
104        StoreCondReq,
105        StoreCondFailReq,       // Failed StoreCondReq in MSHR (never sent)
106        StoreCondResp,
107        SwapReq,
108        SwapResp,
109        MessageReq,
110        MessageResp,
111        // Error responses
112        // @TODO these should be classified as responses rather than
113        // requests; coding them as requests initially for backwards
114        // compatibility
115        InvalidDestError,  // packet dest field invalid
116        BadAddressError,   // memory address invalid
117        FunctionalReadError, // unable to fulfill functional read
118        FunctionalWriteError, // unable to fulfill functional write
119        // Fake simulator-only commands
120        PrintReq,       // Print state matching address
121        FlushReq,      //request for a cache flush
122        InvalidationReq,   // request for address to be invalidated from lsq
123        NUM_MEM_CMDS
124    };
125
126  private:
127    /**
128     * List of command attributes.
129     */
130    enum Attribute
131    {
132        IsRead,         //!< Data flows from responder to requester
133        IsWrite,        //!< Data flows from requester to responder
134        IsUpgrade,
135        IsInvalidate,
136        NeedsExclusive, //!< Requires exclusive copy to complete in-cache
137        IsRequest,      //!< Issued by requester
138        IsResponse,     //!< Issue by responder
139        NeedsResponse,  //!< Requester needs response from target
140        IsSWPrefetch,
141        IsHWPrefetch,
142        IsLlsc,         //!< Alpha/MIPS LL or SC access
143        HasData,        //!< There is an associated payload
144        IsError,        //!< Error response
145        IsPrint,        //!< Print state matching address (for debugging)
146        IsFlush,        //!< Flush the address from caches
147        NUM_COMMAND_ATTRIBUTES
148    };
149
150    /**
151     * Structure that defines attributes and other data associated
152     * with a Command.
153     */
154    struct CommandInfo
155    {
156        /// Set of attribute flags.
157        const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
158        /// Corresponding response for requests; InvalidCmd if no
159        /// response is applicable.
160        const Command response;
161        /// String representation (for printing)
162        const std::string str;
163    };
164
165    /// Array to map Command enum to associated info.
166    static const CommandInfo commandInfo[];
167
168  private:
169
170    Command cmd;
171
172    bool
173    testCmdAttrib(MemCmd::Attribute attrib) const
174    {
175        return commandInfo[cmd].attributes[attrib] != 0;
176    }
177
178  public:
179
180    bool isRead() const         { return testCmdAttrib(IsRead); }
181    bool isWrite() const        { return testCmdAttrib(IsWrite); }
182    bool isUpgrade() const      { return testCmdAttrib(IsUpgrade); }
183    bool isRequest() const      { return testCmdAttrib(IsRequest); }
184    bool isResponse() const     { return testCmdAttrib(IsResponse); }
185    bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
186    bool needsResponse() const  { return testCmdAttrib(NeedsResponse); }
187    bool isInvalidate() const   { return testCmdAttrib(IsInvalidate); }
188    bool hasData() const        { return testCmdAttrib(HasData); }
189    bool isReadWrite() const    { return isRead() && isWrite(); }
190    bool isLLSC() const         { return testCmdAttrib(IsLlsc); }
191    bool isSWPrefetch() const   { return testCmdAttrib(IsSWPrefetch); }
192    bool isHWPrefetch() const   { return testCmdAttrib(IsHWPrefetch); }
193    bool isPrefetch() const     { return testCmdAttrib(IsSWPrefetch) ||
194                                         testCmdAttrib(IsHWPrefetch); }
195    bool isError() const        { return testCmdAttrib(IsError); }
196    bool isPrint() const        { return testCmdAttrib(IsPrint); }
197    bool isFlush() const        { return testCmdAttrib(IsFlush); }
198
199    const Command
200    responseCommand() const
201    {
202        return commandInfo[cmd].response;
203    }
204
205    /// Return the string to a cmd given by idx.
206    const std::string &toString() const { return commandInfo[cmd].str; }
207    int toInt() const { return (int)cmd; }
208
209    MemCmd(Command _cmd) : cmd(_cmd) { }
210    MemCmd(int _cmd) : cmd((Command)_cmd) { }
211    MemCmd() : cmd(InvalidCmd) { }
212
213    bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
214    bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
215};
216
217/**
218 * A Packet is used to encapsulate a transfer between two objects in
219 * the memory system (e.g., the L1 and L2 cache).  (In contrast, a
220 * single Request travels all the way from the requester to the
221 * ultimate destination and back, possibly being conveyed by several
222 * different Packets along the way.)
223 */
224class Packet : public Printable
225{
226  public:
227    typedef uint32_t FlagsType;
228    typedef ::Flags<FlagsType> Flags;
229
230  private:
231    static const FlagsType PUBLIC_FLAGS           = 0x00000000;
232    static const FlagsType PRIVATE_FLAGS          = 0x00007F0F;
233    static const FlagsType COPY_FLAGS             = 0x0000000F;
234
235    static const FlagsType SHARED                 = 0x00000001;
236    // Special control flags
237    /// Special timing-mode atomic snoop for multi-level coherence.
238    static const FlagsType EXPRESS_SNOOP          = 0x00000002;
239    /// Does supplier have exclusive copy?
240    /// Useful for multi-level coherence.
241    static const FlagsType SUPPLY_EXCLUSIVE       = 0x00000004;
242    // Snoop response flags
243    static const FlagsType MEM_INHIBIT            = 0x00000008;
244    /// Are the 'addr' and 'size' fields valid?
245    static const FlagsType VALID_ADDR             = 0x00000100;
246    static const FlagsType VALID_SIZE             = 0x00000200;
247    /// Is the data pointer set to a value that shouldn't be freed
248    /// when the packet is destroyed?
249    static const FlagsType STATIC_DATA            = 0x00001000;
250    /// The data pointer points to a value that should be freed when
251    /// the packet is destroyed.
252    static const FlagsType DYNAMIC_DATA           = 0x00002000;
253    /// the data pointer points to an array (thus delete []) needs to
254    /// be called on it rather than simply delete.
255    static const FlagsType ARRAY_DATA             = 0x00004000;
256    /// suppress the error if this packet encounters a functional
257    /// access failure.
258    static const FlagsType SUPPRESS_FUNC_ERROR    = 0x00008000;
259    // Signal prefetch squash through express snoop flag
260    static const FlagsType PREFETCH_SNOOP_SQUASH  = 0x00010000;
261
262    Flags flags;
263
264  public:
265    typedef MemCmd::Command Command;
266
267    /// The command field of the packet.
268    MemCmd cmd;
269
270    /// A pointer to the original request.
271    RequestPtr req;
272
273  private:
274   /**
275    * A pointer to the data being transfered.  It can be differnt
276    * sizes at each level of the heirarchy so it belongs in the
277    * packet, not request. This may or may not be populated when a
278    * responder recieves the packet. If not populated it memory should
279    * be allocated.
280    */
281    PacketDataPtr data;
282
283    /// The address of the request.  This address could be virtual or
284    /// physical, depending on the system configuration.
285    Addr addr;
286
287    /// True if the request targets the secure memory space.
288    bool _isSecure;
289
290    /// The size of the request or transfer.
291    unsigned size;
292
293    /**
294     * Source port identifier set on a request packet to enable
295     * appropriate routing of the responses. The source port
296     * identifier is set by any multiplexing component, e.g. a
297     * crossbar, as the timing responses need this information to be
298     * routed back to the appropriate port at a later point in
299     * time. The field can be updated (over-written) as the request
300     * packet passes through additional multiplexing components, and
301     * it is their responsibility to remember the original source port
302     * identifier, for example by using an appropriate sender
303     * state. The latter is done in the cache and bridge.
304     */
305    PortID src;
306
307    /**
308     * Destination port identifier that is present on all response
309     * packets that passed through a multiplexing component as a
310     * request packet. The source port identifier is turned into a
311     * destination port identifier when the packet is turned into a
312     * response, and the destination is used, e.g. by the crossbar, to
313     * select the appropriate path through the interconnect.
314     */
315    PortID dest;
316
317    /**
318     * The original value of the command field.  Only valid when the
319     * current command field is an error condition; in that case, the
320     * previous contents of the command field are copied here.  This
321     * field is *not* set on non-error responses.
322     */
323    MemCmd origCmd;
324
325    /**
326     * These values specify the range of bytes found that satisfy a
327     * functional read.
328     */
329    uint16_t bytesValidStart;
330    uint16_t bytesValidEnd;
331
332  public:
333
334    /**
335     * The extra delay from seeing the packet until the first word is
336     * transmitted. This delay is used to communicate the crossbar
337     * forwarding latency to the neighbouring object (e.g. a cache)
338     * that actually makes the packet wait. As the delay is relative,
339     * a 32-bit unsigned should be sufficient.
340     */
341    uint32_t firstWordDelay;
342
343    /**
344     * The extra pipelining delay from seeing the packet until the
345     * last word is transmitted by the component that provided it (if
346     * any). This includes the first word delay. Similar to the first
347     * word 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 lastWordDelay;
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 hasData() const        { return cmd.hasData(); }
504    bool isReadWrite() const    { return cmd.isReadWrite(); }
505    bool isLLSC() const         { return cmd.isLLSC(); }
506    bool isError() const        { return cmd.isError(); }
507    bool isPrint() const        { return cmd.isPrint(); }
508    bool isFlush() const        { return cmd.isFlush(); }
509
510    // Snoop flags
511    void assertMemInhibit()         { flags.set(MEM_INHIBIT); }
512    bool memInhibitAsserted() const { return flags.isSet(MEM_INHIBIT); }
513    void assertShared()             { flags.set(SHARED); }
514    bool sharedAsserted() const     { return flags.isSet(SHARED); }
515
516    // Special control flags
517    void setExpressSnoop()          { flags.set(EXPRESS_SNOOP); }
518    bool isExpressSnoop() const     { return flags.isSet(EXPRESS_SNOOP); }
519    void setSupplyExclusive()       { flags.set(SUPPLY_EXCLUSIVE); }
520    void clearSupplyExclusive()     { flags.clear(SUPPLY_EXCLUSIVE); }
521    bool isSupplyExclusive() const  { return flags.isSet(SUPPLY_EXCLUSIVE); }
522    void setSuppressFuncError()     { flags.set(SUPPRESS_FUNC_ERROR); }
523    bool suppressFuncError() const  { return flags.isSet(SUPPRESS_FUNC_ERROR); }
524    void setPrefetchSquashed()      { flags.set(PREFETCH_SNOOP_SQUASH); }
525    bool prefetchSquashed() const   { return flags.isSet(PREFETCH_SNOOP_SQUASH); }
526
527    // Network error conditions... encapsulate them as methods since
528    // their encoding keeps changing (from result field to command
529    // field, etc.)
530    void
531    setBadAddress()
532    {
533        assert(isResponse());
534        cmd = MemCmd::BadAddressError;
535    }
536
537    bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; }
538    void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
539
540    bool isSrcValid() const { return src != InvalidPortID; }
541    /// Accessor function to get the source index of the packet.
542    PortID getSrc() const { assert(isSrcValid()); return src; }
543    /// Accessor function to set the source index of the packet.
544    void setSrc(PortID _src) { src = _src; }
545
546    bool isDestValid() const { return dest != InvalidPortID; }
547    /// Accessor function for the destination index of the packet.
548    PortID getDest() const { assert(isDestValid()); return dest; }
549    /// Accessor function to set the destination index of the packet.
550    void setDest(PortID _dest) { dest = _dest; }
551    /// Reset destination field, e.g. to turn a response into a request again.
552    void clearDest() { dest = InvalidPortID; }
553
554    Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
555    /**
556     * Update the address of this packet mid-transaction. This is used
557     * by the address mapper to change an already set address to a new
558     * one based on the system configuration. It is intended to remap
559     * an existing address, so it asserts that the current address is
560     * valid.
561     */
562    void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; }
563
564    unsigned getSize() const  { assert(flags.isSet(VALID_SIZE)); return size; }
565    Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
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 thus M5
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(Request *_req, MemCmd _cmd)
603        :  cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
604           size(0), src(InvalidPortID), dest(InvalidPortID),
605           bytesValidStart(0), bytesValidEnd(0),
606           firstWordDelay(0), lastWordDelay(0),
607           senderState(NULL)
608    {
609        if (req->hasPaddr()) {
610            addr = req->getPaddr();
611            flags.set(VALID_ADDR);
612            _isSecure = req->isSecure();
613        }
614        if (req->hasSize()) {
615            size = req->getSize();
616            flags.set(VALID_SIZE);
617        }
618    }
619
620    /**
621     * Alternate constructor if you are trying to create a packet with
622     * a request that is for a whole block, not the address from the
623     * req.  this allows for overriding the size/addr of the req.
624     */
625    Packet(Request *_req, MemCmd _cmd, int _blkSize)
626        :  cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
627           src(InvalidPortID), dest(InvalidPortID),
628           bytesValidStart(0), bytesValidEnd(0),
629           firstWordDelay(0), lastWordDelay(0),
630           senderState(NULL)
631    {
632        if (req->hasPaddr()) {
633            addr = req->getPaddr() & ~(_blkSize - 1);
634            flags.set(VALID_ADDR);
635            _isSecure = req->isSecure();
636        }
637        size = _blkSize;
638        flags.set(VALID_SIZE);
639    }
640
641    /**
642     * Alternate constructor for copying a packet.  Copy all fields
643     * *except* if the original packet's data was dynamic, don't copy
644     * that, as we can't guarantee that the new packet's lifetime is
645     * less than that of the original packet.  In this case the new
646     * packet should allocate its own data.
647     */
648    Packet(Packet *pkt, bool clearFlags = false)
649        :  cmd(pkt->cmd), req(pkt->req),
650           data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
651           addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
652           src(pkt->src), dest(pkt->dest),
653           bytesValidStart(pkt->bytesValidStart),
654           bytesValidEnd(pkt->bytesValidEnd),
655           firstWordDelay(pkt->firstWordDelay),
656           lastWordDelay(pkt->lastWordDelay),
657           senderState(pkt->senderState)
658    {
659        if (!clearFlags)
660            flags.set(pkt->flags & COPY_FLAGS);
661
662        flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
663        flags.set(pkt->flags & STATIC_DATA);
664    }
665
666    /**
667     * Change the packet type based on request type.
668     */
669    void
670    refineCommand()
671    {
672        if (cmd == MemCmd::ReadReq) {
673            if (req->isLLSC()) {
674                cmd = MemCmd::LoadLockedReq;
675            } else if (req->isPrefetch()) {
676                cmd = MemCmd::SoftPFReq;
677            }
678        } else if (cmd == MemCmd::WriteReq) {
679            if (req->isLLSC()) {
680                cmd = MemCmd::StoreCondReq;
681            } else if (req->isSwap()) {
682                cmd = MemCmd::SwapReq;
683            }
684        }
685    }
686
687    /**
688     * Constructor-like methods that return Packets based on Request objects.
689     * Will call refineCommand() to fine-tune the Packet type if it's not a
690     * vanilla read or write.
691     */
692    static PacketPtr
693    createRead(Request *req)
694    {
695        PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
696        pkt->refineCommand();
697        return pkt;
698    }
699
700    static PacketPtr
701    createWrite(Request *req)
702    {
703        PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
704        pkt->refineCommand();
705        return pkt;
706    }
707
708    /**
709     * clean up packet variables
710     */
711    ~Packet()
712    {
713        // If this is a request packet for which there's no response,
714        // delete the request object here, since the requester will
715        // never get the chance.
716        if (req && isRequest() && !needsResponse())
717            delete req;
718        deleteData();
719    }
720
721    /**
722     * Reinitialize packet address and size from the associated
723     * Request object, and reset other fields that may have been
724     * modified by a previous transaction.  Typically called when a
725     * statically allocated Request/Packet pair is reused for multiple
726     * transactions.
727     */
728    void
729    reinitFromRequest()
730    {
731        assert(req->hasPaddr());
732        flags = 0;
733        addr = req->getPaddr();
734        _isSecure = req->isSecure();
735        size = req->getSize();
736
737        src = InvalidPortID;
738        dest = InvalidPortID;
739        bytesValidStart = 0;
740        bytesValidEnd = 0;
741        firstWordDelay = 0;
742        lastWordDelay = 0;
743
744        flags.set(VALID_ADDR|VALID_SIZE);
745        deleteData();
746    }
747
748    /**
749     * Take a request packet and modify it in place to be suitable for
750     * returning as a response to that request. The source field is
751     * turned into the destination, and subsequently cleared. Note
752     * that the latter is not necessary for atomic requests, but
753     * causes no harm as neither field is valid.
754     */
755    void
756    makeResponse()
757    {
758        assert(needsResponse());
759        assert(isRequest());
760        origCmd = cmd;
761        cmd = cmd.responseCommand();
762
763        // responses are never express, even if the snoop that
764        // triggered them was
765        flags.clear(EXPRESS_SNOOP);
766
767        dest = src;
768        src = InvalidPortID;
769    }
770
771    void
772    makeAtomicResponse()
773    {
774        makeResponse();
775    }
776
777    void
778    makeTimingResponse()
779    {
780        makeResponse();
781    }
782
783    void
784    setFunctionalResponseStatus(bool success)
785    {
786        if (!success) {
787            if (isWrite()) {
788                cmd = MemCmd::FunctionalWriteError;
789            } else {
790                cmd = MemCmd::FunctionalReadError;
791            }
792        }
793    }
794
795    void
796    setSize(unsigned size)
797    {
798        assert(!flags.isSet(VALID_SIZE));
799
800        this->size = size;
801        flags.set(VALID_SIZE);
802    }
803
804
805    /**
806     * Set the data pointer to the following value that should not be
807     * freed.
808     */
809    template <typename T>
810    void
811    dataStatic(T *p)
812    {
813        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
814        data = (PacketDataPtr)p;
815        flags.set(STATIC_DATA);
816    }
817
818    /**
819     * Set the data pointer to a value that should have delete []
820     * called on it.
821     */
822    template <typename T>
823    void
824    dataDynamicArray(T *p)
825    {
826        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
827        data = (PacketDataPtr)p;
828        flags.set(DYNAMIC_DATA|ARRAY_DATA);
829    }
830
831    /**
832     * set the data pointer to a value that should have delete called
833     * on it.
834     */
835    template <typename T>
836    void
837    dataDynamic(T *p)
838    {
839        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
840        data = (PacketDataPtr)p;
841        flags.set(DYNAMIC_DATA);
842    }
843
844    /**
845     * get a pointer to the data ptr.
846     */
847    template <typename T>
848    T*
849    getPtr(bool null_ok = false)
850    {
851        assert(null_ok || flags.isSet(STATIC_DATA|DYNAMIC_DATA));
852        return (T*)data;
853    }
854
855    /**
856     * return the value of what is pointed to in the packet.
857     */
858    template <typename T>
859    T get();
860
861    /**
862     * set the value in the data pointer to v.
863     */
864    template <typename T>
865    void set(T v);
866
867    /**
868     * Copy data into the packet from the provided pointer.
869     */
870    void
871    setData(uint8_t *p)
872    {
873        if (p != getPtr<uint8_t>())
874            std::memcpy(getPtr<uint8_t>(), p, getSize());
875    }
876
877    /**
878     * Copy data into the packet from the provided block pointer,
879     * which is aligned to the given block size.
880     */
881    void
882    setDataFromBlock(uint8_t *blk_data, int blkSize)
883    {
884        setData(blk_data + getOffset(blkSize));
885    }
886
887    /**
888     * Copy data from the packet to the provided block pointer, which
889     * is aligned to the given block size.
890     */
891    void
892    writeData(uint8_t *p)
893    {
894        std::memcpy(p, getPtr<uint8_t>(), getSize());
895    }
896
897    /**
898     * Copy data from the packet to the memory at the provided pointer.
899     */
900    void
901    writeDataToBlock(uint8_t *blk_data, int blkSize)
902    {
903        writeData(blk_data + getOffset(blkSize));
904    }
905
906    /**
907     * delete the data pointed to in the data pointer. Ok to call to
908     * matter how data was allocted.
909     */
910    void
911    deleteData()
912    {
913        if (flags.isSet(ARRAY_DATA))
914            delete [] data;
915        else if (flags.isSet(DYNAMIC_DATA))
916            delete data;
917
918        flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA);
919        data = NULL;
920    }
921
922    /** If there isn't data in the packet, allocate some. */
923    void
924    allocate()
925    {
926        if (data) {
927            assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
928            return;
929        }
930
931        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
932        flags.set(DYNAMIC_DATA|ARRAY_DATA);
933        data = new uint8_t[getSize()];
934    }
935
936    /**
937     * Check a functional request against a memory value represented
938     * by a base/size pair and an associated data array.  If the
939     * functional request is a read, it may be satisfied by the memory
940     * value.  If the functional request is a write, it may update the
941     * memory value.
942     */
943    bool checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
944                         uint8_t *data);
945
946    /**
947     * Check a functional request against a memory value stored in
948     * another packet (i.e. an in-transit request or response).
949     */
950    bool
951    checkFunctional(PacketPtr other)
952    {
953        uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL;
954        return checkFunctional(other, other->getAddr(), other->isSecure(),
955                               other->getSize(), data);
956    }
957
958    /**
959     * Push label for PrintReq (safe to call unconditionally).
960     */
961    void
962    pushLabel(const std::string &lbl)
963    {
964        if (isPrint())
965            safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
966    }
967
968    /**
969     * Pop label for PrintReq (safe to call unconditionally).
970     */
971    void
972    popLabel()
973    {
974        if (isPrint())
975            safe_cast<PrintReqState*>(senderState)->popLabel();
976    }
977
978    void print(std::ostream &o, int verbosity = 0,
979               const std::string &prefix = "") const;
980
981    /**
982     * A no-args wrapper of print(std::ostream...)
983     * meant to be invoked from DPRINTFs
984     * avoiding string overheads in fast mode
985     * @return string with the request's type and start<->end addresses
986     */
987    std::string print() const;
988};
989
990#endif //__MEM_PACKET_HH
991