diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/bus.cc | 7 | ||||
-rw-r--r-- | src/mem/cache/base_cache.cc | 68 | ||||
-rw-r--r-- | src/mem/cache/base_cache.hh | 27 | ||||
-rw-r--r-- | src/mem/cache/cache_blk.hh | 19 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 14 | ||||
-rw-r--r-- | src/mem/cache/coherence/uni_coherence.cc | 14 | ||||
-rw-r--r-- | src/mem/cache/miss/miss_queue.cc | 2 | ||||
-rw-r--r-- | src/mem/packet.cc | 93 | ||||
-rw-r--r-- | src/mem/packet.hh | 57 | ||||
-rw-r--r-- | src/mem/physical.cc | 4 | ||||
-rw-r--r-- | src/mem/tport.cc | 18 |
11 files changed, 222 insertions, 101 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 75ffed0d2..b11b6de58 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -320,7 +320,7 @@ Bus::functionalSnoop(Packet *pkt) { std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); - while (!ports.empty()) + while (!ports.empty() && pkt->result != Packet::Success) { interfaces[ports.back()]->sendFunctional(pkt); ports.pop_back(); @@ -367,7 +367,10 @@ Bus::recvFunctional(Packet *pkt) pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); assert(pkt->getDest() == Packet::Broadcast); functionalSnoop(pkt); - findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt); + + // If the snooping found what we were looking for, we're done. + if (pkt->result != Packet::Success) + findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt); } /** Function called by the port when the bus is receiving a status change.*/ diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index 71ea58416..3f7a52fab 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -107,6 +107,42 @@ BaseCache::CachePort::recvAtomic(Packet *pkt) void BaseCache::CachePort::recvFunctional(Packet *pkt) { + //Check storage here first + list<Packet *>::iterator i = drainList.begin(); + list<Packet *>::iterator end = drainList.end(); + for (; i != end; ++i) { + Packet * target = *i; + // If the target contains data, and it overlaps the + // probed request, need to update data + if (target->intersect(pkt)) { + uint8_t* pkt_data; + uint8_t* write_data; + int data_size; + if (target->getAddr() < pkt->getAddr()) { + int offset = pkt->getAddr() - target->getAddr(); + pkt_data = pkt->getPtr<uint8_t>(); + write_data = target->getPtr<uint8_t>() + offset; + data_size = target->getSize() - offset; + assert(data_size > 0); + if (data_size > pkt->getSize()) + data_size = pkt->getSize(); + } else { + int offset = target->getAddr() - pkt->getAddr(); + pkt_data = pkt->getPtr<uint8_t>() + offset; + write_data = target->getPtr<uint8_t>(); + data_size = pkt->getSize() - offset; + assert(data_size > pkt->getSize()); + if (data_size > target->getSize()) + data_size = target->getSize(); + } + + if (pkt->isWrite()) { + memcpy(pkt_data, write_data, data_size); + } else { + memcpy(write_data, pkt_data, data_size); + } + } + } cache->doFunctionalAccess(pkt, isCpuSide); } @@ -153,7 +189,6 @@ BaseCache::CachePort::recvRetry() { DPRINTF(CachePort, "%s has more requests\n", name()); //Still more to issue, rerequest in 1 cycle - pkt = NULL; BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); reqCpu->schedule(curTick + 1); } @@ -166,12 +201,13 @@ BaseCache::CachePort::recvRetry() pkt = cshrRetry; bool success = sendTiming(pkt); waitingOnRetry = !success; - if (success && cache->doSlaveRequest()) + if (success) { - //Still more to issue, rerequest in 1 cycle - pkt = NULL; - BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); - reqCpu->schedule(curTick + 1); + if (cache->doSlaveRequest()) { + //Still more to issue, rerequest in 1 cycle + BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(this); + reqCpu->schedule(curTick + 1); + } cshrRetry = NULL; } } @@ -269,20 +305,28 @@ BaseCache::CacheEvent::process() } else { - assert(cachePort->cache->doSlaveRequest()); //CSHR - pkt = cachePort->cache->getCoherencePacket(); + if (!cachePort->cshrRetry) { + assert(cachePort->cache->doSlaveRequest()); + pkt = cachePort->cache->getCoherencePacket(); + } + else { + pkt = cachePort->cshrRetry; + } bool success = cachePort->sendTiming(pkt); if (!success) { //Need to send on a retry cachePort->cshrRetry = pkt; cachePort->waitingOnRetry = true; } - else if (cachePort->cache->doSlaveRequest()) + else { - //Still more to issue, rerequest in 1 cycle - pkt = NULL; - this->schedule(curTick+1); + cachePort->cshrRetry = NULL; + if (cachePort->cache->doSlaveRequest()) { + //Still more to issue, rerequest in 1 cycle + pkt = NULL; + this->schedule(curTick+1); + } } } return; diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index 563b1ca8b..455e13d9c 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -212,10 +212,6 @@ class BaseCache : public MemObject protected: - /** True if this cache is connected to the CPU. */ - bool topLevelCache; - - /** Stores time the cache blocked for statistics. */ Tick blockedCycle; @@ -337,7 +333,7 @@ class BaseCache : public MemObject */ BaseCache(const std::string &name, Params ¶ms) : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0), - slaveRequests(0), topLevelCache(false), blkSize(params.blkSize), + slaveRequests(0), blkSize(params.blkSize), missCount(params.maxMisses) { //Start ports at null if more than one is created we should panic @@ -358,15 +354,6 @@ class BaseCache : public MemObject } /** - * Returns true if this cache is connect to the CPU. - * @return True if this is a L1 cache. - */ - bool isTopLevel() - { - return topLevelCache; - } - - /** * Returns true if the cache is blocked for accesses. */ bool isBlocked() @@ -561,8 +548,6 @@ class BaseCache : public MemObject */ void respondToSnoop(Packet *pkt, Tick time) { -// assert("Implement\n" && 0); -// mi->respond(pkt,curTick + hitLatency); assert (pkt->needsResponse()); CacheEvent *reqMem = new CacheEvent(memSidePort, pkt); reqMem->schedule(time); @@ -585,15 +570,7 @@ class BaseCache : public MemObject { //This is where snoops get updated AddrRangeList dummy; -// if (!topLevelCache) -// { - cpuSidePort->getPeerAddressRanges(dummy, snoop); -// } -// else -// { -// snoop.push_back(RangeSize(0,-1)); -// } - + cpuSidePort->getPeerAddressRanges(dummy, snoop); return; } } diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index a75c9611d..078c82d82 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -38,8 +38,6 @@ #include "sim/root.hh" // for Tick #include "arch/isa_traits.hh" // for Addr -#include <iostream> - /** * Cache block status bit assignments */ @@ -180,21 +178,4 @@ class CacheBlk }; -/** - * Output a CacheBlk to the given ostream. - * @param out The stream for the output. - * @param blk The cache block to print. - * - * @return The output stream. - */ -inline std::ostream & -operator<<(std::ostream &out, const CacheBlk &blk) -{ - out << std::hex << std::endl; - out << " Tag: " << blk.tag << std::endl; - out << " Status: " << blk.status << std::endl; - - return(out << std::dec); -} - #endif //__CACHE_BLK_HH__ diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index a68418f24..9db79b843 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -151,12 +151,7 @@ Cache(const std::string &_name, doCopy(params.doCopy), blockOnCopy(params.blockOnCopy), hitLatency(params.hitLatency) { -//FIX BUS POINTERS -// if (params.in == NULL) { - topLevelCache = true; -// } -//PLEASE FIX THIS, BUS SIZES NOT BEING USED - tags->setCache(this, blkSize, 1/*params.out->width, params.out->clockRate*/); + tags->setCache(this); tags->setPrefetcher(prefetcher); missQueue->setCache(this); missQueue->setPrefetcher(prefetcher); @@ -389,10 +384,15 @@ template<class TagStore, class Buffering, class Coherence> void Cache<TagStore,Buffering,Coherence>::snoop(Packet * &pkt) { + if (pkt->req->isUncacheable()) { + //Can't get a hit on an uncacheable address + //Revisit this for multi level coherence + return; + } Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1)); BlkType *blk = tags->findBlock(pkt); MSHR *mshr = missQueue->findMSHR(blk_addr); - if (isTopLevel() && coherence->hasProtocol()) { //@todo Move this into handle bus req + if (coherence->hasProtocol()) { //@todo Move this into handle bus req //If we find an mshr, and it is in service, we need to NACK or invalidate if (mshr) { if (mshr->inService) { diff --git a/src/mem/cache/coherence/uni_coherence.cc b/src/mem/cache/coherence/uni_coherence.cc index 5ab706269..0efe393f9 100644 --- a/src/mem/cache/coherence/uni_coherence.cc +++ b/src/mem/cache/coherence/uni_coherence.cc @@ -68,14 +68,12 @@ UniCoherence::handleBusRequest(Packet * &pkt, CacheBlk *blk, MSHR *mshr, if (pkt->isInvalidate()) { DPRINTF(Cache, "snoop inval on blk %x (blk ptr %x)\n", pkt->getAddr(), blk); - if (!cache->isTopLevel()) { - // Forward to other caches - Packet * tmp = new Packet(pkt->req, Packet::InvalidateReq, -1); - cshrs.allocate(tmp); - cache->setSlaveRequest(Request_Coherence, curTick); - if (cshrs.isFull()) { - cache->setBlockedForSnoop(Blocked_Coherence); - } + // Forward to other caches + Packet * tmp = new Packet(pkt->req, Packet::InvalidateReq, -1); + cshrs.allocate(tmp); + cache->setSlaveRequest(Request_Coherence, curTick); + if (cshrs.isFull()) { + cache->setBlockedForSnoop(Blocked_Coherence); } } else { if (blk) { diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc index c7b0e0890..c23b542f5 100644 --- a/src/mem/cache/miss/miss_queue.cc +++ b/src/mem/cache/miss/miss_queue.cc @@ -352,7 +352,7 @@ MissQueue::setPrefetcher(BasePrefetcher *_prefetcher) MSHR* MissQueue::allocateMiss(Packet * &pkt, int size, Tick time) { - MSHR* mshr = mq.allocate(pkt, blkSize); + MSHR* mshr = mq.allocate(pkt, size); mshr->order = order++; if (!pkt->req->isUncacheable() ){//&& !pkt->isNoAllocate()) { // Mark this as a cache line fill diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 4758fda89..64c65dcca 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -34,8 +34,11 @@ * Definition of the Packet Class, a packet is a transaction occuring * between a single level of the memory heirarchy (ie L1->L2). */ + +#include <iostream> #include "base/misc.hh" #include "mem/packet.hh" +#include "base/trace.hh" static const std::string ReadReqString("ReadReq"); static const std::string WriteReqString("WriteReq"); @@ -139,5 +142,93 @@ Packet::intersect(Packet *p) bool fixPacket(Packet *func, Packet *timing) { - panic("Need to implement!"); + Addr funcStart = func->getAddr(); + Addr funcEnd = func->getAddr() + func->getSize() - 1; + Addr timingStart = timing->getAddr(); + Addr timingEnd = timing->getAddr() + timing->getSize() - 1; + + assert(!(funcStart > timingEnd || timingStart < funcEnd)); + + if (DTRACE(FunctionalAccess)) { + DebugOut() << func; + DebugOut() << timing; + } + + // this packet can't solve our problem, continue on + if (!timing->hasData()) + return true; + + if (func->isRead()) { + if (funcStart >= timingStart && funcEnd <= timingEnd) { + func->allocate(); + memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() + + funcStart - timingStart, func->getSize()); + func->result = Packet::Success; + return false; + } else { + // In this case the timing packet only partially satisfies the + // requset, 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("Timing packet only partially satisfies the functional" + "request. Now what?"); + } + } else if (func->isWrite()) { + if (funcStart >= timingStart) { + memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart), + func->getPtr<uint8_t>(), + funcStart - std::min(funcEnd, timingEnd)); + } else { // timingStart > funcStart + memcpy(timing->getPtr<uint8_t>(), + func->getPtr<uint8_t>() + (timingStart - funcStart), + timingStart - std::min(funcEnd, timingEnd)); + } + // we always want to keep going with a write + return true; + } else + panic("Don't know how to handle command type %#x\n", + func->cmdToIndex()); + +} + + +std::ostream & +operator<<(std::ostream &o, const Packet &p) +{ + + o << "[0x"; + o.setf(std::ios_base::hex, std::ios_base::showbase); + o << p.getAddr(); + o.unsetf(std::ios_base::hex| std::ios_base::showbase); + o << ":"; + o.setf(std::ios_base::hex, std::ios_base::showbase); + o << p.getAddr() + p.getSize() - 1 << "] "; + o.unsetf(std::ios_base::hex| std::ios_base::showbase); + + if (p.result == Packet::Success) + o << "Successful "; + if (p.result == Packet::BadAddress) + o << "BadAddress "; + if (p.result == Packet::Nacked) + o << "Nacked "; + if (p.result == Packet::Unknown) + o << "Inflight "; + + if (p.isRead()) + o << "Read "; + if (p.isWrite()) + o << "Read "; + if (p.isInvalidate()) + o << "Read "; + if (p.isRequest()) + o << "Request "; + if (p.isResponse()) + o << "Response "; + if (p.hasData()) + o << "w/Data "; + + o << std::endl; + return o; } + diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 7ede48bfd..48b32ec47 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -171,17 +171,17 @@ class Packet // as well. enum CommandAttribute { - IsRead = 1 << 0, - IsWrite = 1 << 1, - IsPrefetch = 1 << 2, - IsInvalidate = 1 << 3, - IsRequest = 1 << 4, - IsResponse = 1 << 5, - NeedsResponse = 1 << 6, + IsRead = 1 << 0, + IsWrite = 1 << 1, + IsPrefetch = 1 << 2, + IsInvalidate = 1 << 3, + IsRequest = 1 << 4, + IsResponse = 1 << 5, + NeedsResponse = 1 << 6, IsSWPrefetch = 1 << 7, IsHWPrefetch = 1 << 8, IsUpgrade = 1 << 9, - HasData = 1 << 10 + HasData = 1 << 10 }; public: @@ -189,18 +189,18 @@ class Packet enum Command { InvalidCmd = 0, - ReadReq = IsRead | IsRequest | NeedsResponse, - WriteReq = IsWrite | IsRequest | NeedsResponse | HasData, - WriteReqNoAck = IsWrite | IsRequest | HasData, - ReadResp = IsRead | IsResponse | NeedsResponse | HasData, - WriteResp = IsWrite | IsResponse | NeedsResponse, + ReadReq = IsRead | IsRequest | NeedsResponse, + WriteReq = IsWrite | IsRequest | NeedsResponse | HasData, + WriteReqNoAck = IsWrite | IsRequest | HasData, + ReadResp = IsRead | IsResponse | NeedsResponse | HasData, + WriteResp = IsWrite | IsResponse | NeedsResponse, Writeback = IsWrite | IsRequest | HasData, SoftPFReq = IsRead | IsRequest | IsSWPrefetch | NeedsResponse, HardPFReq = IsRead | IsRequest | IsHWPrefetch | NeedsResponse, SoftPFResp = IsRead | IsResponse | IsSWPrefetch | NeedsResponse | HasData, HardPFResp = IsRead | IsResponse | IsHWPrefetch - | NeedsResponse | HasData, + | NeedsResponse | HasData, InvalidateReq = IsInvalidate | IsRequest, WriteInvalidateReq = IsWrite | IsInvalidate | IsRequest | HasData, UpgradeReq = IsInvalidate | IsRequest | IsUpgrade, @@ -222,17 +222,17 @@ class Packet /** The command field of the packet. */ Command cmd; - bool isRead() { return (cmd & IsRead) != 0; } - bool isWrite() { return (cmd & IsWrite) != 0; } - bool isRequest() { return (cmd & IsRequest) != 0; } - bool isResponse() { return (cmd & IsResponse) != 0; } - bool needsResponse() { return (cmd & NeedsResponse) != 0; } - bool isInvalidate() { return (cmd & IsInvalidate) != 0; } - bool hasData() { return (cmd & HasData) != 0; } + bool isRead() const { return (cmd & IsRead) != 0; } + bool isWrite() const { return (cmd & IsWrite) != 0; } + bool isRequest() const { return (cmd & IsRequest) != 0; } + bool isResponse() const { return (cmd & IsResponse) != 0; } + bool needsResponse() const { return (cmd & NeedsResponse) != 0; } + bool isInvalidate() const { return (cmd & IsInvalidate) != 0; } + bool hasData() const { return (cmd & HasData) != 0; } - bool isCacheFill() { return (flags & CACHE_LINE_FILL) != 0; } - bool isNoAllocate() { return (flags & NO_ALLOCATE) != 0; } - bool isCompressed() { return (flags & COMPRESSED) != 0; } + bool isCacheFill() const { return (flags & CACHE_LINE_FILL) != 0; } + bool isNoAllocate() const { return (flags & NO_ALLOCATE) != 0; } + bool isCompressed() const { return (flags & COMPRESSED) != 0; } bool nic_pkt() { assert("Unimplemented\n" && 0); return false; } @@ -401,5 +401,14 @@ class Packet bool intersect(Packet *p); }; + +/** This function given a functional packet and a timing packet either satisfies + * the timing packet, or updates the timing packet to reflect the updated state + * in the timing packet. It returns if the functional packet should continue to + * traverse the memory hierarchy or not. + */ bool fixPacket(Packet *func, Packet *timing); + +std::ostream & operator<<(std::ostream &o, const Packet &p); + #endif //__MEM_PACKET_HH diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 7303f278e..f5a0ade15 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -201,12 +201,16 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt) if (pkt->req->isLocked()) { trackLoadLocked(pkt->req); } + DPRINTF(MemoryAccess, "Performing Read of size %i on address 0x%x\n", + pkt->getSize(), pkt->getAddr()); memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - params()->addrRange.start, pkt->getSize()); } else if (pkt->isWrite()) { if (writeOK(pkt->req)) { + DPRINTF(MemoryAccess, "Performing Write of size %i on address 0x%x\n", + pkt->getSize(), pkt->getAddr()); memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, pkt->getPtr<uint8_t>(), pkt->getSize()); } diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 456878d0a..21907c0ca 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -33,8 +33,22 @@ void SimpleTimingPort::recvFunctional(Packet *pkt) { - // just do an atomic access and throw away the returned latency - recvAtomic(pkt); + //First check queued events + std::list<Packet *>::iterator i = transmitList.begin(); + std::list<Packet *>::iterator end = transmitList.end(); + bool cont = true; + + while (i != end && cont) { + Packet * target = *i; + // If the target contains data, and it overlaps the + // probed request, need to update data + if (target->intersect(pkt)) + fixPacket(pkt, target); + + } + //Then just do an atomic access and throw away the returned latency + if (cont) + recvAtomic(pkt); } bool |