From: Geoffrey Blake Date: Tue, 10 Jan 2012 00:10:05 +0000 (-0600) Subject: Packet: Add derived class FunctionalPacket to enable partial functional reads X-Git-Tag: stable_2012_06_28~275^2~29 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e826d23a2eae6136f20f74d8d48601ff49349e58;p=gem5.git Packet: Add derived class FunctionalPacket to enable partial functional reads This adds the derived class FunctionalPacket to fix a long standing deficiency in the Packet class where it was unable to handle finding data to partially satisfy a functional access. Made this a derived class as functional accesses are used only in certain contexts and to not add any additional overhead to the existing Packet class. --- diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 5ec977ed4..57d85af8a 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * Copyright (c) 2010 Advanced Micro Devices, Inc. * All rights reserved. @@ -192,14 +204,99 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) 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 two byte arrays + 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"); + } + + // Figure out how much of the partial overlap should be copied + // into the packet and not overwrite previously found bytes. + if (bytesValidStart == 0 && bytesValidEnd == 0) { + // No bytes have been copied yet, just set indices + // to found range + bytesValidStart = func_offset; + bytesValidEnd = func_offset + overlap_size; + } else { + // Some bytes have already been copied. Use bytesValid + // indices and offset values to figure out how much data + // to copy and where to copy it to. + + // Indice overlap conditions to check + int a = func_offset - bytesValidStart; + int b = (func_offset + overlap_size) - bytesValidEnd; + int c = func_offset - bytesValidEnd; + int d = (func_offset + overlap_size) - bytesValidStart; + + if (a >= 0 && b <= 0) { + // bytes already in pkt data array are superset of + // found bytes, will not copy any bytes + overlap_size = 0; + } else if (a < 0 && d >= 0 && b <= 0) { + // found bytes will move bytesValidStart towards 0 + overlap_size = bytesValidStart - func_offset; + bytesValidStart = func_offset; + } else if (b > 0 && c <= 0 && a >= 0) { + // found bytes will move bytesValidEnd + // towards end of pkt data array + overlap_size = + (func_offset + overlap_size) - bytesValidEnd; + val_offset += bytesValidEnd - func_offset; + func_offset = bytesValidEnd; + bytesValidEnd += overlap_size; + } else if (a < 0 && b > 0) { + // Found bytes are superset of copied range. Will move + // bytesValidStart towards 0 and bytesValidEnd towards + // end of pkt data array. Need to break copy into two + // pieces so as to not overwrite previously found data. + + // copy the first half + uint8_t *dest = getPtr() + func_offset; + uint8_t *src = data + val_offset; + memcpy(dest, src, (bytesValidStart - func_offset)); + + // re-calc the offsets and indices to do the copy + // required for the second half + val_offset += (bytesValidEnd - func_offset); + bytesValidStart = func_offset; + overlap_size = + (func_offset + overlap_size) - bytesValidEnd; + func_offset = bytesValidEnd; + bytesValidEnd += overlap_size; + } else if ((c > 0 && b > 0) + || (a < 0 && d < 0)) { + // region to be copied is discontiguous! Not supported. + panic("BUG: Discontiguous bytes found" + "for functional copying!"); + } + } + + assert((bytesValidStart >= 0) && (bytesValidEnd <= getSize())); + + // copy partial data into the packet's data array + uint8_t *dest = getPtr() + func_offset; + uint8_t *src = data + val_offset; + memcpy(dest, src, overlap_size); + + // check if we're done filling the functional access + bool done = (bytesValidStart == 0) && (bytesValidEnd == getSize()); + return done; } } else if (isWrite()) { if (offset >= 0) { diff --git a/src/mem/packet.hh b/src/mem/packet.hh index be0c20d42..6347c21ea 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -299,6 +299,13 @@ class Packet : public FastAlloc, public Printable */ MemCmd origCmd; + /** + * These values specify the range of bytes found that satisfy a + * functional read. + */ + uint16_t bytesValidStart; + uint16_t bytesValidEnd; + public: /// Used to calculate latencies for each packet. Tick time; @@ -507,7 +514,8 @@ class Packet : public FastAlloc, public Printable */ Packet(Request *_req, MemCmd _cmd, NodeID _dest) : flags(VALID_DST), cmd(_cmd), req(_req), data(NULL), - dest(_dest), time(curTick()), senderState(NULL) + dest(_dest), bytesValidStart(0), bytesValidEnd(0), + time(curTick()), senderState(NULL) { if (req->hasPaddr()) { addr = req->getPaddr(); @@ -526,7 +534,8 @@ class Packet : public FastAlloc, public Printable */ Packet(Request *_req, MemCmd _cmd, NodeID _dest, int _blkSize) : flags(VALID_DST), cmd(_cmd), req(_req), data(NULL), - dest(_dest), time(curTick()), senderState(NULL) + dest(_dest), bytesValidStart(0), bytesValidEnd(0), + time(curTick()), senderState(NULL) { if (req->hasPaddr()) { addr = req->getPaddr() & ~(_blkSize - 1); @@ -547,6 +556,7 @@ class Packet : public FastAlloc, public Printable : cmd(pkt->cmd), req(pkt->req), data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL), addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest), + bytesValidStart(pkt->bytesValidStart), bytesValidEnd(pkt->bytesValidEnd), time(curTick()), senderState(pkt->senderState) { if (!clearFlags) @@ -554,6 +564,7 @@ class Packet : public FastAlloc, public Printable flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE|VALID_SRC|VALID_DST)); flags.set(pkt->flags & STATIC_DATA); + } /**