packet.hh (4622:f681e10844f3) packet.hh (4626:ed8aacb19c03)
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 40 unchanged lines hidden (view full) ---

49#include "sim/core.hh"
50
51
52struct Packet;
53typedef Packet *PacketPtr;
54typedef uint8_t* PacketDataPtr;
55typedef std::list<PacketPtr> PacketList;
56
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 40 unchanged lines hidden (view full) ---

49#include "sim/core.hh"
50
51
52struct Packet;
53typedef Packet *PacketPtr;
54typedef uint8_t* PacketDataPtr;
55typedef std::list<PacketPtr> PacketList;
56
57//Coherence Flags
58#define NACKED_LINE (1 << 0)
59#define SATISFIED (1 << 1)
60#define SHARED_LINE (1 << 2)
61#define CACHE_LINE_FILL (1 << 3)
62#define COMPRESSED (1 << 4)
63#define NO_ALLOCATE (1 << 5)
64
65#define EXPRESS_SNOOP (1 << 7)
66
67class MemCmd
68{
69 public:
70
71 /** List of all commands associated with a packet. */
72 enum Command
73 {
74 InvalidCmd,
75 ReadReq,
76 ReadResp,
77 WriteReq,
78 WriteResp,
79 Writeback,
80 WritebackAck,
81 SoftPFReq,
82 HardPFReq,
83 SoftPFResp,
84 HardPFResp,
57class MemCmd
58{
59 public:
60
61 /** List of all commands associated with a packet. */
62 enum Command
63 {
64 InvalidCmd,
65 ReadReq,
66 ReadResp,
67 WriteReq,
68 WriteResp,
69 Writeback,
70 WritebackAck,
71 SoftPFReq,
72 HardPFReq,
73 SoftPFResp,
74 HardPFResp,
85 InvalidateReq,
86 WriteInvalidateReq,
87 WriteInvalidateResp,
88 UpgradeReq,
89 ReadExReq,
90 ReadExResp,
75 WriteInvalidateReq,
76 WriteInvalidateResp,
77 UpgradeReq,
78 ReadExReq,
79 ReadExResp,
80 LoadLockedReq,
81 LoadLockedResp,
82 StoreCondReq,
83 StoreCondResp,
91 SwapReq,
92 SwapResp,
93 NUM_MEM_CMDS
94 };
95
96 private:
97 /** List of command attributes. */
98 enum Attribute
99 {
84 SwapReq,
85 SwapResp,
86 NUM_MEM_CMDS
87 };
88
89 private:
90 /** List of command attributes. */
91 enum Attribute
92 {
100 IsRead,
101 IsWrite,
102 IsPrefetch,
93 IsRead, //!< Data flows from responder to requester
94 IsWrite, //!< Data flows from requester to responder
95 IsPrefetch, //!< Not a demand access
103 IsInvalidate,
96 IsInvalidate,
104 IsRequest,
105 IsResponse,
106 NeedsResponse,
97 NeedsExclusive, //!< Requires exclusive copy to complete in-cache
98 IsRequest, //!< Issued by requester
99 IsResponse, //!< Issue by responder
100 NeedsResponse, //!< Requester needs response from target
107 IsSWPrefetch,
108 IsHWPrefetch,
109 IsUpgrade,
101 IsSWPrefetch,
102 IsHWPrefetch,
103 IsUpgrade,
110 HasData,
111 IsReadWrite,
104 IsLocked, //!< Alpha/MIPS LL or SC access
105 HasData, //!< There is an associated payload
112 NUM_COMMAND_ATTRIBUTES
113 };
114
115 /** Structure that defines attributes and other data associated
116 * with a Command. */
117 struct CommandInfo {
118 /** Set of attribute flags. */
119 const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;

--- 16 unchanged lines hidden (view full) ---

136 }
137
138 public:
139
140 bool isRead() const { return testCmdAttrib(IsRead); }
141 bool isWrite() const { return testCmdAttrib(IsWrite); }
142 bool isRequest() const { return testCmdAttrib(IsRequest); }
143 bool isResponse() const { return testCmdAttrib(IsResponse); }
106 NUM_COMMAND_ATTRIBUTES
107 };
108
109 /** Structure that defines attributes and other data associated
110 * with a Command. */
111 struct CommandInfo {
112 /** Set of attribute flags. */
113 const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;

--- 16 unchanged lines hidden (view full) ---

130 }
131
132 public:
133
134 bool isRead() const { return testCmdAttrib(IsRead); }
135 bool isWrite() const { return testCmdAttrib(IsWrite); }
136 bool isRequest() const { return testCmdAttrib(IsRequest); }
137 bool isResponse() const { return testCmdAttrib(IsResponse); }
138 bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
144 bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
145 bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
146 bool hasData() const { return testCmdAttrib(HasData); }
139 bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
140 bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
141 bool hasData() const { return testCmdAttrib(HasData); }
147 bool isReadWrite() const { return testCmdAttrib(IsReadWrite); }
142 bool isReadWrite() const { return isRead() && isWrite(); }
143 bool isLocked() const { return testCmdAttrib(IsLocked); }
148
149 const Command responseCommand() const {
150 return commandInfo[cmd].response;
151 }
152
153 /** Return the string to a cmd given by idx. */
154 const std::string &toString() const {
155 return commandInfo[cmd].str;

--- 27 unchanged lines hidden (view full) ---

183 * different Packets along the way.)
184 */
185class Packet
186{
187 public:
188
189 typedef MemCmd::Command Command;
190
144
145 const Command responseCommand() const {
146 return commandInfo[cmd].response;
147 }
148
149 /** Return the string to a cmd given by idx. */
150 const std::string &toString() const {
151 return commandInfo[cmd].str;

--- 27 unchanged lines hidden (view full) ---

179 * different Packets along the way.)
180 */
181class Packet
182{
183 public:
184
185 typedef MemCmd::Command Command;
186
191 /** Temporary FLAGS field until cache gets working, this should be in coherence/sender state. */
192 uint64_t flags;
193
194 private:
195 /** A pointer to the data being transfered. It can be differnt
196 * sizes at each level of the heirarchy so it belongs in the
197 * packet, not request. This may or may not be populated when a
198 * responder recieves the packet. If not populated it memory
199 * should be allocated.
200 */
201 PacketDataPtr data;

--- 28 unchanged lines hidden (view full) ---

230 * (unlike * addr, size, and src). */
231 short dest;
232
233 /** Are the 'addr' and 'size' fields valid? */
234 bool addrSizeValid;
235 /** Is the 'src' field valid? */
236 bool srcValid;
237
187 private:
188 /** A pointer to the data being transfered. It can be differnt
189 * sizes at each level of the heirarchy so it belongs in the
190 * packet, not request. This may or may not be populated when a
191 * responder recieves the packet. If not populated it memory
192 * should be allocated.
193 */
194 PacketDataPtr data;

--- 28 unchanged lines hidden (view full) ---

223 * (unlike * addr, size, and src). */
224 short dest;
225
226 /** Are the 'addr' and 'size' fields valid? */
227 bool addrSizeValid;
228 /** Is the 'src' field valid? */
229 bool srcValid;
230
231 enum SnoopFlag {
232 MemInhibit,
233 Shared,
234 NUM_SNOOP_FLAGS
235 };
238
236
237 /** Coherence snoopFlags for snooping */
238 std::bitset<NUM_SNOOP_FLAGS> snoopFlags;
239
239 public:
240
241 /** Used to calculate latencies for each packet.*/
242 Tick time;
243
244 /** The time at which the packet will be fully transmitted */
245 Tick finishTime;
246

--- 49 unchanged lines hidden (view full) ---

296 inline int cmdToIndex() const { return cmd.toInt(); }
297
298 public:
299
300 bool isRead() const { return cmd.isRead(); }
301 bool isWrite() const { return cmd.isWrite(); }
302 bool isRequest() const { return cmd.isRequest(); }
303 bool isResponse() const { return cmd.isResponse(); }
240 public:
241
242 /** Used to calculate latencies for each packet.*/
243 Tick time;
244
245 /** The time at which the packet will be fully transmitted */
246 Tick finishTime;
247

--- 49 unchanged lines hidden (view full) ---

297 inline int cmdToIndex() const { return cmd.toInt(); }
298
299 public:
300
301 bool isRead() const { return cmd.isRead(); }
302 bool isWrite() const { return cmd.isWrite(); }
303 bool isRequest() const { return cmd.isRequest(); }
304 bool isResponse() const { return cmd.isResponse(); }
305 bool needsExclusive() const { return cmd.needsExclusive(); }
304 bool needsResponse() const { return cmd.needsResponse(); }
305 bool isInvalidate() const { return cmd.isInvalidate(); }
306 bool hasData() const { return cmd.hasData(); }
307 bool isReadWrite() const { return cmd.isReadWrite(); }
306 bool needsResponse() const { return cmd.needsResponse(); }
307 bool isInvalidate() const { return cmd.isInvalidate(); }
308 bool hasData() const { return cmd.hasData(); }
309 bool isReadWrite() const { return cmd.isReadWrite(); }
310 bool isLocked() const { return cmd.isLocked(); }
308
311
309 bool isCacheFill() const { return (flags & CACHE_LINE_FILL) != 0; }
310 bool isNoAllocate() const { return (flags & NO_ALLOCATE) != 0; }
311 bool isCompressed() const { return (flags & COMPRESSED) != 0; }
312 void assertMemInhibit() { snoopFlags[MemInhibit] = true; }
313 void assertShared() { snoopFlags[Shared] = true; }
314 bool memInhibitAsserted() { return snoopFlags[MemInhibit]; }
315 bool sharedAsserted() { return snoopFlags[Shared]; }
312
313 bool nic_pkt() { panic("Unimplemented"); M5_DUMMY_RETURN }
314
315 /** Possible results of a packet's request. */
316 enum Result
317 {
318 Success,
319 BadAddress,
320 Nacked,
321 Unknown
322 };
323
324 /** The result of this packet's request. */
325 Result result;
326
327 /** Accessor function that returns the source index of the packet. */
328 short getSrc() const { assert(srcValid); return src; }
329 void setSrc(short _src) { src = _src; srcValid = true; }
316
317 bool nic_pkt() { panic("Unimplemented"); M5_DUMMY_RETURN }
318
319 /** Possible results of a packet's request. */
320 enum Result
321 {
322 Success,
323 BadAddress,
324 Nacked,
325 Unknown
326 };
327
328 /** The result of this packet's request. */
329 Result result;
330
331 /** Accessor function that returns the source index of the packet. */
332 short getSrc() const { assert(srcValid); return src; }
333 void setSrc(short _src) { src = _src; srcValid = true; }
334 /** Reset source field, e.g. to retransmit packet on different bus. */
335 void clearSrc() { srcValid = false; }
330
331 /** Accessor function that returns the destination index of
332 the packet. */
333 short getDest() const { return dest; }
334 void setDest(short _dest) { dest = _dest; }
335
336 Addr getAddr() const { assert(addrSizeValid); return addr; }
337 int getSize() const { assert(addrSizeValid); return size; }

--- 4 unchanged lines hidden (view full) ---

342
343 /** Constructor. Note that a Request object must be constructed
344 * first, but the Requests's physical address and size fields
345 * need not be valid. The command and destination addresses
346 * must be supplied. */
347 Packet(Request *_req, MemCmd _cmd, short _dest)
348 : data(NULL), staticData(false), dynamicData(false), arrayData(false),
349 addr(_req->paddr), size(_req->size), dest(_dest),
336
337 /** Accessor function that returns the destination index of
338 the packet. */
339 short getDest() const { return dest; }
340 void setDest(short _dest) { dest = _dest; }
341
342 Addr getAddr() const { assert(addrSizeValid); return addr; }
343 int getSize() const { assert(addrSizeValid); return size; }

--- 4 unchanged lines hidden (view full) ---

348
349 /** Constructor. Note that a Request object must be constructed
350 * first, but the Requests's physical address and size fields
351 * need not be valid. The command and destination addresses
352 * must be supplied. */
353 Packet(Request *_req, MemCmd _cmd, short _dest)
354 : data(NULL), staticData(false), dynamicData(false), arrayData(false),
355 addr(_req->paddr), size(_req->size), dest(_dest),
350 addrSizeValid(_req->validPaddr),
351 srcValid(false),
356 addrSizeValid(_req->validPaddr), srcValid(false),
357 snoopFlags(0),
358 time(curTick),
352 req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
353 result(Unknown)
354 {
359 req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
360 result(Unknown)
361 {
355 flags = 0;
356 time = curTick;
357 }
358
359 /** Alternate constructor if you are trying to create a packet with
360 * a request that is for a whole block, not the address from the req.
361 * this allows for overriding the size/addr of the req.*/
362 Packet(Request *_req, MemCmd _cmd, short _dest, int _blkSize)
363 : data(NULL), staticData(false), dynamicData(false), arrayData(false),
362 }
363
364 /** Alternate constructor if you are trying to create a packet with
365 * a request that is for a whole block, not the address from the req.
366 * this allows for overriding the size/addr of the req.*/
367 Packet(Request *_req, MemCmd _cmd, short _dest, int _blkSize)
368 : data(NULL), staticData(false), dynamicData(false), arrayData(false),
364 addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize),
365 dest(_dest),
369 addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest),
366 addrSizeValid(_req->validPaddr), srcValid(false),
370 addrSizeValid(_req->validPaddr), srcValid(false),
371 snoopFlags(0),
372 time(curTick),
367 req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
368 result(Unknown)
369 {
373 req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
374 result(Unknown)
375 {
370 flags = 0;
371 time = curTick;
372 }
373
376 }
377
378 /** Alternate constructor for copying a packet. Copy all fields
379 * *except* set data allocation as static... even if the original
380 * packet's data was dynamic, we don't want to free it when the
381 * new packet is deallocated. Note that if original packet used
382 * dynamic data, user must guarantee that the new packet's
383 * lifetime is less than that of the original packet. */
384 Packet(Packet *origPkt)
385 : data(NULL), staticData(false), dynamicData(false), arrayData(false),
386 addr(origPkt->addr), size(origPkt->size),
387 dest(origPkt->dest),
388 addrSizeValid(origPkt->addrSizeValid), srcValid(origPkt->srcValid),
389 snoopFlags(origPkt->snoopFlags),
390 time(curTick),
391 req(origPkt->req), coherence(origPkt->coherence),
392 senderState(origPkt->senderState), cmd(origPkt->cmd),
393 result(origPkt->result)
394 {
395 }
396
374 /** Destructor. */
375 ~Packet()
376 { if (staticData || dynamicData) deleteData(); }
377
378 /** Reinitialize packet address and size from the associated
379 * Request object, and reset other fields that may have been
380 * modified by a previous transaction. Typically called when a
381 * statically allocated Request/Packet pair is reused for
382 * multiple transactions. */
383 void reinitFromRequest() {
384 assert(req->validPaddr);
397 /** Destructor. */
398 ~Packet()
399 { if (staticData || dynamicData) deleteData(); }
400
401 /** Reinitialize packet address and size from the associated
402 * Request object, and reset other fields that may have been
403 * modified by a previous transaction. Typically called when a
404 * statically allocated Request/Packet pair is reused for
405 * multiple transactions. */
406 void reinitFromRequest() {
407 assert(req->validPaddr);
385 flags = 0;
408 snoopFlags = 0;
386 addr = req->paddr;
387 size = req->size;
388 time = req->time;
389 addrSizeValid = true;
390 result = Unknown;
391 if (dynamicData) {
392 deleteData();
393 dynamicData = false;
394 arrayData = false;
395 }
396 }
397
409 addr = req->paddr;
410 size = req->size;
411 time = req->time;
412 addrSizeValid = true;
413 result = Unknown;
414 if (dynamicData) {
415 deleteData();
416 dynamicData = false;
417 arrayData = false;
418 }
419 }
420
398 /** Take a request packet and modify it in place to be suitable
399 * for returning as a response to that request. Used for timing
400 * accesses only. For atomic and functional accesses, the
401 * request packet is always implicitly passed back *without*
402 * modifying the destination fields, so this function
403 * should not be called. */
404 void makeTimingResponse() {
421 /**
422 * Take a request packet and modify it in place to be suitable for
423 * returning as a response to that request. The source and
424 * destination fields are *not* modified, as is appropriate for
425 * atomic accesses.
426 */
427 void makeAtomicResponse()
428 {
405 assert(needsResponse());
406 assert(isRequest());
429 assert(needsResponse());
430 assert(isRequest());
431 assert(result == Unknown);
407 cmd = cmd.responseCommand();
432 cmd = cmd.responseCommand();
433 result = Success;
434 }
435
436 /**
437 * Perform the additional work required for timing responses above
438 * and beyond atomic responses; i.e., change the destination to
439 * point back to the requester and clear the source field.
440 */
441 void convertAtomicToTimingResponse()
442 {
408 dest = src;
409 srcValid = false;
410 }
411
412 /**
413 * Take a request packet and modify it in place to be suitable for
443 dest = src;
444 srcValid = false;
445 }
446
447 /**
448 * Take a request packet and modify it in place to be suitable for
414 * returning as a response to that request.
449 * returning as a response to a timing request.
415 */
450 */
416 void makeAtomicResponse()
451 void makeTimingResponse()
417 {
452 {
418 assert(needsResponse());
419 assert(isRequest());
420 cmd = cmd.responseCommand();
453 makeAtomicResponse();
454 convertAtomicToTimingResponse();
421 }
422
423 /**
424 * Take a request packet that has been returned as NACKED and
425 * modify it so that it can be sent out again. Only packets that
426 * need a response can be NACKED, so verify that that is true.
427 */
428 void

--- 60 unchanged lines hidden (view full) ---

489 template <typename T>
490 T get();
491
492 /** set the value in the data pointer to v. */
493 template <typename T>
494 void set(T v);
495
496 /**
455 }
456
457 /**
458 * Take a request packet that has been returned as NACKED and
459 * modify it so that it can be sent out again. Only packets that
460 * need a response can be NACKED, so verify that that is true.
461 */
462 void

--- 60 unchanged lines hidden (view full) ---

523 template <typename T>
524 T get();
525
526 /** set the value in the data pointer to v. */
527 template <typename T>
528 void set(T v);
529
530 /**
531 * Copy data into the packet from the provided pointer.
532 */
533 void setData(uint8_t *p)
534 {
535 std::memcpy(getPtr<uint8_t>(), p, getSize());
536 }
537
538 /**
539 * Copy data into the packet from the provided block pointer,
540 * which is aligned to the given block size.
541 */
542 void setDataFromBlock(uint8_t *blk_data, int blkSize)
543 {
544 setData(blk_data + getOffset(blkSize));
545 }
546
547 /**
548 * Copy data from the packet to the provided block pointer, which
549 * is aligned to the given block size.
550 */
551 void writeData(uint8_t *p)
552 {
553 std::memcpy(p, getPtr<uint8_t>(), getSize());
554 }
555
556 /**
557 * Copy data from the packet to the memory at the provided pointer.
558 */
559 void writeDataToBlock(uint8_t *blk_data, int blkSize)
560 {
561 writeData(blk_data + getOffset(blkSize));
562 }
563
564 /**
497 * delete the data pointed to in the data pointer. Ok to call to
498 * matter how data was allocted.
499 */
500 void deleteData();
501
502 /** If there isn't data in the packet, allocate some. */
503 void allocate();
504
505 /** Do the packet modify the same addresses. */
506 bool intersect(PacketPtr p);
565 * delete the data pointed to in the data pointer. Ok to call to
566 * matter how data was allocted.
567 */
568 void deleteData();
569
570 /** If there isn't data in the packet, allocate some. */
571 void allocate();
572
573 /** Do the packet modify the same addresses. */
574 bool intersect(PacketPtr p);
575
576 /**
577 * Check a functional request against a memory value represented
578 * by a base/size pair and an associated data array. If the
579 * functional request is a read, it may be satisfied by the memory
580 * value. If the functional request is a write, it may update the
581 * memory value.
582 */
583 bool checkFunctional(Addr base, int size, uint8_t *data);
584
585 /**
586 * Check a functional request against a memory value stored in
587 * another packet (i.e. an in-transit request or response).
588 */
589 bool checkFunctional(PacketPtr otherPkt) {
590 return (otherPkt->hasData() &&
591 checkFunctional(otherPkt->getAddr(), otherPkt->getSize(),
592 otherPkt->getPtr<uint8_t>()));
593 }
507};
508
594};
595
509/** This function given a functional packet and a timing packet either
510 * satisfies the timing packet, or updates the timing packet to
511 * reflect the updated state in the timing packet. It returns if the
512 * functional packet should continue to traverse the memory hierarchy
513 * or not.
596
597
598/** Temporary for backwards compatibility.
514 */
599 */
515bool fixPacket(PacketPtr func, PacketPtr timing);
600inline
601bool fixPacket(PacketPtr func, PacketPtr timing) {
602 return !func->checkFunctional(timing);
603}
516
517/** This function is a wrapper for the fixPacket field that toggles
518 * the hasData bit it is used when a response is waiting in the
519 * caches, but hasn't been marked as a response yet (so the fixPacket
520 * needs to get the correct value for the hasData)
521 */
522bool fixDelayedResponsePacket(PacketPtr func, PacketPtr timing);
523
524std::ostream & operator<<(std::ostream &o, const Packet &p);
525
526#endif //__MEM_PACKET_HH
604
605/** This function is a wrapper for the fixPacket field that toggles
606 * the hasData bit it is used when a response is waiting in the
607 * caches, but hasn't been marked as a response yet (so the fixPacket
608 * needs to get the correct value for the hasData)
609 */
610bool fixDelayedResponsePacket(PacketPtr func, PacketPtr timing);
611
612std::ostream & operator<<(std::ostream &o, const Packet &p);
613
614#endif //__MEM_PACKET_HH