diff -r e9d13c5d5559 -r 168451e24941 src/mem/SConscript --- a/src/mem/SConscript Tue Dec 06 10:36:40 2011 -0600 +++ b/src/mem/SConscript Mon Dec 12 14:33:29 2011 -0600 @@ -38,6 +38,7 @@ Source('bus.cc') Source('mem_object.cc') Source('packet.cc') +Source('functional_packet.cc') Source('port.cc') Source('tport.cc') Source('mport.cc') diff -r e9d13c5d5559 -r 168451e24941 src/mem/functional_packet.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/functional_packet.hh Mon Dec 12 14:33:29 2011 -0600 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2010-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. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Geoffrey Blake + */ + +/** + * @file + * Declaration of the Functional Packet class. + */ + +#ifndef __FUNC_MEM_PACKET_HH__ +#define __FUNC_MEM_PACKET_HH__ + +#include + +#include "mem/packet.hh" + +class FunctionalPacket; +typedef FunctionalPacket * FunctionalPacketPtr; + +/** + * FunctionalPacket is a specialization of the Packet object that + * supports finding partial matches to read data, thereby eliminating + * a limitation of the standard Packet object. Meant to only + * be used for functional accesses to the memory system. Useful + * for objects like the CheckerCPU that make heavy use of functional + * accesses to the memory system. + */ +class FunctionalPacket : public Packet +{ + public: + /** + * Constructor. Same arguments and requirements as the + * base Packet class constructor. + */ + FunctionalPacket(Request *_req, MemCmd _cmd, NodeID _dest) + : Packet(_req, _cmd, _dest) + { + bytes_valid.resize(getSize()); + } + + /** + * Alternate constructor. Same arguments and requirements as base + * Packet class alt constructor. + */ + FunctionalPacket(Request *_req, MemCmd _cmd, NodeID _dest, int _blkSize) + : Packet(_req, _cmd, _dest, _blkSize) + { + bytes_valid.resize(getSize()); + } + + /** + * Alternate constructor for copying a functional packet from a + * regular packet. Same arguments and requirements as the base + * Packet class. + */ + FunctionalPacket(Packet *pkt, bool clearFlags = false) + : Packet(pkt, clearFlags) + { + bytes_valid.resize(getSize()); + } + + /** + * clean up FunctionalPacket variables + */ + ~FunctionalPacket() + { + if (req && isRequest() && !needsResponse()) + delete req; + deleteData(); + } + + /** + * 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 + * value. If the functional request is a write, it may update the + * memory value. + */ + bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data); + + bool checkFunctional(PacketPtr other) + { + uint8_t *data = other->hasData() ? other->getPtr() : NULL; + return checkFunctional(other, other->getAddr(), other->getSize(), + data); + } + + private: + /** + * A vector for tracking partial functional access completion. + */ + std::vector bytes_valid; +}; + +#endif diff -r e9d13c5d5559 -r 168451e24941 src/mem/functional_packet.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/functional_packet.cc Mon Dec 12 14:33:29 2011 -0600 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2010-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. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Geoffrey Blake + */ + +/** + * @file + * Definition of the FunctionalPacket Class. A FunctionalPacket is + * a specialization of the Packet Class to support features like + * partial functional reads. Only meant to be used with Functional + * accesses to the memory system. + */ + +#include "mem/functional_packet.hh" + +bool +FunctionalPacket::checkFunctionalComplete() +{ + bool done = true; + for (int i = 0; i < bytes_valid.size(); i++) { + if (!bytes_valid[i]) + done = false; + } + return done; +} + +bool +FunctionalPacket::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) +{ + Addr func_start = getAddr(); + Addr func_end = getAddr() + getSize() - 1; + Addr val_start = addr; + Addr val_end = val_start + size - 1; + + if (func_start > val_end || val_start > func_end) { + // no intersection + return false; + } + + // check print first since it doesn't require data + if (isPrint()) { + dynamic_cast(senderState)->printObj(obj); + return false; + } + + // if there's no data, there's no need to look further + if (!data) { + return false; + } + + // offset of functional request into supplied value (could be + // negative if partial overlap) + int offset = func_start - val_start; + + if (isRead()) { + if (func_start >= val_start && func_end <= val_end) { + allocate(); + memcpy(getPtr(), data + offset, getSize()); + return true; + } else { + // 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) { + memcpy(data + offset, getPtr(), + (std::min(func_end, val_end) - func_start) + 1); + } else { + // val_start > func_start + memcpy(data, getPtr() - offset, + (std::min(func_end, val_end) - val_start) + 1); + } + } else { + panic("Don't know how to handle command %s\n", cmdString()); + } + + // keep going with request by default + return false; +} diff -r e9d13c5d5559 -r 168451e24941 src/mem/packet.hh --- a/src/mem/packet.hh Tue Dec 06 10:36:40 2011 -0600 +++ b/src/mem/packet.hh Mon Dec 12 14:33:29 2011 -0600 @@ -798,13 +798,14 @@ * value. If the functional request is a write, it may update the * memory value. */ - bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data); + virtual bool checkFunctional(Printable *obj, Addr base, + int size, uint8_t *data); /** * Check a functional request against a memory value stored in * another packet (i.e. an in-transit request or response). */ - bool + virtual bool checkFunctional(PacketPtr other) { uint8_t *data = other->hasData() ? other->getPtr() : NULL; diff -r e9d13c5d5559 -r 168451e24941 src/mem/packet.cc --- a/src/mem/packet.cc Tue Dec 06 10:36:40 2011 -0600 +++ b/src/mem/packet.cc Mon Dec 12 14:33:29 2011 -0600 @@ -192,14 +192,11 @@ 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. + // Finding partial data not supported in Packet class. + // Use FunctionalPacket instead if this support is needed. panic("Memory value only partially satisfies the functional " - "request. Now what?"); + "request. Not supported in Packet. " + "Use FunctionalPacket instead."); } } else if (isWrite()) { if (offset >= 0) { diff -r e9d13c5d5559 -r 168451e24941 src/mem/port.hh --- a/src/mem/port.hh Tue Dec 06 10:36:40 2011 -0600 +++ b/src/mem/port.hh Mon Dec 12 14:33:29 2011 -0600 @@ -45,6 +45,7 @@ #include "base/misc.hh" #include "base/range.hh" #include "base/types.hh" +#include "mem/functional_packet.hh" #include "mem/packet.hh" #include "mem/request.hh" #include "sim/eventq.hh" diff -r e9d13c5d5559 -r 168451e24941 src/mem/port.cc --- a/src/mem/port.cc Tue Dec 06 10:36:40 2011 -0600 +++ b/src/mem/port.cc Mon Dec 12 14:33:29 2011 -0600 @@ -133,7 +133,7 @@ for (ChunkGenerator gen(addr, size, peerBlockSize()); !gen.done(); gen.next()) { req.setPhys(gen.addr(), gen.size(), 0); - Packet pkt(&req, cmd, Packet::Broadcast); + FunctionalPacket pkt(&req, cmd, Packet::Broadcast); pkt.dataStatic(p); sendFunctional(&pkt); p += gen.size();