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