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