diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/alpha/tlb.cc | 33 | ||||
-rw-r--r-- | src/arch/alpha/tlb.hh | 12 | ||||
-rw-r--r-- | src/base/compiler.hh | 2 | ||||
-rw-r--r-- | src/base/range_ops.hh | 55 | ||||
-rw-r--r-- | src/cpu/BaseCPU.py | 5 | ||||
-rw-r--r-- | src/cpu/simple/AtomicSimpleCPU.py | 3 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 33 | ||||
-rw-r--r-- | src/cpu/simple/atomic.hh | 4 | ||||
-rw-r--r-- | src/dev/io_device.hh | 3 | ||||
-rw-r--r-- | src/mem/Bridge.py | 6 | ||||
-rw-r--r-- | src/mem/bridge.cc | 33 | ||||
-rw-r--r-- | src/mem/bridge.hh | 6 | ||||
-rw-r--r-- | src/mem/bus.cc | 43 | ||||
-rw-r--r-- | src/mem/bus.hh | 17 | ||||
-rw-r--r-- | src/mem/cache/BaseCache.py | 4 | ||||
-rw-r--r-- | src/mem/cache/base_cache.cc | 5 | ||||
-rw-r--r-- | src/mem/cache/base_cache.hh | 16 | ||||
-rw-r--r-- | src/mem/cache/cache.hh | 6 | ||||
-rw-r--r-- | src/mem/cache/cache_builder.cc | 3 | ||||
-rw-r--r-- | src/mem/cache/cache_impl.hh | 25 | ||||
-rw-r--r-- | src/mem/cache/miss/mshr.cc | 2 | ||||
-rw-r--r-- | src/mem/tport.cc | 1 | ||||
-rw-r--r-- | src/python/generate.py | 2 |
23 files changed, 215 insertions, 104 deletions
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 205b81baf..f701c423d 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -75,21 +75,26 @@ TLB::~TLB() // look up an entry in the TLB PTE * -TLB::lookup(Addr vpn, uint8_t asn) const +TLB::lookup(Addr vpn, uint8_t asn) { // assume not found... PTE *retval = NULL; - if (PTECache[0] && vpn == PTECache[0]->tag && - (PTECache[0]->asma || PTECache[0]->asn == asn)) - retval = PTECache[0]; - else if (PTECache[1] && vpn == PTECache[1]->tag && - (PTECache[1]->asma || PTECache[1]->asn == asn)) - retval = PTECache[1]; - else if (PTECache[2] && vpn == PTECache[2]->tag && - (PTECache[2]->asma || PTECache[2]->asn == asn)) - retval = PTECache[2]; - else { + if (PTECache[0]) { + if (vpn == PTECache[0]->tag && + (PTECache[0]->asma || PTECache[0]->asn == asn)) + retval = PTECache[0]; + else if (PTECache[1]) { + if (vpn == PTECache[1]->tag && + (PTECache[1]->asma || PTECache[1]->asn == asn)) + retval = PTECache[1]; + else if (PTECache[2] && vpn == PTECache[2]->tag && + (PTECache[2]->asma || PTECache[2]->asn == asn)) + retval = PTECache[2]; + } + } + + if (retval == NULL) { PageTable::const_iterator i = lookupTable.find(vpn); if (i != lookupTable.end()) { while (i->first == vpn) { @@ -97,7 +102,7 @@ TLB::lookup(Addr vpn, uint8_t asn) const PTE *pte = &table[index]; assert(pte->valid); if (vpn == pte->tag && (pte->asma || pte->asn == asn)) { - retval = pte; + retval = updateCache(pte); break; } @@ -307,7 +312,7 @@ ITB::regStats() Fault -ITB::translate(RequestPtr &req, ThreadContext *tc) const +ITB::translate(RequestPtr &req, ThreadContext *tc) { //If this is a pal pc, then set PHYSICAL if(FULL_SYSTEM && PcPAL(req->getPC())) @@ -469,7 +474,7 @@ DTB::regStats() } Fault -DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const +DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) { Addr pc = tc->readPC(); diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index 5be7eab59..a4255f3c5 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -61,7 +61,7 @@ namespace AlphaISA int nlu; // not last used entry (for replacement) void nextnlu() { if (++nlu >= size) nlu = 0; } - PTE *lookup(Addr vpn, uint8_t asn) const; + PTE *lookup(Addr vpn, uint8_t asn); public: TLB(const std::string &name, int size); @@ -92,6 +92,12 @@ namespace AlphaISA // Most recently used page table entries PTE *PTECache[3]; inline void flushCache() { memset(PTECache, 0, 3 * sizeof(PTE*)); } + inline PTE* updateCache(PTE *pte) { + PTECache[2] = PTECache[1]; + PTECache[1] = PTECache[0]; + PTECache[0] = pte; + return pte; + } }; class ITB : public TLB @@ -106,7 +112,7 @@ namespace AlphaISA ITB(const std::string &name, int size); virtual void regStats(); - Fault translate(RequestPtr &req, ThreadContext *tc) const; + Fault translate(RequestPtr &req, ThreadContext *tc); }; class DTB : public TLB @@ -129,7 +135,7 @@ namespace AlphaISA DTB(const std::string &name, int size); virtual void regStats(); - Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const; + Fault translate(RequestPtr &req, ThreadContext *tc, bool write); }; } diff --git a/src/base/compiler.hh b/src/base/compiler.hh index dc23ed7b3..2c655af60 100644 --- a/src/base/compiler.hh +++ b/src/base/compiler.hh @@ -40,11 +40,13 @@ #define M5_ATTR_NORETURN __attribute__((noreturn)) #define M5_PRAGMA_NORETURN(x) #define M5_DUMMY_RETURN +#define M5_VAR_USED __attribute__((unused)) #elif defined(__SUNPRO_CC) // this doesn't do anything with sun cc, but why not #define M5_ATTR_NORETURN __sun_attr__((__noreturn__)) #define M5_DUMMY_RETURN return (0); #define DO_PRAGMA(x) _Pragma(#x) +#define M5_VAR_USED #define M5_PRAGMA_NORETURN(x) DO_PRAGMA(does_not_return(x)) #else #error "Need to define compiler options in base/compiler.hh" diff --git a/src/base/range_ops.hh b/src/base/range_ops.hh new file mode 100644 index 000000000..f2b11b649 --- /dev/null +++ b/src/base/range_ops.hh @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2007 The Regents of The University of Michigan + * All rights reserved. + * + * 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: Ali Saidi + */ + +#ifndef __BASE_RANGE_OPS_HH__ +#define __BASE_RANGE_OPS_HH__ +#include <list> +#include <vector> + +#include "base/range.hh" + +template <class T> +inline void +FilterRangeList(std::vector<Range<T> > filter_list, std::list<Range<T> > + &range_list) { + typename std::list<Range<T> >::iterator i; + for (int x = 0; x < filter_list.size(); x++) { + for (i = range_list.begin(); i != range_list.end(); ) { + // Is the range within one of our filter ranges? + if (filter_list[x] == i->start || filter_list[x] == i->end) + range_list.erase(i++); + else + i++; + } + } +} + +#endif //__BASE_RANGE_OPS_HH__ + diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 8be84392d..7a51650e6 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -93,10 +93,11 @@ class BaseCPU(SimObject): def connectMemPorts(self, bus): for p in self._mem_ports: - exec('self.%s = bus.port' % p) + if p != 'physmem_port': + exec('self.%s = bus.port' % p) def addPrivateSplitL1Caches(self, ic, dc): - assert(len(self._mem_ports) == 2) + assert(len(self._mem_ports) == 2 or len(self._mem_ports) == 3) self.icache = ic self.dcache = dc self.icache_port = ic.cpu_side diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index e97f059c1..bfd1825c2 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -40,4 +40,5 @@ class AtomicSimpleCPU(BaseCPU): profile = Param.Latency('0ns', "trace the kernel stack") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") - _mem_ports = ['icache_port', 'dcache_port'] + physmem_port = Port("Physical Memory Port") + _mem_ports = ['icache_port', 'dcache_port', 'physmem_port'] diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 704b65f36..e2a7d5938 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -67,6 +67,10 @@ AtomicSimpleCPU::getPort(const std::string &if_name, int idx) return &dcachePort; else if (if_name == "icache_port") return &icachePort; + else if (if_name == "physmem_port") { + hasPhysMemPort = true; + return &physmemPort; + } else panic("No Such Port\n"); } @@ -83,6 +87,12 @@ AtomicSimpleCPU::init() TheISA::initCPU(tc, tc->readCpuId()); } #endif + if (hasPhysMemPort) { + bool snoop = false; + AddrRangeList pmAddrList; + physmemPort.getPeerAddressRanges(pmAddrList, snoop); + physMemAddr = *pmAddrList.begin(); + } } bool @@ -141,7 +151,8 @@ AtomicSimpleCPU::DcachePort::setPeer(Port *port) AtomicSimpleCPU::AtomicSimpleCPU(Params *p) : BaseSimpleCPU(p), tickEvent(this), width(p->width), simulate_stalls(p->simulate_stalls), - icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this) + icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this), + physmemPort(name() + "-iport", this), hasPhysMemPort(false) { _status = Idle; @@ -293,8 +304,12 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) if (req->isMmapedIpr()) dcache_latency = TheISA::handleIprRead(thread->getTC(), &pkt); - else - dcache_latency = dcachePort.sendAtomic(&pkt); + else { + if (hasPhysMemPort && pkt.getAddr() == physMemAddr) + dcache_latency = physmemPort.sendAtomic(&pkt); + else + dcache_latency = dcachePort.sendAtomic(&pkt); + } dcache_access = true; assert(!pkt.isError()); @@ -402,7 +417,10 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) dcache_latency = TheISA::handleIprWrite(thread->getTC(), &pkt); } else { data = htog(data); - dcache_latency = dcachePort.sendAtomic(&pkt); + if (hasPhysMemPort && pkt.getAddr() == physMemAddr) + dcache_latency = physmemPort.sendAtomic(&pkt); + else + dcache_latency = dcachePort.sendAtomic(&pkt); } dcache_access = true; assert(!pkt.isError()); @@ -513,7 +531,12 @@ AtomicSimpleCPU::tick() Packet::Broadcast); ifetch_pkt.dataStatic(&inst); - icache_latency = icachePort.sendAtomic(&ifetch_pkt); + if (hasPhysMemPort && ifetch_pkt.getAddr() == physMemAddr) + icache_latency = physmemPort.sendAtomic(&ifetch_pkt); + else + icache_latency = icachePort.sendAtomic(&ifetch_pkt); + + // ifetch_req is initialized to read the instruction directly // into the CPU object's inst field. //} diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 28e883b24..96429e5b1 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -121,6 +121,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU }; DcachePort dcachePort; + CpuPort physmemPort; + bool hasPhysMemPort; Request ifetch_req; Request data_read_req; Request data_write_req; @@ -128,6 +130,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU bool dcache_access; Tick dcache_latency; + Range<Addr> physMemAddr; + public: virtual Port *getPort(const std::string &if_name, int idx = -1); diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index e65400ca2..876166adb 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -266,8 +266,7 @@ class DmaDevice : public PioDevice void dmaWrite(Addr addr, int size, Event *event, uint8_t *data) { - dmaPort->dmaAction(MemCmd::WriteInvalidateReq, - addr, size, event, data); + dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data); } void dmaRead(Addr addr, int size, Event *event, uint8_t *data) diff --git a/src/mem/Bridge.py b/src/mem/Bridge.py index 8377221cd..b48e1684d 100644 --- a/src/mem/Bridge.py +++ b/src/mem/Bridge.py @@ -40,5 +40,7 @@ class Bridge(MemObject): delay = Param.Latency('0ns', "The latency of this bridge") nack_delay = Param.Latency('0ns', "The latency of this bridge") write_ack = Param.Bool(False, "Should this bridge ack writes") - fix_partial_write_a = Param.Bool(False, "Should this bridge fixup partial block writes") - fix_partial_write_b = Param.Bool(False, "Should this bridge fixup partial block writes") + filter_ranges_a = VectorParam.AddrRange([], + "What addresses shouldn't be passed through the side of the bridge") + filter_ranges_b = VectorParam.AddrRange([], + "What addresses shouldn't be passed through the side of the bridge") diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index 6cfa5a2ac..c502c5130 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -37,6 +37,7 @@ #include <algorithm> +#include "base/range_ops.hh" #include "base/trace.hh" #include "mem/bridge.hh" #include "params/Bridge.hh" @@ -44,9 +45,10 @@ Bridge::BridgePort::BridgePort(const std::string &_name, Bridge *_bridge, BridgePort *_otherPort, int _delay, int _nack_delay, int _req_limit, - int _resp_limit, bool fix_partial_write) + int _resp_limit, + std::vector<Range<Addr> > filter_ranges) : Port(_name), bridge(_bridge), otherPort(_otherPort), - delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write), + delay(_delay), nackDelay(_nack_delay), filterRanges(filter_ranges), outstandingResponses(0), queuedRequests(0), inRetry(false), reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this) { @@ -55,9 +57,9 @@ Bridge::BridgePort::BridgePort(const std::string &_name, Bridge::Bridge(Params *p) : MemObject(p->name), portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay, - p->req_size_a, p->resp_size_a, p->fix_partial_write_a), + p->req_size_a, p->resp_size_a, p->filter_ranges_a), portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay, - p->req_size_b, p->resp_size_b, p->fix_partial_write_b), + p->req_size_b, p->resp_size_b, p->filter_ranges_b), ackWrites(p->write_ack), _params(p) { if (ackWrites) @@ -243,17 +245,6 @@ Bridge::BridgePort::trySend() PacketPtr pkt = buf->pkt; - // Ugly! @todo When multilevel coherence works this will be removed - if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite && - !pkt->wasNacked()) { - PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq, - Packet::Broadcast); - funcPkt->dataStatic(pkt->getPtr<uint8_t>()); - sendFunctional(funcPkt); - pkt->cmd = MemCmd::WriteReq; - delete funcPkt; - } - DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", buf->origSrc, pkt->getDest(), pkt->getAddr()); @@ -313,17 +304,6 @@ Bridge::BridgePort::recvRetry() Tick Bridge::BridgePort::recvAtomic(PacketPtr pkt) { - // fix partial atomic writes... similar to the timing code that does the - // same... will be removed once our code gets this right - if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite) { - - PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq, - Packet::Broadcast); - funcPkt->dataStatic(pkt->getPtr<uint8_t>()); - otherPort->sendFunctional(funcPkt); - delete funcPkt; - pkt->cmd = MemCmd::WriteReq; - } return delay + otherPort->sendAtomic(pkt); } @@ -355,6 +335,7 @@ Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) { otherPort->getPeerAddressRanges(resp, snoop); + FilterRangeList(filterRanges, resp); // we don't allow snooping across bridges snoop = false; } diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index d3bbf2ddf..82001948e 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -70,7 +70,8 @@ class Bridge : public MemObject /** Min delay to respond to a nack. */ Tick nackDelay; - bool fixPartialWrite; + /** Pass ranges from one side of the bridge to the other? */ + std::vector<Range<Addr> > filterRanges; class PacketBuffer : public Packet::SenderState { @@ -156,7 +157,8 @@ class Bridge : public MemObject /** Constructor for the BusPort.*/ BridgePort(const std::string &_name, Bridge *_bridge, BridgePort *_otherPort, int _delay, int _nack_delay, - int _req_limit, int _resp_limit, bool fix_partial_write); + int _req_limit, int _resp_limit, + std::vector<Range<Addr> > filter_ranges); protected: diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 9fa61a76d..620e2ac60 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -148,10 +148,7 @@ void Bus::occupyBus(PacketPtr pkt) // The first word will be delivered after the current tick, the delivery // of the address if any, and one bus cycle to deliver the data - pkt->firstWordTime = - tickNextIdle + - pkt->isRequest() ? clock : 0 + - clock; + pkt->firstWordTime = tickNextIdle + (pkt->isRequest() ? clock : 0) + clock; //Advance it numCycles bus cycles. //XXX Should this use the repeated addition trick as well? @@ -211,19 +208,13 @@ Bus::recvTiming(PacketPtr pkt) dest_port_id = findPort(pkt->getAddr()); dest_port = (dest_port_id == defaultId) ? defaultPort : interfaces[dest_port_id]; - for (SnoopIter s_iter = snoopPorts.begin(); - s_iter != snoopPorts.end(); - s_iter++) { + SnoopIter s_end = snoopPorts.end(); + for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { BusPort *p = *s_iter; if (p != dest_port && p != src_port) { -#ifndef NDEBUG // cache is not allowed to refuse snoop - bool success = p->sendTiming(pkt); + bool success M5_VAR_USED = p->sendTiming(pkt); assert(success); -#else - // avoid unused variable warning - p->sendTiming(pkt); -#endif } } } else { @@ -320,9 +311,9 @@ Bus::findPort(Addr addr) // Check if this matches the default range if (dest_id == -1) { - for (AddrRangeIter iter = defaultRange.begin(); - iter != defaultRange.end(); iter++) { - if (*iter == addr) { + AddrRangeIter a_end = defaultRange.end(); + for (AddrRangeIter i = defaultRange.begin(); i != a_end; i++) { + if (*i == addr) { DPRINTF(Bus, " found addr %#llx on default\n", addr); return defaultId; } @@ -437,9 +428,8 @@ Bus::recvFunctional(PacketPtr pkt) assert(pkt->isRequest()); // hasn't already been satisfied - for (SnoopIter s_iter = snoopPorts.begin(); - s_iter != snoopPorts.end(); - s_iter++) { + SnoopIter s_end = snoopPorts.end(); + for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { BusPort *p = *s_iter; if (p != port && p->getId() != src_id) { p->sendFunctional(pkt); @@ -464,6 +454,10 @@ Bus::recvStatusChange(Port::Status status, int id) bool snoops; AddrRangeIter iter; + if (inRecvStatusChange.count(id)) + return; + inRecvStatusChange.insert(id); + assert(status == Port::RangeChange && "The other statuses need to be implemented."); @@ -531,6 +525,7 @@ Bus::recvStatusChange(Port::Status status, int id) if (id != defaultId && defaultPort) defaultPort->sendStatusChange(Port::RangeChange); + inRecvStatusChange.erase(id); } void @@ -589,14 +584,14 @@ Bus::findBlockSize(int id) int max_bs = -1; - for (PortIter portIter = portMap.begin(); - portIter != portMap.end(); portIter++) { - int tmp_bs = interfaces[portIter->second]->peerBlockSize(); + PortIter p_end = portMap.end(); + for (PortIter p_iter = portMap.begin(); p_iter != p_end; p_iter++) { + int tmp_bs = interfaces[p_iter->second]->peerBlockSize(); if (tmp_bs > max_bs) max_bs = tmp_bs; } - for (SnoopIter s_iter = snoopPorts.begin(); - s_iter != snoopPorts.end(); s_iter++) { + SnoopIter s_end = snoopPorts.end(); + for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { int tmp_bs = (*s_iter)->peerBlockSize(); if (tmp_bs > max_bs) max_bs = tmp_bs; diff --git a/src/mem/bus.hh b/src/mem/bus.hh index f5cad0586..0c594c463 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -38,6 +38,7 @@ #define __MEM_BUS_HH__ #include <string> +#include <set> #include <list> #include <inttypes.h> @@ -196,11 +197,13 @@ class Bus : public MemObject if (portCache[0].valid && addr >= portCache[0].start && addr < portCache[0].end) { return portCache[0].id; - } else if (portCache[1].valid && addr >= portCache[1].start && + } + if (portCache[1].valid && addr >= portCache[1].start && addr < portCache[1].end) { return portCache[1].id; - } else if (portCache[2].valid && addr >= portCache[2].start && - addr < portCache[2].end) { + } + if (portCache[2].valid && addr >= portCache[2].start && + addr < portCache[2].end) { return portCache[2].id; } @@ -251,6 +254,7 @@ class Bus : public MemObject BusFreeEvent busIdle; bool inRetry; + std::set<int> inRecvStatusChange; /** max number of bus ids we've handed out so far */ short maxId; @@ -312,9 +316,11 @@ class Bus : public MemObject inline BusPort* checkBusCache(short id) { if (busCache[0].valid && id == busCache[0].id) { return busCache[0].port; - } else if (busCache[1].valid && id == busCache[1].id) { + } + if (busCache[1].valid && id == busCache[1].id) { return busCache[1].port; - } else if (busCache[2].valid && id == busCache[2].id) { + } + if (busCache[2].valid && id == busCache[2].id) { return busCache[2].port; } @@ -338,7 +344,6 @@ class Bus : public MemObject // Invalidates the cache. Needs to be called in constructor. inline void clearBusCache() { - // memset(busCache, 0, 3 * sizeof(BusCache)); busCache[2].valid = false; busCache[1].valid = false; busCache[0].valid = false; diff --git a/src/mem/cache/BaseCache.py b/src/mem/cache/BaseCache.py index 2bf44cdf9..f6d42b1ef 100644 --- a/src/mem/cache/BaseCache.py +++ b/src/mem/cache/BaseCache.py @@ -81,4 +81,8 @@ class BaseCache(MemObject): "Only prefetch on data not on instruction accesses") cpu_side = Port("Port on side closer to CPU") mem_side = Port("Port on side closer to MEM") + cpu_side_filter_ranges = VectorParam.AddrRange([], + "What addresses shouldn't be passed through the side of the bridge") + mem_side_filter_ranges = VectorParam.AddrRange([], + "What addresses shouldn't be passed through the side of the bridge") addr_range = VectorParam.AddrRange(AllMemory, "The address range in bytes") diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index b44468486..0c8b02cb3 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -40,9 +40,10 @@ using namespace std; -BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache) +BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, + std::vector<Range<Addr> > filter_ranges) : SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL), - blocked(false), mustSendRetry(false) + blocked(false), mustSendRetry(false), filterRanges(filter_ranges) { } diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index 719ab0245..6a4eec43e 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -98,7 +98,8 @@ class BaseCache : public MemObject BaseCache *cache; protected: - CachePort(const std::string &_name, BaseCache *_cache); + CachePort(const std::string &_name, BaseCache *_cache, + std::vector<Range<Addr> > filter_ranges); virtual void recvStatusChange(Status status); @@ -124,6 +125,9 @@ class BaseCache : public MemObject bool mustSendRetry; + /** filter ranges */ + std::vector<Range<Addr> > filterRanges; + void requestBus(RequestCause cause, Tick time) { DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause); @@ -367,15 +371,21 @@ class BaseCache : public MemObject */ Counter maxMisses; + std::vector<Range<Addr> > cpuSideFilterRanges; + std::vector<Range<Addr> > memSideFilterRanges; /** * Construct an instance of this parameter class. */ Params(int _hitLatency, int _blkSize, int _numMSHRs, int _numTargets, int _numWriteBuffers, - Counter _maxMisses) + Counter _maxMisses, + std::vector<Range<Addr> > cpu_side_filter_ranges, + std::vector<Range<Addr> > mem_side_filter_ranges) : hitLatency(_hitLatency), blkSize(_blkSize), numMSHRs(_numMSHRs), numTargets(_numTargets), - numWriteBuffers(_numWriteBuffers), maxMisses(_maxMisses) + numWriteBuffers(_numWriteBuffers), maxMisses(_maxMisses), + cpuSideFilterRanges(cpu_side_filter_ranges), + memSideFilterRanges(mem_side_filter_ranges) { } }; diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 57028a05e..821fa9702 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -72,7 +72,8 @@ class Cache : public BaseCache { public: CpuSidePort(const std::string &_name, - Cache<TagStore> *_cache); + Cache<TagStore> *_cache, + std::vector<Range<Addr> > filterRanges); // BaseCache::CachePort just has a BaseCache *; this function // lets us get back the type info we lost when we stored the @@ -95,7 +96,8 @@ class Cache : public BaseCache { public: MemSidePort(const std::string &_name, - Cache<TagStore> *_cache); + Cache<TagStore> *_cache, + std::vector<Range<Addr> > filterRanges); // BaseCache::CachePort just has a BaseCache *; this function // lets us get back the type info we lost when we stored the diff --git a/src/mem/cache/cache_builder.cc b/src/mem/cache/cache_builder.cc index 4c9592a1b..0f8b52af2 100644 --- a/src/mem/cache/cache_builder.cc +++ b/src/mem/cache/cache_builder.cc @@ -241,7 +241,8 @@ BaseCacheParams::create() // Build BaseCache param object BaseCache::Params base_params(latency, block_size, mshrs, tgts_per_mshr, write_buffers, - max_miss_count); + max_miss_count, cpu_side_filter_ranges, + mem_side_filter_ranges); //Warnings about prefetcher policy if (prefetch_policy == Enums::none) { diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index d144266ed..02e951df4 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -39,6 +39,7 @@ #include "sim/host.hh" #include "base/misc.hh" +#include "base/range_ops.hh" #include "mem/cache/cache.hh" #include "mem/cache/cache_blk.hh" @@ -61,8 +62,10 @@ Cache<TagStore>::Cache(const std::string &_name, tempBlock = new BlkType(); tempBlock->data = new uint8_t[blkSize]; - cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this); - memSidePort = new MemSidePort(_name + "-mem_side_port", this); + cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this, + params.baseParams.cpuSideFilterRanges); + memSidePort = new MemSidePort(_name + "-mem_side_port", this, + params.baseParams.memSideFilterRanges); cpuSidePort->setOtherPort(memSidePort); memSidePort->setOtherPort(cpuSidePort); @@ -88,7 +91,8 @@ Cache<TagStore>::getPort(const std::string &if_name, int idx) } else if (if_name == "mem_side") { return memSidePort; } else if (if_name == "functional") { - return new CpuSidePort(name() + "-cpu_side_funcport", this); + return new CpuSidePort(name() + "-cpu_side_funcport", this, + std::vector<Range<Addr> >()); } else { panic("Port name %s unrecognized\n", if_name); } @@ -732,7 +736,7 @@ Cache<TagStore>::handleResponse(PacketPtr pkt) // If critical word (no offset) return first word time completion_time = tags->getHitLatency() + - transfer_offset ? pkt->finishTime : pkt->firstWordTime; + (transfer_offset ? pkt->finishTime : pkt->firstWordTime); assert(!target->pkt->req->isUncacheable()); missLatency[target->pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += @@ -1221,6 +1225,7 @@ getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) // CPU side port doesn't snoop; it's a target only. bool dummy; otherPort->getPeerAddressRanges(resp, dummy); + FilterRangeList(filterRanges, resp); snoop = false; } @@ -1262,8 +1267,9 @@ Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt) template<class TagStore> Cache<TagStore>:: CpuSidePort::CpuSidePort(const std::string &_name, - Cache<TagStore> *_cache) - : BaseCache::CachePort(_name, _cache) + Cache<TagStore> *_cache, std::vector<Range<Addr> > + filterRanges) + : BaseCache::CachePort(_name, _cache, filterRanges) { } @@ -1279,6 +1285,8 @@ Cache<TagStore>::MemSidePort:: getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) { otherPort->getPeerAddressRanges(resp, snoop); + FilterRangeList(filterRanges, resp); + // Memory-side port always snoops, so unconditionally set flag for // caller. snoop = true; @@ -1416,8 +1424,9 @@ Cache<TagStore>::MemSidePort::processSendEvent() template<class TagStore> Cache<TagStore>:: -MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache) - : BaseCache::CachePort(_name, _cache) +MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache, + std::vector<Range<Addr> > filterRanges) + : BaseCache::CachePort(_name, _cache, filterRanges) { // override default send event from SimpleTimingPort delete sendEvent; diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index 7796773a3..4e9b98481 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -263,7 +263,7 @@ MSHR::handleSnoop(PacketPtr pkt, Counter _order) if (targets->needsExclusive || pkt->needsExclusive()) { // actual target device (typ. PhysicalMemory) will delete the // packet on reception, so we need to save a copy here - PacketPtr cp_pkt = new Packet(pkt); + PacketPtr cp_pkt = new Packet(pkt, true); targets->add(cp_pkt, curTick, _order, false); ++ntargets; diff --git a/src/mem/tport.cc b/src/mem/tport.cc index b1a6a4813..9fa27046b 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -95,6 +95,7 @@ void SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when) { assert(when > curTick); + assert(when < curTick + Clock::Int::ms); // Nothing is on the list: add it and schedule an event if (transmitList.empty() || when < transmitList.front().tick) { diff --git a/src/python/generate.py b/src/python/generate.py index 6b167552e..7c6ca1c5e 100644 --- a/src/python/generate.py +++ b/src/python/generate.py @@ -46,8 +46,10 @@ class DictImporter(object): self.unload() def unload(self): + import sys for module in self.installed: del sys.modules[module] + self.installed = set() def find_module(self, fullname, path): if fullname == '__scons': |