First Pass At Cmp/Swap in caches

--HG--
extra : convert_revision : 211bfb7c6a59e9e120dae1600d4754baaf231332
This commit is contained in:
Ron Dreslinski 2007-03-27 17:05:25 -05:00
parent c6e85efc50
commit 6b8cd9d06d
3 changed files with 65 additions and 6 deletions

View file

@ -227,6 +227,12 @@ class Cache : public BaseCache
BlkType* handleAccess(PacketPtr &pkt, int & lat, BlkType* handleAccess(PacketPtr &pkt, int & lat,
PacketList & writebacks, bool update = true); PacketList & writebacks, bool update = true);
/**
*Handle doing the Compare and Swap function for SPARC.
*/
void cmpAndSwap(BlkType *blk, PacketPtr &pkt);
/** /**
* Populates a cache block and handles all outstanding requests for the * Populates a cache block and handles all outstanding requests for the
* satisfied fill request. This version takes an MSHR pointer and uses its * satisfied fill request. This version takes an MSHR pointer and uses its

View file

@ -122,12 +122,15 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
if (blk != NULL) { if (blk != NULL) {
if (!update) { if (!update) {
if (pkt->isWrite()){ if (pkt->isWrite()){
assert(offset < blkSize); assert(offset < blkSize);
assert(pkt->getSize() <= blkSize); assert(pkt->getSize() <= blkSize);
assert(offset+pkt->getSize() <= blkSize); assert(offset+pkt->getSize() <= blkSize);
std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(), std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(),
pkt->getSize()); pkt->getSize());
} else if (pkt->isReadWrite()) {
cmpAndSwap(blk, pkt);
} else if (!(pkt->flags & SATISFIED)) { } else if (!(pkt->flags & SATISFIED)) {
pkt->flags |= SATISFIED; pkt->flags |= SATISFIED;
pkt->result = Packet::Success; pkt->result = Packet::Success;
@ -154,7 +157,8 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
} }
} }
if ((pkt->isWrite() && blk->isWritable()) || if ((pkt->isReadWrite() && blk->isWritable()) ||
(pkt->isWrite() && blk->isWritable()) ||
(pkt->isRead() && blk->isValid())) { (pkt->isRead() && blk->isValid())) {
// We are satisfying the request // We are satisfying the request
@ -180,13 +184,15 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(), std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(),
pkt->getSize()); pkt->getSize());
} }
} else if (pkt->isReadWrite()) {
cmpAndSwap(blk, pkt);
} else { } else {
assert(pkt->isRead()); assert(pkt->isRead());
if (pkt->req->isLocked()) { if (pkt->req->isLocked()) {
blk->trackLoadLocked(pkt->req); blk->trackLoadLocked(pkt->req);
} }
std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset, std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset,
pkt->getSize()); pkt->getSize());
} }
if (write_data || if (write_data ||
@ -214,6 +220,44 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
return blk; return blk;
} }
template<class TagStore, class Coherence>
void
Cache<TagStore,Coherence>::cmpAndSwap(BlkType *blk, PacketPtr &pkt){
uint64_t overwrite_val;
bool overwrite_mem;
uint64_t condition_val64;
uint32_t condition_val32;
int offset = tags->extractBlkOffset(pkt->getAddr());
assert(sizeof(uint64_t) >= pkt->getSize());
overwrite_mem = true;
// keep a copy of our possible write value, and copy what is at the
// memory address into the packet
std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset,
pkt->getSize());
if (pkt->req->isCondSwap()) {
if (pkt->getSize() == sizeof(uint64_t)) {
condition_val64 = pkt->req->getExtraData();
overwrite_mem = !std::memcmp(&condition_val64, blk->data + offset,
sizeof(uint64_t));
} else if (pkt->getSize() == sizeof(uint32_t)) {
condition_val32 = (uint32_t)pkt->req->getExtraData();
overwrite_mem = !std::memcmp(&condition_val32, blk->data + offset,
sizeof(uint32_t));
} else
panic("Invalid size for conditional read/write\n");
}
if (overwrite_mem)
std::memcpy(blk->data + offset,
&overwrite_val, pkt->getSize());
}
template<class TagStore, class Coherence> template<class TagStore, class Coherence>
typename Cache<TagStore,Coherence>::BlkType* typename Cache<TagStore,Coherence>::BlkType*
Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt, Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt,
@ -244,8 +288,9 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt,
blk = NULL; blk = NULL;
} }
if (blk && (target->isWrite() ? blk->isWritable() : blk->isValid())) { if (blk && ((target->isWrite() || target->isReadWrite()) ?
assert(target->isWrite() || target->isRead()); blk->isWritable() : blk->isValid())) {
assert(target->isWrite() || target->isReadWrite() || target->isRead());
assert(target->getOffset(blkSize) + target->getSize() <= blkSize); assert(target->getOffset(blkSize) + target->getSize() <= blkSize);
if (target->isWrite()) { if (target->isWrite()) {
if (blk->checkWrite(pkt->req)) { if (blk->checkWrite(pkt->req)) {
@ -253,6 +298,8 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt,
std::memcpy(blk->data + target->getOffset(blkSize), std::memcpy(blk->data + target->getOffset(blkSize),
target->getPtr<uint8_t>(), target->getSize()); target->getPtr<uint8_t>(), target->getSize());
} }
} else if (target->isReadWrite()) {
cmpAndSwap(blk, pkt);
} else { } else {
if (pkt->req->isLocked()) { if (pkt->req->isLocked()) {
blk->trackLoadLocked(pkt->req); blk->trackLoadLocked(pkt->req);
@ -332,8 +379,9 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr,
continue; continue;
} }
if (blk && (target->isWrite() ? blk->isWritable() : blk->isValid())) { if (blk && ((target->isWrite() || target->isReadWrite()) ?
assert(target->isWrite() || target->isRead()); blk->isWritable() : blk->isValid())) {
assert(target->isWrite() || target->isRead() || target->isReadWrite() );
assert(target->getOffset(blkSize) + target->getSize() <= blkSize); assert(target->getOffset(blkSize) + target->getSize() <= blkSize);
if (target->isWrite()) { if (target->isWrite()) {
if (blk->checkWrite(pkt->req)) { if (blk->checkWrite(pkt->req)) {
@ -341,6 +389,8 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr,
std::memcpy(blk->data + target->getOffset(blkSize), std::memcpy(blk->data + target->getOffset(blkSize),
target->getPtr<uint8_t>(), target->getSize()); target->getPtr<uint8_t>(), target->getSize());
} }
} else if (target->isReadWrite()) {
cmpAndSwap(blk, pkt);
} else { } else {
if (target->req->isLocked()) { if (target->req->isLocked()) {
blk->trackLoadLocked(target->req); blk->trackLoadLocked(target->req);

View file

@ -295,9 +295,12 @@ CoherenceProtocol::CoherenceProtocol(const string &name,
tt[Invalid][MC::ReadReq].onRequest(MC::ReadReq); tt[Invalid][MC::ReadReq].onRequest(MC::ReadReq);
// we only support write allocate right now // we only support write allocate right now
tt[Invalid][MC::WriteReq].onRequest(MC::ReadExReq); tt[Invalid][MC::WriteReq].onRequest(MC::ReadExReq);
tt[Invalid][MC::SwapReq].onRequest(MC::ReadExReq);
tt[Shared][MC::WriteReq].onRequest(writeToSharedCmd); tt[Shared][MC::WriteReq].onRequest(writeToSharedCmd);
tt[Shared][MC::SwapReq].onRequest(writeToSharedCmd);
if (hasOwned) { if (hasOwned) {
tt[Owned][MC::WriteReq].onRequest(writeToSharedCmd); tt[Owned][MC::WriteReq].onRequest(writeToSharedCmd);
tt[Owned][MC::SwapReq].onRequest(writeToSharedCmd);
} }
// Prefetching causes a read // Prefetching causes a read