packet.hh revision 8949:3fa1ee293096
1/* 2 * Copyright (c) 2012 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 */ 45 46/** 47 * @file 48 * Declaration of the Packet class. 49 */ 50 51#ifndef __MEM_PACKET_HH__ 52#define __MEM_PACKET_HH__ 53 54#include <bitset> 55#include <cassert> 56#include <list> 57 58#include "base/cast.hh" 59#include "base/compiler.hh" 60#include "base/fast_alloc.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 NetworkNackError, // nacked at network layer (not by protocol) 116 InvalidDestError, // packet dest field invalid 117 BadAddressError, // memory address invalid 118 FunctionalReadError, // unable to fulfill functional read 119 FunctionalWriteError, // unable to fulfill functional write 120 // Fake simulator-only commands 121 PrintReq, // Print state matching address 122 FlushReq, //request for a cache flush 123 InvalidationReq, // request for address to be invalidated from lsq 124 NUM_MEM_CMDS 125 }; 126 127 private: 128 /** 129 * List of command attributes. 130 */ 131 enum Attribute 132 { 133 IsRead, //!< Data flows from responder to requester 134 IsWrite, //!< Data flows from requester to responder 135 IsUpgrade, 136 IsPrefetch, //!< Not a demand access 137 IsInvalidate, 138 NeedsExclusive, //!< Requires exclusive copy to complete in-cache 139 IsRequest, //!< Issued by requester 140 IsResponse, //!< Issue by responder 141 NeedsResponse, //!< Requester needs response from target 142 IsSWPrefetch, 143 IsHWPrefetch, 144 IsLlsc, //!< Alpha/MIPS LL or SC access 145 HasData, //!< There is an associated payload 146 IsError, //!< Error response 147 IsPrint, //!< Print state matching address (for debugging) 148 IsFlush, //!< Flush the address from caches 149 NUM_COMMAND_ATTRIBUTES 150 }; 151 152 /** 153 * Structure that defines attributes and other data associated 154 * with a Command. 155 */ 156 struct CommandInfo 157 { 158 /// Set of attribute flags. 159 const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes; 160 /// Corresponding response for requests; InvalidCmd if no 161 /// response is applicable. 162 const Command response; 163 /// String representation (for printing) 164 const std::string str; 165 }; 166 167 /// Array to map Command enum to associated info. 168 static const CommandInfo commandInfo[]; 169 170 private: 171 172 Command cmd; 173 174 bool 175 testCmdAttrib(MemCmd::Attribute attrib) const 176 { 177 return commandInfo[cmd].attributes[attrib] != 0; 178 } 179 180 public: 181 182 bool isRead() const { return testCmdAttrib(IsRead); } 183 bool isWrite() const { return testCmdAttrib(IsWrite); } 184 bool isUpgrade() const { return testCmdAttrib(IsUpgrade); } 185 bool isRequest() const { return testCmdAttrib(IsRequest); } 186 bool isResponse() const { return testCmdAttrib(IsResponse); } 187 bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); } 188 bool needsResponse() const { return testCmdAttrib(NeedsResponse); } 189 bool isInvalidate() const { return testCmdAttrib(IsInvalidate); } 190 bool hasData() const { return testCmdAttrib(HasData); } 191 bool isReadWrite() const { return isRead() && isWrite(); } 192 bool isLLSC() const { return testCmdAttrib(IsLlsc); } 193 bool isError() const { return testCmdAttrib(IsError); } 194 bool isPrint() const { return testCmdAttrib(IsPrint); } 195 bool isFlush() const { return testCmdAttrib(IsFlush); } 196 197 const Command 198 responseCommand() const 199 { 200 return commandInfo[cmd].response; 201 } 202 203 /// Return the string to a cmd given by idx. 204 const std::string &toString() const { return commandInfo[cmd].str; } 205 int toInt() const { return (int)cmd; } 206 207 MemCmd(Command _cmd) : cmd(_cmd) { } 208 MemCmd(int _cmd) : cmd((Command)_cmd) { } 209 MemCmd() : cmd(InvalidCmd) { } 210 211 bool operator==(MemCmd c2) const { return (cmd == c2.cmd); } 212 bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); } 213}; 214 215/** 216 * A Packet is used to encapsulate a transfer between two objects in 217 * the memory system (e.g., the L1 and L2 cache). (In contrast, a 218 * single Request travels all the way from the requester to the 219 * ultimate destination and back, possibly being conveyed by several 220 * different Packets along the way.) 221 */ 222class Packet : public FastAlloc, public Printable 223{ 224 public: 225 typedef uint32_t FlagsType; 226 typedef ::Flags<FlagsType> Flags; 227 typedef short NodeID; 228 229 private: 230 static const FlagsType PUBLIC_FLAGS = 0x00000000; 231 static const FlagsType PRIVATE_FLAGS = 0x00007F0F; 232 static const FlagsType COPY_FLAGS = 0x0000000F; 233 234 static const FlagsType SHARED = 0x00000001; 235 // Special control flags 236 /// Special timing-mode atomic snoop for multi-level coherence. 237 static const FlagsType EXPRESS_SNOOP = 0x00000002; 238 /// Does supplier have exclusive copy? 239 /// Useful for multi-level coherence. 240 static const FlagsType SUPPLY_EXCLUSIVE = 0x00000004; 241 // Snoop response flags 242 static const FlagsType MEM_INHIBIT = 0x00000008; 243 /// Are the 'addr' and 'size' fields valid? 244 static const FlagsType VALID_ADDR = 0x00000100; 245 static const FlagsType VALID_SIZE = 0x00000200; 246 /// Is the 'src' field valid? 247 static const FlagsType VALID_SRC = 0x00000400; 248 static const FlagsType VALID_DST = 0x00000800; 249 /// Is the data pointer set to a value that shouldn't be freed 250 /// when the packet is destroyed? 251 static const FlagsType STATIC_DATA = 0x00001000; 252 /// The data pointer points to a value that should be freed when 253 /// the packet is destroyed. 254 static const FlagsType DYNAMIC_DATA = 0x00002000; 255 /// the data pointer points to an array (thus delete []) needs to 256 /// be called on it rather than simply delete. 257 static const FlagsType ARRAY_DATA = 0x00004000; 258 /// suppress the error if this packet encounters a functional 259 /// access failure. 260 static const FlagsType SUPPRESS_FUNC_ERROR = 0x00008000; 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 /// The size of the request or transfer. 288 unsigned size; 289 290 /** 291 * Device address (e.g., bus ID) of the source of the 292 * transaction. The source is not responsible for setting this 293 * field; it is set implicitly by the interconnect when the packet 294 * is first sent. 295 */ 296 NodeID src; 297 298 /** 299 * Device address (e.g., bus ID) of the destination of the 300 * transaction. The special value Broadcast indicates that the 301 * packet should be routed based on its address. This field is 302 * initialized in the constructor and is thus always valid (unlike 303 * addr, size, and src). 304 */ 305 NodeID dest; 306 307 /** 308 * The original value of the command field. Only valid when the 309 * current command field is an error condition; in that case, the 310 * previous contents of the command field are copied here. This 311 * field is *not* set on non-error responses. 312 */ 313 MemCmd origCmd; 314 315 /** 316 * These values specify the range of bytes found that satisfy a 317 * functional read. 318 */ 319 uint16_t bytesValidStart; 320 uint16_t bytesValidEnd; 321 322 public: 323 /// Used to calculate latencies for each packet. 324 Tick time; 325 326 /// The time at which the packet will be fully transmitted 327 Tick finishTime; 328 329 /// The time at which the first chunk of the packet will be transmitted 330 Tick firstWordTime; 331 332 /** 333 * A virtual base opaque structure used to hold state associated 334 * with the packet but specific to the sending device (e.g., an 335 * MSHR). A pointer to this state is returned in the packet's 336 * response so that the sender can quickly look up the state 337 * needed to process it. A specific subclass would be derived 338 * from this to carry state specific to a particular sending 339 * device. 340 */ 341 struct SenderState 342 { 343 virtual ~SenderState() {} 344 }; 345 346 /** 347 * Object used to maintain state of a PrintReq. The senderState 348 * field of a PrintReq should always be of this type. 349 */ 350 class PrintReqState : public SenderState, public FastAlloc 351 { 352 private: 353 /** 354 * An entry in the label stack. 355 */ 356 struct LabelStackEntry 357 { 358 const std::string label; 359 std::string *prefix; 360 bool labelPrinted; 361 LabelStackEntry(const std::string &_label, std::string *_prefix); 362 }; 363 364 typedef std::list<LabelStackEntry> LabelStack; 365 LabelStack labelStack; 366 367 std::string *curPrefixPtr; 368 369 public: 370 std::ostream &os; 371 const int verbosity; 372 373 PrintReqState(std::ostream &os, int verbosity = 0); 374 ~PrintReqState(); 375 376 /** 377 * Returns the current line prefix. 378 */ 379 const std::string &curPrefix() { return *curPrefixPtr; } 380 381 /** 382 * Push a label onto the label stack, and prepend the given 383 * prefix string onto the current prefix. Labels will only be 384 * printed if an object within the label's scope is printed. 385 */ 386 void pushLabel(const std::string &lbl, 387 const std::string &prefix = " "); 388 389 /** 390 * Pop a label off the label stack. 391 */ 392 void popLabel(); 393 394 /** 395 * Print all of the pending unprinted labels on the 396 * stack. Called by printObj(), so normally not called by 397 * users unless bypassing printObj(). 398 */ 399 void printLabels(); 400 401 /** 402 * Print a Printable object to os, because it matched the 403 * address on a PrintReq. 404 */ 405 void printObj(Printable *obj); 406 }; 407 408 /** 409 * This packet's sender state. Devices should use dynamic_cast<> 410 * to cast to the state appropriate to the sender. The intent of 411 * this variable is to allow a device to attach extra information 412 * to a request. A response packet must return the sender state 413 * that was attached to the original request (even if a new packet 414 * is created). 415 */ 416 SenderState *senderState; 417 418 /// Return the string name of the cmd field (for debugging and 419 /// tracing). 420 const std::string &cmdString() const { return cmd.toString(); } 421 422 /// Return the index of this command. 423 inline int cmdToIndex() const { return cmd.toInt(); } 424 425 bool isRead() const { return cmd.isRead(); } 426 bool isWrite() const { return cmd.isWrite(); } 427 bool isUpgrade() const { return cmd.isUpgrade(); } 428 bool isRequest() const { return cmd.isRequest(); } 429 bool isResponse() const { return cmd.isResponse(); } 430 bool needsExclusive() const { return cmd.needsExclusive(); } 431 bool needsResponse() const { return cmd.needsResponse(); } 432 bool isInvalidate() const { return cmd.isInvalidate(); } 433 bool hasData() const { return cmd.hasData(); } 434 bool isReadWrite() const { return cmd.isReadWrite(); } 435 bool isLLSC() const { return cmd.isLLSC(); } 436 bool isError() const { return cmd.isError(); } 437 bool isPrint() const { return cmd.isPrint(); } 438 bool isFlush() const { return cmd.isFlush(); } 439 440 // Snoop flags 441 void assertMemInhibit() { flags.set(MEM_INHIBIT); } 442 bool memInhibitAsserted() { return flags.isSet(MEM_INHIBIT); } 443 void assertShared() { flags.set(SHARED); } 444 bool sharedAsserted() { return flags.isSet(SHARED); } 445 446 // Special control flags 447 void setExpressSnoop() { flags.set(EXPRESS_SNOOP); } 448 bool isExpressSnoop() { return flags.isSet(EXPRESS_SNOOP); } 449 void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); } 450 void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); } 451 bool isSupplyExclusive() { return flags.isSet(SUPPLY_EXCLUSIVE); } 452 void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); } 453 bool suppressFuncError() { return flags.isSet(SUPPRESS_FUNC_ERROR); } 454 455 // Network error conditions... encapsulate them as methods since 456 // their encoding keeps changing (from result field to command 457 // field, etc.) 458 void 459 setNacked() 460 { 461 assert(isResponse()); 462 cmd = MemCmd::NetworkNackError; 463 } 464 465 void 466 setBadAddress() 467 { 468 assert(isResponse()); 469 cmd = MemCmd::BadAddressError; 470 } 471 472 bool wasNacked() const { return cmd == MemCmd::NetworkNackError; } 473 bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; } 474 void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; } 475 476 bool isSrcValid() { return flags.isSet(VALID_SRC); } 477 /// Accessor function to get the source index of the packet. 478 NodeID getSrc() const { assert(flags.isSet(VALID_SRC)); return src; } 479 /// Accessor function to set the source index of the packet. 480 void setSrc(NodeID _src) { src = _src; flags.set(VALID_SRC); } 481 /// Reset source field, e.g. to retransmit packet on different bus. 482 void clearSrc() { flags.clear(VALID_SRC); } 483 484 bool isDestValid() { return flags.isSet(VALID_DST); } 485 /// Accessor function for the destination index of the packet. 486 NodeID getDest() const { assert(flags.isSet(VALID_DST)); return dest; } 487 /// Accessor function to set the destination index of the packet. 488 void setDest(NodeID _dest) { dest = _dest; flags.set(VALID_DST); } 489 /// Reset destination field, e.g. to turn a response into a request again. 490 void clearDest() { flags.clear(VALID_DST); } 491 492 Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; } 493 unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; } 494 Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); } 495 496 /** 497 * It has been determined that the SC packet should successfully update 498 * memory. Therefore, convert this SC packet to a normal write. 499 */ 500 void 501 convertScToWrite() 502 { 503 assert(isLLSC()); 504 assert(isWrite()); 505 cmd = MemCmd::WriteReq; 506 } 507 508 /** 509 * When ruby is in use, Ruby will monitor the cache line and thus M5 510 * phys memory should treat LL ops as normal reads. 511 */ 512 void 513 convertLlToRead() 514 { 515 assert(isLLSC()); 516 assert(isRead()); 517 cmd = MemCmd::ReadReq; 518 } 519 520 /** 521 * Constructor. Note that a Request object must be constructed 522 * first, but the Requests's physical address and size fields need 523 * not be valid. The command and destination addresses must be 524 * supplied. 525 */ 526 Packet(Request *_req, MemCmd _cmd) 527 : cmd(_cmd), req(_req), data(NULL), 528 bytesValidStart(0), bytesValidEnd(0), 529 time(curTick()), senderState(NULL) 530 { 531 if (req->hasPaddr()) { 532 addr = req->getPaddr(); 533 flags.set(VALID_ADDR); 534 } 535 if (req->hasSize()) { 536 size = req->getSize(); 537 flags.set(VALID_SIZE); 538 } 539 } 540 541 /** 542 * Alternate constructor if you are trying to create a packet with 543 * a request that is for a whole block, not the address from the 544 * req. this allows for overriding the size/addr of the req. 545 */ 546 Packet(Request *_req, MemCmd _cmd, int _blkSize) 547 : cmd(_cmd), req(_req), data(NULL), 548 bytesValidStart(0), bytesValidEnd(0), 549 time(curTick()), senderState(NULL) 550 { 551 if (req->hasPaddr()) { 552 addr = req->getPaddr() & ~(_blkSize - 1); 553 flags.set(VALID_ADDR); 554 } 555 size = _blkSize; 556 flags.set(VALID_SIZE); 557 } 558 559 /** 560 * Alternate constructor for copying a packet. Copy all fields 561 * *except* if the original packet's data was dynamic, don't copy 562 * that, as we can't guarantee that the new packet's lifetime is 563 * less than that of the original packet. In this case the new 564 * packet should allocate its own data. 565 */ 566 Packet(Packet *pkt, bool clearFlags = false) 567 : cmd(pkt->cmd), req(pkt->req), 568 data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL), 569 addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest), 570 bytesValidStart(pkt->bytesValidStart), bytesValidEnd(pkt->bytesValidEnd), 571 time(curTick()), senderState(pkt->senderState) 572 { 573 if (!clearFlags) 574 flags.set(pkt->flags & COPY_FLAGS); 575 576 flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE|VALID_SRC|VALID_DST)); 577 flags.set(pkt->flags & STATIC_DATA); 578 579 } 580 581 /** 582 * clean up packet variables 583 */ 584 ~Packet() 585 { 586 // If this is a request packet for which there's no response, 587 // delete the request object here, since the requester will 588 // never get the chance. 589 if (req && isRequest() && !needsResponse()) 590 delete req; 591 deleteData(); 592 } 593 594 /** 595 * Reinitialize packet address and size from the associated 596 * Request object, and reset other fields that may have been 597 * modified by a previous transaction. Typically called when a 598 * statically allocated Request/Packet pair is reused for multiple 599 * transactions. 600 */ 601 void 602 reinitFromRequest() 603 { 604 assert(req->hasPaddr()); 605 flags = 0; 606 addr = req->getPaddr(); 607 size = req->getSize(); 608 time = req->time(); 609 610 flags.set(VALID_ADDR|VALID_SIZE); 611 deleteData(); 612 } 613 614 /** 615 * Take a request packet and modify it in place to be suitable for 616 * returning as a response to that request. The source and 617 * destination fields are *not* modified, as is appropriate for 618 * atomic accesses. 619 */ 620 void 621 makeResponse() 622 { 623 assert(needsResponse()); 624 assert(isRequest()); 625 origCmd = cmd; 626 cmd = cmd.responseCommand(); 627 628 // responses are never express, even if the snoop that 629 // triggered them was 630 flags.clear(EXPRESS_SNOOP); 631 632 dest = src; 633 flags.set(VALID_DST, flags.isSet(VALID_SRC)); 634 flags.clear(VALID_SRC); 635 } 636 637 void 638 makeAtomicResponse() 639 { 640 makeResponse(); 641 } 642 643 void 644 makeTimingResponse() 645 { 646 makeResponse(); 647 } 648 649 void 650 setFunctionalResponseStatus(bool success) 651 { 652 if (!success) { 653 if (isWrite()) { 654 cmd = MemCmd::FunctionalWriteError; 655 } else { 656 cmd = MemCmd::FunctionalReadError; 657 } 658 } 659 } 660 661 /** 662 * Take a request packet that has been returned as NACKED and 663 * modify it so that it can be sent out again. Only packets that 664 * need a response can be NACKED, so verify that that is true. 665 */ 666 void 667 reinitNacked() 668 { 669 assert(wasNacked()); 670 cmd = origCmd; 671 assert(needsResponse()); 672 clearDest(); 673 } 674 675 void 676 setSize(unsigned size) 677 { 678 assert(!flags.isSet(VALID_SIZE)); 679 680 this->size = size; 681 flags.set(VALID_SIZE); 682 } 683 684 685 /** 686 * Set the data pointer to the following value that should not be 687 * freed. 688 */ 689 template <typename T> 690 void 691 dataStatic(T *p) 692 { 693 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); 694 data = (PacketDataPtr)p; 695 flags.set(STATIC_DATA); 696 } 697 698 /** 699 * Set the data pointer to a value that should have delete [] 700 * called on it. 701 */ 702 template <typename T> 703 void 704 dataDynamicArray(T *p) 705 { 706 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); 707 data = (PacketDataPtr)p; 708 flags.set(DYNAMIC_DATA|ARRAY_DATA); 709 } 710 711 /** 712 * set the data pointer to a value that should have delete called 713 * on it. 714 */ 715 template <typename T> 716 void 717 dataDynamic(T *p) 718 { 719 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); 720 data = (PacketDataPtr)p; 721 flags.set(DYNAMIC_DATA); 722 } 723 724 /** 725 * get a pointer to the data ptr. 726 */ 727 template <typename T> 728 T* 729 getPtr(bool null_ok = false) 730 { 731 assert(null_ok || flags.isSet(STATIC_DATA|DYNAMIC_DATA)); 732 return (T*)data; 733 } 734 735 /** 736 * return the value of what is pointed to in the packet. 737 */ 738 template <typename T> 739 T get(); 740 741 /** 742 * set the value in the data pointer to v. 743 */ 744 template <typename T> 745 void set(T v); 746 747 /** 748 * Copy data into the packet from the provided pointer. 749 */ 750 void 751 setData(uint8_t *p) 752 { 753 if (p != getPtr<uint8_t>()) 754 std::memcpy(getPtr<uint8_t>(), p, getSize()); 755 } 756 757 /** 758 * Copy data into the packet from the provided block pointer, 759 * which is aligned to the given block size. 760 */ 761 void 762 setDataFromBlock(uint8_t *blk_data, int blkSize) 763 { 764 setData(blk_data + getOffset(blkSize)); 765 } 766 767 /** 768 * Copy data from the packet to the provided block pointer, which 769 * is aligned to the given block size. 770 */ 771 void 772 writeData(uint8_t *p) 773 { 774 std::memcpy(p, getPtr<uint8_t>(), getSize()); 775 } 776 777 /** 778 * Copy data from the packet to the memory at the provided pointer. 779 */ 780 void 781 writeDataToBlock(uint8_t *blk_data, int blkSize) 782 { 783 writeData(blk_data + getOffset(blkSize)); 784 } 785 786 /** 787 * delete the data pointed to in the data pointer. Ok to call to 788 * matter how data was allocted. 789 */ 790 void 791 deleteData() 792 { 793 if (flags.isSet(ARRAY_DATA)) 794 delete [] data; 795 else if (flags.isSet(DYNAMIC_DATA)) 796 delete data; 797 798 flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA); 799 data = NULL; 800 } 801 802 /** If there isn't data in the packet, allocate some. */ 803 void 804 allocate() 805 { 806 if (data) { 807 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); 808 return; 809 } 810 811 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 812 flags.set(DYNAMIC_DATA|ARRAY_DATA); 813 data = new uint8_t[getSize()]; 814 } 815 816 /** 817 * Check a functional request against a memory value represented 818 * by a base/size pair and an associated data array. If the 819 * functional request is a read, it may be satisfied by the memory 820 * value. If the functional request is a write, it may update the 821 * memory value. 822 */ 823 bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data); 824 825 /** 826 * Check a functional request against a memory value stored in 827 * another packet (i.e. an in-transit request or response). 828 */ 829 bool 830 checkFunctional(PacketPtr other) 831 { 832 uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL; 833 return checkFunctional(other, other->getAddr(), other->getSize(), 834 data); 835 } 836 837 /** 838 * Push label for PrintReq (safe to call unconditionally). 839 */ 840 void 841 pushLabel(const std::string &lbl) 842 { 843 if (isPrint()) 844 safe_cast<PrintReqState*>(senderState)->pushLabel(lbl); 845 } 846 847 /** 848 * Pop label for PrintReq (safe to call unconditionally). 849 */ 850 void 851 popLabel() 852 { 853 if (isPrint()) 854 safe_cast<PrintReqState*>(senderState)->popLabel(); 855 } 856 857 void print(std::ostream &o, int verbosity = 0, 858 const std::string &prefix = "") const; 859}; 860 861#endif //__MEM_PACKET_HH 862