packet.hh revision 11600
1/* 2 * Copyright (c) 2012-2016 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,2015 Advanced Micro Devices, Inc. 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Ron Dreslinski 42 * Steve Reinhardt 43 * Ali Saidi 44 * Andreas Hansson 45 */ 46 47/** 48 * @file 49 * Declaration of the Packet class. 50 */ 51 52#ifndef __MEM_PACKET_HH__ 53#define __MEM_PACKET_HH__ 54 55#include <bitset> 56#include <cassert> 57#include <list> 58 59#include "base/cast.hh" 60#include "base/compiler.hh" 61#include "base/flags.hh" 62#include "base/misc.hh" 63#include "base/printable.hh" 64#include "base/types.hh" 65#include "mem/request.hh" 66#include "sim/core.hh" 67 68class Packet; 69typedef Packet *PacketPtr; 70typedef uint8_t* PacketDataPtr; 71typedef std::list<PacketPtr> PacketList; 72 73class MemCmd 74{ 75 friend class Packet; 76 77 public: 78 /** 79 * List of all commands associated with a packet. 80 */ 81 enum Command 82 { 83 InvalidCmd, 84 ReadReq, 85 ReadResp, 86 ReadRespWithInvalidate, 87 WriteReq, 88 WriteResp, 89 WritebackDirty, 90 WritebackClean, 91 CleanEvict, 92 SoftPFReq, 93 HardPFReq, 94 SoftPFResp, 95 HardPFResp, 96 WriteLineReq, 97 UpgradeReq, 98 SCUpgradeReq, // Special "weak" upgrade for StoreCond 99 UpgradeResp, 100 SCUpgradeFailReq, // Failed SCUpgradeReq in MSHR (never sent) 101 UpgradeFailResp, // Valid for SCUpgradeReq only 102 ReadExReq, 103 ReadExResp, 104 ReadCleanReq, 105 ReadSharedReq, 106 LoadLockedReq, 107 StoreCondReq, 108 StoreCondFailReq, // Failed StoreCondReq in MSHR (never sent) 109 StoreCondResp, 110 SwapReq, 111 SwapResp, 112 MessageReq, 113 MessageResp, 114 MemFenceReq, 115 MemFenceResp, 116 // Error responses 117 // @TODO these should be classified as responses rather than 118 // requests; coding them as requests initially for backwards 119 // compatibility 120 InvalidDestError, // packet dest field invalid 121 BadAddressError, // memory address invalid 122 FunctionalReadError, // unable to fulfill functional read 123 FunctionalWriteError, // unable to fulfill functional write 124 // Fake simulator-only commands 125 PrintReq, // Print state matching address 126 FlushReq, //request for a cache flush 127 InvalidateReq, // request for address to be invalidated 128 InvalidateResp, 129 NUM_MEM_CMDS 130 }; 131 132 private: 133 /** 134 * List of command attributes. 135 */ 136 enum Attribute 137 { 138 IsRead, //!< Data flows from responder to requester 139 IsWrite, //!< Data flows from requester to responder 140 IsUpgrade, 141 IsInvalidate, 142 NeedsWritable, //!< Requires writable copy to complete in-cache 143 IsRequest, //!< Issued by requester 144 IsResponse, //!< Issue by responder 145 NeedsResponse, //!< Requester needs response from target 146 IsEviction, 147 IsSWPrefetch, 148 IsHWPrefetch, 149 IsLlsc, //!< Alpha/MIPS LL or SC access 150 HasData, //!< There is an associated payload 151 IsError, //!< Error response 152 IsPrint, //!< Print state matching address (for debugging) 153 IsFlush, //!< Flush the address from caches 154 FromCache, //!< Request originated from a caching agent 155 NUM_COMMAND_ATTRIBUTES 156 }; 157 158 /** 159 * Structure that defines attributes and other data associated 160 * with a Command. 161 */ 162 struct CommandInfo 163 { 164 /// Set of attribute flags. 165 const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes; 166 /// Corresponding response for requests; InvalidCmd if no 167 /// response is applicable. 168 const Command response; 169 /// String representation (for printing) 170 const std::string str; 171 }; 172 173 /// Array to map Command enum to associated info. 174 static const CommandInfo commandInfo[]; 175 176 private: 177 178 Command cmd; 179 180 bool 181 testCmdAttrib(MemCmd::Attribute attrib) const 182 { 183 return commandInfo[cmd].attributes[attrib] != 0; 184 } 185 186 public: 187 188 bool isRead() const { return testCmdAttrib(IsRead); } 189 bool isWrite() const { return testCmdAttrib(IsWrite); } 190 bool isUpgrade() const { return testCmdAttrib(IsUpgrade); } 191 bool isRequest() const { return testCmdAttrib(IsRequest); } 192 bool isResponse() const { return testCmdAttrib(IsResponse); } 193 bool needsWritable() const { return testCmdAttrib(NeedsWritable); } 194 bool needsResponse() const { return testCmdAttrib(NeedsResponse); } 195 bool isInvalidate() const { return testCmdAttrib(IsInvalidate); } 196 bool isEviction() const { return testCmdAttrib(IsEviction); } 197 bool fromCache() const { return testCmdAttrib(FromCache); } 198 199 /** 200 * A writeback is an eviction that carries data. 201 */ 202 bool isWriteback() const { return testCmdAttrib(IsEviction) && 203 testCmdAttrib(HasData); } 204 205 /** 206 * Check if this particular packet type carries payload data. Note 207 * that this does not reflect if the data pointer of the packet is 208 * valid or not. 209 */ 210 bool hasData() const { return testCmdAttrib(HasData); } 211 bool isLLSC() const { return testCmdAttrib(IsLlsc); } 212 bool isSWPrefetch() const { return testCmdAttrib(IsSWPrefetch); } 213 bool isHWPrefetch() const { return testCmdAttrib(IsHWPrefetch); } 214 bool isPrefetch() const { return testCmdAttrib(IsSWPrefetch) || 215 testCmdAttrib(IsHWPrefetch); } 216 bool isError() const { return testCmdAttrib(IsError); } 217 bool isPrint() const { return testCmdAttrib(IsPrint); } 218 bool isFlush() const { return testCmdAttrib(IsFlush); } 219 220 Command 221 responseCommand() const 222 { 223 return commandInfo[cmd].response; 224 } 225 226 /// Return the string to a cmd given by idx. 227 const std::string &toString() const { return commandInfo[cmd].str; } 228 int toInt() const { return (int)cmd; } 229 230 MemCmd(Command _cmd) : cmd(_cmd) { } 231 MemCmd(int _cmd) : cmd((Command)_cmd) { } 232 MemCmd() : cmd(InvalidCmd) { } 233 234 bool operator==(MemCmd c2) const { return (cmd == c2.cmd); } 235 bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); } 236}; 237 238/** 239 * A Packet is used to encapsulate a transfer between two objects in 240 * the memory system (e.g., the L1 and L2 cache). (In contrast, a 241 * single Request travels all the way from the requester to the 242 * ultimate destination and back, possibly being conveyed by several 243 * different Packets along the way.) 244 */ 245class Packet : public Printable 246{ 247 public: 248 typedef uint32_t FlagsType; 249 typedef ::Flags<FlagsType> Flags; 250 251 private: 252 253 enum : FlagsType { 254 // Flags to transfer across when copying a packet 255 COPY_FLAGS = 0x0000000F, 256 257 // Does this packet have sharers (which means it should not be 258 // considered writable) or not. See setHasSharers below. 259 HAS_SHARERS = 0x00000001, 260 261 // Special control flags 262 /// Special timing-mode atomic snoop for multi-level coherence. 263 EXPRESS_SNOOP = 0x00000002, 264 265 /// Allow a responding cache to inform the cache hierarchy 266 /// that it had a writable copy before responding. See 267 /// setResponderHadWritable below. 268 RESPONDER_HAD_WRITABLE = 0x00000004, 269 270 // Snoop co-ordination flag to indicate that a cache is 271 // responding to a snoop. See setCacheResponding below. 272 CACHE_RESPONDING = 0x00000008, 273 274 /// Are the 'addr' and 'size' fields valid? 275 VALID_ADDR = 0x00000100, 276 VALID_SIZE = 0x00000200, 277 278 /// Is the data pointer set to a value that shouldn't be freed 279 /// when the packet is destroyed? 280 STATIC_DATA = 0x00001000, 281 /// The data pointer points to a value that should be freed when 282 /// the packet is destroyed. The pointer is assumed to be pointing 283 /// to an array, and delete [] is consequently called 284 DYNAMIC_DATA = 0x00002000, 285 286 /// suppress the error if this packet encounters a functional 287 /// access failure. 288 SUPPRESS_FUNC_ERROR = 0x00008000, 289 290 // Signal block present to squash prefetch and cache evict packets 291 // through express snoop flag 292 BLOCK_CACHED = 0x00010000 293 }; 294 295 Flags flags; 296 297 public: 298 typedef MemCmd::Command Command; 299 300 /// The command field of the packet. 301 MemCmd cmd; 302 303 /// A pointer to the original request. 304 const RequestPtr req; 305 306 private: 307 /** 308 * A pointer to the data being transfered. It can be differnt 309 * sizes at each level of the heirarchy so it belongs in the 310 * packet, not request. This may or may not be populated when a 311 * responder recieves the packet. If not populated it memory should 312 * be allocated. 313 */ 314 PacketDataPtr data; 315 316 /// The address of the request. This address could be virtual or 317 /// physical, depending on the system configuration. 318 Addr addr; 319 320 /// True if the request targets the secure memory space. 321 bool _isSecure; 322 323 /// The size of the request or transfer. 324 unsigned size; 325 326 /** 327 * Track the bytes found that satisfy a functional read. 328 */ 329 std::vector<bool> bytesValid; 330 331 public: 332 333 /** 334 * The extra delay from seeing the packet until the header is 335 * transmitted. This delay is used to communicate the crossbar 336 * forwarding latency to the neighbouring object (e.g. a cache) 337 * that actually makes the packet wait. As the delay is relative, 338 * a 32-bit unsigned should be sufficient. 339 */ 340 uint32_t headerDelay; 341 342 /** 343 * Keep track of the extra delay incurred by snooping upwards 344 * before sending a request down the memory system. This is used 345 * by the coherent crossbar to account for the additional request 346 * delay. 347 */ 348 uint32_t snoopDelay; 349 350 /** 351 * The extra pipelining delay from seeing the packet until the end of 352 * payload is transmitted by the component that provided it (if 353 * any). This includes the header delay. Similar to the header 354 * delay, this is used to make up for the fact that the 355 * crossbar does not make the packet wait. As the delay is 356 * relative, a 32-bit unsigned should be sufficient. 357 */ 358 uint32_t payloadDelay; 359 360 /** 361 * A virtual base opaque structure used to hold state associated 362 * with the packet (e.g., an MSHR), specific to a MemObject that 363 * sees the packet. A pointer to this state is returned in the 364 * packet's response so that the MemObject in question can quickly 365 * look up the state needed to process it. A specific subclass 366 * would be derived from this to carry state specific to a 367 * particular sending device. 368 * 369 * As multiple MemObjects may add their SenderState throughout the 370 * memory system, the SenderStates create a stack, where a 371 * MemObject can add a new Senderstate, as long as the 372 * predecessing SenderState is restored when the response comes 373 * back. For this reason, the predecessor should always be 374 * populated with the current SenderState of a packet before 375 * modifying the senderState field in the request packet. 376 */ 377 struct SenderState 378 { 379 SenderState* predecessor; 380 SenderState() : predecessor(NULL) {} 381 virtual ~SenderState() {} 382 }; 383 384 /** 385 * Object used to maintain state of a PrintReq. The senderState 386 * field of a PrintReq should always be of this type. 387 */ 388 class PrintReqState : public SenderState 389 { 390 private: 391 /** 392 * An entry in the label stack. 393 */ 394 struct LabelStackEntry 395 { 396 const std::string label; 397 std::string *prefix; 398 bool labelPrinted; 399 LabelStackEntry(const std::string &_label, std::string *_prefix); 400 }; 401 402 typedef std::list<LabelStackEntry> LabelStack; 403 LabelStack labelStack; 404 405 std::string *curPrefixPtr; 406 407 public: 408 std::ostream &os; 409 const int verbosity; 410 411 PrintReqState(std::ostream &os, int verbosity = 0); 412 ~PrintReqState(); 413 414 /** 415 * Returns the current line prefix. 416 */ 417 const std::string &curPrefix() { return *curPrefixPtr; } 418 419 /** 420 * Push a label onto the label stack, and prepend the given 421 * prefix string onto the current prefix. Labels will only be 422 * printed if an object within the label's scope is printed. 423 */ 424 void pushLabel(const std::string &lbl, 425 const std::string &prefix = " "); 426 427 /** 428 * Pop a label off the label stack. 429 */ 430 void popLabel(); 431 432 /** 433 * Print all of the pending unprinted labels on the 434 * stack. Called by printObj(), so normally not called by 435 * users unless bypassing printObj(). 436 */ 437 void printLabels(); 438 439 /** 440 * Print a Printable object to os, because it matched the 441 * address on a PrintReq. 442 */ 443 void printObj(Printable *obj); 444 }; 445 446 /** 447 * This packet's sender state. Devices should use dynamic_cast<> 448 * to cast to the state appropriate to the sender. The intent of 449 * this variable is to allow a device to attach extra information 450 * to a request. A response packet must return the sender state 451 * that was attached to the original request (even if a new packet 452 * is created). 453 */ 454 SenderState *senderState; 455 456 /** 457 * Push a new sender state to the packet and make the current 458 * sender state the predecessor of the new one. This should be 459 * prefered over direct manipulation of the senderState member 460 * variable. 461 * 462 * @param sender_state SenderState to push at the top of the stack 463 */ 464 void pushSenderState(SenderState *sender_state); 465 466 /** 467 * Pop the top of the state stack and return a pointer to it. This 468 * assumes the current sender state is not NULL. This should be 469 * preferred over direct manipulation of the senderState member 470 * variable. 471 * 472 * @return The current top of the stack 473 */ 474 SenderState *popSenderState(); 475 476 /** 477 * Go through the sender state stack and return the first instance 478 * that is of type T (as determined by a dynamic_cast). If there 479 * is no sender state of type T, NULL is returned. 480 * 481 * @return The topmost state of type T 482 */ 483 template <typename T> 484 T * findNextSenderState() const 485 { 486 T *t = NULL; 487 SenderState* sender_state = senderState; 488 while (t == NULL && sender_state != NULL) { 489 t = dynamic_cast<T*>(sender_state); 490 sender_state = sender_state->predecessor; 491 } 492 return t; 493 } 494 495 /// Return the string name of the cmd field (for debugging and 496 /// tracing). 497 const std::string &cmdString() const { return cmd.toString(); } 498 499 /// Return the index of this command. 500 inline int cmdToIndex() const { return cmd.toInt(); } 501 502 bool isRead() const { return cmd.isRead(); } 503 bool isWrite() const { return cmd.isWrite(); } 504 bool isUpgrade() const { return cmd.isUpgrade(); } 505 bool isRequest() const { return cmd.isRequest(); } 506 bool isResponse() const { return cmd.isResponse(); } 507 bool needsWritable() const 508 { 509 // we should never check if a response needsWritable, the 510 // request has this flag, and for a response we should rather 511 // look at the hasSharers flag (if not set, the response is to 512 // be considered writable) 513 assert(isRequest()); 514 return cmd.needsWritable(); 515 } 516 bool needsResponse() const { return cmd.needsResponse(); } 517 bool isInvalidate() const { return cmd.isInvalidate(); } 518 bool isEviction() const { return cmd.isEviction(); } 519 bool fromCache() const { return cmd.fromCache(); } 520 bool isWriteback() const { return cmd.isWriteback(); } 521 bool hasData() const { return cmd.hasData(); } 522 bool hasRespData() const 523 { 524 MemCmd resp_cmd = cmd.responseCommand(); 525 return resp_cmd.hasData(); 526 } 527 bool isLLSC() const { return cmd.isLLSC(); } 528 bool isError() const { return cmd.isError(); } 529 bool isPrint() const { return cmd.isPrint(); } 530 bool isFlush() const { return cmd.isFlush(); } 531 532 //@{ 533 /// Snoop flags 534 /** 535 * Set the cacheResponding flag. This is used by the caches to 536 * signal another cache that they are responding to a request. A 537 * cache will only respond to snoops if it has the line in either 538 * Modified or Owned state. Note that on snoop hits we always pass 539 * the line as Modified and never Owned. In the case of an Owned 540 * line we proceed to invalidate all other copies. 541 * 542 * On a cache fill (see Cache::handleFill), we check hasSharers 543 * first, ignoring the cacheResponding flag if hasSharers is set. 544 * A line is consequently allocated as: 545 * 546 * hasSharers cacheResponding state 547 * true false Shared 548 * true true Shared 549 * false false Exclusive 550 * false true Modified 551 */ 552 void setCacheResponding() 553 { 554 assert(isRequest()); 555 assert(!flags.isSet(CACHE_RESPONDING)); 556 flags.set(CACHE_RESPONDING); 557 } 558 bool cacheResponding() const { return flags.isSet(CACHE_RESPONDING); } 559 /** 560 * On fills, the hasSharers flag is used by the caches in 561 * combination with the cacheResponding flag, as clarified 562 * above. If the hasSharers flag is not set, the packet is passing 563 * writable. Thus, a response from a memory passes the line as 564 * writable by default. 565 * 566 * The hasSharers flag is also used by upstream caches to inform a 567 * downstream cache that they have the block (by calling 568 * setHasSharers on snoop request packets that hit in upstream 569 * cachs tags or MSHRs). If the snoop packet has sharers, a 570 * downstream cache is prevented from passing a dirty line upwards 571 * if it was not explicitly asked for a writable copy. See 572 * Cache::satisfyCpuSideRequest. 573 * 574 * The hasSharers flag is also used on writebacks, in 575 * combination with the WritbackClean or WritebackDirty commands, 576 * to allocate the block downstream either as: 577 * 578 * command hasSharers state 579 * WritebackDirty false Modified 580 * WritebackDirty true Owned 581 * WritebackClean false Exclusive 582 * WritebackClean true Shared 583 */ 584 void setHasSharers() { flags.set(HAS_SHARERS); } 585 bool hasSharers() const { return flags.isSet(HAS_SHARERS); } 586 //@} 587 588 /** 589 * The express snoop flag is used for two purposes. Firstly, it is 590 * used to bypass flow control for normal (non-snoop) requests 591 * going downstream in the memory system. In cases where a cache 592 * is responding to a snoop from another cache (it had a dirty 593 * line), but the line is not writable (and there are possibly 594 * other copies), the express snoop flag is set by the downstream 595 * cache to invalidate all other copies in zero time. Secondly, 596 * the express snoop flag is also set to be able to distinguish 597 * snoop packets that came from a downstream cache, rather than 598 * snoop packets from neighbouring caches. 599 */ 600 void setExpressSnoop() { flags.set(EXPRESS_SNOOP); } 601 bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); } 602 603 /** 604 * On responding to a snoop request (which only happens for 605 * Modified or Owned lines), make sure that we can transform an 606 * Owned response to a Modified one. If this flag is not set, the 607 * responding cache had the line in the Owned state, and there are 608 * possibly other Shared copies in the memory system. A downstream 609 * cache helps in orchestrating the invalidation of these copies 610 * by sending out the appropriate express snoops. 611 */ 612 void setResponderHadWritable() 613 { 614 assert(cacheResponding()); 615 flags.set(RESPONDER_HAD_WRITABLE); 616 } 617 bool responderHadWritable() const 618 { return flags.isSet(RESPONDER_HAD_WRITABLE); } 619 620 void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); } 621 bool suppressFuncError() const { return flags.isSet(SUPPRESS_FUNC_ERROR); } 622 void setBlockCached() { flags.set(BLOCK_CACHED); } 623 bool isBlockCached() const { return flags.isSet(BLOCK_CACHED); } 624 void clearBlockCached() { flags.clear(BLOCK_CACHED); } 625 626 // Network error conditions... encapsulate them as methods since 627 // their encoding keeps changing (from result field to command 628 // field, etc.) 629 void 630 setBadAddress() 631 { 632 assert(isResponse()); 633 cmd = MemCmd::BadAddressError; 634 } 635 636 void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; } 637 638 Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; } 639 /** 640 * Update the address of this packet mid-transaction. This is used 641 * by the address mapper to change an already set address to a new 642 * one based on the system configuration. It is intended to remap 643 * an existing address, so it asserts that the current address is 644 * valid. 645 */ 646 void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; } 647 648 unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; } 649 650 Addr getOffset(unsigned int blk_size) const 651 { 652 return getAddr() & Addr(blk_size - 1); 653 } 654 655 Addr getBlockAddr(unsigned int blk_size) const 656 { 657 return getAddr() & ~(Addr(blk_size - 1)); 658 } 659 660 bool isSecure() const 661 { 662 assert(flags.isSet(VALID_ADDR)); 663 return _isSecure; 664 } 665 666 /** 667 * Accessor function to atomic op. 668 */ 669 AtomicOpFunctor *getAtomicOp() const { return req->getAtomicOpFunctor(); } 670 bool isAtomicOp() const { return req->isAtomic(); } 671 672 /** 673 * It has been determined that the SC packet should successfully update 674 * memory. Therefore, convert this SC packet to a normal write. 675 */ 676 void 677 convertScToWrite() 678 { 679 assert(isLLSC()); 680 assert(isWrite()); 681 cmd = MemCmd::WriteReq; 682 } 683 684 /** 685 * When ruby is in use, Ruby will monitor the cache line and the 686 * phys memory should treat LL ops as normal reads. 687 */ 688 void 689 convertLlToRead() 690 { 691 assert(isLLSC()); 692 assert(isRead()); 693 cmd = MemCmd::ReadReq; 694 } 695 696 /** 697 * Constructor. Note that a Request object must be constructed 698 * first, but the Requests's physical address and size fields need 699 * not be valid. The command must be supplied. 700 */ 701 Packet(const RequestPtr _req, MemCmd _cmd) 702 : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false), 703 size(0), headerDelay(0), snoopDelay(0), payloadDelay(0), 704 senderState(NULL) 705 { 706 if (req->hasPaddr()) { 707 addr = req->getPaddr(); 708 flags.set(VALID_ADDR); 709 _isSecure = req->isSecure(); 710 } 711 if (req->hasSize()) { 712 size = req->getSize(); 713 flags.set(VALID_SIZE); 714 } 715 } 716 717 /** 718 * Alternate constructor if you are trying to create a packet with 719 * a request that is for a whole block, not the address from the 720 * req. this allows for overriding the size/addr of the req. 721 */ 722 Packet(const RequestPtr _req, MemCmd _cmd, int _blkSize) 723 : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false), 724 headerDelay(0), snoopDelay(0), payloadDelay(0), 725 senderState(NULL) 726 { 727 if (req->hasPaddr()) { 728 addr = req->getPaddr() & ~(_blkSize - 1); 729 flags.set(VALID_ADDR); 730 _isSecure = req->isSecure(); 731 } 732 size = _blkSize; 733 flags.set(VALID_SIZE); 734 } 735 736 /** 737 * Alternate constructor for copying a packet. Copy all fields 738 * *except* if the original packet's data was dynamic, don't copy 739 * that, as we can't guarantee that the new packet's lifetime is 740 * less than that of the original packet. In this case the new 741 * packet should allocate its own data. 742 */ 743 Packet(const PacketPtr pkt, bool clear_flags, bool alloc_data) 744 : cmd(pkt->cmd), req(pkt->req), 745 data(nullptr), 746 addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size), 747 bytesValid(pkt->bytesValid), 748 headerDelay(pkt->headerDelay), 749 snoopDelay(0), 750 payloadDelay(pkt->payloadDelay), 751 senderState(pkt->senderState) 752 { 753 if (!clear_flags) 754 flags.set(pkt->flags & COPY_FLAGS); 755 756 flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE)); 757 758 // should we allocate space for data, or not, the express 759 // snoops do not need to carry any data as they only serve to 760 // co-ordinate state changes 761 if (alloc_data) { 762 // even if asked to allocate data, if the original packet 763 // holds static data, then the sender will not be doing 764 // any memcpy on receiving the response, thus we simply 765 // carry the pointer forward 766 if (pkt->flags.isSet(STATIC_DATA)) { 767 data = pkt->data; 768 flags.set(STATIC_DATA); 769 } else { 770 allocate(); 771 } 772 } 773 } 774 775 /** 776 * Generate the appropriate read MemCmd based on the Request flags. 777 */ 778 static MemCmd 779 makeReadCmd(const RequestPtr req) 780 { 781 if (req->isLLSC()) 782 return MemCmd::LoadLockedReq; 783 else if (req->isPrefetch()) 784 return MemCmd::SoftPFReq; 785 else 786 return MemCmd::ReadReq; 787 } 788 789 /** 790 * Generate the appropriate write MemCmd based on the Request flags. 791 */ 792 static MemCmd 793 makeWriteCmd(const RequestPtr req) 794 { 795 if (req->isLLSC()) 796 return MemCmd::StoreCondReq; 797 else if (req->isSwap()) 798 return MemCmd::SwapReq; 799 else 800 return MemCmd::WriteReq; 801 } 802 803 /** 804 * Constructor-like methods that return Packets based on Request objects. 805 * Fine-tune the MemCmd type if it's not a vanilla read or write. 806 */ 807 static PacketPtr 808 createRead(const RequestPtr req) 809 { 810 return new Packet(req, makeReadCmd(req)); 811 } 812 813 static PacketPtr 814 createWrite(const RequestPtr req) 815 { 816 return new Packet(req, makeWriteCmd(req)); 817 } 818 819 /** 820 * clean up packet variables 821 */ 822 ~Packet() 823 { 824 // Delete the request object if this is a request packet which 825 // does not need a response, because the requester will not get 826 // a chance. If the request packet needs a response then the 827 // request will be deleted on receipt of the response 828 // packet. We also make sure to never delete the request for 829 // express snoops, even for cases when responses are not 830 // needed (CleanEvict and Writeback), since the snoop packet 831 // re-uses the same request. 832 if (req && isRequest() && !needsResponse() && 833 !isExpressSnoop()) { 834 delete req; 835 } 836 deleteData(); 837 } 838 839 /** 840 * Take a request packet and modify it in place to be suitable for 841 * returning as a response to that request. 842 */ 843 void 844 makeResponse() 845 { 846 assert(needsResponse()); 847 assert(isRequest()); 848 cmd = cmd.responseCommand(); 849 850 // responses are never express, even if the snoop that 851 // triggered them was 852 flags.clear(EXPRESS_SNOOP); 853 } 854 855 void 856 makeAtomicResponse() 857 { 858 makeResponse(); 859 } 860 861 void 862 makeTimingResponse() 863 { 864 makeResponse(); 865 } 866 867 void 868 setFunctionalResponseStatus(bool success) 869 { 870 if (!success) { 871 if (isWrite()) { 872 cmd = MemCmd::FunctionalWriteError; 873 } else { 874 cmd = MemCmd::FunctionalReadError; 875 } 876 } 877 } 878 879 void 880 setSize(unsigned size) 881 { 882 assert(!flags.isSet(VALID_SIZE)); 883 884 this->size = size; 885 flags.set(VALID_SIZE); 886 } 887 888 889 public: 890 /** 891 * @{ 892 * @name Data accessor mehtods 893 */ 894 895 /** 896 * Set the data pointer to the following value that should not be 897 * freed. Static data allows us to do a single memcpy even if 898 * multiple packets are required to get from source to destination 899 * and back. In essence the pointer is set calling dataStatic on 900 * the original packet, and whenever this packet is copied and 901 * forwarded the same pointer is passed on. When a packet 902 * eventually reaches the destination holding the data, it is 903 * copied once into the location originally set. On the way back 904 * to the source, no copies are necessary. 905 */ 906 template <typename T> 907 void 908 dataStatic(T *p) 909 { 910 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 911 data = (PacketDataPtr)p; 912 flags.set(STATIC_DATA); 913 } 914 915 /** 916 * Set the data pointer to the following value that should not be 917 * freed. This version of the function allows the pointer passed 918 * to us to be const. To avoid issues down the line we cast the 919 * constness away, the alternative would be to keep both a const 920 * and non-const data pointer and cleverly choose between 921 * them. Note that this is only allowed for static data. 922 */ 923 template <typename T> 924 void 925 dataStaticConst(const T *p) 926 { 927 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 928 data = const_cast<PacketDataPtr>(p); 929 flags.set(STATIC_DATA); 930 } 931 932 /** 933 * Set the data pointer to a value that should have delete [] 934 * called on it. Dynamic data is local to this packet, and as the 935 * packet travels from source to destination, forwarded packets 936 * will allocate their own data. When a packet reaches the final 937 * destination it will populate the dynamic data of that specific 938 * packet, and on the way back towards the source, memcpy will be 939 * invoked in every step where a new packet was created e.g. in 940 * the caches. Ultimately when the response reaches the source a 941 * final memcpy is needed to extract the data from the packet 942 * before it is deallocated. 943 */ 944 template <typename T> 945 void 946 dataDynamic(T *p) 947 { 948 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 949 data = (PacketDataPtr)p; 950 flags.set(DYNAMIC_DATA); 951 } 952 953 /** 954 * get a pointer to the data ptr. 955 */ 956 template <typename T> 957 T* 958 getPtr() 959 { 960 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); 961 return (T*)data; 962 } 963 964 template <typename T> 965 const T* 966 getConstPtr() const 967 { 968 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); 969 return (const T*)data; 970 } 971 972 /** 973 * Get the data in the packet byte swapped from big endian to 974 * host endian. 975 */ 976 template <typename T> 977 T getBE() const; 978 979 /** 980 * Get the data in the packet byte swapped from little endian to 981 * host endian. 982 */ 983 template <typename T> 984 T getLE() const; 985 986 /** 987 * Get the data in the packet byte swapped from the specified 988 * endianness. 989 */ 990 template <typename T> 991 T get(ByteOrder endian) const; 992 993 /** 994 * Get the data in the packet byte swapped from guest to host 995 * endian. 996 */ 997 template <typename T> 998 T get() const; 999 1000 /** Set the value in the data pointer to v as big endian. */ 1001 template <typename T> 1002 void setBE(T v); 1003 1004 /** Set the value in the data pointer to v as little endian. */ 1005 template <typename T> 1006 void setLE(T v); 1007 1008 /** 1009 * Set the value in the data pointer to v using the specified 1010 * endianness. 1011 */ 1012 template <typename T> 1013 void set(T v, ByteOrder endian); 1014 1015 /** Set the value in the data pointer to v as guest endian. */ 1016 template <typename T> 1017 void set(T v); 1018 1019 /** 1020 * Copy data into the packet from the provided pointer. 1021 */ 1022 void 1023 setData(const uint8_t *p) 1024 { 1025 // we should never be copying data onto itself, which means we 1026 // must idenfity packets with static data, as they carry the 1027 // same pointer from source to destination and back 1028 assert(p != getPtr<uint8_t>() || flags.isSet(STATIC_DATA)); 1029 1030 if (p != getPtr<uint8_t>()) 1031 // for packet with allocated dynamic data, we copy data from 1032 // one to the other, e.g. a forwarded response to a response 1033 std::memcpy(getPtr<uint8_t>(), p, getSize()); 1034 } 1035 1036 /** 1037 * Copy data into the packet from the provided block pointer, 1038 * which is aligned to the given block size. 1039 */ 1040 void 1041 setDataFromBlock(const uint8_t *blk_data, int blkSize) 1042 { 1043 setData(blk_data + getOffset(blkSize)); 1044 } 1045 1046 /** 1047 * Copy data from the packet to the provided block pointer, which 1048 * is aligned to the given block size. 1049 */ 1050 void 1051 writeData(uint8_t *p) const 1052 { 1053 std::memcpy(p, getConstPtr<uint8_t>(), getSize()); 1054 } 1055 1056 /** 1057 * Copy data from the packet to the memory at the provided pointer. 1058 */ 1059 void 1060 writeDataToBlock(uint8_t *blk_data, int blkSize) const 1061 { 1062 writeData(blk_data + getOffset(blkSize)); 1063 } 1064 1065 /** 1066 * delete the data pointed to in the data pointer. Ok to call to 1067 * matter how data was allocted. 1068 */ 1069 void 1070 deleteData() 1071 { 1072 if (flags.isSet(DYNAMIC_DATA)) 1073 delete [] data; 1074 1075 flags.clear(STATIC_DATA|DYNAMIC_DATA); 1076 data = NULL; 1077 } 1078 1079 /** Allocate memory for the packet. */ 1080 void 1081 allocate() 1082 { 1083 // if either this command or the response command has a data 1084 // payload, actually allocate space 1085 if (hasData() || hasRespData()) { 1086 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 1087 flags.set(DYNAMIC_DATA); 1088 data = new uint8_t[getSize()]; 1089 } 1090 } 1091 1092 /** @} */ 1093 1094 private: // Private data accessor methods 1095 /** Get the data in the packet without byte swapping. */ 1096 template <typename T> 1097 T getRaw() const; 1098 1099 /** Set the value in the data pointer to v without byte swapping. */ 1100 template <typename T> 1101 void setRaw(T v); 1102 1103 public: 1104 /** 1105 * Check a functional request against a memory value stored in 1106 * another packet (i.e. an in-transit request or 1107 * response). Returns true if the current packet is a read, and 1108 * the other packet provides the data, which is then copied to the 1109 * current packet. If the current packet is a write, and the other 1110 * packet intersects this one, then we update the data 1111 * accordingly. 1112 */ 1113 bool 1114 checkFunctional(PacketPtr other) 1115 { 1116 // all packets that are carrying a payload should have a valid 1117 // data pointer 1118 return checkFunctional(other, other->getAddr(), other->isSecure(), 1119 other->getSize(), 1120 other->hasData() ? 1121 other->getPtr<uint8_t>() : NULL); 1122 } 1123 1124 /** 1125 * Does the request need to check for cached copies of the same block 1126 * in the memory hierarchy above. 1127 **/ 1128 bool 1129 mustCheckAbove() const 1130 { 1131 return cmd == MemCmd::HardPFReq || isEviction(); 1132 } 1133 1134 /** 1135 * Is this packet a clean eviction, including both actual clean 1136 * evict packets, but also clean writebacks. 1137 */ 1138 bool 1139 isCleanEviction() const 1140 { 1141 return cmd == MemCmd::CleanEvict || cmd == MemCmd::WritebackClean; 1142 } 1143 1144 /** 1145 * Check a functional request against a memory value represented 1146 * by a base/size pair and an associated data array. If the 1147 * current packet is a read, it may be satisfied by the memory 1148 * value. If the current packet is a write, it may update the 1149 * memory value. 1150 */ 1151 bool 1152 checkFunctional(Printable *obj, Addr base, bool is_secure, int size, 1153 uint8_t *_data); 1154 1155 /** 1156 * Push label for PrintReq (safe to call unconditionally). 1157 */ 1158 void 1159 pushLabel(const std::string &lbl) 1160 { 1161 if (isPrint()) 1162 safe_cast<PrintReqState*>(senderState)->pushLabel(lbl); 1163 } 1164 1165 /** 1166 * Pop label for PrintReq (safe to call unconditionally). 1167 */ 1168 void 1169 popLabel() 1170 { 1171 if (isPrint()) 1172 safe_cast<PrintReqState*>(senderState)->popLabel(); 1173 } 1174 1175 void print(std::ostream &o, int verbosity = 0, 1176 const std::string &prefix = "") const; 1177 1178 /** 1179 * A no-args wrapper of print(std::ostream...) 1180 * meant to be invoked from DPRINTFs 1181 * avoiding string overheads in fast mode 1182 * @return string with the request's type and start<->end addresses 1183 */ 1184 std::string print() const; 1185}; 1186 1187#endif //__MEM_PACKET_HH 1188