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