diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/bus.cc | 70 | ||||
-rw-r--r-- | src/mem/bus.hh | 3 | ||||
-rw-r--r-- | src/mem/cache/base_cache.cc | 75 | ||||
-rw-r--r-- | src/mem/cache/base_cache.hh | 54 | ||||
-rw-r--r-- | src/mem/cache/cache.hh | 48 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 220 | ||||
-rw-r--r-- | src/mem/request.hh | 41 |
7 files changed, 265 insertions, 246 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc index e9a870b80..bd721dd68 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -260,19 +260,12 @@ Bus::findPort(Addr addr, int id) { /* An interval tree would be a better way to do this. --ali. */ int dest_id = -1; - int i = 0; - bool found = false; AddrRangeIter iter; + range_map<Addr,int>::iterator i; - while (i < portList.size() && !found) - { - if (portList[i].range == addr) { - dest_id = portList[i].portId; - found = true; - DPRINTF(Bus, " found addr %#llx on device %d\n", addr, dest_id); - } - i++; - } + i = portMap.find(RangeSize(addr,1)); + if (i != portMap.end()) + dest_id = i->second; // Check if this matches the default range if (dest_id == -1) { @@ -463,13 +456,13 @@ Bus::recvStatusChange(Port::Status status, int id) assert((id < interfaces.size() && id >= 0) || id == defaultId); Port *port = interfaces[id]; - std::vector<DevMap>::iterator portIter; + range_map<Addr,int>::iterator portIter; std::vector<DevMap>::iterator snoopIter; // Clean out any previously existent ids - for (portIter = portList.begin(); portIter != portList.end(); ) { - if (portIter->portId == id) - portIter = portList.erase(portIter); + for (portIter = portMap.begin(); portIter != portMap.end(); ) { + if (portIter->second == id) + portMap.erase(portIter++); else portIter++; } @@ -495,16 +488,14 @@ Bus::recvStatusChange(Port::Status status, int id) } for(iter = ranges.begin(); iter != ranges.end(); iter++) { - DevMap dm; - dm.portId = id; - dm.range = *iter; - DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", - dm.range.start, dm.range.end, id); - portList.push_back(dm); + iter->start, iter->end, id); + if (portMap.insert(*iter, id) == portMap.end()) + panic("Two devices with same range\n"); + } } - DPRINTF(MMU, "port list has %d entries\n", portList.size()); + DPRINTF(MMU, "port list has %d entries\n", portMap.size()); // tell all our peers that our address range has changed. // Don't tell the device that caused this change, it already knows @@ -519,7 +510,8 @@ Bus::recvStatusChange(Port::Status status, int id) void Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) { - std::vector<DevMap>::iterator portIter; + std::vector<DevMap>::iterator snoopIter; + range_map<Addr,int>::iterator portIter; AddrRangeIter dflt_iter; bool subset; @@ -534,37 +526,37 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start, dflt_iter->end); } - for (portIter = portList.begin(); portIter != portList.end(); portIter++) { + for (portIter = portMap.begin(); portIter != portMap.end(); portIter++) { subset = false; for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end(); dflt_iter++) { - if ((portIter->range.start < dflt_iter->start && - portIter->range.end >= dflt_iter->start) || - (portIter->range.start < dflt_iter->end && - portIter->range.end >= dflt_iter->end)) + if ((portIter->first.start < dflt_iter->start && + portIter->first.end >= dflt_iter->start) || + (portIter->first.start < dflt_iter->end && + portIter->first.end >= dflt_iter->end)) fatal("Devices can not set ranges that itersect the default set\ but are not a subset of the default set.\n"); - if (portIter->range.start >= dflt_iter->start && - portIter->range.end <= dflt_iter->end) { + if (portIter->first.start >= dflt_iter->start && + portIter->first.end <= dflt_iter->end) { subset = true; DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n", - portIter->range.start, portIter->range.end); + portIter->first.start, portIter->first.end); } } - if (portIter->portId != id && !subset) { - resp.push_back(portIter->range); + if (portIter->second != id && !subset) { + resp.push_back(portIter->first); DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", - portIter->range.start, portIter->range.end); + portIter->first.start, portIter->first.end); } } - for (portIter = portSnoopList.begin(); - portIter != portSnoopList.end(); portIter++) + for (snoopIter = portSnoopList.begin(); + snoopIter != portSnoopList.end(); snoopIter++) { - if (portIter->portId != id) { - snoop.push_back(portIter->range); + if (snoopIter->portId != id) { + snoop.push_back(snoopIter->range); DPRINTF(BusAddrRanges, " -- Snoop: %#llx : %#llx\n", - portIter->range.start, portIter->range.end); + snoopIter->range.start, snoopIter->range.end); //@todo We need to properly insert snoop ranges //not overlapping the ranges (multiple) } diff --git a/src/mem/bus.hh b/src/mem/bus.hh index c472b6143..0ad4aad60 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -42,6 +42,7 @@ #include <inttypes.h> #include "base/range.hh" +#include "base/range_map.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" #include "mem/port.hh" @@ -67,7 +68,7 @@ class Bus : public MemObject int portId; Range<Addr> range; }; - std::vector<DevMap> portList; + range_map<Addr, int> portMap; AddrRangeList defaultRange; std::vector<DevMap> portSnoopList; diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index 3af61375d..d9e6c5e1f 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -51,6 +51,7 @@ BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, //memSidePort = NULL; } + void BaseCache::CachePort::recvStatusChange(Port::Status status) { @@ -71,38 +72,6 @@ BaseCache::CachePort::deviceBlockSize() } bool -BaseCache::CachePort::recvTiming(PacketPtr pkt) -{ - if (isCpuSide - && !pkt->req->isUncacheable() - && pkt->isInvalidate() - && !pkt->isRead() && !pkt->isWrite()) { - //Upgrade or Invalidate - //Look into what happens if two slave caches on bus - DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr()); - - assert(!(pkt->flags & SATISFIED)); - pkt->flags |= SATISFIED; - //Invalidates/Upgrades need no response if they get the bus - return true; - } - - if (pkt->isRequest() && blocked) - { - DPRINTF(Cache,"Scheduling a retry while blocked\n"); - mustSendRetry = true; - return false; - } - return cache->doTimingAccess(pkt, this, isCpuSide); -} - -Tick -BaseCache::CachePort::recvAtomic(PacketPtr pkt) -{ - return cache->doAtomicAccess(pkt, isCpuSide); -} - -bool BaseCache::CachePort::checkFunctional(PacketPtr pkt) { //Check storage here first @@ -139,14 +108,6 @@ BaseCache::CachePort::checkFunctional(PacketPtr pkt) } void -BaseCache::CachePort::recvFunctional(PacketPtr pkt) -{ - bool notDone = checkFunctional(pkt); - if (notDone) - cache->doFunctionalAccess(pkt, isCpuSide); -} - -void BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt) { bool notDone = checkFunctional(pkt); @@ -398,40 +359,6 @@ BaseCache::CacheEvent::description() return "timing event\n"; } -Port* -BaseCache::getPort(const std::string &if_name, int idx) -{ - if (if_name == "") - { - if(cpuSidePort == NULL) { - cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); - sendEvent = new CacheEvent(cpuSidePort, true); - } - return cpuSidePort; - } - else if (if_name == "functional") - { - return new CachePort(name() + "-cpu_side_port", this, true); - } - else if (if_name == "cpu_side") - { - if(cpuSidePort == NULL) { - cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); - sendEvent = new CacheEvent(cpuSidePort, true); - } - return cpuSidePort; - } - else if (if_name == "mem_side") - { - if (memSidePort != NULL) - panic("Already have a mem side for this cache\n"); - memSidePort = new CachePort(name() + "-mem_side_port", this, false); - memSendEvent = new CacheEvent(memSidePort, true); - return memSidePort; - } - else panic("Port name %s unrecognized\n", if_name); -} - void BaseCache::init() { diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index ef4955432..a7f035dce 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -82,15 +82,8 @@ class BaseCache : public MemObject public: BaseCache *cache; - CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); - protected: - virtual bool recvTiming(PacketPtr pkt); - - virtual Tick recvAtomic(PacketPtr pkt); - - virtual void recvFunctional(PacketPtr pkt); - + CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide); virtual void recvStatusChange(Status status); virtual void getDeviceAddressRanges(AddrRangeList &resp, @@ -137,33 +130,12 @@ class BaseCache : public MemObject public: //Made public so coherence can get at it. CachePort *cpuSidePort; + CachePort *memSidePort; CacheEvent *sendEvent; CacheEvent *memSendEvent; - protected: - CachePort *memSidePort; - - public: - virtual Port *getPort(const std::string &if_name, int idx = -1); - private: - //To be defined in cache_impl.hh not in base class - virtual bool doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide) - { - fatal("No implementation"); - } - - virtual Tick doAtomicAccess(PacketPtr pkt, bool isCpuSide) - { - fatal("No implementation"); - } - - virtual void doFunctionalAccess(PacketPtr pkt, bool isCpuSide) - { - fatal("No implementation"); - } - void recvStatusChange(Port::Status status, bool isCpuSide) { if (status == Port::RangeChange){ @@ -176,27 +148,13 @@ class BaseCache : public MemObject } } - virtual PacketPtr getPacket() - { - fatal("No implementation"); - } + virtual PacketPtr getPacket() = 0; - virtual PacketPtr getCoherencePacket() - { - fatal("No implementation"); - } - - virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) - { + virtual PacketPtr getCoherencePacket() = 0; - fatal("No implementation"); - } + virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0; - virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) - { - - fatal("No implementation"); - } + virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0; /** * Bit vector of the blocking reasons for the access path. diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 29502042c..097b0f513 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -64,8 +64,49 @@ class Cache : public BaseCache typedef typename TagStore::BlkType BlkType; bool prefetchAccess; + protected: + class CpuSidePort : public CachePort + { + public: + CpuSidePort(const std::string &_name, + Cache<TagStore,Coherence> *_cache); + + // BaseCache::CachePort just has a BaseCache *; this function + // lets us get back the type info we lost when we stored the + // cache pointer there. + Cache<TagStore,Coherence> *myCache() { + return static_cast<Cache<TagStore,Coherence> *>(cache); + } + + virtual bool recvTiming(PacketPtr pkt); + + virtual Tick recvAtomic(PacketPtr pkt); + + virtual void recvFunctional(PacketPtr pkt); + }; + + class MemSidePort : public CachePort + { + public: + MemSidePort(const std::string &_name, + Cache<TagStore,Coherence> *_cache); + + // BaseCache::CachePort just has a BaseCache *; this function + // lets us get back the type info we lost when we stored the + // cache pointer there. + Cache<TagStore,Coherence> *myCache() { + return static_cast<Cache<TagStore,Coherence> *>(cache); + } + + virtual bool recvTiming(PacketPtr pkt); + + virtual Tick recvAtomic(PacketPtr pkt); + + virtual void recvFunctional(PacketPtr pkt); + }; + /** Tag and data Storage */ TagStore *tags; /** Miss and Writeback handler */ @@ -128,12 +169,7 @@ class Cache : public BaseCache /** Instantiates a basic cache object. */ Cache(const std::string &_name, Params ¶ms); - virtual bool doTimingAccess(PacketPtr pkt, CachePort *cachePort, - bool isCpuSide); - - virtual Tick doAtomicAccess(PacketPtr pkt, bool isCpuSide); - - virtual void doFunctionalAccess(PacketPtr pkt, bool isCpuSide); + virtual Port *getPort(const std::string &if_name, int idx = -1); virtual void recvStatusChange(Port::Status status, bool isCpuSide); diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 6742d5892..9f48ff1f3 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -56,74 +56,6 @@ bool SIGNAL_NACK_HACK; template<class TagStore, class Coherence> -bool -Cache<TagStore,Coherence>:: -doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide) -{ - if (isCpuSide) - { - if (pkt->isWrite() && (pkt->req->isLocked())) { - pkt->req->setScResult(1); - } - access(pkt); - - } - else - { - if (pkt->isResponse()) - handleResponse(pkt); - else { - //Check if we should do the snoop - if (pkt->flags & SNOOP_COMMIT) - snoop(pkt); - } - } - return true; -} - -template<class TagStore, class Coherence> -Tick -Cache<TagStore,Coherence>:: -doAtomicAccess(PacketPtr pkt, bool isCpuSide) -{ - if (isCpuSide) - { - probe(pkt, true, NULL); - //TEMP ALWAYS SUCCES FOR NOW - pkt->result = Packet::Success; - } - else - { - if (pkt->isResponse()) - handleResponse(pkt); - else - return snoopProbe(pkt); - } - //Fix this timing info - return hitLatency; -} - -template<class TagStore, class Coherence> -void -Cache<TagStore,Coherence>:: -doFunctionalAccess(PacketPtr pkt, bool isCpuSide) -{ - if (isCpuSide) - { - //TEMP USE CPU?THREAD 0 0 - pkt->req->setThreadContext(0,0); - - probe(pkt, false, memSidePort); - //TEMP ALWAYS SUCCESFUL FOR NOW - pkt->result = Packet::Success; - } - else - { - probe(pkt, false, cpuSidePort); - } -} - -template<class TagStore, class Coherence> void Cache<TagStore,Coherence>:: recvStatusChange(Port::Status status, bool isCpuSide) @@ -727,3 +659,155 @@ Cache<TagStore,Coherence>::snoopProbe(PacketPtr &pkt) return 0; } +template<class TagStore, class Coherence> +Port * +Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx) +{ + if (if_name == "") + { + if (cpuSidePort == NULL) { + cpuSidePort = new CpuSidePort(name() + "-cpu_side_port", this); + sendEvent = new CacheEvent(cpuSidePort, true); + } + return cpuSidePort; + } + else if (if_name == "functional") + { + return new CpuSidePort(name() + "-cpu_side_port", this); + } + else if (if_name == "cpu_side") + { + if (cpuSidePort == NULL) { + cpuSidePort = new CpuSidePort(name() + "-cpu_side_port", this); + sendEvent = new CacheEvent(cpuSidePort, true); + } + return cpuSidePort; + } + else if (if_name == "mem_side") + { + if (memSidePort != NULL) + panic("Already have a mem side for this cache\n"); + memSidePort = new MemSidePort(name() + "-mem_side_port", this); + memSendEvent = new CacheEvent(memSidePort, true); + return memSidePort; + } + else panic("Port name %s unrecognized\n", if_name); +} + + +template<class TagStore, class Coherence> +bool +Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt) +{ + if (!pkt->req->isUncacheable() + && pkt->isInvalidate() + && !pkt->isRead() && !pkt->isWrite()) { + //Upgrade or Invalidate + //Look into what happens if two slave caches on bus + DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr()); + + assert(!(pkt->flags & SATISFIED)); + pkt->flags |= SATISFIED; + //Invalidates/Upgrades need no response if they get the bus + return true; + } + + if (pkt->isRequest() && blocked) + { + DPRINTF(Cache,"Scheduling a retry while blocked\n"); + mustSendRetry = true; + return false; + } + + if (pkt->isWrite() && (pkt->req->isLocked())) { + pkt->req->setScResult(1); + } + myCache()->access(pkt); + return true; +} + +template<class TagStore, class Coherence> +Tick +Cache<TagStore,Coherence>::CpuSidePort::recvAtomic(PacketPtr pkt) +{ + myCache()->probe(pkt, true, NULL); + //TEMP ALWAYS SUCCES FOR NOW + pkt->result = Packet::Success; + //Fix this timing info + return myCache()->hitLatency; +} + +template<class TagStore, class Coherence> +void +Cache<TagStore,Coherence>::CpuSidePort::recvFunctional(PacketPtr pkt) +{ + if (checkFunctional(pkt)) { + //TEMP USE CPU?THREAD 0 0 + pkt->req->setThreadContext(0,0); + + myCache()->probe(pkt, false, cache->memSidePort); + //TEMP ALWAYS SUCCESFUL FOR NOW + pkt->result = Packet::Success; + } +} + + +template<class TagStore, class Coherence> +bool +Cache<TagStore,Coherence>::MemSidePort::recvTiming(PacketPtr pkt) +{ + if (pkt->isRequest() && blocked) + { + DPRINTF(Cache,"Scheduling a retry while blocked\n"); + mustSendRetry = true; + return false; + } + + if (pkt->isResponse()) + myCache()->handleResponse(pkt); + else { + //Check if we should do the snoop + if (pkt->flags & SNOOP_COMMIT) + myCache()->snoop(pkt); + } + return true; +} + +template<class TagStore, class Coherence> +Tick +Cache<TagStore,Coherence>::MemSidePort::recvAtomic(PacketPtr pkt) +{ + if (pkt->isResponse()) + myCache()->handleResponse(pkt); + else + return myCache()->snoopProbe(pkt); + //Fix this timing info + return myCache()->hitLatency; +} + +template<class TagStore, class Coherence> +void +Cache<TagStore,Coherence>::MemSidePort::recvFunctional(PacketPtr pkt) +{ + if (checkFunctional(pkt)) { + myCache()->probe(pkt, false, cache->cpuSidePort); + } +} + + +template<class TagStore, class Coherence> +Cache<TagStore,Coherence>:: +CpuSidePort::CpuSidePort(const std::string &_name, + Cache<TagStore,Coherence> *_cache) + : BaseCache::CachePort(_name, _cache, true) +{ +} + +template<class TagStore, class Coherence> +Cache<TagStore,Coherence>:: +MemSidePort::MemSidePort(const std::string &_name, + Cache<TagStore,Coherence> *_cache) + : BaseCache::CachePort(_name, _cache, false) +{ +} + diff --git a/src/mem/request.hh b/src/mem/request.hh index e54984fcd..de0512e1c 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -49,26 +49,28 @@ class Request; typedef Request* RequestPtr; +/** ASI information for this request if it exsits. */ +const uint32_t ASI_BITS = 0x000FF; /** The request is a Load locked/store conditional. */ -const unsigned LOCKED = 0x001; +const uint32_t LOCKED = 0x00100; /** The virtual address is also the physical address. */ -const unsigned PHYSICAL = 0x002; +const uint32_t PHYSICAL = 0x00200; /** The request is an ALPHA VPTE pal access (hw_ld). */ -const unsigned VPTE = 0x004; +const uint32_t VPTE = 0x00400; /** Use the alternate mode bits in ALPHA. */ -const unsigned ALTMODE = 0x008; +const uint32_t ALTMODE = 0x00800; /** The request is to an uncacheable address. */ -const unsigned UNCACHEABLE = 0x010; +const uint32_t UNCACHEABLE = 0x01000; /** The request should not cause a page fault. */ -const unsigned NO_FAULT = 0x020; +const uint32_t NO_FAULT = 0x02000; /** The request should be prefetched into the exclusive state. */ -const unsigned PF_EXCLUSIVE = 0x100; +const uint32_t PF_EXCLUSIVE = 0x10000; /** The request should be marked as LRU. */ -const unsigned EVICT_NEXT = 0x200; +const uint32_t EVICT_NEXT = 0x20000; /** The request should ignore unaligned access faults */ -const unsigned NO_ALIGN_FAULT = 0x400; +const uint32_t NO_ALIGN_FAULT = 0x40000; /** The request was an instruction read. */ -const unsigned INST_READ = 0x800; +const uint32_t INST_READ = 0x80000; class Request { @@ -95,6 +97,10 @@ class Request /** The address space ID. */ int asid; + + /** This request is to a memory mapped register. */ + bool mmapedIpr; + /** The virtual address of the request. */ Addr vaddr; @@ -164,6 +170,7 @@ class Request validAsidVaddr = false; validPC = false; validScResult = false; + mmapedIpr = false; } /** @@ -181,6 +188,7 @@ class Request validAsidVaddr = true; validPC = true; validScResult = false; + mmapedIpr = false; } /** Set just the physical address. This should only be used to @@ -215,6 +223,19 @@ class Request /** Accessor function for asid.*/ int getAsid() { assert(validAsidVaddr); return asid; } + /** Accessor function for asi.*/ + uint8_t getAsi() { assert(validAsidVaddr); return flags & ASI_BITS; } + + /** Accessor function for asi.*/ + void setAsi(uint8_t a) + { assert(validAsidVaddr); flags = (flags & ~ASI_BITS) | a; } + + /** Accessor function for asi.*/ + bool isMmapedIpr() { assert(validPaddr); return mmapedIpr; } + + /** Accessor function for asi.*/ + void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; } + /** Accessor function to check if sc result is valid. */ bool scResultValid() { return validScResult; } /** Accessor function for store conditional return value.*/ |