packet.hh (10564:a8c16e2d466a) packet.hh (10565:23593fdaadcd)
1/*
2 * Copyright (c) 2012-2014 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 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 Writeback,
90 SoftPFReq,
91 HardPFReq,
92 SoftPFResp,
93 HardPFResp,
94 WriteInvalidateReq,
95 WriteInvalidateResp,
96 UpgradeReq,
97 SCUpgradeReq, // Special "weak" upgrade for StoreCond
98 UpgradeResp,
99 SCUpgradeFailReq, // Failed SCUpgradeReq in MSHR (never sent)
100 UpgradeFailResp, // Valid for SCUpgradeReq only
101 ReadExReq,
102 ReadExResp,
103 LoadLockedReq,
104 StoreCondReq,
105 StoreCondFailReq, // Failed StoreCondReq in MSHR (never sent)
106 StoreCondResp,
107 SwapReq,
108 SwapResp,
109 MessageReq,
110 MessageResp,
111 // Error responses
112 // @TODO these should be classified as responses rather than
113 // requests; coding them as requests initially for backwards
114 // compatibility
115 InvalidDestError, // packet dest field invalid
116 BadAddressError, // memory address invalid
117 FunctionalReadError, // unable to fulfill functional read
118 FunctionalWriteError, // unable to fulfill functional write
119 // Fake simulator-only commands
120 PrintReq, // Print state matching address
121 FlushReq, //request for a cache flush
122 InvalidationReq, // request for address to be invalidated from lsq
123 NUM_MEM_CMDS
124 };
125
126 private:
127 /**
128 * List of command attributes.
129 */
130 enum Attribute
131 {
132 IsRead, //!< Data flows from responder to requester
133 IsWrite, //!< Data flows from requester to responder
134 IsUpgrade,
135 IsInvalidate,
136 NeedsExclusive, //!< Requires exclusive copy to complete in-cache
137 IsRequest, //!< Issued by requester
138 IsResponse, //!< Issue by responder
139 NeedsResponse, //!< Requester needs response from target
140 IsSWPrefetch,
141 IsHWPrefetch,
142 IsLlsc, //!< Alpha/MIPS LL or SC access
143 HasData, //!< There is an associated payload
144 IsError, //!< Error response
145 IsPrint, //!< Print state matching address (for debugging)
146 IsFlush, //!< Flush the address from caches
147 NUM_COMMAND_ATTRIBUTES
148 };
149
150 /**
151 * Structure that defines attributes and other data associated
152 * with a Command.
153 */
154 struct CommandInfo
155 {
156 /// Set of attribute flags.
157 const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
158 /// Corresponding response for requests; InvalidCmd if no
159 /// response is applicable.
160 const Command response;
161 /// String representation (for printing)
162 const std::string str;
163 };
164
165 /// Array to map Command enum to associated info.
166 static const CommandInfo commandInfo[];
167
168 private:
169
170 Command cmd;
171
172 bool
173 testCmdAttrib(MemCmd::Attribute attrib) const
174 {
175 return commandInfo[cmd].attributes[attrib] != 0;
176 }
177
178 public:
179
180 bool isRead() const { return testCmdAttrib(IsRead); }
181 bool isWrite() const { return testCmdAttrib(IsWrite); }
182 bool isUpgrade() const { return testCmdAttrib(IsUpgrade); }
183 bool isRequest() const { return testCmdAttrib(IsRequest); }
184 bool isResponse() const { return testCmdAttrib(IsResponse); }
185 bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
186 bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
187 bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
188 bool hasData() const { return testCmdAttrib(HasData); }
189 bool isLLSC() const { return testCmdAttrib(IsLlsc); }
190 bool isSWPrefetch() const { return testCmdAttrib(IsSWPrefetch); }
191 bool isHWPrefetch() const { return testCmdAttrib(IsHWPrefetch); }
192 bool isPrefetch() const { return testCmdAttrib(IsSWPrefetch) ||
193 testCmdAttrib(IsHWPrefetch); }
194 bool isError() const { return testCmdAttrib(IsError); }
195 bool isPrint() const { return testCmdAttrib(IsPrint); }
196 bool isFlush() const { return testCmdAttrib(IsFlush); }
197
198 const Command
199 responseCommand() const
200 {
201 return commandInfo[cmd].response;
202 }
203
204 /// Return the string to a cmd given by idx.
205 const std::string &toString() const { return commandInfo[cmd].str; }
206 int toInt() const { return (int)cmd; }
207
208 MemCmd(Command _cmd) : cmd(_cmd) { }
209 MemCmd(int _cmd) : cmd((Command)_cmd) { }
210 MemCmd() : cmd(InvalidCmd) { }
211
212 bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
213 bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
214};
215
216/**
217 * A Packet is used to encapsulate a transfer between two objects in
218 * the memory system (e.g., the L1 and L2 cache). (In contrast, a
219 * single Request travels all the way from the requester to the
220 * ultimate destination and back, possibly being conveyed by several
221 * different Packets along the way.)
222 */
223class Packet : public Printable
224{
225 public:
226 typedef uint32_t FlagsType;
227 typedef ::Flags<FlagsType> Flags;
228
229 private:
230 static const FlagsType PUBLIC_FLAGS = 0x00000000;
231 static const FlagsType PRIVATE_FLAGS = 0x00007F0F;
232 static const FlagsType COPY_FLAGS = 0x0000000F;
233
234 static const FlagsType SHARED = 0x00000001;
235 // Special control flags
236 /// Special timing-mode atomic snoop for multi-level coherence.
237 static const FlagsType EXPRESS_SNOOP = 0x00000002;
238 /// Does supplier have exclusive copy?
239 /// Useful for multi-level coherence.
240 static const FlagsType SUPPLY_EXCLUSIVE = 0x00000004;
241 // Snoop response flags
242 static const FlagsType MEM_INHIBIT = 0x00000008;
243 /// Are the 'addr' and 'size' fields valid?
244 static const FlagsType VALID_ADDR = 0x00000100;
245 static const FlagsType VALID_SIZE = 0x00000200;
246 /// Is the data pointer set to a value that shouldn't be freed
247 /// when the packet is destroyed?
248 static const FlagsType STATIC_DATA = 0x00001000;
249 /// The data pointer points to a value that should be freed when
250 /// the packet is destroyed.
251 static const FlagsType DYNAMIC_DATA = 0x00002000;
252 /// the data pointer points to an array (thus delete []) needs to
253 /// be called on it rather than simply delete.
254 static const FlagsType ARRAY_DATA = 0x00004000;
255 /// suppress the error if this packet encounters a functional
256 /// access failure.
257 static const FlagsType SUPPRESS_FUNC_ERROR = 0x00008000;
258 // Signal prefetch squash through express snoop flag
259 static const FlagsType PREFETCH_SNOOP_SQUASH = 0x00010000;
260
261 Flags flags;
262
263 public:
264 typedef MemCmd::Command Command;
265
266 /// The command field of the packet.
267 MemCmd cmd;
268
269 /// A pointer to the original request.
270 RequestPtr req;
271
272 private:
273 /**
274 * A pointer to the data being transfered. It can be differnt
275 * sizes at each level of the heirarchy so it belongs in the
276 * packet, not request. This may or may not be populated when a
277 * responder recieves the packet. If not populated it memory should
278 * be allocated.
279 */
280 PacketDataPtr data;
281
282 /// The address of the request. This address could be virtual or
283 /// physical, depending on the system configuration.
284 Addr addr;
285
286 /// True if the request targets the secure memory space.
287 bool _isSecure;
288
289 /// The size of the request or transfer.
290 unsigned size;
291
292 /**
293 * Source port identifier set on a request packet to enable
294 * appropriate routing of the responses. The source port
295 * identifier is set by any multiplexing component, e.g. a
296 * crossbar, as the timing responses need this information to be
297 * routed back to the appropriate port at a later point in
298 * time. The field can be updated (over-written) as the request
299 * packet passes through additional multiplexing components, and
300 * it is their responsibility to remember the original source port
301 * identifier, for example by using an appropriate sender
302 * state. The latter is done in the cache and bridge.
303 */
304 PortID src;
305
306 /**
307 * Destination port identifier that is present on all response
308 * packets that passed through a multiplexing component as a
309 * request packet. The source port identifier is turned into a
310 * destination port identifier when the packet is turned into a
311 * response, and the destination is used, e.g. by the crossbar, to
312 * select the appropriate path through the interconnect.
313 */
314 PortID dest;
315
316 /**
317 * The original value of the command field. Only valid when the
318 * current command field is an error condition; in that case, the
319 * previous contents of the command field are copied here. This
320 * field is *not* set on non-error responses.
321 */
322 MemCmd origCmd;
323
324 /**
325 * These values specify the range of bytes found that satisfy a
326 * functional read.
327 */
328 uint16_t bytesValidStart;
329 uint16_t bytesValidEnd;
330
331 public:
332
333 /**
334 * The extra delay from seeing the packet until the first word 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 firstWordDelay;
341
342 /**
343 * The extra pipelining delay from seeing the packet until the
344 * last word is transmitted by the component that provided it (if
345 * any). This includes the first word delay. Similar to the first
346 * word delay, this is used to make up for the fact that the
347 * crossbar does not make the packet wait. As the delay is
348 * relative, a 32-bit unsigned should be sufficient.
349 */
350 uint32_t lastWordDelay;
351
352 /**
353 * A virtual base opaque structure used to hold state associated
354 * with the packet (e.g., an MSHR), specific to a MemObject that
355 * sees the packet. A pointer to this state is returned in the
356 * packet's response so that the MemObject in question can quickly
357 * look up the state needed to process it. A specific subclass
358 * would be derived from this to carry state specific to a
359 * particular sending device.
360 *
361 * As multiple MemObjects may add their SenderState throughout the
362 * memory system, the SenderStates create a stack, where a
363 * MemObject can add a new Senderstate, as long as the
364 * predecessing SenderState is restored when the response comes
365 * back. For this reason, the predecessor should always be
366 * populated with the current SenderState of a packet before
367 * modifying the senderState field in the request packet.
368 */
369 struct SenderState
370 {
371 SenderState* predecessor;
372 SenderState() : predecessor(NULL) {}
373 virtual ~SenderState() {}
374 };
375
376 /**
377 * Object used to maintain state of a PrintReq. The senderState
378 * field of a PrintReq should always be of this type.
379 */
380 class PrintReqState : public SenderState
381 {
382 private:
383 /**
384 * An entry in the label stack.
385 */
386 struct LabelStackEntry
387 {
388 const std::string label;
389 std::string *prefix;
390 bool labelPrinted;
391 LabelStackEntry(const std::string &_label, std::string *_prefix);
392 };
393
394 typedef std::list<LabelStackEntry> LabelStack;
395 LabelStack labelStack;
396
397 std::string *curPrefixPtr;
398
399 public:
400 std::ostream &os;
401 const int verbosity;
402
403 PrintReqState(std::ostream &os, int verbosity = 0);
404 ~PrintReqState();
405
406 /**
407 * Returns the current line prefix.
408 */
409 const std::string &curPrefix() { return *curPrefixPtr; }
410
411 /**
412 * Push a label onto the label stack, and prepend the given
413 * prefix string onto the current prefix. Labels will only be
414 * printed if an object within the label's scope is printed.
415 */
416 void pushLabel(const std::string &lbl,
417 const std::string &prefix = " ");
418
419 /**
420 * Pop a label off the label stack.
421 */
422 void popLabel();
423
424 /**
425 * Print all of the pending unprinted labels on the
426 * stack. Called by printObj(), so normally not called by
427 * users unless bypassing printObj().
428 */
429 void printLabels();
430
431 /**
432 * Print a Printable object to os, because it matched the
433 * address on a PrintReq.
434 */
435 void printObj(Printable *obj);
436 };
437
438 /**
439 * This packet's sender state. Devices should use dynamic_cast<>
440 * to cast to the state appropriate to the sender. The intent of
441 * this variable is to allow a device to attach extra information
442 * to a request. A response packet must return the sender state
443 * that was attached to the original request (even if a new packet
444 * is created).
445 */
446 SenderState *senderState;
447
448 /**
449 * Push a new sender state to the packet and make the current
450 * sender state the predecessor of the new one. This should be
451 * prefered over direct manipulation of the senderState member
452 * variable.
453 *
454 * @param sender_state SenderState to push at the top of the stack
455 */
456 void pushSenderState(SenderState *sender_state);
457
458 /**
459 * Pop the top of the state stack and return a pointer to it. This
460 * assumes the current sender state is not NULL. This should be
461 * preferred over direct manipulation of the senderState member
462 * variable.
463 *
464 * @return The current top of the stack
465 */
466 SenderState *popSenderState();
467
468 /**
469 * Go through the sender state stack and return the first instance
470 * that is of type T (as determined by a dynamic_cast). If there
471 * is no sender state of type T, NULL is returned.
472 *
473 * @return The topmost state of type T
474 */
475 template <typename T>
476 T * findNextSenderState() const
477 {
478 T *t = NULL;
479 SenderState* sender_state = senderState;
480 while (t == NULL && sender_state != NULL) {
481 t = dynamic_cast<T*>(sender_state);
482 sender_state = sender_state->predecessor;
483 }
484 return t;
485 }
486
487 /// Return the string name of the cmd field (for debugging and
488 /// tracing).
489 const std::string &cmdString() const { return cmd.toString(); }
490
491 /// Return the index of this command.
492 inline int cmdToIndex() const { return cmd.toInt(); }
493
494 bool isRead() const { return cmd.isRead(); }
495 bool isWrite() const { return cmd.isWrite(); }
496 bool isUpgrade() const { return cmd.isUpgrade(); }
497 bool isRequest() const { return cmd.isRequest(); }
498 bool isResponse() const { return cmd.isResponse(); }
499 bool needsExclusive() const { return cmd.needsExclusive(); }
500 bool needsResponse() const { return cmd.needsResponse(); }
501 bool isInvalidate() const { return cmd.isInvalidate(); }
502 bool hasData() const { return cmd.hasData(); }
503 bool isLLSC() const { return cmd.isLLSC(); }
504 bool isError() const { return cmd.isError(); }
505 bool isPrint() const { return cmd.isPrint(); }
506 bool isFlush() const { return cmd.isFlush(); }
507
508 // Snoop flags
509 void assertMemInhibit() { flags.set(MEM_INHIBIT); }
510 bool memInhibitAsserted() const { return flags.isSet(MEM_INHIBIT); }
511 void assertShared() { flags.set(SHARED); }
512 bool sharedAsserted() const { return flags.isSet(SHARED); }
513
514 // Special control flags
515 void setExpressSnoop() { flags.set(EXPRESS_SNOOP); }
516 bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); }
517 void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); }
518 void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); }
519 bool isSupplyExclusive() const { return flags.isSet(SUPPLY_EXCLUSIVE); }
520 void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); }
521 bool suppressFuncError() const { return flags.isSet(SUPPRESS_FUNC_ERROR); }
522 void setPrefetchSquashed() { flags.set(PREFETCH_SNOOP_SQUASH); }
523 bool prefetchSquashed() const { return flags.isSet(PREFETCH_SNOOP_SQUASH); }
524
525 // Network error conditions... encapsulate them as methods since
526 // their encoding keeps changing (from result field to command
527 // field, etc.)
528 void
529 setBadAddress()
530 {
531 assert(isResponse());
532 cmd = MemCmd::BadAddressError;
533 }
534
535 bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; }
536 void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
537
538 bool isSrcValid() const { return src != InvalidPortID; }
539 /// Accessor function to get the source index of the packet.
540 PortID getSrc() const { assert(isSrcValid()); return src; }
541 /// Accessor function to set the source index of the packet.
542 void setSrc(PortID _src) { src = _src; }
543
544 bool isDestValid() const { return dest != InvalidPortID; }
545 /// Accessor function for the destination index of the packet.
546 PortID getDest() const { assert(isDestValid()); return dest; }
547 /// Accessor function to set the destination index of the packet.
548 void setDest(PortID _dest) { dest = _dest; }
549 /// Reset destination field, e.g. to turn a response into a request again.
550 void clearDest() { dest = InvalidPortID; }
551
552 Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
553 /**
554 * Update the address of this packet mid-transaction. This is used
555 * by the address mapper to change an already set address to a new
556 * one based on the system configuration. It is intended to remap
557 * an existing address, so it asserts that the current address is
558 * valid.
559 */
560 void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; }
561
562 unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; }
563 Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
564
565 bool isSecure() const
566 {
567 assert(flags.isSet(VALID_ADDR));
568 return _isSecure;
569 }
570
571 /**
572 * It has been determined that the SC packet should successfully update
573 * memory. Therefore, convert this SC packet to a normal write.
574 */
575 void
576 convertScToWrite()
577 {
578 assert(isLLSC());
579 assert(isWrite());
580 cmd = MemCmd::WriteReq;
581 }
582
583 /**
584 * When ruby is in use, Ruby will monitor the cache line and thus M5
585 * phys memory should treat LL ops as normal reads.
586 */
587 void
588 convertLlToRead()
589 {
590 assert(isLLSC());
591 assert(isRead());
592 cmd = MemCmd::ReadReq;
593 }
594
595 /**
596 * Constructor. Note that a Request object must be constructed
597 * first, but the Requests's physical address and size fields need
598 * not be valid. The command must be supplied.
599 */
600 Packet(Request *_req, MemCmd _cmd)
601 : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
602 size(0), src(InvalidPortID), dest(InvalidPortID),
603 bytesValidStart(0), bytesValidEnd(0),
604 firstWordDelay(0), lastWordDelay(0),
605 senderState(NULL)
606 {
607 if (req->hasPaddr()) {
608 addr = req->getPaddr();
609 flags.set(VALID_ADDR);
610 _isSecure = req->isSecure();
611 }
612 if (req->hasSize()) {
613 size = req->getSize();
614 flags.set(VALID_SIZE);
615 }
616 }
617
618 /**
619 * Alternate constructor if you are trying to create a packet with
620 * a request that is for a whole block, not the address from the
621 * req. this allows for overriding the size/addr of the req.
622 */
623 Packet(Request *_req, MemCmd _cmd, int _blkSize)
624 : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
625 src(InvalidPortID), dest(InvalidPortID),
626 bytesValidStart(0), bytesValidEnd(0),
627 firstWordDelay(0), lastWordDelay(0),
628 senderState(NULL)
629 {
630 if (req->hasPaddr()) {
631 addr = req->getPaddr() & ~(_blkSize - 1);
632 flags.set(VALID_ADDR);
633 _isSecure = req->isSecure();
634 }
635 size = _blkSize;
636 flags.set(VALID_SIZE);
637 }
638
639 /**
640 * Alternate constructor for copying a packet. Copy all fields
641 * *except* if the original packet's data was dynamic, don't copy
642 * that, as we can't guarantee that the new packet's lifetime is
643 * less than that of the original packet. In this case the new
644 * packet should allocate its own data.
645 */
646 Packet(Packet *pkt, bool clearFlags = false)
647 : cmd(pkt->cmd), req(pkt->req),
648 data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
649 addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
650 src(pkt->src), dest(pkt->dest),
651 bytesValidStart(pkt->bytesValidStart),
652 bytesValidEnd(pkt->bytesValidEnd),
653 firstWordDelay(pkt->firstWordDelay),
654 lastWordDelay(pkt->lastWordDelay),
655 senderState(pkt->senderState)
656 {
657 if (!clearFlags)
658 flags.set(pkt->flags & COPY_FLAGS);
659
660 flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
661 flags.set(pkt->flags & STATIC_DATA);
1/*
2 * Copyright (c) 2012-2014 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 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 Writeback,
90 SoftPFReq,
91 HardPFReq,
92 SoftPFResp,
93 HardPFResp,
94 WriteInvalidateReq,
95 WriteInvalidateResp,
96 UpgradeReq,
97 SCUpgradeReq, // Special "weak" upgrade for StoreCond
98 UpgradeResp,
99 SCUpgradeFailReq, // Failed SCUpgradeReq in MSHR (never sent)
100 UpgradeFailResp, // Valid for SCUpgradeReq only
101 ReadExReq,
102 ReadExResp,
103 LoadLockedReq,
104 StoreCondReq,
105 StoreCondFailReq, // Failed StoreCondReq in MSHR (never sent)
106 StoreCondResp,
107 SwapReq,
108 SwapResp,
109 MessageReq,
110 MessageResp,
111 // Error responses
112 // @TODO these should be classified as responses rather than
113 // requests; coding them as requests initially for backwards
114 // compatibility
115 InvalidDestError, // packet dest field invalid
116 BadAddressError, // memory address invalid
117 FunctionalReadError, // unable to fulfill functional read
118 FunctionalWriteError, // unable to fulfill functional write
119 // Fake simulator-only commands
120 PrintReq, // Print state matching address
121 FlushReq, //request for a cache flush
122 InvalidationReq, // request for address to be invalidated from lsq
123 NUM_MEM_CMDS
124 };
125
126 private:
127 /**
128 * List of command attributes.
129 */
130 enum Attribute
131 {
132 IsRead, //!< Data flows from responder to requester
133 IsWrite, //!< Data flows from requester to responder
134 IsUpgrade,
135 IsInvalidate,
136 NeedsExclusive, //!< Requires exclusive copy to complete in-cache
137 IsRequest, //!< Issued by requester
138 IsResponse, //!< Issue by responder
139 NeedsResponse, //!< Requester needs response from target
140 IsSWPrefetch,
141 IsHWPrefetch,
142 IsLlsc, //!< Alpha/MIPS LL or SC access
143 HasData, //!< There is an associated payload
144 IsError, //!< Error response
145 IsPrint, //!< Print state matching address (for debugging)
146 IsFlush, //!< Flush the address from caches
147 NUM_COMMAND_ATTRIBUTES
148 };
149
150 /**
151 * Structure that defines attributes and other data associated
152 * with a Command.
153 */
154 struct CommandInfo
155 {
156 /// Set of attribute flags.
157 const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
158 /// Corresponding response for requests; InvalidCmd if no
159 /// response is applicable.
160 const Command response;
161 /// String representation (for printing)
162 const std::string str;
163 };
164
165 /// Array to map Command enum to associated info.
166 static const CommandInfo commandInfo[];
167
168 private:
169
170 Command cmd;
171
172 bool
173 testCmdAttrib(MemCmd::Attribute attrib) const
174 {
175 return commandInfo[cmd].attributes[attrib] != 0;
176 }
177
178 public:
179
180 bool isRead() const { return testCmdAttrib(IsRead); }
181 bool isWrite() const { return testCmdAttrib(IsWrite); }
182 bool isUpgrade() const { return testCmdAttrib(IsUpgrade); }
183 bool isRequest() const { return testCmdAttrib(IsRequest); }
184 bool isResponse() const { return testCmdAttrib(IsResponse); }
185 bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
186 bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
187 bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
188 bool hasData() const { return testCmdAttrib(HasData); }
189 bool isLLSC() const { return testCmdAttrib(IsLlsc); }
190 bool isSWPrefetch() const { return testCmdAttrib(IsSWPrefetch); }
191 bool isHWPrefetch() const { return testCmdAttrib(IsHWPrefetch); }
192 bool isPrefetch() const { return testCmdAttrib(IsSWPrefetch) ||
193 testCmdAttrib(IsHWPrefetch); }
194 bool isError() const { return testCmdAttrib(IsError); }
195 bool isPrint() const { return testCmdAttrib(IsPrint); }
196 bool isFlush() const { return testCmdAttrib(IsFlush); }
197
198 const Command
199 responseCommand() const
200 {
201 return commandInfo[cmd].response;
202 }
203
204 /// Return the string to a cmd given by idx.
205 const std::string &toString() const { return commandInfo[cmd].str; }
206 int toInt() const { return (int)cmd; }
207
208 MemCmd(Command _cmd) : cmd(_cmd) { }
209 MemCmd(int _cmd) : cmd((Command)_cmd) { }
210 MemCmd() : cmd(InvalidCmd) { }
211
212 bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
213 bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
214};
215
216/**
217 * A Packet is used to encapsulate a transfer between two objects in
218 * the memory system (e.g., the L1 and L2 cache). (In contrast, a
219 * single Request travels all the way from the requester to the
220 * ultimate destination and back, possibly being conveyed by several
221 * different Packets along the way.)
222 */
223class Packet : public Printable
224{
225 public:
226 typedef uint32_t FlagsType;
227 typedef ::Flags<FlagsType> Flags;
228
229 private:
230 static const FlagsType PUBLIC_FLAGS = 0x00000000;
231 static const FlagsType PRIVATE_FLAGS = 0x00007F0F;
232 static const FlagsType COPY_FLAGS = 0x0000000F;
233
234 static const FlagsType SHARED = 0x00000001;
235 // Special control flags
236 /// Special timing-mode atomic snoop for multi-level coherence.
237 static const FlagsType EXPRESS_SNOOP = 0x00000002;
238 /// Does supplier have exclusive copy?
239 /// Useful for multi-level coherence.
240 static const FlagsType SUPPLY_EXCLUSIVE = 0x00000004;
241 // Snoop response flags
242 static const FlagsType MEM_INHIBIT = 0x00000008;
243 /// Are the 'addr' and 'size' fields valid?
244 static const FlagsType VALID_ADDR = 0x00000100;
245 static const FlagsType VALID_SIZE = 0x00000200;
246 /// Is the data pointer set to a value that shouldn't be freed
247 /// when the packet is destroyed?
248 static const FlagsType STATIC_DATA = 0x00001000;
249 /// The data pointer points to a value that should be freed when
250 /// the packet is destroyed.
251 static const FlagsType DYNAMIC_DATA = 0x00002000;
252 /// the data pointer points to an array (thus delete []) needs to
253 /// be called on it rather than simply delete.
254 static const FlagsType ARRAY_DATA = 0x00004000;
255 /// suppress the error if this packet encounters a functional
256 /// access failure.
257 static const FlagsType SUPPRESS_FUNC_ERROR = 0x00008000;
258 // Signal prefetch squash through express snoop flag
259 static const FlagsType PREFETCH_SNOOP_SQUASH = 0x00010000;
260
261 Flags flags;
262
263 public:
264 typedef MemCmd::Command Command;
265
266 /// The command field of the packet.
267 MemCmd cmd;
268
269 /// A pointer to the original request.
270 RequestPtr req;
271
272 private:
273 /**
274 * A pointer to the data being transfered. It can be differnt
275 * sizes at each level of the heirarchy so it belongs in the
276 * packet, not request. This may or may not be populated when a
277 * responder recieves the packet. If not populated it memory should
278 * be allocated.
279 */
280 PacketDataPtr data;
281
282 /// The address of the request. This address could be virtual or
283 /// physical, depending on the system configuration.
284 Addr addr;
285
286 /// True if the request targets the secure memory space.
287 bool _isSecure;
288
289 /// The size of the request or transfer.
290 unsigned size;
291
292 /**
293 * Source port identifier set on a request packet to enable
294 * appropriate routing of the responses. The source port
295 * identifier is set by any multiplexing component, e.g. a
296 * crossbar, as the timing responses need this information to be
297 * routed back to the appropriate port at a later point in
298 * time. The field can be updated (over-written) as the request
299 * packet passes through additional multiplexing components, and
300 * it is their responsibility to remember the original source port
301 * identifier, for example by using an appropriate sender
302 * state. The latter is done in the cache and bridge.
303 */
304 PortID src;
305
306 /**
307 * Destination port identifier that is present on all response
308 * packets that passed through a multiplexing component as a
309 * request packet. The source port identifier is turned into a
310 * destination port identifier when the packet is turned into a
311 * response, and the destination is used, e.g. by the crossbar, to
312 * select the appropriate path through the interconnect.
313 */
314 PortID dest;
315
316 /**
317 * The original value of the command field. Only valid when the
318 * current command field is an error condition; in that case, the
319 * previous contents of the command field are copied here. This
320 * field is *not* set on non-error responses.
321 */
322 MemCmd origCmd;
323
324 /**
325 * These values specify the range of bytes found that satisfy a
326 * functional read.
327 */
328 uint16_t bytesValidStart;
329 uint16_t bytesValidEnd;
330
331 public:
332
333 /**
334 * The extra delay from seeing the packet until the first word 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 firstWordDelay;
341
342 /**
343 * The extra pipelining delay from seeing the packet until the
344 * last word is transmitted by the component that provided it (if
345 * any). This includes the first word delay. Similar to the first
346 * word delay, this is used to make up for the fact that the
347 * crossbar does not make the packet wait. As the delay is
348 * relative, a 32-bit unsigned should be sufficient.
349 */
350 uint32_t lastWordDelay;
351
352 /**
353 * A virtual base opaque structure used to hold state associated
354 * with the packet (e.g., an MSHR), specific to a MemObject that
355 * sees the packet. A pointer to this state is returned in the
356 * packet's response so that the MemObject in question can quickly
357 * look up the state needed to process it. A specific subclass
358 * would be derived from this to carry state specific to a
359 * particular sending device.
360 *
361 * As multiple MemObjects may add their SenderState throughout the
362 * memory system, the SenderStates create a stack, where a
363 * MemObject can add a new Senderstate, as long as the
364 * predecessing SenderState is restored when the response comes
365 * back. For this reason, the predecessor should always be
366 * populated with the current SenderState of a packet before
367 * modifying the senderState field in the request packet.
368 */
369 struct SenderState
370 {
371 SenderState* predecessor;
372 SenderState() : predecessor(NULL) {}
373 virtual ~SenderState() {}
374 };
375
376 /**
377 * Object used to maintain state of a PrintReq. The senderState
378 * field of a PrintReq should always be of this type.
379 */
380 class PrintReqState : public SenderState
381 {
382 private:
383 /**
384 * An entry in the label stack.
385 */
386 struct LabelStackEntry
387 {
388 const std::string label;
389 std::string *prefix;
390 bool labelPrinted;
391 LabelStackEntry(const std::string &_label, std::string *_prefix);
392 };
393
394 typedef std::list<LabelStackEntry> LabelStack;
395 LabelStack labelStack;
396
397 std::string *curPrefixPtr;
398
399 public:
400 std::ostream &os;
401 const int verbosity;
402
403 PrintReqState(std::ostream &os, int verbosity = 0);
404 ~PrintReqState();
405
406 /**
407 * Returns the current line prefix.
408 */
409 const std::string &curPrefix() { return *curPrefixPtr; }
410
411 /**
412 * Push a label onto the label stack, and prepend the given
413 * prefix string onto the current prefix. Labels will only be
414 * printed if an object within the label's scope is printed.
415 */
416 void pushLabel(const std::string &lbl,
417 const std::string &prefix = " ");
418
419 /**
420 * Pop a label off the label stack.
421 */
422 void popLabel();
423
424 /**
425 * Print all of the pending unprinted labels on the
426 * stack. Called by printObj(), so normally not called by
427 * users unless bypassing printObj().
428 */
429 void printLabels();
430
431 /**
432 * Print a Printable object to os, because it matched the
433 * address on a PrintReq.
434 */
435 void printObj(Printable *obj);
436 };
437
438 /**
439 * This packet's sender state. Devices should use dynamic_cast<>
440 * to cast to the state appropriate to the sender. The intent of
441 * this variable is to allow a device to attach extra information
442 * to a request. A response packet must return the sender state
443 * that was attached to the original request (even if a new packet
444 * is created).
445 */
446 SenderState *senderState;
447
448 /**
449 * Push a new sender state to the packet and make the current
450 * sender state the predecessor of the new one. This should be
451 * prefered over direct manipulation of the senderState member
452 * variable.
453 *
454 * @param sender_state SenderState to push at the top of the stack
455 */
456 void pushSenderState(SenderState *sender_state);
457
458 /**
459 * Pop the top of the state stack and return a pointer to it. This
460 * assumes the current sender state is not NULL. This should be
461 * preferred over direct manipulation of the senderState member
462 * variable.
463 *
464 * @return The current top of the stack
465 */
466 SenderState *popSenderState();
467
468 /**
469 * Go through the sender state stack and return the first instance
470 * that is of type T (as determined by a dynamic_cast). If there
471 * is no sender state of type T, NULL is returned.
472 *
473 * @return The topmost state of type T
474 */
475 template <typename T>
476 T * findNextSenderState() const
477 {
478 T *t = NULL;
479 SenderState* sender_state = senderState;
480 while (t == NULL && sender_state != NULL) {
481 t = dynamic_cast<T*>(sender_state);
482 sender_state = sender_state->predecessor;
483 }
484 return t;
485 }
486
487 /// Return the string name of the cmd field (for debugging and
488 /// tracing).
489 const std::string &cmdString() const { return cmd.toString(); }
490
491 /// Return the index of this command.
492 inline int cmdToIndex() const { return cmd.toInt(); }
493
494 bool isRead() const { return cmd.isRead(); }
495 bool isWrite() const { return cmd.isWrite(); }
496 bool isUpgrade() const { return cmd.isUpgrade(); }
497 bool isRequest() const { return cmd.isRequest(); }
498 bool isResponse() const { return cmd.isResponse(); }
499 bool needsExclusive() const { return cmd.needsExclusive(); }
500 bool needsResponse() const { return cmd.needsResponse(); }
501 bool isInvalidate() const { return cmd.isInvalidate(); }
502 bool hasData() const { return cmd.hasData(); }
503 bool isLLSC() const { return cmd.isLLSC(); }
504 bool isError() const { return cmd.isError(); }
505 bool isPrint() const { return cmd.isPrint(); }
506 bool isFlush() const { return cmd.isFlush(); }
507
508 // Snoop flags
509 void assertMemInhibit() { flags.set(MEM_INHIBIT); }
510 bool memInhibitAsserted() const { return flags.isSet(MEM_INHIBIT); }
511 void assertShared() { flags.set(SHARED); }
512 bool sharedAsserted() const { return flags.isSet(SHARED); }
513
514 // Special control flags
515 void setExpressSnoop() { flags.set(EXPRESS_SNOOP); }
516 bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); }
517 void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); }
518 void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); }
519 bool isSupplyExclusive() const { return flags.isSet(SUPPLY_EXCLUSIVE); }
520 void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); }
521 bool suppressFuncError() const { return flags.isSet(SUPPRESS_FUNC_ERROR); }
522 void setPrefetchSquashed() { flags.set(PREFETCH_SNOOP_SQUASH); }
523 bool prefetchSquashed() const { return flags.isSet(PREFETCH_SNOOP_SQUASH); }
524
525 // Network error conditions... encapsulate them as methods since
526 // their encoding keeps changing (from result field to command
527 // field, etc.)
528 void
529 setBadAddress()
530 {
531 assert(isResponse());
532 cmd = MemCmd::BadAddressError;
533 }
534
535 bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; }
536 void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
537
538 bool isSrcValid() const { return src != InvalidPortID; }
539 /// Accessor function to get the source index of the packet.
540 PortID getSrc() const { assert(isSrcValid()); return src; }
541 /// Accessor function to set the source index of the packet.
542 void setSrc(PortID _src) { src = _src; }
543
544 bool isDestValid() const { return dest != InvalidPortID; }
545 /// Accessor function for the destination index of the packet.
546 PortID getDest() const { assert(isDestValid()); return dest; }
547 /// Accessor function to set the destination index of the packet.
548 void setDest(PortID _dest) { dest = _dest; }
549 /// Reset destination field, e.g. to turn a response into a request again.
550 void clearDest() { dest = InvalidPortID; }
551
552 Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
553 /**
554 * Update the address of this packet mid-transaction. This is used
555 * by the address mapper to change an already set address to a new
556 * one based on the system configuration. It is intended to remap
557 * an existing address, so it asserts that the current address is
558 * valid.
559 */
560 void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; }
561
562 unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; }
563 Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
564
565 bool isSecure() const
566 {
567 assert(flags.isSet(VALID_ADDR));
568 return _isSecure;
569 }
570
571 /**
572 * It has been determined that the SC packet should successfully update
573 * memory. Therefore, convert this SC packet to a normal write.
574 */
575 void
576 convertScToWrite()
577 {
578 assert(isLLSC());
579 assert(isWrite());
580 cmd = MemCmd::WriteReq;
581 }
582
583 /**
584 * When ruby is in use, Ruby will monitor the cache line and thus M5
585 * phys memory should treat LL ops as normal reads.
586 */
587 void
588 convertLlToRead()
589 {
590 assert(isLLSC());
591 assert(isRead());
592 cmd = MemCmd::ReadReq;
593 }
594
595 /**
596 * Constructor. Note that a Request object must be constructed
597 * first, but the Requests's physical address and size fields need
598 * not be valid. The command must be supplied.
599 */
600 Packet(Request *_req, MemCmd _cmd)
601 : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
602 size(0), src(InvalidPortID), dest(InvalidPortID),
603 bytesValidStart(0), bytesValidEnd(0),
604 firstWordDelay(0), lastWordDelay(0),
605 senderState(NULL)
606 {
607 if (req->hasPaddr()) {
608 addr = req->getPaddr();
609 flags.set(VALID_ADDR);
610 _isSecure = req->isSecure();
611 }
612 if (req->hasSize()) {
613 size = req->getSize();
614 flags.set(VALID_SIZE);
615 }
616 }
617
618 /**
619 * Alternate constructor if you are trying to create a packet with
620 * a request that is for a whole block, not the address from the
621 * req. this allows for overriding the size/addr of the req.
622 */
623 Packet(Request *_req, MemCmd _cmd, int _blkSize)
624 : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
625 src(InvalidPortID), dest(InvalidPortID),
626 bytesValidStart(0), bytesValidEnd(0),
627 firstWordDelay(0), lastWordDelay(0),
628 senderState(NULL)
629 {
630 if (req->hasPaddr()) {
631 addr = req->getPaddr() & ~(_blkSize - 1);
632 flags.set(VALID_ADDR);
633 _isSecure = req->isSecure();
634 }
635 size = _blkSize;
636 flags.set(VALID_SIZE);
637 }
638
639 /**
640 * Alternate constructor for copying a packet. Copy all fields
641 * *except* if the original packet's data was dynamic, don't copy
642 * that, as we can't guarantee that the new packet's lifetime is
643 * less than that of the original packet. In this case the new
644 * packet should allocate its own data.
645 */
646 Packet(Packet *pkt, bool clearFlags = false)
647 : cmd(pkt->cmd), req(pkt->req),
648 data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
649 addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
650 src(pkt->src), dest(pkt->dest),
651 bytesValidStart(pkt->bytesValidStart),
652 bytesValidEnd(pkt->bytesValidEnd),
653 firstWordDelay(pkt->firstWordDelay),
654 lastWordDelay(pkt->lastWordDelay),
655 senderState(pkt->senderState)
656 {
657 if (!clearFlags)
658 flags.set(pkt->flags & COPY_FLAGS);
659
660 flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
661 flags.set(pkt->flags & STATIC_DATA);
662
663 // if we did not copy the static data pointer, allocate data
664 // dynamically instead
665 if (!data)
666 allocate();
662 }
663
664 /**
665 * Change the packet type based on request type.
666 */
667 void
668 refineCommand()
669 {
670 if (cmd == MemCmd::ReadReq) {
671 if (req->isLLSC()) {
672 cmd = MemCmd::LoadLockedReq;
673 } else if (req->isPrefetch()) {
674 cmd = MemCmd::SoftPFReq;
675 }
676 } else if (cmd == MemCmd::WriteReq) {
677 if (req->isLLSC()) {
678 cmd = MemCmd::StoreCondReq;
679 } else if (req->isSwap()) {
680 cmd = MemCmd::SwapReq;
681 }
682 }
683 }
684
685 /**
686 * Constructor-like methods that return Packets based on Request objects.
687 * Will call refineCommand() to fine-tune the Packet type if it's not a
688 * vanilla read or write.
689 */
690 static PacketPtr
691 createRead(Request *req)
692 {
693 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
694 pkt->refineCommand();
695 return pkt;
696 }
697
698 static PacketPtr
699 createWrite(Request *req)
700 {
701 PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
702 pkt->refineCommand();
703 return pkt;
704 }
705
706 /**
707 * clean up packet variables
708 */
709 ~Packet()
710 {
711 // If this is a request packet for which there's no response,
712 // delete the request object here, since the requester will
713 // never get the chance.
714 if (req && isRequest() && !needsResponse())
715 delete req;
716 deleteData();
717 }
718
719 /**
720 * Reinitialize packet address and size from the associated
721 * Request object, and reset other fields that may have been
722 * modified by a previous transaction. Typically called when a
723 * statically allocated Request/Packet pair is reused for multiple
724 * transactions.
725 */
726 void
727 reinitFromRequest()
728 {
729 assert(req->hasPaddr());
730 flags = 0;
731 addr = req->getPaddr();
732 _isSecure = req->isSecure();
733 size = req->getSize();
734
735 src = InvalidPortID;
736 dest = InvalidPortID;
737 bytesValidStart = 0;
738 bytesValidEnd = 0;
739 firstWordDelay = 0;
740 lastWordDelay = 0;
741
742 flags.set(VALID_ADDR|VALID_SIZE);
743 deleteData();
744 }
745
746 /**
747 * Take a request packet and modify it in place to be suitable for
748 * returning as a response to that request. The source field is
749 * turned into the destination, and subsequently cleared. Note
750 * that the latter is not necessary for atomic requests, but
751 * causes no harm as neither field is valid.
752 */
753 void
754 makeResponse()
755 {
756 assert(needsResponse());
757 assert(isRequest());
758 origCmd = cmd;
759 cmd = cmd.responseCommand();
760
761 // responses are never express, even if the snoop that
762 // triggered them was
763 flags.clear(EXPRESS_SNOOP);
764
765 dest = src;
766 src = InvalidPortID;
767 }
768
769 void
770 makeAtomicResponse()
771 {
772 makeResponse();
773 }
774
775 void
776 makeTimingResponse()
777 {
778 makeResponse();
779 }
780
781 void
782 setFunctionalResponseStatus(bool success)
783 {
784 if (!success) {
785 if (isWrite()) {
786 cmd = MemCmd::FunctionalWriteError;
787 } else {
788 cmd = MemCmd::FunctionalReadError;
789 }
790 }
791 }
792
793 void
794 setSize(unsigned size)
795 {
796 assert(!flags.isSet(VALID_SIZE));
797
798 this->size = size;
799 flags.set(VALID_SIZE);
800 }
801
802
803 /**
804 * Set the data pointer to the following value that should not be
805 * freed.
806 */
807 template <typename T>
808 void
809 dataStatic(T *p)
810 {
811 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
812 data = (PacketDataPtr)p;
813 flags.set(STATIC_DATA);
814 }
815
816 /**
817 * Set the data pointer to the following value that should not be
818 * freed. This version of the function allows the pointer passed
819 * to us to be const. To avoid issues down the line we cast the
820 * constness away, the alternative would be to keep both a const
821 * and non-const data pointer and cleverly choose between
822 * them. Note that this is only allowed for static data.
823 */
824 template <typename T>
825 void
826 dataStaticConst(const T *p)
827 {
828 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
829 data = const_cast<PacketDataPtr>(p);
830 flags.set(STATIC_DATA);
831 }
832
833 /**
834 * Set the data pointer to a value that should have delete []
835 * called on it.
836 */
837 template <typename T>
838 void
839 dataDynamicArray(T *p)
840 {
841 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
842 data = (PacketDataPtr)p;
843 flags.set(DYNAMIC_DATA|ARRAY_DATA);
844 }
845
846 /**
847 * set the data pointer to a value that should have delete called
848 * on it.
849 */
850 template <typename T>
851 void
852 dataDynamic(T *p)
853 {
854 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
855 data = (PacketDataPtr)p;
856 flags.set(DYNAMIC_DATA);
857 }
858
859 /**
860 * get a pointer to the data ptr.
861 */
862 template <typename T>
863 T*
864 getPtr()
865 {
866 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
867 return (T*)data;
868 }
869
870 template <typename T>
871 const T*
872 getConstPtr() const
873 {
874 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
875 return (const T*)data;
876 }
877
878 /**
879 * return the value of what is pointed to in the packet.
880 */
881 template <typename T>
882 T get() const;
883
884 /**
885 * set the value in the data pointer to v.
886 */
887 template <typename T>
888 void set(T v);
889
890 /**
891 * Copy data into the packet from the provided pointer.
892 */
893 void
894 setData(const uint8_t *p)
895 {
896 if (p != getPtr<uint8_t>())
897 std::memcpy(getPtr<uint8_t>(), p, getSize());
898 }
899
900 /**
901 * Copy data into the packet from the provided block pointer,
902 * which is aligned to the given block size.
903 */
904 void
905 setDataFromBlock(const uint8_t *blk_data, int blkSize)
906 {
907 setData(blk_data + getOffset(blkSize));
908 }
909
910 /**
911 * Copy data from the packet to the provided block pointer, which
912 * is aligned to the given block size.
913 */
914 void
915 writeData(uint8_t *p) const
916 {
917 std::memcpy(p, getConstPtr<uint8_t>(), getSize());
918 }
919
920 /**
921 * Copy data from the packet to the memory at the provided pointer.
922 */
923 void
924 writeDataToBlock(uint8_t *blk_data, int blkSize) const
925 {
926 writeData(blk_data + getOffset(blkSize));
927 }
928
929 /**
930 * delete the data pointed to in the data pointer. Ok to call to
931 * matter how data was allocted.
932 */
933 void
934 deleteData()
935 {
936 if (flags.isSet(ARRAY_DATA))
937 delete [] data;
938 else if (flags.isSet(DYNAMIC_DATA))
939 delete data;
940
941 flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA);
942 data = NULL;
943 }
944
667 }
668
669 /**
670 * Change the packet type based on request type.
671 */
672 void
673 refineCommand()
674 {
675 if (cmd == MemCmd::ReadReq) {
676 if (req->isLLSC()) {
677 cmd = MemCmd::LoadLockedReq;
678 } else if (req->isPrefetch()) {
679 cmd = MemCmd::SoftPFReq;
680 }
681 } else if (cmd == MemCmd::WriteReq) {
682 if (req->isLLSC()) {
683 cmd = MemCmd::StoreCondReq;
684 } else if (req->isSwap()) {
685 cmd = MemCmd::SwapReq;
686 }
687 }
688 }
689
690 /**
691 * Constructor-like methods that return Packets based on Request objects.
692 * Will call refineCommand() to fine-tune the Packet type if it's not a
693 * vanilla read or write.
694 */
695 static PacketPtr
696 createRead(Request *req)
697 {
698 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
699 pkt->refineCommand();
700 return pkt;
701 }
702
703 static PacketPtr
704 createWrite(Request *req)
705 {
706 PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
707 pkt->refineCommand();
708 return pkt;
709 }
710
711 /**
712 * clean up packet variables
713 */
714 ~Packet()
715 {
716 // If this is a request packet for which there's no response,
717 // delete the request object here, since the requester will
718 // never get the chance.
719 if (req && isRequest() && !needsResponse())
720 delete req;
721 deleteData();
722 }
723
724 /**
725 * Reinitialize packet address and size from the associated
726 * Request object, and reset other fields that may have been
727 * modified by a previous transaction. Typically called when a
728 * statically allocated Request/Packet pair is reused for multiple
729 * transactions.
730 */
731 void
732 reinitFromRequest()
733 {
734 assert(req->hasPaddr());
735 flags = 0;
736 addr = req->getPaddr();
737 _isSecure = req->isSecure();
738 size = req->getSize();
739
740 src = InvalidPortID;
741 dest = InvalidPortID;
742 bytesValidStart = 0;
743 bytesValidEnd = 0;
744 firstWordDelay = 0;
745 lastWordDelay = 0;
746
747 flags.set(VALID_ADDR|VALID_SIZE);
748 deleteData();
749 }
750
751 /**
752 * Take a request packet and modify it in place to be suitable for
753 * returning as a response to that request. The source field is
754 * turned into the destination, and subsequently cleared. Note
755 * that the latter is not necessary for atomic requests, but
756 * causes no harm as neither field is valid.
757 */
758 void
759 makeResponse()
760 {
761 assert(needsResponse());
762 assert(isRequest());
763 origCmd = cmd;
764 cmd = cmd.responseCommand();
765
766 // responses are never express, even if the snoop that
767 // triggered them was
768 flags.clear(EXPRESS_SNOOP);
769
770 dest = src;
771 src = InvalidPortID;
772 }
773
774 void
775 makeAtomicResponse()
776 {
777 makeResponse();
778 }
779
780 void
781 makeTimingResponse()
782 {
783 makeResponse();
784 }
785
786 void
787 setFunctionalResponseStatus(bool success)
788 {
789 if (!success) {
790 if (isWrite()) {
791 cmd = MemCmd::FunctionalWriteError;
792 } else {
793 cmd = MemCmd::FunctionalReadError;
794 }
795 }
796 }
797
798 void
799 setSize(unsigned size)
800 {
801 assert(!flags.isSet(VALID_SIZE));
802
803 this->size = size;
804 flags.set(VALID_SIZE);
805 }
806
807
808 /**
809 * Set the data pointer to the following value that should not be
810 * freed.
811 */
812 template <typename T>
813 void
814 dataStatic(T *p)
815 {
816 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
817 data = (PacketDataPtr)p;
818 flags.set(STATIC_DATA);
819 }
820
821 /**
822 * Set the data pointer to the following value that should not be
823 * freed. This version of the function allows the pointer passed
824 * to us to be const. To avoid issues down the line we cast the
825 * constness away, the alternative would be to keep both a const
826 * and non-const data pointer and cleverly choose between
827 * them. Note that this is only allowed for static data.
828 */
829 template <typename T>
830 void
831 dataStaticConst(const T *p)
832 {
833 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
834 data = const_cast<PacketDataPtr>(p);
835 flags.set(STATIC_DATA);
836 }
837
838 /**
839 * Set the data pointer to a value that should have delete []
840 * called on it.
841 */
842 template <typename T>
843 void
844 dataDynamicArray(T *p)
845 {
846 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
847 data = (PacketDataPtr)p;
848 flags.set(DYNAMIC_DATA|ARRAY_DATA);
849 }
850
851 /**
852 * set the data pointer to a value that should have delete called
853 * on it.
854 */
855 template <typename T>
856 void
857 dataDynamic(T *p)
858 {
859 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
860 data = (PacketDataPtr)p;
861 flags.set(DYNAMIC_DATA);
862 }
863
864 /**
865 * get a pointer to the data ptr.
866 */
867 template <typename T>
868 T*
869 getPtr()
870 {
871 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
872 return (T*)data;
873 }
874
875 template <typename T>
876 const T*
877 getConstPtr() const
878 {
879 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
880 return (const T*)data;
881 }
882
883 /**
884 * return the value of what is pointed to in the packet.
885 */
886 template <typename T>
887 T get() const;
888
889 /**
890 * set the value in the data pointer to v.
891 */
892 template <typename T>
893 void set(T v);
894
895 /**
896 * Copy data into the packet from the provided pointer.
897 */
898 void
899 setData(const uint8_t *p)
900 {
901 if (p != getPtr<uint8_t>())
902 std::memcpy(getPtr<uint8_t>(), p, getSize());
903 }
904
905 /**
906 * Copy data into the packet from the provided block pointer,
907 * which is aligned to the given block size.
908 */
909 void
910 setDataFromBlock(const uint8_t *blk_data, int blkSize)
911 {
912 setData(blk_data + getOffset(blkSize));
913 }
914
915 /**
916 * Copy data from the packet to the provided block pointer, which
917 * is aligned to the given block size.
918 */
919 void
920 writeData(uint8_t *p) const
921 {
922 std::memcpy(p, getConstPtr<uint8_t>(), getSize());
923 }
924
925 /**
926 * Copy data from the packet to the memory at the provided pointer.
927 */
928 void
929 writeDataToBlock(uint8_t *blk_data, int blkSize) const
930 {
931 writeData(blk_data + getOffset(blkSize));
932 }
933
934 /**
935 * delete the data pointed to in the data pointer. Ok to call to
936 * matter how data was allocted.
937 */
938 void
939 deleteData()
940 {
941 if (flags.isSet(ARRAY_DATA))
942 delete [] data;
943 else if (flags.isSet(DYNAMIC_DATA))
944 delete data;
945
946 flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA);
947 data = NULL;
948 }
949
945 /** If there isn't data in the packet, allocate some. */
950 /** Allocate memory for the packet. */
946 void
947 allocate()
948 {
951 void
952 allocate()
953 {
949 if (data) {
950 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
951 return;
952 }
953
954 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
955 flags.set(DYNAMIC_DATA|ARRAY_DATA);
956 data = new uint8_t[getSize()];
957 }
958
959 /**
960 * Check a functional request against a memory value represented
961 * by a base/size pair and an associated data array. If the
962 * functional request is a read, it may be satisfied by the memory
963 * value. If the functional request is a write, it may update the
964 * memory value.
965 */
966 bool checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
967 uint8_t *data);
968
969 /**
970 * Check a functional request against a memory value stored in
971 * another packet (i.e. an in-transit request or response).
972 */
973 bool
974 checkFunctional(PacketPtr other)
975 {
976 uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL;
977 return checkFunctional(other, other->getAddr(), other->isSecure(),
978 other->getSize(), data);
979 }
980
981 /**
982 * Push label for PrintReq (safe to call unconditionally).
983 */
984 void
985 pushLabel(const std::string &lbl)
986 {
987 if (isPrint())
988 safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
989 }
990
991 /**
992 * Pop label for PrintReq (safe to call unconditionally).
993 */
994 void
995 popLabel()
996 {
997 if (isPrint())
998 safe_cast<PrintReqState*>(senderState)->popLabel();
999 }
1000
1001 void print(std::ostream &o, int verbosity = 0,
1002 const std::string &prefix = "") const;
1003
1004 /**
1005 * A no-args wrapper of print(std::ostream...)
1006 * meant to be invoked from DPRINTFs
1007 * avoiding string overheads in fast mode
1008 * @return string with the request's type and start<->end addresses
1009 */
1010 std::string print() const;
1011};
1012
1013#endif //__MEM_PACKET_HH
954 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
955 flags.set(DYNAMIC_DATA|ARRAY_DATA);
956 data = new uint8_t[getSize()];
957 }
958
959 /**
960 * Check a functional request against a memory value represented
961 * by a base/size pair and an associated data array. If the
962 * functional request is a read, it may be satisfied by the memory
963 * value. If the functional request is a write, it may update the
964 * memory value.
965 */
966 bool checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
967 uint8_t *data);
968
969 /**
970 * Check a functional request against a memory value stored in
971 * another packet (i.e. an in-transit request or response).
972 */
973 bool
974 checkFunctional(PacketPtr other)
975 {
976 uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL;
977 return checkFunctional(other, other->getAddr(), other->isSecure(),
978 other->getSize(), data);
979 }
980
981 /**
982 * Push label for PrintReq (safe to call unconditionally).
983 */
984 void
985 pushLabel(const std::string &lbl)
986 {
987 if (isPrint())
988 safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
989 }
990
991 /**
992 * Pop label for PrintReq (safe to call unconditionally).
993 */
994 void
995 popLabel()
996 {
997 if (isPrint())
998 safe_cast<PrintReqState*>(senderState)->popLabel();
999 }
1000
1001 void print(std::ostream &o, int verbosity = 0,
1002 const std::string &prefix = "") const;
1003
1004 /**
1005 * A no-args wrapper of print(std::ostream...)
1006 * meant to be invoked from DPRINTFs
1007 * avoiding string overheads in fast mode
1008 * @return string with the request's type and start<->end addresses
1009 */
1010 std::string print() const;
1011};
1012
1013#endif //__MEM_PACKET_HH