packet.hh revision 9031
14486Sbinkertn@umich.edu/*
24486Sbinkertn@umich.edu * Copyright (c) 2012 ARM Limited
34486Sbinkertn@umich.edu * All rights reserved
44486Sbinkertn@umich.edu *
54486Sbinkertn@umich.edu * The license below extends only to copyright in the software and shall
64486Sbinkertn@umich.edu * not be construed as granting a license to any other intellectual
74486Sbinkertn@umich.edu * property including but not limited to intellectual property relating
84486Sbinkertn@umich.edu * to a hardware implementation of the functionality of the software
94486Sbinkertn@umich.edu * licensed hereunder.  You may use the software subject to the license
104486Sbinkertn@umich.edu * terms below provided that you ensure that this notice is replicated
114486Sbinkertn@umich.edu * unmodified and in its entirety in all distributions of the software,
124486Sbinkertn@umich.edu * modified or unmodified, in source code or in binary form.
134486Sbinkertn@umich.edu *
144486Sbinkertn@umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
154486Sbinkertn@umich.edu * Copyright (c) 2010 Advanced Micro Devices, Inc.
164486Sbinkertn@umich.edu * All rights reserved.
174486Sbinkertn@umich.edu *
184486Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without
194486Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are
204486Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright
214486Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer;
224486Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright
234486Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the
244486Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution;
254486Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its
264486Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from
274486Sbinkertn@umich.edu * this software without specific prior written permission.
284486Sbinkertn@umich.edu *
293102SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
303102SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312736SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322736SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332736SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342736SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352736SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362736SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372736SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382736SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392736SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402736SN/A *
412736SN/A * Authors: Ron Dreslinski
422736SN/A *          Steve Reinhardt
432736SN/A *          Ali Saidi
442736SN/A *          Andreas Hansson
452736SN/A */
462736SN/A
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/fast_alloc.hh"
62#include "base/flags.hh"
63#include "base/misc.hh"
64#include "base/printable.hh"
65#include "base/types.hh"
66#include "mem/request.hh"
67#include "sim/core.hh"
68
69class Packet;
70typedef Packet *PacketPtr;
71typedef uint8_t* PacketDataPtr;
72typedef std::list<PacketPtr> PacketList;
73
74class MemCmd
75{
76    friend class Packet;
77
78  public:
79    /**
80     * List of all commands associated with a packet.
81     */
82    enum Command
83    {
84        InvalidCmd,
85        ReadReq,
86        ReadResp,
87        ReadRespWithInvalidate,
88        WriteReq,
89        WriteResp,
90        Writeback,
91        SoftPFReq,
92        HardPFReq,
93        SoftPFResp,
94        HardPFResp,
95        // WriteInvalidateReq transactions used to be generated by the
96        // DMA ports when writing full blocks to memory, however, it
97        // is not used anymore since we put the I/O cache in place to
98        // deal with partial block writes. Hence, WriteInvalidateReq
99        // and WriteInvalidateResp are currently unused. The
100        // implication is that the I/O cache does read-exclusive
101        // operations on every full-cache-block DMA, and ultimately
102        // this needs to be fixed.
103        WriteInvalidateReq,
104        WriteInvalidateResp,
105        UpgradeReq,
106        SCUpgradeReq,           // Special "weak" upgrade for StoreCond
107        UpgradeResp,
108        SCUpgradeFailReq,       // Failed SCUpgradeReq in MSHR (never sent)
109        UpgradeFailResp,        // Valid for SCUpgradeReq only
110        ReadExReq,
111        ReadExResp,
112        LoadLockedReq,
113        StoreCondReq,
114        StoreCondFailReq,       // Failed StoreCondReq in MSHR (never sent)
115        StoreCondResp,
116        SwapReq,
117        SwapResp,
118        MessageReq,
119        MessageResp,
120        // Error responses
121        // @TODO these should be classified as responses rather than
122        // requests; coding them as requests initially for backwards
123        // compatibility
124        NetworkNackError,  // nacked at network layer (not by protocol)
125        InvalidDestError,  // packet dest field invalid
126        BadAddressError,   // memory address invalid
127        FunctionalReadError, // unable to fulfill functional read
128        FunctionalWriteError, // unable to fulfill functional write
129        // Fake simulator-only commands
130        PrintReq,       // Print state matching address
131        FlushReq,      //request for a cache flush
132        InvalidationReq,   // request for address to be invalidated from lsq
133        NUM_MEM_CMDS
134    };
135
136  private:
137    /**
138     * List of command attributes.
139     */
140    enum Attribute
141    {
142        IsRead,         //!< Data flows from responder to requester
143        IsWrite,        //!< Data flows from requester to responder
144        IsUpgrade,
145        IsInvalidate,
146        NeedsExclusive, //!< Requires exclusive copy to complete in-cache
147        IsRequest,      //!< Issued by requester
148        IsResponse,     //!< Issue by responder
149        NeedsResponse,  //!< Requester needs response from target
150        IsSWPrefetch,
151        IsHWPrefetch,
152        IsLlsc,         //!< Alpha/MIPS LL or SC access
153        HasData,        //!< There is an associated payload
154        IsError,        //!< Error response
155        IsPrint,        //!< Print state matching address (for debugging)
156        IsFlush,        //!< Flush the address from caches
157        NUM_COMMAND_ATTRIBUTES
158    };
159
160    /**
161     * Structure that defines attributes and other data associated
162     * with a Command.
163     */
164    struct CommandInfo
165    {
166        /// Set of attribute flags.
167        const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
168        /// Corresponding response for requests; InvalidCmd if no
169        /// response is applicable.
170        const Command response;
171        /// String representation (for printing)
172        const std::string str;
173    };
174
175    /// Array to map Command enum to associated info.
176    static const CommandInfo commandInfo[];
177
178  private:
179
180    Command cmd;
181
182    bool
183    testCmdAttrib(MemCmd::Attribute attrib) const
184    {
185        return commandInfo[cmd].attributes[attrib] != 0;
186    }
187
188  public:
189
190    bool isRead() const         { return testCmdAttrib(IsRead); }
191    bool isWrite() const        { return testCmdAttrib(IsWrite); }
192    bool isUpgrade() const      { return testCmdAttrib(IsUpgrade); }
193    bool isRequest() const      { return testCmdAttrib(IsRequest); }
194    bool isResponse() const     { return testCmdAttrib(IsResponse); }
195    bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
196    bool needsResponse() const  { return testCmdAttrib(NeedsResponse); }
197    bool isInvalidate() const   { return testCmdAttrib(IsInvalidate); }
198    bool hasData() const        { return testCmdAttrib(HasData); }
199    bool isReadWrite() const    { return isRead() && isWrite(); }
200    bool isLLSC() const         { return testCmdAttrib(IsLlsc); }
201    bool isError() const        { return testCmdAttrib(IsError); }
202    bool isPrint() const        { return testCmdAttrib(IsPrint); }
203    bool isFlush() const        { return testCmdAttrib(IsFlush); }
204
205    const Command
206    responseCommand() const
207    {
208        return commandInfo[cmd].response;
209    }
210
211    /// Return the string to a cmd given by idx.
212    const std::string &toString() const { return commandInfo[cmd].str; }
213    int toInt() const { return (int)cmd; }
214
215    MemCmd(Command _cmd) : cmd(_cmd) { }
216    MemCmd(int _cmd) : cmd((Command)_cmd) { }
217    MemCmd() : cmd(InvalidCmd) { }
218
219    bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
220    bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
221};
222
223/**
224 * A Packet is used to encapsulate a transfer between two objects in
225 * the memory system (e.g., the L1 and L2 cache).  (In contrast, a
226 * single Request travels all the way from the requester to the
227 * ultimate destination and back, possibly being conveyed by several
228 * different Packets along the way.)
229 */
230class Packet : public FastAlloc, public Printable
231{
232  public:
233    typedef uint32_t FlagsType;
234    typedef ::Flags<FlagsType> Flags;
235
236  private:
237    static const FlagsType PUBLIC_FLAGS           = 0x00000000;
238    static const FlagsType PRIVATE_FLAGS          = 0x00007F0F;
239    static const FlagsType COPY_FLAGS             = 0x0000000F;
240
241    static const FlagsType SHARED                 = 0x00000001;
242    // Special control flags
243    /// Special timing-mode atomic snoop for multi-level coherence.
244    static const FlagsType EXPRESS_SNOOP          = 0x00000002;
245    /// Does supplier have exclusive copy?
246    /// Useful for multi-level coherence.
247    static const FlagsType SUPPLY_EXCLUSIVE       = 0x00000004;
248    // Snoop response flags
249    static const FlagsType MEM_INHIBIT            = 0x00000008;
250    /// Are the 'addr' and 'size' fields valid?
251    static const FlagsType VALID_ADDR             = 0x00000100;
252    static const FlagsType VALID_SIZE             = 0x00000200;
253    /// Is the data pointer set to a value that shouldn't be freed
254    /// when the packet is destroyed?
255    static const FlagsType STATIC_DATA            = 0x00001000;
256    /// The data pointer points to a value that should be freed when
257    /// the packet is destroyed.
258    static const FlagsType DYNAMIC_DATA           = 0x00002000;
259    /// the data pointer points to an array (thus delete []) needs to
260    /// be called on it rather than simply delete.
261    static const FlagsType ARRAY_DATA             = 0x00004000;
262    /// suppress the error if this packet encounters a functional
263    /// access failure.
264    static const FlagsType SUPPRESS_FUNC_ERROR    = 0x00008000;
265
266    Flags flags;
267
268  public:
269    typedef MemCmd::Command Command;
270
271    /// The command field of the packet.
272    MemCmd cmd;
273
274    /// A pointer to the original request.
275    RequestPtr req;
276
277  private:
278   /**
279    * A pointer to the data being transfered.  It can be differnt
280    * sizes at each level of the heirarchy so it belongs in the
281    * packet, not request. This may or may not be populated when a
282    * responder recieves the packet. If not populated it memory should
283    * be allocated.
284    */
285    PacketDataPtr data;
286
287    /// The address of the request.  This address could be virtual or
288    /// physical, depending on the system configuration.
289    Addr addr;
290
291    /// The size of the request or transfer.
292    unsigned size;
293
294    /**
295     * Source port identifier set on a request packet to enable
296     * appropriate routing of the responses. The source port
297     * identifier is set by any multiplexing component, e.g. a bus, as
298     * the timing responses need this information to be routed back to
299     * the appropriate port at a later point in time. The field can be
300     * updated (over-written) as the request packet passes through
301     * additional multiplexing components, and it is their
302     * responsibility to remember the original source port identifier,
303     * for example by using an appropriate sender state. The latter is
304     * done in the cache and bridge.
305     */
306    PortID src;
307
308    /**
309     * Destination port identifier that is present on all response
310     * packets that passed through a multiplexing component as a
311     * request packet. The source port identifier is turned into a
312     * destination port identifier when the packet is turned into a
313     * response, and the destination is used, e.g. by the bus, to
314     * select the appropriate path through the interconnect.
315     */
316    PortID dest;
317
318    /**
319     * The original value of the command field.  Only valid when the
320     * current command field is an error condition; in that case, the
321     * previous contents of the command field are copied here.  This
322     * field is *not* set on non-error responses.
323     */
324    MemCmd origCmd;
325
326    /**
327     * These values specify the range of bytes found that satisfy a
328     * functional read.
329     */
330    uint16_t bytesValidStart;
331    uint16_t bytesValidEnd;
332
333  public:
334    /// Used to calculate latencies for each packet.
335    Tick time;
336
337    /// The time at which the packet will be fully transmitted
338    Tick finishTime;
339
340    /// The time at which the first chunk of the packet will be transmitted
341    Tick firstWordTime;
342
343    /**
344     * A virtual base opaque structure used to hold state associated
345     * with the packet but specific to the sending device (e.g., an
346     * MSHR).  A pointer to this state is returned in the packet's
347     * response so that the sender can quickly look up the state
348     * needed to process it.  A specific subclass would be derived
349     * from this to carry state specific to a particular sending
350     * device.
351     */
352    struct SenderState
353    {
354        virtual ~SenderState() {}
355    };
356
357    /**
358     * Object used to maintain state of a PrintReq.  The senderState
359     * field of a PrintReq should always be of this type.
360     */
361    class PrintReqState : public SenderState, public FastAlloc
362    {
363      private:
364        /**
365         * An entry in the label stack.
366         */
367        struct LabelStackEntry
368        {
369            const std::string label;
370            std::string *prefix;
371            bool labelPrinted;
372            LabelStackEntry(const std::string &_label, std::string *_prefix);
373        };
374
375        typedef std::list<LabelStackEntry> LabelStack;
376        LabelStack labelStack;
377
378        std::string *curPrefixPtr;
379
380      public:
381        std::ostream &os;
382        const int verbosity;
383
384        PrintReqState(std::ostream &os, int verbosity = 0);
385        ~PrintReqState();
386
387        /**
388         * Returns the current line prefix.
389         */
390        const std::string &curPrefix() { return *curPrefixPtr; }
391
392        /**
393         * Push a label onto the label stack, and prepend the given
394         * prefix string onto the current prefix.  Labels will only be
395         * printed if an object within the label's scope is printed.
396         */
397        void pushLabel(const std::string &lbl,
398                       const std::string &prefix = "  ");
399
400        /**
401         * Pop a label off the label stack.
402         */
403        void popLabel();
404
405        /**
406         * Print all of the pending unprinted labels on the
407         * stack. Called by printObj(), so normally not called by
408         * users unless bypassing printObj().
409         */
410        void printLabels();
411
412        /**
413         * Print a Printable object to os, because it matched the
414         * address on a PrintReq.
415         */
416        void printObj(Printable *obj);
417    };
418
419    /**
420     * This packet's sender state.  Devices should use dynamic_cast<>
421     * to cast to the state appropriate to the sender.  The intent of
422     * this variable is to allow a device to attach extra information
423     * to a request.  A response packet must return the sender state
424     * that was attached to the original request (even if a new packet
425     * is created).
426     */
427    SenderState *senderState;
428
429    /// Return the string name of the cmd field (for debugging and
430    /// tracing).
431    const std::string &cmdString() const { return cmd.toString(); }
432
433    /// Return the index of this command.
434    inline int cmdToIndex() const { return cmd.toInt(); }
435
436    bool isRead() const         { return cmd.isRead(); }
437    bool isWrite() const        { return cmd.isWrite(); }
438    bool isUpgrade()  const     { return cmd.isUpgrade(); }
439    bool isRequest() const      { return cmd.isRequest(); }
440    bool isResponse() const     { return cmd.isResponse(); }
441    bool needsExclusive() const { return cmd.needsExclusive(); }
442    bool needsResponse() const  { return cmd.needsResponse(); }
443    bool isInvalidate() const   { return cmd.isInvalidate(); }
444    bool hasData() const        { return cmd.hasData(); }
445    bool isReadWrite() const    { return cmd.isReadWrite(); }
446    bool isLLSC() const         { return cmd.isLLSC(); }
447    bool isError() const        { return cmd.isError(); }
448    bool isPrint() const        { return cmd.isPrint(); }
449    bool isFlush() const        { return cmd.isFlush(); }
450
451    // Snoop flags
452    void assertMemInhibit()     { flags.set(MEM_INHIBIT); }
453    bool memInhibitAsserted()   { return flags.isSet(MEM_INHIBIT); }
454    void assertShared()         { flags.set(SHARED); }
455    bool sharedAsserted()       { return flags.isSet(SHARED); }
456
457    // Special control flags
458    void setExpressSnoop()      { flags.set(EXPRESS_SNOOP); }
459    bool isExpressSnoop()       { return flags.isSet(EXPRESS_SNOOP); }
460    void setSupplyExclusive()   { flags.set(SUPPLY_EXCLUSIVE); }
461    void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); }
462    bool isSupplyExclusive()    { return flags.isSet(SUPPLY_EXCLUSIVE); }
463    void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); }
464    bool suppressFuncError()    { return flags.isSet(SUPPRESS_FUNC_ERROR); }
465
466    // Network error conditions... encapsulate them as methods since
467    // their encoding keeps changing (from result field to command
468    // field, etc.)
469    void
470    setNacked()
471    {
472        assert(isResponse());
473        cmd = MemCmd::NetworkNackError;
474    }
475
476    void
477    setBadAddress()
478    {
479        assert(isResponse());
480        cmd = MemCmd::BadAddressError;
481    }
482
483    bool wasNacked() const     { return cmd == MemCmd::NetworkNackError; }
484    bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; }
485    void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
486
487    bool isSrcValid() const { return src != InvalidPortID; }
488    /// Accessor function to get the source index of the packet.
489    PortID getSrc() const { assert(isSrcValid()); return src; }
490    /// Accessor function to set the source index of the packet.
491    void setSrc(PortID _src) { src = _src; }
492    /// Reset source field, e.g. to retransmit packet on different bus.
493    void clearSrc() { src = InvalidPortID; }
494
495    bool isDestValid() const { return dest != InvalidPortID; }
496    /// Accessor function for the destination index of the packet.
497    PortID getDest() const { assert(isDestValid()); return dest; }
498    /// Accessor function to set the destination index of the packet.
499    void setDest(PortID _dest) { dest = _dest; }
500    /// Reset destination field, e.g. to turn a response into a request again.
501    void clearDest() { dest = InvalidPortID; }
502
503    Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
504    unsigned getSize() const  { assert(flags.isSet(VALID_SIZE)); return size; }
505    Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
506
507    /**
508     * It has been determined that the SC packet should successfully update
509     * memory.  Therefore, convert this SC packet to a normal write.
510     */
511    void
512    convertScToWrite()
513    {
514        assert(isLLSC());
515        assert(isWrite());
516        cmd = MemCmd::WriteReq;
517    }
518
519    /**
520     * When ruby is in use, Ruby will monitor the cache line and thus M5
521     * phys memory should treat LL ops as normal reads.
522     */
523    void
524    convertLlToRead()
525    {
526        assert(isLLSC());
527        assert(isRead());
528        cmd = MemCmd::ReadReq;
529    }
530
531    /**
532     * Constructor.  Note that a Request object must be constructed
533     * first, but the Requests's physical address and size fields need
534     * not be valid. The command must be supplied.
535     */
536    Packet(Request *_req, MemCmd _cmd)
537        :  cmd(_cmd), req(_req), data(NULL),
538           src(InvalidPortID), dest(InvalidPortID),
539           bytesValidStart(0), bytesValidEnd(0),
540           time(curTick()), senderState(NULL)
541    {
542        if (req->hasPaddr()) {
543            addr = req->getPaddr();
544            flags.set(VALID_ADDR);
545        }
546        if (req->hasSize()) {
547            size = req->getSize();
548            flags.set(VALID_SIZE);
549        }
550    }
551
552    /**
553     * Alternate constructor if you are trying to create a packet with
554     * a request that is for a whole block, not the address from the
555     * req.  this allows for overriding the size/addr of the req.
556     */
557    Packet(Request *_req, MemCmd _cmd, int _blkSize)
558        :  cmd(_cmd), req(_req), data(NULL),
559           src(InvalidPortID), dest(InvalidPortID),
560           bytesValidStart(0), bytesValidEnd(0),
561           time(curTick()), senderState(NULL)
562    {
563        if (req->hasPaddr()) {
564            addr = req->getPaddr() & ~(_blkSize - 1);
565            flags.set(VALID_ADDR);
566        }
567        size = _blkSize;
568        flags.set(VALID_SIZE);
569    }
570
571    /**
572     * Alternate constructor for copying a packet.  Copy all fields
573     * *except* if the original packet's data was dynamic, don't copy
574     * that, as we can't guarantee that the new packet's lifetime is
575     * less than that of the original packet.  In this case the new
576     * packet should allocate its own data.
577     */
578    Packet(Packet *pkt, bool clearFlags = false)
579        :  cmd(pkt->cmd), req(pkt->req),
580           data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
581           addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest),
582           bytesValidStart(pkt->bytesValidStart), bytesValidEnd(pkt->bytesValidEnd),
583           time(curTick()), senderState(pkt->senderState)
584    {
585        if (!clearFlags)
586            flags.set(pkt->flags & COPY_FLAGS);
587
588        flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
589        flags.set(pkt->flags & STATIC_DATA);
590
591    }
592
593    /**
594     * clean up packet variables
595     */
596    ~Packet()
597    {
598        // If this is a request packet for which there's no response,
599        // delete the request object here, since the requester will
600        // never get the chance.
601        if (req && isRequest() && !needsResponse())
602            delete req;
603        deleteData();
604    }
605
606    /**
607     * Reinitialize packet address and size from the associated
608     * Request object, and reset other fields that may have been
609     * modified by a previous transaction.  Typically called when a
610     * statically allocated Request/Packet pair is reused for multiple
611     * transactions.
612     */
613    void
614    reinitFromRequest()
615    {
616        assert(req->hasPaddr());
617        flags = 0;
618        addr = req->getPaddr();
619        size = req->getSize();
620        time = req->time();
621
622        flags.set(VALID_ADDR|VALID_SIZE);
623        deleteData();
624    }
625
626    /**
627     * Take a request packet and modify it in place to be suitable for
628     * returning as a response to that request. The source field is
629     * turned into the destination, and subsequently cleared. Note
630     * that the latter is not necessary for atomic requests, but
631     * causes no harm as neither field is valid.
632     */
633    void
634    makeResponse()
635    {
636        assert(needsResponse());
637        assert(isRequest());
638        origCmd = cmd;
639        cmd = cmd.responseCommand();
640
641        // responses are never express, even if the snoop that
642        // triggered them was
643        flags.clear(EXPRESS_SNOOP);
644
645        dest = src;
646        clearSrc();
647    }
648
649    void
650    makeAtomicResponse()
651    {
652        makeResponse();
653    }
654
655    void
656    makeTimingResponse()
657    {
658        makeResponse();
659    }
660
661    void
662    setFunctionalResponseStatus(bool success)
663    {
664        if (!success) {
665            if (isWrite()) {
666                cmd = MemCmd::FunctionalWriteError;
667            } else {
668                cmd = MemCmd::FunctionalReadError;
669            }
670        }
671    }
672
673    /**
674     * Take a request packet that has been returned as NACKED and
675     * modify it so that it can be sent out again. Only packets that
676     * need a response can be NACKED, so verify that that is true.
677     */
678    void
679    reinitNacked()
680    {
681        assert(wasNacked());
682        cmd = origCmd;
683        assert(needsResponse());
684        clearDest();
685    }
686
687    void
688    setSize(unsigned size)
689    {
690        assert(!flags.isSet(VALID_SIZE));
691
692        this->size = size;
693        flags.set(VALID_SIZE);
694    }
695
696
697    /**
698     * Set the data pointer to the following value that should not be
699     * freed.
700     */
701    template <typename T>
702    void
703    dataStatic(T *p)
704    {
705        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
706        data = (PacketDataPtr)p;
707        flags.set(STATIC_DATA);
708    }
709
710    /**
711     * Set the data pointer to a value that should have delete []
712     * called on it.
713     */
714    template <typename T>
715    void
716    dataDynamicArray(T *p)
717    {
718        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
719        data = (PacketDataPtr)p;
720        flags.set(DYNAMIC_DATA|ARRAY_DATA);
721    }
722
723    /**
724     * set the data pointer to a value that should have delete called
725     * on it.
726     */
727    template <typename T>
728    void
729    dataDynamic(T *p)
730    {
731        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
732        data = (PacketDataPtr)p;
733        flags.set(DYNAMIC_DATA);
734    }
735
736    /**
737     * get a pointer to the data ptr.
738     */
739    template <typename T>
740    T*
741    getPtr(bool null_ok = false)
742    {
743        assert(null_ok || flags.isSet(STATIC_DATA|DYNAMIC_DATA));
744        return (T*)data;
745    }
746
747    /**
748     * return the value of what is pointed to in the packet.
749     */
750    template <typename T>
751    T get();
752
753    /**
754     * set the value in the data pointer to v.
755     */
756    template <typename T>
757    void set(T v);
758
759    /**
760     * Copy data into the packet from the provided pointer.
761     */
762    void
763    setData(uint8_t *p)
764    {
765        if (p != getPtr<uint8_t>())
766            std::memcpy(getPtr<uint8_t>(), p, getSize());
767    }
768
769    /**
770     * Copy data into the packet from the provided block pointer,
771     * which is aligned to the given block size.
772     */
773    void
774    setDataFromBlock(uint8_t *blk_data, int blkSize)
775    {
776        setData(blk_data + getOffset(blkSize));
777    }
778
779    /**
780     * Copy data from the packet to the provided block pointer, which
781     * is aligned to the given block size.
782     */
783    void
784    writeData(uint8_t *p)
785    {
786        std::memcpy(p, getPtr<uint8_t>(), getSize());
787    }
788
789    /**
790     * Copy data from the packet to the memory at the provided pointer.
791     */
792    void
793    writeDataToBlock(uint8_t *blk_data, int blkSize)
794    {
795        writeData(blk_data + getOffset(blkSize));
796    }
797
798    /**
799     * delete the data pointed to in the data pointer. Ok to call to
800     * matter how data was allocted.
801     */
802    void
803    deleteData()
804    {
805        if (flags.isSet(ARRAY_DATA))
806            delete [] data;
807        else if (flags.isSet(DYNAMIC_DATA))
808            delete data;
809
810        flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA);
811        data = NULL;
812    }
813
814    /** If there isn't data in the packet, allocate some. */
815    void
816    allocate()
817    {
818        if (data) {
819            assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
820            return;
821        }
822
823        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
824        flags.set(DYNAMIC_DATA|ARRAY_DATA);
825        data = new uint8_t[getSize()];
826    }
827
828    /**
829     * Check a functional request against a memory value represented
830     * by a base/size pair and an associated data array.  If the
831     * functional request is a read, it may be satisfied by the memory
832     * value.  If the functional request is a write, it may update the
833     * memory value.
834     */
835    bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data);
836
837    /**
838     * Check a functional request against a memory value stored in
839     * another packet (i.e. an in-transit request or response).
840     */
841    bool
842    checkFunctional(PacketPtr other)
843    {
844        uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL;
845        return checkFunctional(other, other->getAddr(), other->getSize(),
846                               data);
847    }
848
849    /**
850     * Push label for PrintReq (safe to call unconditionally).
851     */
852    void
853    pushLabel(const std::string &lbl)
854    {
855        if (isPrint())
856            safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
857    }
858
859    /**
860     * Pop label for PrintReq (safe to call unconditionally).
861     */
862    void
863    popLabel()
864    {
865        if (isPrint())
866            safe_cast<PrintReqState*>(senderState)->popLabel();
867    }
868
869    void print(std::ostream &o, int verbosity = 0,
870               const std::string &prefix = "") const;
871};
872
873#endif //__MEM_PACKET_HH
874