mem: Make the requests carried by packets const

This adds a basic level of sanity checking to the packet by ensuring
that a request is not modified once the packet is created. The only
issue that had to be worked around is the relaying of
software-prefetches in the cache. The specific situation is now solved
by first copying the request, and then creating a new packet
accordingly.
This commit is contained in:
Andreas Hansson 2014-12-02 06:07:50 -05:00
parent fa60d5cf27
commit a2ee51f631
2 changed files with 20 additions and 42 deletions

View file

@ -614,15 +614,18 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
// to an existing MSHR. If an outstanding request is already // to an existing MSHR. If an outstanding request is already
// in progress, there is nothing for the prefetch to do. // in progress, there is nothing for the prefetch to do.
// If this is the case, we don't even create a request at all. // If this is the case, we don't even create a request at all.
PacketPtr pf = mshr ? NULL : new Packet(pkt); PacketPtr pf = nullptr;
if (pf) { if (!mshr) {
pf->req = new Request(pkt->req->getPaddr(), // copy the request and create a new SoftPFReq packet
RequestPtr req = new Request(pkt->req->getPaddr(),
pkt->req->getSize(), pkt->req->getSize(),
pkt->req->getFlags(), pkt->req->getFlags(),
pkt->req->masterId()); pkt->req->masterId());
// The core will clean up prior senderState; we need our own. pf = new Packet(req, pkt->cmd);
pf->senderState = NULL; pf->allocate();
assert(pf->getAddr() == pkt->getAddr());
assert(pf->getSize() == pkt->getSize());
} }
pkt->makeTimingResponse(); pkt->makeTimingResponse();
@ -632,6 +635,8 @@ Cache<TagStore>::recvTimingReq(PacketPtr pkt)
std::memset(pkt->getPtr<uint8_t>(), 0xFF, pkt->getSize()); std::memset(pkt->getPtr<uint8_t>(), 0xFF, pkt->getSize());
cpuSidePort->schedTimingResp(pkt, clockEdge(lat)); cpuSidePort->schedTimingResp(pkt, clockEdge(lat));
// If an outstanding request is in progress (we found an
// MSHR) this is set to null
pkt = pf; pkt = pf;
} }

View file

@ -265,7 +265,7 @@ class Packet : public Printable
MemCmd cmd; MemCmd cmd;
/// A pointer to the original request. /// A pointer to the original request.
RequestPtr req; const RequestPtr req;
private: private:
/** /**
@ -600,7 +600,7 @@ class Packet : public Printable
* first, but the Requests's physical address and size fields need * first, but the Requests's physical address and size fields need
* not be valid. The command must be supplied. * not be valid. The command must be supplied.
*/ */
Packet(Request *_req, MemCmd _cmd) Packet(const RequestPtr _req, MemCmd _cmd)
: cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false), : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
size(0), src(InvalidPortID), dest(InvalidPortID), size(0), src(InvalidPortID), dest(InvalidPortID),
bytesValidStart(0), bytesValidEnd(0), bytesValidStart(0), bytesValidEnd(0),
@ -623,7 +623,7 @@ class Packet : public Printable
* a request that is for a whole block, not the address from the * a request that is for a whole block, not the address from the
* req. this allows for overriding the size/addr of the req. * req. this allows for overriding the size/addr of the req.
*/ */
Packet(Request *_req, MemCmd _cmd, int _blkSize) Packet(const RequestPtr _req, MemCmd _cmd, int _blkSize)
: cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false), : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
src(InvalidPortID), dest(InvalidPortID), src(InvalidPortID), dest(InvalidPortID),
bytesValidStart(0), bytesValidEnd(0), bytesValidStart(0), bytesValidEnd(0),
@ -646,7 +646,7 @@ class Packet : public Printable
* less than that of the original packet. In this case the new * less than that of the original packet. In this case the new
* packet should allocate its own data. * packet should allocate its own data.
*/ */
Packet(Packet *pkt, bool clearFlags = false) Packet(PacketPtr pkt, bool clearFlags = false)
: cmd(pkt->cmd), req(pkt->req), : cmd(pkt->cmd), req(pkt->req),
data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL), data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size), addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
@ -696,7 +696,7 @@ class Packet : public Printable
* vanilla read or write. * vanilla read or write.
*/ */
static PacketPtr static PacketPtr
createRead(Request *req) createRead(const RequestPtr req)
{ {
PacketPtr pkt = new Packet(req, MemCmd::ReadReq); PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
pkt->refineCommand(); pkt->refineCommand();
@ -704,7 +704,7 @@ class Packet : public Printable
} }
static PacketPtr static PacketPtr
createWrite(Request *req) createWrite(const RequestPtr req)
{ {
PacketPtr pkt = new Packet(req, MemCmd::WriteReq); PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
pkt->refineCommand(); pkt->refineCommand();
@ -724,33 +724,6 @@ class Packet : public Printable
deleteData(); deleteData();
} }
/**
* Reinitialize packet address and size from the associated
* Request object, and reset other fields that may have been
* modified by a previous transaction. Typically called when a
* statically allocated Request/Packet pair is reused for multiple
* transactions.
*/
void
reinitFromRequest()
{
assert(req->hasPaddr());
flags = 0;
addr = req->getPaddr();
_isSecure = req->isSecure();
size = req->getSize();
src = InvalidPortID;
dest = InvalidPortID;
bytesValidStart = 0;
bytesValidEnd = 0;
firstWordDelay = 0;
lastWordDelay = 0;
flags.set(VALID_ADDR|VALID_SIZE);
deleteData();
}
/** /**
* Take a request packet and modify it in place to be suitable for * Take a request packet and modify it in place to be suitable for
* returning as a response to that request. The source field is * returning as a response to that request. The source field is