mem: Cleanup Packet::checkFunctional and hasData usage

This patch cleans up the use of hasData and checkFunctional in the
packet. The hasData function is unfortunately suggesting that it
checks if the packet has a valid data pointer, when it does in fact
only check if the specific packet type is specified to have a data
payload. The confusion led to a bug in checkFunctional. The latter
function is also tidied up to avoid name overloading.
This commit is contained in:
Andreas Hansson 2014-12-02 06:07:52 -05:00
parent a2ee51f631
commit f012166bb6
3 changed files with 48 additions and 23 deletions

View file

@ -1481,6 +1481,10 @@ Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
if (blk == NULL) { if (blk == NULL) {
// better have read new data... // better have read new data...
assert(pkt->hasData()); assert(pkt->hasData());
// only read reaponses have data
assert(pkt->isRead());
// need to do a replacement // need to do a replacement
blk = allocateBlock(addr, is_secure, writebacks); blk = allocateBlock(addr, is_secure, writebacks);
if (blk == NULL) { if (blk == NULL) {
@ -1538,8 +1542,10 @@ Cache<TagStore>::handleFill(PacketPtr pkt, BlkType *blk,
DPRINTF(Cache, "Block addr %x (%s) moving from state %x to %s\n", DPRINTF(Cache, "Block addr %x (%s) moving from state %x to %s\n",
addr, is_secure ? "s" : "ns", old_state, blk->print()); addr, is_secure ? "s" : "ns", old_state, blk->print());
// if we got new data, copy it in // if we got new data, copy it in (checking for a read response
// and a response that has data is the same in the end)
if (pkt->isRead()) { if (pkt->isRead()) {
assert(pkt->hasData());
std::memcpy(blk->data, pkt->getConstPtr<uint8_t>(), blkSize); std::memcpy(blk->data, pkt->getConstPtr<uint8_t>(), blkSize);
} }

View file

@ -174,7 +174,7 @@ MemCmd::commandInfo[] =
bool bool
Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size, Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size,
uint8_t *data) uint8_t *_data)
{ {
Addr func_start = getAddr(); Addr func_start = getAddr();
Addr func_end = getAddr() + getSize() - 1; Addr func_end = getAddr() + getSize() - 1;
@ -189,12 +189,14 @@ Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size,
// check print first since it doesn't require data // check print first since it doesn't require data
if (isPrint()) { if (isPrint()) {
assert(!_data);
safe_cast<PrintReqState*>(senderState)->printObj(obj); safe_cast<PrintReqState*>(senderState)->printObj(obj);
return false; return false;
} }
// if there's no data, there's no need to look further // we allow the caller to pass NULL to signify the other packet
if (!data) { // has no data
if (!_data) {
return false; return false;
} }
@ -204,7 +206,9 @@ Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size,
if (isRead()) { if (isRead()) {
if (func_start >= val_start && func_end <= val_end) { if (func_start >= val_start && func_end <= val_end) {
memcpy(getPtr<uint8_t>(), data + offset, getSize()); memcpy(getPtr<uint8_t>(), _data + offset, getSize());
// complete overlap, and as the current packet is a read
// we are done
return true; return true;
} else { } else {
// Offsets and sizes to copy in case of partial overlap // Offsets and sizes to copy in case of partial overlap
@ -271,7 +275,7 @@ Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size,
// copy the first half // copy the first half
uint8_t *dest = getPtr<uint8_t>() + func_offset; uint8_t *dest = getPtr<uint8_t>() + func_offset;
uint8_t *src = data + val_offset; uint8_t *src = _data + val_offset;
memcpy(dest, src, (bytesValidStart - func_offset)); memcpy(dest, src, (bytesValidStart - func_offset));
// re-calc the offsets and indices to do the copy // re-calc the offsets and indices to do the copy
@ -293,7 +297,7 @@ Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size,
// copy partial data into the packet's data array // copy partial data into the packet's data array
uint8_t *dest = getPtr<uint8_t>() + func_offset; uint8_t *dest = getPtr<uint8_t>() + func_offset;
uint8_t *src = data + val_offset; uint8_t *src = _data + val_offset;
memcpy(dest, src, overlap_size); memcpy(dest, src, overlap_size);
// check if we're done filling the functional access // check if we're done filling the functional access
@ -302,11 +306,11 @@ Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size,
} }
} else if (isWrite()) { } else if (isWrite()) {
if (offset >= 0) { if (offset >= 0) {
memcpy(data + offset, getConstPtr<uint8_t>(), memcpy(_data + offset, getConstPtr<uint8_t>(),
(min(func_end, val_end) - func_start) + 1); (min(func_end, val_end) - func_start) + 1);
} else { } else {
// val_start > func_start // val_start > func_start
memcpy(data, getConstPtr<uint8_t>() - offset, memcpy(_data, getConstPtr<uint8_t>() - offset,
(min(func_end, val_end) - val_start) + 1); (min(func_end, val_end) - val_start) + 1);
} }
} else { } else {

View file

@ -185,6 +185,12 @@ class MemCmd
bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); } bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
bool needsResponse() const { return testCmdAttrib(NeedsResponse); } bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
bool isInvalidate() const { return testCmdAttrib(IsInvalidate); } bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
/**
* Check if this particular packet type carries payload data. Note
* that this does not reflect if the data pointer of the packet is
* valid or not.
*/
bool hasData() const { return testCmdAttrib(HasData); } bool hasData() const { return testCmdAttrib(HasData); }
bool isLLSC() const { return testCmdAttrib(IsLlsc); } bool isLLSC() const { return testCmdAttrib(IsLlsc); }
bool isSWPrefetch() const { return testCmdAttrib(IsSWPrefetch); } bool isSWPrefetch() const { return testCmdAttrib(IsSWPrefetch); }
@ -917,28 +923,37 @@ class Packet : public Printable
data = new uint8_t[getSize()]; data = new uint8_t[getSize()];
} }
/**
* Check a functional request against a memory value represented
* by a base/size pair and an associated data array. If the
* functional request is a read, it may be satisfied by the memory
* value. If the functional request is a write, it may update the
* memory value.
*/
bool checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
uint8_t *data);
/** /**
* Check a functional request against a memory value stored in * Check a functional request against a memory value stored in
* another packet (i.e. an in-transit request or response). * another packet (i.e. an in-transit request or
* response). Returns true if the current packet is a read, and
* the other packet provides the data, which is then copied to the
* current packet. If the current packet is a write, and the other
* packet intersects this one, then we update the data
* accordingly.
*/ */
bool bool
checkFunctional(PacketPtr other) checkFunctional(PacketPtr other)
{ {
uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL; // all packets that are carrying a payload should have a valid
// data pointer
return checkFunctional(other, other->getAddr(), other->isSecure(), return checkFunctional(other, other->getAddr(), other->isSecure(),
other->getSize(), data); other->getSize(),
other->hasData() ?
other->getPtr<uint8_t>() : NULL);
} }
/**
* Check a functional request against a memory value represented
* by a base/size pair and an associated data array. If the
* current packet is a read, it may be satisfied by the memory
* value. If the current packet is a write, it may update the
* memory value.
*/
bool
checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
uint8_t *_data);
/** /**
* Push label for PrintReq (safe to call unconditionally). * Push label for PrintReq (safe to call unconditionally).
*/ */