diff -r 2e8399d5ec8f -r 49ba4bd4928c src/mem/packet.hh --- a/src/mem/packet.hh Mon Nov 21 09:28:32 2011 -0600 +++ b/src/mem/packet.hh Tue Nov 29 09:46:02 2011 -0600 @@ -42,6 +42,7 @@ #include #include #include +#include #include "base/cast.hh" #include "base/compiler.hh" @@ -267,6 +268,13 @@ */ PacketDataPtr data; + /** + * A vector for tracking partial functional access completion. + * Would use a bitset if it was able to be dynamically allocated + * since functional accesses can be arbitrary sizes. + */ + std::vector bytes_valid; + /// The address of the request. This address could be virtual or /// physical, depending on the system configuration. Addr addr; @@ -517,6 +525,7 @@ size = req->getSize(); flags.set(VALID_SIZE); } + bytes_valid.resize(size); } /** @@ -534,6 +543,7 @@ } size = _blkSize; flags.set(VALID_SIZE); + bytes_valid.resize(size); } /** @@ -554,6 +564,7 @@ flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE|VALID_SRC|VALID_DST)); flags.set(pkt->flags & STATIC_DATA); + bytes_valid.resize(size); } /** @@ -587,6 +598,8 @@ flags.set(VALID_ADDR|VALID_SIZE); deleteData(); + bytes_valid.clear(); + bytes_valid.resize(size); } /** @@ -657,6 +670,8 @@ this->size = size; flags.set(VALID_SIZE); + bytes_valid.clear(); + bytes_valid.resize(size); } @@ -792,6 +807,12 @@ } /** + * Helper function for checkFunctional to scan bit vector bytes_valid and + * determine if all data has been collected for request completion. + */ + bool checkFunctionalComplete(); + + /** * 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 diff -r 2e8399d5ec8f -r 49ba4bd4928c src/mem/packet.cc --- a/src/mem/packet.cc Mon Nov 21 09:28:32 2011 -0600 +++ b/src/mem/packet.cc Tue Nov 29 09:46:02 2011 -0600 @@ -159,6 +159,17 @@ }; bool +Packet::checkFunctionalComplete() +{ + bool done = true; + for (int i = 0; i < bytes_valid.size(); i++) { + if (!bytes_valid[i]) + done = false; + } + return done; +} + +bool Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) { Addr func_start = getAddr(); @@ -192,14 +203,40 @@ memcpy(getPtr(), data + offset, getSize()); return true; } else { - // In this case the timing packet only partially satisfies - // the request, so we would need more information to make - // this work. Like bytes valid in the packet or - // something, so the request could continue and get this - // bit of possibly newer data along with the older data - // not written to yet. - panic("Memory value only partially satisfies the functional " - "request. Now what?"); + // Offsets and sizes to copy in case of partial overlap + int func_offset; + int val_offset; + int overlap_size; + + // calculate offsets and copy sizes for the three partial overlap cases + if (val_start < func_start && val_end <= func_end) { + val_offset = func_start - val_start; + func_offset = 0; + overlap_size = val_end - func_start; + } else if (val_start >= func_start && val_end > func_end) { + val_offset = 0; + func_offset = val_start - func_start; + overlap_size = func_end - val_start; + } else if (val_start >= func_start && val_end <= func_end) { + val_offset = 0; + func_offset = val_start - func_start; + overlap_size = size; + } else { + panic("BUG: Missed a case for a partial functional request"); + } + + // copy partial data that is missing as indicated by bytes_valid mask + // and avoid copying stale data into already filled data + for (int i = 0; i < overlap_size; i++) { + if (bytes_valid[i + func_offset] == false) { + getPtr()[i + func_offset] = data[val_offset + i]; + bytes_valid[i + func_offset] = true; + } + } + // check if we're done filling the functional access + bool done = true; + done = checkFunctionalComplete(); + return done; } } else if (isWrite()) { if (offset >= 0) {