From 5cb1840b311a7bba93a658481703ce1e09ccf7bb Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Sun, 8 Oct 2006 20:30:42 -0400 Subject: Fixes for functional path. If the cpu needs to update any state when it gets a functional write (LSQ??) then that code needs to be written. src/cpu/o3/fetch_impl.hh: src/cpu/o3/lsq_impl.hh: src/cpu/ozone/front_end_impl.hh: src/cpu/ozone/lw_lsq_impl.hh: src/cpu/simple/atomic.cc: src/cpu/simple/timing.cc: CPU's can recieve functional accesses, they need to determine if they need to do anything with them. src/mem/bus.cc: src/mem/bus.hh: Make the fuctional path do the correct tye of snoop --HG-- extra : convert_revision : 70d09f954b907a8aa9b8137579cd2b06e02ae2ff --- src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/o3/lsq_impl.hh | 2 +- src/cpu/ozone/front_end_impl.hh | 2 +- src/cpu/ozone/lw_lsq_impl.hh | 2 +- src/cpu/simple/atomic.cc | 5 +++-- src/cpu/simple/timing.cc | 3 ++- src/mem/bus.cc | 14 +++++++++++++- src/mem/bus.hh | 3 +++ 8 files changed, 25 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 497179576..b3c3caaad 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -63,7 +63,7 @@ template void DefaultFetch::IcachePort::recvFunctional(PacketPtr pkt) { - panic("DefaultFetch doesn't expect recvFunctional callback!"); + warn("Default fetch doesn't update it's state from a functional call."); } template diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 2bbab71f0..7b7d1eb8e 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -46,7 +46,7 @@ template void LSQ::DcachePort::recvFunctional(PacketPtr pkt) { - panic("O3CPU doesn't expect recvFunctional callback!"); + warn("O3CPU doesn't update things on a recvFunctional."); } template diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 5956c5cba..c814ff9c7 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -59,7 +59,7 @@ template void FrontEnd::IcachePort::recvFunctional(PacketPtr pkt) { - panic("FrontEnd doesn't expect recvFunctional callback!"); + warn("FrontEnd doesn't update state from functional calls"); } template diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index 9d17b027f..e523712da 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -72,7 +72,7 @@ template void OzoneLWLSQ::DcachePort::recvFunctional(PacketPtr pkt) { - panic("O3CPU doesn't expect recvFunctional callback!"); + warn("O3CPU doesn't update things on a recvFunctional"); } template diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 42b0e9783..e21065ebc 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -94,7 +94,7 @@ AtomicSimpleCPU::init() bool AtomicSimpleCPU::CpuPort::recvTiming(Packet *pkt) { - panic("AtomicSimpleCPU doesn't expect recvAtomic callback!"); + panic("AtomicSimpleCPU doesn't expect recvTiming callback!"); return true; } @@ -108,7 +108,8 @@ AtomicSimpleCPU::CpuPort::recvAtomic(Packet *pkt) void AtomicSimpleCPU::CpuPort::recvFunctional(Packet *pkt) { - panic("AtomicSimpleCPU doesn't expect recvFunctional callback!"); + //No internal storage to update, just return + return; } void diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index a394468b9..48362c42a 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -74,7 +74,8 @@ TimingSimpleCPU::CpuPort::recvAtomic(Packet *pkt) void TimingSimpleCPU::CpuPort::recvFunctional(Packet *pkt) { - panic("TimingSimpleCPU doesn't expect recvFunctional callback!"); + //No internal storage to update, jusst return + return; } void diff --git a/src/mem/bus.cc b/src/mem/bus.cc index daca6f985..1646cbd57 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -200,6 +200,18 @@ Bus::atomicSnoop(Packet *pkt) } } +void +Bus::functionalSnoop(Packet *pkt) +{ + std::vector ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc()); + + while (!ports.empty()) + { + interfaces[ports.back()]->sendFunctional(pkt); + ports.pop_back(); + } +} + bool Bus::timingSnoop(Packet *pkt) { @@ -236,7 +248,7 @@ Bus::recvFunctional(Packet *pkt) DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n", pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString()); assert(pkt->getDest() == Packet::Broadcast); - atomicSnoop(pkt); + functionalSnoop(pkt); findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt); } diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 3d7f4ad65..ff4ec9c8c 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -102,6 +102,9 @@ class Bus : public MemObject /** Snoop all relevant ports atomicly. */ void atomicSnoop(Packet *pkt); + /** Snoop all relevant ports functionally. */ + void functionalSnoop(Packet *pkt); + /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want * the snoop to happen * @return True if succeds. -- cgit v1.2.3 From 4cfddc0d772eff614a5b6d61efa846aa7fa706a8 Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Sun, 8 Oct 2006 20:47:50 -0400 Subject: Make sure to propogate sendFunctional calls with functional not atomic. src/mem/cache/cache_impl.hh: Fix a error case by putting a panic in. Make sure to propogate sendFunctional calls with functional not atomic. --HG-- extra : convert_revision : 05d03f729a40cfa3ecb68bcba172eb560b24e897 --- src/mem/cache/cache_impl.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 1f03065b6..9ce8f515d 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -603,7 +603,7 @@ Cache::probe(Packet * &pkt, bool update, CachePort // update the cache state and statistics if (mshr || !writes.empty()){ // Can't handle it, return pktuest unsatisfied. - return 0; + panic("Atomic access ran into outstanding MSHR's or WB's!"); } if (!pkt->req->isUncacheable()) { // Fetch the cache block to fill @@ -655,7 +655,7 @@ Cache::probe(Packet * &pkt, bool update, CachePort hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; } else if (pkt->isWrite()) { // Still need to change data in all locations. - return otherSidePort->sendAtomic(pkt); + otherSidePort->sendFunctional(pkt); } return curTick + lat; } -- cgit v1.2.3 From 31f3f2421454b8ba3286f6e536bcc58af5debf48 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sun, 8 Oct 2006 18:26:59 -0700 Subject: Fixes for Port proxies and proxy parameters. --HG-- extra : convert_revision : 76b16fe2926611bd1c12c8ad7392355ad30a5138 --- src/python/m5/params.py | 2 +- src/python/m5/proxy.py | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/python/m5/params.py b/src/python/m5/params.py index cbbd23004..93d784181 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -804,7 +804,7 @@ class PortRef(object): newRef.simobj = simobj assert(isSimObject(newRef.simobj)) if self.peer and not proxy.isproxy(self.peer): - peerObj = memo[self.peer.simobj] + peerObj = self.peer.simobj(_memo=memo) newRef.peer = self.peer.clone(peerObj, memo) assert(not isinstance(newRef.peer, VectorPortRef)) return newRef diff --git a/src/python/m5/proxy.py b/src/python/m5/proxy.py index 7ebc0ae19..e539f14ee 100644 --- a/src/python/m5/proxy.py +++ b/src/python/m5/proxy.py @@ -33,6 +33,8 @@ # ##################################################################### +import copy + class BaseProxy(object): def __init__(self, search_self, search_up): self._search_self = search_self @@ -129,15 +131,22 @@ class AttrProxy(BaseProxy): return super(AttrProxy, self).__getattr__(self, attr) if hasattr(self, '_pdesc'): raise AttributeError, "Attribute reference on bound proxy" - self._modifiers.append(attr) - return self + # Return a copy of self rather than modifying self in place + # since self could be an indirect reference via a variable or + # parameter + new_self = copy.deepcopy(self) + new_self._modifiers.append(attr) + return new_self # support indexing on proxies (e.g., Self.cpu[0]) def __getitem__(self, key): if not isinstance(key, int): raise TypeError, "Proxy object requires integer index" - self._modifiers.append(key) - return self + if hasattr(self, '_pdesc'): + raise AttributeError, "Index operation on bound proxy" + new_self = copy.deepcopy(self) + new_self._modifiers.append(key) + return new_self def find(self, obj): try: -- cgit v1.2.3 From d52117d1e3b833727ce115c0d6fafeabd826bd90 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Sun, 8 Oct 2006 23:16:40 -0400 Subject: add in serialization of AtomicSimpleCPU _status. This is needed because right now unserializing breaks an assert since CPU status is not saved. Kev says that this will break uniform serialization across CPUs since each type of CPU has its own "status" enum set. So, the repercussions are that if you serialize in this CPU, you must first unserialize in this CPU before switching to something else you want. src/cpu/simple/atomic.cc: add in serialization of AtomicSimpleCPU _status. Kev says that this will break uniform serialization across CPUs since each type of CPU has its own "status" enum set. So, the repercussions are that if you serialize in this CPU, you must first unserialize in this CPU before switching to something else you want. --HG-- extra : convert_revision : 7000f660aecea6fef712bf81853d9a7b90d625ee --- src/cpu/simple/atomic.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 42b0e9783..b0356b2bf 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -161,6 +161,8 @@ AtomicSimpleCPU::serialize(ostream &os) { SimObject::State so_state = SimObject::getState(); SERIALIZE_ENUM(so_state); + Status _status = status(); + SERIALIZE_ENUM(_status); BaseSimpleCPU::serialize(os); nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); @@ -171,6 +173,7 @@ AtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { SimObject::State so_state; UNSERIALIZE_ENUM(so_state); + UNSERIALIZE_ENUM(_status); BaseSimpleCPU::unserialize(cp, section); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); } -- cgit v1.2.3 From 97c1f6eff75fb1698b04f0f681681cbf80ba58c8 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Sun, 8 Oct 2006 23:18:19 -0400 Subject: post checkpoint restoration the bus ranges need to be re-initialized for ALL pci devs, not just ide. src/dev/ide_ctrl.cc: this range change needs to be done for all pio devices, not just the ide. src/dev/pcidev.cc: range change needs to be done at here, not in the ide_ctrl file. --HG-- extra : convert_revision : 60c65c55e965b02d671dba7aa8793e5a81f40348 --- src/dev/ide_ctrl.cc | 1 - src/dev/pcidev.cc | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index e8d7f4817..8007fda5e 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -742,7 +742,6 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(bm_enabled); UNSERIALIZE_ARRAY(cmd_in_progress, sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); - pioPort->sendStatusChange(Port::RangeChange); } #ifndef DOXYGEN_SHOULD_SKIP_THIS diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index c3b83f448..b16ddb31a 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -302,6 +302,8 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); UNSERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0])); + pioPort->sendStatusChange(Port::RangeChange); + } #ifndef DOXYGEN_SHOULD_SKIP_THIS -- cgit v1.2.3 From 6c7ab02682aba37c173962ec907b97483625d18b Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 00:26:10 -0400 Subject: Update the Memtester, commit a config file/test for it. src/cpu/SConscript: Add memtester to the compilation environment. Someone who knows this better should make the MemTest a cpu model parameter. For now attached with the build of o3 cpu. src/cpu/memtest/memtest.cc: src/cpu/memtest/memtest.hh: Update Memtest for new mem system src/python/m5/objects/MemTest.py: Update memtest python description --HG-- extra : convert_revision : d6a63e08fda0975a7abfb23814a86a0caf53e482 --- src/cpu/SConscript | 1 + src/cpu/memtest/memtest.cc | 328 ++++++++++++++++++++++++--------------- src/cpu/memtest/memtest.hh | 102 ++++++++---- src/python/m5/objects/MemTest.py | 10 +- 4 files changed, 276 insertions(+), 165 deletions(-) (limited to 'src') diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 2bb9a2399..5771a7904 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -158,6 +158,7 @@ if 'O3CPU' in env['CPU_MODELS']: o3/scoreboard.cc o3/store_set.cc ''') + sources += Split('memtest/memtest.cc') if env['USE_CHECKER']: sources += Split('o3/checker_builder.cc') else: diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 7ea9eaefc..186b6ba50 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -38,39 +38,80 @@ #include "base/misc.hh" #include "base/statistics.hh" -#include "cpu/simple_thread.hh" +//#include "cpu/simple_thread.hh" #include "cpu/memtest/memtest.hh" -#include "mem/cache/base_cache.hh" +//#include "mem/cache/base_cache.hh" +//#include "mem/physical.hh" #include "sim/builder.hh" #include "sim/sim_events.hh" #include "sim/stats.hh" +#include "mem/packet.hh" +#include "mem/request.hh" +#include "mem/port.hh" +#include "mem/mem_object.hh" using namespace std; -using namespace TheISA; int TESTER_ALLOCATOR=0; +bool +MemTest::CpuPort::recvTiming(Packet *pkt) +{ + memtest->completeRequest(pkt); + return true; +} + +Tick +MemTest::CpuPort::recvAtomic(Packet *pkt) +{ + panic("MemTest doesn't expect recvAtomic callback!"); + return curTick; +} + +void +MemTest::CpuPort::recvFunctional(Packet *pkt) +{ + memtest->completeRequest(pkt); +} + +void +MemTest::CpuPort::recvStatusChange(Status status) +{ + if (status == RangeChange) + return; + + panic("MemTest doesn't expect recvStatusChange callback!"); +} + +void +MemTest::CpuPort::recvRetry() +{ + memtest->doRetry(); +} + MemTest::MemTest(const string &name, - MemInterface *_cache_interface, - FunctionalMemory *main_mem, - FunctionalMemory *check_mem, +// MemInterface *_cache_interface, +// PhysicalMemory *main_mem, +// PhysicalMemory *check_mem, unsigned _memorySize, unsigned _percentReads, - unsigned _percentCopies, +// unsigned _percentCopies, unsigned _percentUncacheable, unsigned _progressInterval, unsigned _percentSourceUnaligned, unsigned _percentDestUnaligned, Addr _traceAddr, Counter _max_loads) - : SimObject(name), + : MemObject(name), tickEvent(this), - cacheInterface(_cache_interface), - mainMem(main_mem), - checkMem(check_mem), + cachePort("test", this), + funcPort("functional", this), + retryPkt(NULL), +// mainMem(main_mem), +// checkMem(check_mem), size(_memorySize), percentReads(_percentReads), - percentCopies(_percentCopies), +// percentCopies(_percentCopies), percentUncacheable(_percentUncacheable), progressInterval(_progressInterval), nextProgressMessage(_progressInterval), @@ -81,43 +122,52 @@ MemTest::MemTest(const string &name, vector cmd; cmd.push_back("/bin/ls"); vector null_vec; - thread = new SimpleThread(NULL, 0, mainMem, 0); - - blockSize = cacheInterface->getBlockSize(); - blockAddrMask = blockSize - 1; - traceBlockAddr = blockAddr(_traceAddr); - - //setup data storage with interesting values - uint8_t *data1 = new uint8_t[size]; - uint8_t *data2 = new uint8_t[size]; - uint8_t *data3 = new uint8_t[size]; - memset(data1, 1, size); - memset(data2, 2, size); - memset(data3, 3, size); + // thread = new SimpleThread(NULL, 0, NULL, 0, mainMem); curTick = 0; + // Needs to be masked off once we know the block size. + traceBlockAddr = _traceAddr; baseAddr1 = 0x100000; baseAddr2 = 0x400000; uncacheAddr = 0x800000; - // set up intial memory contents here - mainMem->prot_write(baseAddr1, data1, size); - checkMem->prot_write(baseAddr1, data1, size); - mainMem->prot_write(baseAddr2, data2, size); - checkMem->prot_write(baseAddr2, data2, size); - mainMem->prot_write(uncacheAddr, data3, size); - checkMem->prot_write(uncacheAddr, data3, size); - - delete [] data1; - delete [] data2; - delete [] data3; - // set up counters noResponseCycles = 0; numReads = 0; tickEvent.schedule(0); id = TESTER_ALLOCATOR++; + + accessRetry = false; +} + +Port * +MemTest::getPort(const std::string &if_name, int idx) +{ + if (if_name == "functional") + return &funcPort; + else if (if_name == "test") + return &cachePort; + else + panic("No Such Port\n"); +} + +void +MemTest::init() +{ + // By the time init() is called, the ports should be hooked up. + blockSize = cachePort.peerBlockSize(); + blockAddrMask = blockSize - 1; + traceBlockAddr = blockAddr(traceBlockAddr); + + // set up intial memory contents here + + cachePort.memsetBlob(baseAddr1, 1, size); + funcPort.memsetBlob(baseAddr1, 1, size); + cachePort.memsetBlob(baseAddr2, 2, size); + funcPort.memsetBlob(baseAddr2, 2, size); + cachePort.memsetBlob(uncacheAddr, 3, size); + funcPort.memsetBlob(uncacheAddr, 3, size); } static void @@ -132,23 +182,31 @@ printData(ostream &os, uint8_t *data, int nbytes) } void -MemTest::completeRequest(MemReqPtr &req, uint8_t *data) +MemTest::completeRequest(Packet *pkt) { + MemTestSenderState *state = + dynamic_cast(pkt->senderState); + + uint8_t *data = state->data; + uint8_t *pkt_data = pkt->getPtr(); + Request *req = pkt->req; + //Remove the address from the list of outstanding - std::set::iterator removeAddr = outstandingAddrs.find(req->paddr); + std::set::iterator removeAddr = outstandingAddrs.find(req->getPaddr()); assert(removeAddr != outstandingAddrs.end()); outstandingAddrs.erase(removeAddr); - switch (req->cmd) { - case Read: - if (memcmp(req->data, data, req->size) != 0) { - cerr << name() << ": on read of 0x" << hex << req->paddr - << " (0x" << hex << blockAddr(req->paddr) << ")" + switch (pkt->cmd) { + case Packet::ReadResp: + + if (memcmp(pkt_data, data, pkt->getSize()) != 0) { + cerr << name() << ": on read of 0x" << hex << req->getPaddr() + << " (0x" << hex << blockAddr(req->getPaddr()) << ")" << "@ cycle " << dec << curTick << ", cache returns 0x"; - printData(cerr, req->data, req->size); + printData(cerr, pkt_data, pkt->getSize()); cerr << ", expected 0x"; - printData(cerr, data, req->size); + printData(cerr, data, pkt->getSize()); cerr << endl; fatal(""); } @@ -163,13 +221,13 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data) } if (numReads >= maxLoads) - SimExit(curTick, "Maximum number of loads reached!"); + exitSimLoop("Maximum number of loads reached!"); break; - case Write: + case Packet::WriteResp: numWritesStat++; break; - +/* case Copy: //Also remove dest from outstanding list removeAddr = outstandingAddrs.find(req->dest); @@ -177,36 +235,37 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data) outstandingAddrs.erase(removeAddr); numCopiesStat++; break; - +*/ default: panic("invalid command"); } - if (blockAddr(req->paddr) == traceBlockAddr) { + if (blockAddr(req->getPaddr()) == traceBlockAddr) { cerr << name() << ": completed " - << (req->cmd.isWrite() ? "write" : "read") + << (pkt->isWrite() ? "write" : "read") << " access of " - << dec << req->size << " bytes at address 0x" - << hex << req->paddr - << " (0x" << hex << blockAddr(req->paddr) << ")" + << dec << pkt->getSize() << " bytes at address 0x" + << hex << req->getPaddr() + << " (0x" << hex << blockAddr(req->getPaddr()) << ")" << ", value = 0x"; - printData(cerr, req->data, req->size); + printData(cerr, pkt_data, pkt->getSize()); cerr << " @ cycle " << dec << curTick; cerr << endl; } noResponseCycles = 0; + delete state; delete [] data; + delete pkt->req; + delete pkt; } - void MemTest::regStats() { using namespace Stats; - numReadsStat .name(name() + ".num_reads") .desc("number of read accesses completed") @@ -234,7 +293,7 @@ MemTest::tick() fatal(""); } - if (cacheInterface->isBlocked()) { + if (accessRetry) { return; } @@ -248,30 +307,30 @@ MemTest::tick() //If we aren't doing copies, use id as offset, and do a false sharing //mem tester - if (percentCopies == 0) { - //We can eliminate the lower bits of the offset, and then use the id - //to offset within the blks - offset &= ~63; //Not the low order bits - offset += id; - access_size = 0; - } + //We can eliminate the lower bits of the offset, and then use the id + //to offset within the blks + offset &= ~63; //Not the low order bits + offset += id; + access_size = 0; - MemReqPtr req = new MemReq(); + Request *req = new Request(); + uint32_t flags = 0; + Addr paddr; if (cacheable < percentUncacheable) { - req->flags |= UNCACHEABLE; - req->paddr = uncacheAddr + offset; + flags |= UNCACHEABLE; + paddr = uncacheAddr + offset; } else { - req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset; + paddr = ((base) ? baseAddr1 : baseAddr2) + offset; } // bool probe = (random() % 2 == 1) && !req->isUncacheable(); bool probe = false; - req->size = 1 << access_size; - req->data = new uint8_t[req->size]; - req->paddr &= ~(req->size - 1); - req->time = curTick; - req->xc = thread->getProxy(); + paddr &= ~((1 << access_size) - 1); + req->setPhys(paddr, 1 << access_size, flags); + req->setThreadContext(id,0); + + uint8_t *result = new uint8_t[8]; if (cmd < percentReads) { // read @@ -279,60 +338,81 @@ MemTest::tick() //For now we only allow one outstanding request per addreess per tester //This means we assume CPU does write forwarding to reads that alias something //in the cpu store buffer. - if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return; - else outstandingAddrs.insert(req->paddr); + if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return; + else outstandingAddrs.insert(paddr); - req->cmd = Read; - uint8_t *result = new uint8_t[8]; - checkMem->access(Read, req->paddr, result, req->size); - if (blockAddr(req->paddr) == traceBlockAddr) { + // ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin + funcPort.readBlob(req->getPaddr(), result, req->getSize()); + + if (blockAddr(paddr) == traceBlockAddr) { cerr << name() << ": initiating read " << ((probe) ? "probe of " : "access of ") - << dec << req->size << " bytes from addr 0x" - << hex << req->paddr - << " (0x" << hex << blockAddr(req->paddr) << ")" + << dec << req->getSize() << " bytes from addr 0x" + << hex << paddr + << " (0x" << hex << blockAddr(paddr) << ")" << " at cycle " << dec << curTick << endl; } + + Packet *pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); + pkt->dataDynamicArray(new uint8_t[req->getSize()]); + MemTestSenderState *state = new MemTestSenderState(result); + pkt->senderState = state; + if (probe) { - cacheInterface->probeAndUpdate(req); - completeRequest(req, result); + cachePort.sendFunctional(pkt); +// completeRequest(pkt, result); } else { - req->completionEvent = new MemCompleteEvent(req, result, this); - cacheInterface->access(req); +// req->completionEvent = new MemCompleteEvent(req, result, this); + if (!cachePort.sendTiming(pkt)) { + accessRetry = true; + retryPkt = pkt; + } } - } else if (cmd < (100 - percentCopies)){ + } else { // write //For now we only allow one outstanding request per addreess per tester //This means we assume CPU does write forwarding to reads that alias something //in the cpu store buffer. - if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return; - else outstandingAddrs.insert(req->paddr); + if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return; + else outstandingAddrs.insert(paddr); - req->cmd = Write; - memcpy(req->data, &data, req->size); - checkMem->access(Write, req->paddr, req->data, req->size); - if (blockAddr(req->paddr) == traceBlockAddr) { +/* + if (blockAddr(req->getPaddr()) == traceBlockAddr) { cerr << name() << ": initiating write " << ((probe)?"probe of ":"access of ") - << dec << req->size << " bytes (value = 0x"; - printData(cerr, req->data, req->size); + << dec << req->getSize() << " bytes (value = 0x"; + printData(cerr, data_pkt->getPtr(), req->getSize()); cerr << ") to addr 0x" - << hex << req->paddr - << " (0x" << hex << blockAddr(req->paddr) << ")" + << hex << req->getPaddr() + << " (0x" << hex << blockAddr(req->getPaddr()) << ")" << " at cycle " << dec << curTick << endl; } +*/ + Packet *pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + uint8_t *pkt_data = new uint8_t[req->getSize()]; + pkt->dataDynamicArray(pkt_data); + memcpy(pkt_data, &data, req->getSize()); + MemTestSenderState *state = new MemTestSenderState(result); + pkt->senderState = state; + + funcPort.writeBlob(req->getPaddr(), pkt_data, req->getSize()); + if (probe) { - cacheInterface->probeAndUpdate(req); - completeRequest(req, NULL); + cachePort.sendFunctional(pkt); +// completeRequest(req, NULL); } else { - req->completionEvent = new MemCompleteEvent(req, NULL, this); - cacheInterface->access(req); +// req->completionEvent = new MemCompleteEvent(req, NULL, this); + if (!cachePort.sendTiming(pkt)) { + accessRetry = true; + retryPkt = pkt; + } } - } else { + } +/* else { // copy unsigned source_align = random() % 100; unsigned dest_align = random() % 100; @@ -369,38 +449,32 @@ MemTest::tick() << " (0x" << hex << blockAddr(dest) << ")" << " at cycle " << dec << curTick << endl; - } + }* cacheInterface->access(req); uint8_t result[blockSize]; checkMem->access(Read, source, &result, blockSize); checkMem->access(Write, dest, &result, blockSize); } +*/ } - void -MemCompleteEvent::process() -{ - tester->completeRequest(req, data); - delete this; -} - - -const char * -MemCompleteEvent::description() +MemTest::doRetry() { - return "memory access completion"; + if (cachePort.sendTiming(retryPkt)) { + accessRetry = false; + retryPkt = NULL; + } } - BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest) - SimObjectParam cache; - SimObjectParam main_mem; - SimObjectParam check_mem; +// SimObjectParam cache; +// SimObjectParam main_mem; +// SimObjectParam check_mem; Param memory_size; Param percent_reads; - Param percent_copies; +// Param percent_copies; Param percent_uncacheable; Param progress_interval; Param percent_source_unaligned; @@ -413,12 +487,12 @@ END_DECLARE_SIM_OBJECT_PARAMS(MemTest) BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest) - INIT_PARAM(cache, "L1 cache"), - INIT_PARAM(main_mem, "hierarchical memory"), - INIT_PARAM(check_mem, "check memory"), +// INIT_PARAM(cache, "L1 cache"), +// INIT_PARAM(main_mem, "hierarchical memory"), +// INIT_PARAM(check_mem, "check memory"), INIT_PARAM(memory_size, "memory size"), INIT_PARAM(percent_reads, "target read percentage"), - INIT_PARAM(percent_copies, "target copy percentage"), +// INIT_PARAM(percent_copies, "target copy percentage"), INIT_PARAM(percent_uncacheable, "target uncacheable percentage"), INIT_PARAM(progress_interval, "progress report interval (in accesses)"), INIT_PARAM(percent_source_unaligned, @@ -433,8 +507,8 @@ END_INIT_SIM_OBJECT_PARAMS(MemTest) CREATE_SIM_OBJECT(MemTest) { - return new MemTest(getInstanceName(), cache->getInterface(), main_mem, - check_mem, memory_size, percent_reads, percent_copies, + return new MemTest(getInstanceName(), /*cache->getInterface(),*/ /*main_mem,*/ + /*check_mem,*/ memory_size, percent_reads, /*percent_copies,*/ percent_uncacheable, progress_interval, percent_source_unaligned, percent_dest_unaligned, trace_addr, max_loads); diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index 42fb235db..278012eba 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -35,25 +35,27 @@ #include #include "base/statistics.hh" -#include "mem/functional/functional.hh" -#include "mem/mem_interface.hh" +//#include "mem/functional/functional.hh" +//#include "mem/mem_interface.hh" #include "sim/eventq.hh" #include "sim/sim_exit.hh" #include "sim/sim_object.hh" #include "sim/stats.hh" +#include "mem/mem_object.hh" +#include "mem/port.hh" -class ThreadContext; -class MemTest : public SimObject +class Packet; +class MemTest : public MemObject { public: MemTest(const std::string &name, - MemInterface *_cache_interface, - FunctionalMemory *main_mem, - FunctionalMemory *check_mem, +// MemInterface *_cache_interface, +// PhysicalMemory *main_mem, +// PhysicalMemory *check_mem, unsigned _memorySize, unsigned _percentReads, - unsigned _percentCopies, +// unsigned _percentCopies, unsigned _percentUncacheable, unsigned _progressInterval, unsigned _percentSourceUnaligned, @@ -61,6 +63,8 @@ class MemTest : public SimObject Addr _traceAddr, Counter _max_loads); + virtual void init(); + // register statistics virtual void regStats(); @@ -69,6 +73,8 @@ class MemTest : public SimObject // main simulation loop (one cycle) void tick(); + virtual Port *getPort(const std::string &if_name, int idx = -1); + protected: class TickEvent : public Event { @@ -82,16 +88,62 @@ class MemTest : public SimObject }; TickEvent tickEvent; + class CpuPort : public Port + { + + MemTest *memtest; + + public: + + CpuPort(const std::string &_name, MemTest *_memtest) + : Port(_name), memtest(_memtest) + { } + + protected: + + virtual bool recvTiming(Packet *pkt); + + virtual Tick recvAtomic(Packet *pkt); + + virtual void recvFunctional(Packet *pkt); + + virtual void recvStatusChange(Status status); + + virtual void recvRetry(); + + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) + { resp.clear(); snoop.clear(); } + }; + + CpuPort cachePort; + CpuPort funcPort; + + class MemTestSenderState : public Packet::SenderState + { + public: + /** Constructor. */ + MemTestSenderState(uint8_t *_data) + : data(_data) + { } + + // Hold onto data pointer + uint8_t *data; + }; + +// Request *dataReq; + Packet *retryPkt; +// MemInterface *cacheInterface; +// PhysicalMemory *mainMem; +// PhysicalMemory *checkMem; +// SimpleThread *thread; - MemInterface *cacheInterface; - FunctionalMemory *mainMem; - FunctionalMemory *checkMem; - SimpleThread *thread; + bool accessRetry; unsigned size; // size of testing memory region unsigned percentReads; // target percentage of read accesses - unsigned percentCopies; // target percentage of copy accesses +// unsigned percentCopies; // target percentage of copy accesses unsigned percentUncacheable; int id; @@ -128,29 +180,11 @@ class MemTest : public SimObject Stats::Scalar<> numCopiesStat; // called by MemCompleteEvent::process() - void completeRequest(MemReqPtr &req, uint8_t *data); + void completeRequest(Packet *pkt); - friend class MemCompleteEvent; -}; + void doRetry(); - -class MemCompleteEvent : public Event -{ - MemReqPtr req; - uint8_t *data; - MemTest *tester; - - public: - - MemCompleteEvent(MemReqPtr &_req, uint8_t *_data, MemTest *_tester) - : Event(&mainEventQueue), - req(_req), data(_data), tester(_tester) - { - } - - void process(); - - virtual const char *description(); + friend class MemCompleteEvent; }; #endif // __CPU_MEMTEST_MEMTEST_HH__ diff --git a/src/python/m5/objects/MemTest.py b/src/python/m5/objects/MemTest.py index 97600768f..18aff03f4 100644 --- a/src/python/m5/objects/MemTest.py +++ b/src/python/m5/objects/MemTest.py @@ -1,13 +1,12 @@ from m5.SimObject import SimObject from m5.params import * +from m5.proxy import * +from m5 import build_env + class MemTest(SimObject): type = 'MemTest' - cache = Param.BaseCache("L1 cache") - check_mem = Param.FunctionalMemory("check memory") - main_mem = Param.FunctionalMemory("hierarchical memory") max_loads = Param.Counter("number of loads to execute") memory_size = Param.Int(65536, "memory size") - percent_copies = Param.Percent(0, "target copy percentage") percent_dest_unaligned = Param.Percent(50, "percent of copy dest address that are unaligned") percent_reads = Param.Percent(65, "target read percentage") @@ -18,3 +17,6 @@ class MemTest(SimObject): progress_interval = Param.Counter(1000000, "progress report interval (in accesses)") trace_addr = Param.Addr(0, "address to trace") + + test = Port("Port to the memory system to test") + functional = Port("Port to the functional memory used for verification") -- cgit v1.2.3 From 4f93c43d34f66b164cc67f87e7a75fc500a79fa6 Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 00:27:03 -0400 Subject: Don't block responses even if the cache is blocked. --HG-- extra : convert_revision : a1558eb55806b2a3e7e63249601df2c143e2235d --- src/mem/cache/base_cache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index d7ccca8c0..6b035bc16 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -71,7 +71,7 @@ BaseCache::CachePort::deviceBlockSize() bool BaseCache::CachePort::recvTiming(Packet *pkt) { - if (blocked) + if (pkt->isRequest() && blocked) { DPRINTF(Cache,"Scheduling a retry while blocked\n"); mustSendRetry = true; -- cgit v1.2.3 From 0087061681869c9aaab81c3797020b083a83d46a Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 00:27:41 -0400 Subject: Don't create a response if one isn't needed. --HG-- extra : convert_revision : 37bd230f527f64eb12779157869aae9dcfdde7fd --- src/mem/cache/cache_impl.hh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 9ce8f515d..ac2d7af8b 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -620,7 +620,9 @@ Cache::probe(Packet * &pkt, bool update, CachePort lat = memSidePort->sendAtomic(busPkt); //Be sure to flip the response to a request for coherence - busPkt->makeAtomicResponse(); + if (busPkt->needsResponse()) { + busPkt->makeAtomicResponse(); + } /* if (!(busPkt->flags & SATISFIED)) { // blocked at a higher level, just return -- cgit v1.2.3 From 095d5991f50aaccd2a25792cb7ce44b43a98b29c Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 00:31:24 -0400 Subject: Put a check in so people know not to create more than 8 memtesters. --HG-- extra : convert_revision : 41ab297dc681b2601be1df33aba30c39f49466d8 --- src/cpu/memtest/memtest.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 186b6ba50..609a07a8e 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -137,6 +137,8 @@ MemTest::MemTest(const string &name, tickEvent.schedule(0); id = TESTER_ALLOCATOR++; + if (TESTER_ALLOCATOR > 8) + panic("False sharing memtester only allows up to 8 testers"); accessRetry = false; } -- cgit v1.2.3 From bc732b59fd82689490306090974f1f4c06741b0a Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 01:04:37 -0400 Subject: Have cpus send snoop ranges --HG-- extra : convert_revision : 2a1fba141e409ee1d7a0b69b5b21d236e3d4ce68 --- src/cpu/o3/fetch.hh | 2 +- src/cpu/o3/lsq.hh | 2 +- src/cpu/ozone/front_end.hh | 2 +- src/cpu/ozone/lw_lsq.hh | 2 +- src/cpu/simple/atomic.hh | 4 ++-- src/cpu/simple/timing.hh | 2 +- src/mem/cache/base_cache.hh | 16 ++++++++-------- 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 1a2ca32a4..280bf0e71 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -96,7 +96,7 @@ class DefaultFetch /** Returns the address ranges of this device. */ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } /** Timing version of receive. Handles setting fetch to the * proper status to start fetching. */ diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 190734dc2..6b12d75b4 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -311,7 +311,7 @@ class LSQ { /** Returns the address ranges of this device. */ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } /** Timing version of receive. Handles writing back and * completing the load or store that has returned from diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index 5ffd3666e..59cf9785c 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -92,7 +92,7 @@ class FrontEnd /** Returns the address ranges of this device. */ virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } /** Timing version of receive. Handles setting fetch to the * proper status to start fetching. */ diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 347f4569b..9b93ce74f 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -260,7 +260,7 @@ class OzoneLWLSQ { virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1); } virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index b602af558..52afd76ef 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -104,9 +104,9 @@ class AtomicSimpleCPU : public BaseSimpleCPU virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } - }; + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } + }; CpuPort icachePort; CpuPort dcachePort; diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index b65eebd99..18e13aeb2 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -92,7 +92,7 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) - { resp.clear(); snoop.clear(); } + { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); } struct TickEvent : public Event { diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index 2e92e7730..de8a19cac 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -156,7 +156,7 @@ class BaseCache : public MemObject if (status == Port::RangeChange){ if (!isCpuSide) { cpuSidePort->sendStatusChange(Port::RangeChange); - if (topLevelCache && !snoopRangesSent) { + if (!snoopRangesSent) { snoopRangesSent = true; memSidePort->sendStatusChange(Port::RangeChange); } @@ -568,14 +568,14 @@ class BaseCache : public MemObject { //This is where snoops get updated AddrRangeList dummy; - if (!topLevelCache) - { +// if (!topLevelCache) +// { cpuSidePort->getPeerAddressRanges(dummy, snoop); - } - else - { - snoop.push_back(RangeSize(0,-1)); - } +// } +// else +// { +// snoop.push_back(RangeSize(0,-1)); +// } return; } -- cgit v1.2.3 From afce51d10ad1441247b39edb2a61b85d3cd7af04 Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 16:37:02 -0400 Subject: Set size properly on uncache accesses Don't use the senderState after you get a succesful sendTiming. Not guarnteed to be correct src/mem/cache/base_cache.cc: src/mem/cache/base_cache.hh: src/mem/cache/cache.hh: src/mem/cache/cache_impl.hh: src/mem/cache/miss/blocking_buffer.cc: src/mem/cache/miss/blocking_buffer.hh: src/mem/cache/miss/miss_queue.hh: Don't use the senderState after you get a succesful sendTiming. Not guarnteed to be correct --HG-- extra : convert_revision : 2e8e812bf7fd3ba2b4cba7f7173cb41862f761af --- src/mem/cache/base_cache.cc | 16 ++++++++++++---- src/mem/cache/base_cache.hh | 5 ++++- src/mem/cache/cache.hh | 2 +- src/mem/cache/cache_impl.hh | 6 +++--- src/mem/cache/miss/blocking_buffer.cc | 6 +++--- src/mem/cache/miss/blocking_buffer.hh | 2 +- src/mem/cache/miss/miss_queue.cc | 13 ++++++------- src/mem/cache/miss/miss_queue.hh | 2 +- 8 files changed, 31 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index 6b035bc16..1a0f63d17 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -109,10 +109,11 @@ BaseCache::CachePort::recvRetry() if (!isCpuSide) { pkt = cache->getPacket(); + MSHR* mshr = (MSHR*)pkt->senderState; bool success = sendTiming(pkt); DPRINTF(Cache, "Address %x was %s in sending the timing request\n", pkt->getAddr(), success ? "succesful" : "unsuccesful"); - cache->sendResult(pkt, success); + cache->sendResult(pkt, mshr, success); if (success && cache->doMasterRequest()) { //Still more to issue, rerequest in 1 cycle @@ -123,7 +124,9 @@ BaseCache::CachePort::recvRetry() } else { - pkt = cache->getCoherencePacket(); + //pkt = cache->getCoherencePacket(); + //We save the packet, no reordering on CSHRS + pkt = cshrRetry; bool success = sendTiming(pkt); if (success && cache->doSlaveRequest()) { @@ -182,10 +185,11 @@ BaseCache::CacheEvent::process() { //MSHR pkt = cachePort->cache->getPacket(); + MSHR* mshr = (MSHR*) pkt->senderState; bool success = cachePort->sendTiming(pkt); DPRINTF(Cache, "Address %x was %s in sending the timing request\n", pkt->getAddr(), success ? "succesful" : "unsuccesful"); - cachePort->cache->sendResult(pkt, success); + cachePort->cache->sendResult(pkt, mshr, success); if (success && cachePort->cache->doMasterRequest()) { //Still more to issue, rerequest in 1 cycle @@ -198,7 +202,11 @@ BaseCache::CacheEvent::process() //CSHR pkt = cachePort->cache->getCoherencePacket(); bool success = cachePort->sendTiming(pkt); - if (success && cachePort->cache->doSlaveRequest()) + if (!success) { + //Need to send on a retry + cachePort->cshrRetry = pkt; + } + else if (cachePort->cache->doSlaveRequest()) { //Still more to issue, rerequest in 1 cycle pkt = NULL; diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index de8a19cac..c45f3b71b 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -72,6 +72,7 @@ enum RequestCause{ Request_PF }; +class MSHR; /** * A basic cache interface. Implements some common functions for speed. */ @@ -112,6 +113,8 @@ class BaseCache : public MemObject bool isCpuSide; std::list drainList; + + Packet *cshrRetry; }; struct CacheEvent : public Event @@ -177,7 +180,7 @@ class BaseCache : public MemObject fatal("No implementation"); } - virtual void sendResult(Packet* &pkt, bool success) + virtual void sendResult(Packet* &pkt, MSHR* mshr, bool success) { fatal("No implementation"); diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 4b8870c95..923bf8255 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -175,7 +175,7 @@ class Cache : public BaseCache * @param pkt The request. * @param success True if the request was sent successfully. */ - virtual void sendResult(Packet * &pkt, bool success); + virtual void sendResult(Packet * &pkt, MSHR* mshr, bool success); /** * Handles a response (cache line fill/write ack) from the bus. diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index ac2d7af8b..32f561d71 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -287,10 +287,10 @@ Cache::getPacket() template void -Cache::sendResult(PacketPtr &pkt, bool success) +Cache::sendResult(PacketPtr &pkt, MSHR* mshr, bool success) { if (success) { - missQueue->markInService(pkt); + missQueue->markInService(pkt, mshr); //Temp Hack for UPGRADES if (pkt->cmd == Packet::UpgradeReq) { handleResponse(pkt); @@ -444,7 +444,7 @@ Cache::snoop(Packet * &pkt) if (pkt->isInvalidate()) { //This must be an upgrade or other cache will take ownership - missQueue->markInService(mshr->pkt); + missQueue->markInService(mshr->pkt, mshr); } return; } diff --git a/src/mem/cache/miss/blocking_buffer.cc b/src/mem/cache/miss/blocking_buffer.cc index 7a6ea9133..f7aacff89 100644 --- a/src/mem/cache/miss/blocking_buffer.cc +++ b/src/mem/cache/miss/blocking_buffer.cc @@ -123,12 +123,12 @@ BlockingBuffer::restoreOrigCmd(Packet * &pkt) } void -BlockingBuffer::markInService(Packet * &pkt) +BlockingBuffer::markInService(Packet * &pkt, MSHR* mshr) { if (!pkt->isCacheFill() && pkt->isWrite()) { // Forwarding a write/ writeback, don't need to change // the command - assert((MSHR*)pkt->senderState == &wb); + assert(mshr == &wb); cache->clearMasterRequest(Request_WB); if (!pkt->needsResponse()) { assert(wb.getNumTargets() == 0); @@ -138,7 +138,7 @@ BlockingBuffer::markInService(Packet * &pkt) wb.inService = true; } } else { - assert((MSHR*)pkt->senderState == &miss); + assert(mshr == &miss); cache->clearMasterRequest(Request_MSHR); if (!pkt->needsResponse()) { assert(miss.getNumTargets() == 0); diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh index 641d5a798..f7069696c 100644 --- a/src/mem/cache/miss/blocking_buffer.hh +++ b/src/mem/cache/miss/blocking_buffer.hh @@ -152,7 +152,7 @@ public: * are successfully sent. * @param pkt The request that was sent on the bus. */ - void markInService(Packet * &pkt); + void markInService(Packet * &pkt, MSHR* mshr); /** * Frees the resources of the pktuest and unblock the cache. diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc index 273b6587f..bdb7a39c8 100644 --- a/src/mem/cache/miss/miss_queue.cc +++ b/src/mem/cache/miss/miss_queue.cc @@ -372,7 +372,7 @@ MissQueue::allocateMiss(Packet * &pkt, int size, Tick time) MSHR* MissQueue::allocateWrite(Packet * &pkt, int size, Tick time) { - MSHR* mshr = wb.allocate(pkt,blkSize); + MSHR* mshr = wb.allocate(pkt,size); mshr->order = order++; //REMOVING COMPRESSION FOR NOW @@ -446,7 +446,7 @@ MissQueue::handleMiss(Packet * &pkt, int blkSize, Tick time) /** * @todo Add write merging here. */ - mshr = allocateWrite(pkt, blkSize, time); + mshr = allocateWrite(pkt, pkt->getSize(), time); return; } @@ -526,9 +526,8 @@ MissQueue::restoreOrigCmd(Packet * &pkt) } void -MissQueue::markInService(Packet * &pkt) +MissQueue::markInService(Packet * &pkt, MSHR* mshr) { - assert(pkt->senderState != 0); bool unblock = false; BlockedCause cause = NUM_BLOCKED_CAUSES; @@ -540,7 +539,7 @@ MissQueue::markInService(Packet * &pkt) // Forwarding a write/ writeback, don't need to change // the command unblock = wb.isFull(); - wb.markInService((MSHR*)pkt->senderState); + wb.markInService(mshr); if (!wb.havePending()){ cache->clearMasterRequest(Request_WB); } @@ -551,11 +550,11 @@ MissQueue::markInService(Packet * &pkt) } } else { unblock = mq.isFull(); - mq.markInService((MSHR*)pkt->senderState); + mq.markInService(mshr); if (!mq.havePending()){ cache->clearMasterRequest(Request_MSHR); } - if (((MSHR*)(pkt->senderState))->originalCmd == Packet::HardPFReq) { + if (mshr->originalCmd == Packet::HardPFReq) { DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n", cache->name()); //Also clear pending if need be diff --git a/src/mem/cache/miss/miss_queue.hh b/src/mem/cache/miss/miss_queue.hh index 505d1f90c..179638d2b 100644 --- a/src/mem/cache/miss/miss_queue.hh +++ b/src/mem/cache/miss/miss_queue.hh @@ -256,7 +256,7 @@ class MissQueue * are successfully sent. * @param pkt The request that was sent on the bus. */ - void markInService(Packet * &pkt); + void markInService(Packet * &pkt, MSHR* mshr); /** * Collect statistics and free resources of a satisfied pktuest. -- cgit v1.2.3 From 45732376f6f781cf3671b830321e96478a01dd3d Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 16:47:55 -0400 Subject: Add more DPRINTF's fix a supply condition. src/mem/cache/cache_impl.hh: Add more usefull DPRINTF's REmove the PC to get rid of asserts --HG-- extra : convert_revision : 3f6d832b138d058dbe79bb5f42bd2db9c50b35b5 --- src/mem/cache/cache_impl.hh | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index ac2d7af8b..b6556f252 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -236,9 +236,9 @@ Cache::access(PacketPtr &pkt) missQueue->doWriteback(writebacks.front()); writebacks.pop_front(); } - DPRINTF(Cache, "%s %x %s blk_addr: %x pc %x\n", pkt->cmdString(), + DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(), pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss", - pkt->getAddr() & ~((Addr)blkSize - 1), pkt->req->getPC()); + pkt->getAddr() & ~((Addr)blkSize - 1)); if (blk) { // Hit hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; @@ -314,9 +314,11 @@ Cache::handleResponse(Packet * &pkt) blk = tags->findBlock(pkt); CacheBlk::State old_state = (blk) ? blk->status : 0; PacketList writebacks; + CacheBlk::State new_state = coherence->getNewState(pkt,old_state); + DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n", + pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state); blk = tags->handleFill(blk, (MSHR*)pkt->senderState, - coherence->getNewState(pkt,old_state), - writebacks, pkt); + new_state, writebacks, pkt); while (!writebacks.empty()) { missQueue->doWriteback(writebacks.front()); writebacks.pop_front(); @@ -387,6 +389,7 @@ Cache::snoop(Packet * &pkt) //If the outstanding request was an invalidate (upgrade,readex,..) //Then we need to ACK the request until we get the data //Also NACK if the outstanding request is not a cachefill (writeback) + assert(!(pkt->flags & SATISFIED)); pkt->flags |= SATISFIED; pkt->flags |= NACKED_LINE; assert("Don't detect these on the other side yet\n"); @@ -426,6 +429,7 @@ Cache::snoop(Packet * &pkt) if (pkt->isRead()) { //Only Upgrades don't get here //Supply the data + assert(!(pkt->flags & SATISFIED)); pkt->flags |= SATISFIED; //If we are in an exclusive protocol, make it ask again @@ -454,10 +458,16 @@ Cache::snoop(Packet * &pkt) CacheBlk::State new_state; bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); if (satisfy) { + DPRINTF(Cache, "Cache snooped a %c request and now supplying data," + "new state is %i\n", + pkt->cmdString(), new_state); + tags->handleSnoop(blk, new_state, pkt); respondToSnoop(pkt, curTick + hitLatency); return; } + if (blk) DPRINTF(Cache, "Cache snooped a %c request, new state is %i\n", + pkt->cmdString(), new_state); tags->handleSnoop(blk, new_state); } @@ -675,9 +685,15 @@ Cache::snoopProbe(PacketPtr &pkt) CacheBlk::State new_state = 0; bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); if (satisfy) { + DPRINTF(Cache, "Cache snooped a %c request and now supplying data," + "new state is %i\n", + pkt->cmdString(), new_state); + tags->handleSnoop(blk, new_state, pkt); return hitLatency; } + if (blk) DPRINTF(Cache, "Cache snooped a %c request, new state is %i\n", + pkt->cmdString(), new_state); tags->handleSnoop(blk, new_state); return 0; } -- cgit v1.2.3 From b9fb4d4870dd45c552fd4cd5e531e9626754f19f Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 17:13:50 -0400 Subject: Make memtest work with 8 memtesters src/mem/physical.cc: Update comment to match memtest use src/python/m5/objects/PhysicalMemory.py: Make memtester have a way to connect functionally tests/configs/memtest.py: Properly create 8 memtesters and connect them to the memory system --HG-- extra : convert_revision : e5a2dd9c8918d58051b553b5c6a14785d48b34ca --- src/mem/physical.cc | 2 +- src/python/m5/objects/PhysicalMemory.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 070693442..96d78bd99 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -231,7 +231,7 @@ PhysicalMemory::getPort(const std::string &if_name, int idx) port = new MemoryPort(name() + "-port", this); return port; } else if (if_name == "functional") { - /* special port for functional writes at startup. */ + /* special port for functional writes at startup. And for memtester */ return new MemoryPort(name() + "-funcport", this); } else { panic("PhysicalMemory::getPort: unknown port %s requested", if_name); diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py index dd3ffd651..4e097543d 100644 --- a/src/python/m5/objects/PhysicalMemory.py +++ b/src/python/m5/objects/PhysicalMemory.py @@ -5,6 +5,7 @@ from MemObject import * class PhysicalMemory(MemObject): type = 'PhysicalMemory' port = Port("the access port") + functional = Port("Functional Access Port") range = Param.AddrRange(AddrRange('128MB'), "Device Address") file = Param.String('', "memory mapped file") latency = Param.Latency(Parent.clock, "latency of an access") -- cgit v1.2.3 From fd27c229b6bae09098864361dd6e51065fbaec3c Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 17:18:34 -0400 Subject: Fix a bitwise operation that was accidentally a logical operation. --HG-- extra : convert_revision : 30f64bcb6bea47fd8cd6d77b0df17eff04dbbad0 --- src/mem/cache/cache_impl.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 8d028e97f..7764b97c1 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -73,7 +73,7 @@ doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide) handleResponse(pkt); else { //Check if we should do the snoop - if (pkt->flags && SNOOP_COMMIT) + if (pkt->flags & SNOOP_COMMIT) snoop(pkt); } } -- cgit v1.2.3 From c4dba7a8ed496c2e534b6caa8754678d642124c7 Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 17:30:54 -0400 Subject: Fix a typo in the printf --HG-- extra : convert_revision : bfa8ffae0a9bef25ceca168ff376ba816abf23f3 --- src/mem/cache/cache_impl.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 7764b97c1..bde7ac04b 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -458,7 +458,7 @@ Cache::snoop(Packet * &pkt) CacheBlk::State new_state; bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); if (satisfy) { - DPRINTF(Cache, "Cache snooped a %c request and now supplying data," + DPRINTF(Cache, "Cache snooped a %s request and now supplying data," "new state is %i\n", pkt->cmdString(), new_state); @@ -466,7 +466,7 @@ Cache::snoop(Packet * &pkt) respondToSnoop(pkt, curTick + hitLatency); return; } - if (blk) DPRINTF(Cache, "Cache snooped a %c request, new state is %i\n", + if (blk) DPRINTF(Cache, "Cache snooped a %s request, new state is %i\n", pkt->cmdString(), new_state); tags->handleSnoop(blk, new_state); } @@ -685,14 +685,14 @@ Cache::snoopProbe(PacketPtr &pkt) CacheBlk::State new_state = 0; bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); if (satisfy) { - DPRINTF(Cache, "Cache snooped a %c request and now supplying data," + DPRINTF(Cache, "Cache snooped a %s request and now supplying data," "new state is %i\n", pkt->cmdString(), new_state); tags->handleSnoop(blk, new_state, pkt); return hitLatency; } - if (blk) DPRINTF(Cache, "Cache snooped a %c request, new state is %i\n", + if (blk) DPRINTF(Cache, "Cache snooped a %s request, new state is %i\n", pkt->cmdString(), new_state); tags->handleSnoop(blk, new_state); return 0; -- cgit v1.2.3