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