From 027dfa01e6ca7e9feed334eef5fab7cfbbb18c52 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 8 Mar 2007 18:57:15 -0500 Subject: stop m5 from leaking like a sieve don't create a new physPort/virtPort every time activateContext() is called add the ability to tell a memory object to delete it's reference to a port and a method to have a port call deletePortRefs() on the port owner as well as delete it's peer still need to stop calling connectMemoPorts() every time activateContext() is called or we'll overflow the bus id and panic src/cpu/thread_state.cc: if we hav ea (phys|virt)Port don't create a new on, have it delete it's peer and then reuse it src/mem/bus.cc: src/mem/bus.hh: add ability to delete a port by usig a hash_map instead of an array to store port ids add a function to do deleting src/mem/cache/cache.hh: src/mem/cache/cache_impl.hh: src/mem/mem_object.cc: src/mem/mem_object.hh: adda function to delete port references from a memory object src/mem/port.cc: src/mem/port.hh: add a removeConn function that tell the owener to delete any references to the port and then deletes its peer --HG-- extra : convert_revision : 272f0c8f80e1cf1ab1750d8be5a6c9aa110b06a4 --- src/cpu/thread_state.cc | 10 ++++++++-- src/mem/bus.cc | 33 +++++++++++++++++++++++---------- src/mem/bus.hh | 9 +++++++-- src/mem/cache/cache.hh | 1 + src/mem/cache/cache_impl.hh | 11 ++++++++++- src/mem/mem_object.cc | 5 +++++ src/mem/mem_object.hh | 4 ++++ src/mem/port.cc | 10 ++++++++++ src/mem/port.hh | 5 +++++ 9 files changed, 73 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 93dd1e2eb..4b65ca4b8 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -125,7 +125,10 @@ ThreadState::connectPhysPort() // @todo: For now this disregards any older port that may have // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. - physPort = new FunctionalPort(csprintf("%s-%d-funcport", + if (physPort) + physPort->removeConn(); + else + physPort = new FunctionalPort(csprintf("%s-%d-funcport", baseCpu->name(), tid)); connectToMemFunc(physPort); } @@ -136,7 +139,10 @@ ThreadState::connectVirtPort() // @todo: For now this disregards any older port that may have // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. - virtPort = new VirtualPort(csprintf("%s-%d-vport", + if (virtPort) + virtPort->removeConn(); + else + virtPort = new VirtualPort(csprintf("%s-%d-vport", baseCpu->name(), tid)); connectToMemFunc(virtPort); } diff --git a/src/mem/bus.cc b/src/mem/bus.cc index cc2137e66..4988df3c5 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -34,6 +34,8 @@ */ +#include + #include "base/misc.hh" #include "base/trace.hh" #include "mem/bus.hh" @@ -52,20 +54,30 @@ Bus::getPort(const std::string &if_name, int idx) } // if_name ignored? forced to be empty? - int id = interfaces.size(); + int id = maxId++; + assert(maxId < std::numeric_limits::max()); BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); - interfaces.push_back(bp); + interfaces[id] = bp; return bp; } +void +Bus::deletePortRefs(Port *p) +{ + BusPort *bp = dynamic_cast(p); + if (bp == NULL) + panic("Couldn't convert Port* to BusPort*\n"); + interfaces.erase(bp->getId()); +} + /** Get the ranges of anyone other buses that we are connected to. */ void Bus::init() { - std::vector::iterator intIter; + m5::hash_map::iterator intIter; for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) - (*intIter)->sendStatusChange(Port::RangeChange); + intIter->second->sendStatusChange(Port::RangeChange); } Bus::BusFreeEvent::BusFreeEvent(Bus *_bus) : Event(&mainEventQueue), bus(_bus) @@ -186,7 +198,7 @@ Bus::recvTiming(PacketPtr pkt) return false; } } else { - assert(dest >= 0 && dest < interfaces.size()); + assert(dest >= 0 && dest < maxId); assert(dest != pkt->getSrc()); // catch infinite loops port = interfaces[dest]; } @@ -435,7 +447,6 @@ Bus::recvStatusChange(Port::Status status, int id) { AddrRangeList ranges; AddrRangeList snoops; - int x; AddrRangeIter iter; assert(status == Port::RangeChange && @@ -457,7 +468,7 @@ Bus::recvStatusChange(Port::Status status, int id) } } else { - assert((id < interfaces.size() && id >= 0) || id == defaultId); + assert((id < maxId && id >= 0) || id == defaultId); Port *port = interfaces[id]; range_map::iterator portIter; std::vector::iterator snoopIter; @@ -502,9 +513,11 @@ Bus::recvStatusChange(Port::Status status, int id) // tell all our peers that our address range has changed. // Don't tell the device that caused this change, it already knows - for (x = 0; x < interfaces.size(); x++) - if (x != id) - interfaces[x]->sendStatusChange(Port::RangeChange); + m5::hash_map::iterator intIter; + + for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) + if (intIter->first != id) + intIter->second->sendStatusChange(Port::RangeChange); if (id != defaultId && defaultPort) defaultPort->sendStatusChange(Port::RangeChange); diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 350a67b43..6706b6c77 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -42,6 +42,7 @@ #include #include "base/range.hh" +#include "base/hashmap.hh" #include "base/range_map.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" @@ -212,9 +213,12 @@ class Bus : public MemObject bool inRetry; + /** max number of bus ids we've handed out so far */ + short maxId; + /** An array of pointers to the peer port interfaces connected to this bus.*/ - std::vector interfaces; + m5::hash_map interfaces; /** An array of pointers to ports that retry should be called on because the * original send failed for whatever reason.*/ @@ -252,6 +256,7 @@ class Bus : public MemObject /** A function used to return the port associated with this bus object. */ virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual void deletePortRefs(Port *p); virtual void init(); @@ -261,7 +266,7 @@ class Bus : public MemObject bool responder_set) : MemObject(n), busId(bus_id), clock(_clock), width(_width), tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false), - defaultPort(NULL), responderSet(responder_set) + maxId(0), defaultPort(NULL), responderSet(responder_set) { //Both the width and clock period must be positive if (width <= 0) diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 26dab2179..722ce216b 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -331,6 +331,7 @@ class Cache : public BaseCache Cache(const std::string &_name, Params ¶ms); virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual void deletePortRefs(Port *p); 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 dac2b93a4..056f6033f 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -1100,7 +1100,7 @@ Cache::getPort(const std::string &if_name, int idx) } else if (if_name == "functional") { - return new CpuSidePort(name() + "-cpu_side_port", this); + return new CpuSidePort(name() + "-cpu_side_funcport", this); } else if (if_name == "cpu_side") { @@ -1121,6 +1121,15 @@ Cache::getPort(const std::string &if_name, int idx) else panic("Port name %s unrecognized\n", if_name); } +template +void +Cache::deletePortRefs(Port *p) +{ + if (cpuSidePort == p || memSidePort == p) + panic("Can only delete functional ports\n"); + // nothing else to do +} + template bool diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc index d4d3fd283..ef31cf999 100644 --- a/src/mem/mem_object.cc +++ b/src/mem/mem_object.cc @@ -35,5 +35,10 @@ MemObject::MemObject(const std::string &name) : SimObject(name) { } +void +MemObject::deletePortRefs(Port *p) +{ + panic("This object does not support port deletion\n"); +} DEFINE_SIM_OBJECT_CLASS_NAME("MemObject", MemObject) diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh index d12eeffe0..ec6fa2b2a 100644 --- a/src/mem/mem_object.hh +++ b/src/mem/mem_object.hh @@ -51,6 +51,10 @@ class MemObject : public SimObject public: /** Additional function to return the Port of a memory object. */ virtual Port *getPort(const std::string &if_name, int idx = -1) = 0; + + /** Tell object that this port is about to disappear, so it should remove it + * from any structures that it's keeping it in. */ + virtual void deletePortRefs(Port *p) ; }; #endif //__MEM_MEM_OBJECT_HH__ diff --git a/src/mem/port.cc b/src/mem/port.cc index 048d7cf6d..e75e50e4d 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -36,6 +36,7 @@ #include "base/chunk_generator.hh" #include "base/trace.hh" +#include "mem/mem_object.hh" #include "mem/port.hh" void @@ -45,6 +46,15 @@ Port::setPeer(Port *port) peer = port; } +void +Port::removeConn() +{ + if (peer->getOwner()) + peer->getOwner()->deletePortRefs(peer); + delete peer; + peer = NULL; +} + void Port::blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) { diff --git a/src/mem/port.hh b/src/mem/port.hh index fdb5bfab4..52162bf76 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -131,6 +131,11 @@ class Port /** Function to return the owner of this port. */ MemObject *getOwner() { return owner; } + /** Inform the peer port to delete itself and notify it's owner about it's + * demise. */ + void removeConn(); + + protected: /** These functions are protected because they should only be -- cgit v1.2.3 From 1158da37fb7a60fcb1f13318d08d11c2df287c99 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 8 Mar 2007 21:49:13 -0500 Subject: Panic if any CMT registers are accessed src/arch/sparc/asi.cc: src/arch/sparc/asi.hh: add CMT ASI registers src/arch/sparc/tlb.cc: Panic if any of the CMT registers are being accessed --HG-- extra : convert_revision : b9a94281e2074a576ac21d042b756950d509e758 --- src/arch/sparc/asi.cc | 6 ++++-- src/arch/sparc/asi.hh | 1 + src/arch/sparc/tlb.cc | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc index d8cd84af5..254635bff 100644 --- a/src/arch/sparc/asi.cc +++ b/src/arch/sparc/asi.cc @@ -247,7 +247,8 @@ namespace SparcISA bool AsiIsCmt(ASI asi) { return - (asi == ASI_CMT_PER_STRAND); + (asi == ASI_CMT_PER_STRAND) || + (asi == ASI_CMT_SHARED); } bool AsiIsQueue(ASI asi) @@ -295,7 +296,8 @@ namespace SparcISA bool AsiIsReg(ASI asi) { return AsiIsMmu(asi) || AsiIsScratchPad(asi) || - AsiIsSparcError(asi) || AsiIsInterrupt(asi); + AsiIsSparcError(asi) || AsiIsInterrupt(asi) + || AsiIsCmt(asi); } bool AsiIsSparcError(ASI asi) diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index 166c3867e..eba2d518f 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -115,6 +115,7 @@ namespace SparcISA ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1 = 0x3E, ASI_IMMU_CTXT_NONZERO_CONFIG = 0x3F, ASI_STREAM_MA = 0x40, + ASI_CMT_SHARED = 0x41, //0x41 implementation dependent ASI_SPARC_BIST_CONTROL = 0x42, ASI_INST_MASK_REG = 0x42, diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index c39969769..09266fd6e 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -693,6 +693,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (AsiIsPartialStore(asi)) panic("Partial Store ASIs not supported\n"); + if (AsiIsCmt(asi)) + panic("Cmt ASI registers not implmented\n"); + if (AsiIsInterrupt(asi)) goto handleIntRegAccess; if (AsiIsMmu(asi)) -- cgit v1.2.3 From ad4483490785236f49b009f0d7ef3328abaf8cc5 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Fri, 9 Mar 2007 10:06:09 -0500 Subject: Two fixes: 1. Make sure connectMemPorts() only gets called when the CPU's peer gets changed. This is done by making setPeer() virtual, and overriding it in the CPU's ports. When it gets called on a CPU's port (dcache specifically), it calls the normal setPeer() function, and also connectMemPorts(). 2. Consolidate redundant code that handles switching in a CPU. src/cpu/base.cc: Move common code of switching over peers to base CPU. src/cpu/base.hh: Move common code of switching over peers to BaseCPU. src/cpu/o3/cpu.cc: Add in function that updates thread context's ports. Also use updated function to takeOverFrom() in BaseCPU. This gets rid of some repeated code. src/cpu/o3/cpu.hh: Include function to update thread context's memory ports. src/cpu/o3/lsq.hh: Add function to dcache port that will update the memory ports upon getting a new peer. Also include a function that will tell the CPU to update those memory ports. src/cpu/o3/lsq_impl.hh: Add function that will update the memory ports upon getting a new peer. src/cpu/simple/atomic.cc: src/cpu/simple/timing.cc: Add function that will update thread context's memory ports upon getting a new peer. Also use the new BaseCPU's take over from function. src/cpu/simple/atomic.hh: Add in function (and dcache port) that will allow the dcache to update memory ports when it gets assigned a new peer. src/cpu/simple/timing.hh: Add function that will update thread context's memory ports upon getting a new peer. src/mem/port.hh: Make setPeer virtual so that other classes can override it. --HG-- extra : convert_revision : 2050f1241dd2e83875d281cfc5ad5c6c8705fdaf --- src/cpu/base.cc | 22 +++++++++++++++++++++- src/cpu/base.hh | 2 +- src/cpu/o3/cpu.cc | 39 +++++++++++++-------------------------- src/cpu/o3/cpu.hh | 4 ++++ src/cpu/o3/lsq.hh | 7 +++++++ src/cpu/o3/lsq_impl.hh | 13 +++++++++++++ src/cpu/simple/atomic.cc | 19 ++++++++++++------- src/cpu/simple/atomic.hh | 17 +++++++++++++---- src/cpu/simple/timing.cc | 37 +++++++++++++------------------------ src/cpu/simple/timing.hh | 2 ++ src/mem/port.hh | 2 +- 11 files changed, 100 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 104b3b6bb..3e0be6ad8 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -319,7 +319,7 @@ BaseCPU::switchOut() } void -BaseCPU::takeOverFrom(BaseCPU *oldCPU) +BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) { assert(threadContexts.size() == oldCPU->threadContexts.size()); @@ -352,6 +352,26 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) // if (profileEvent) // profileEvent->schedule(curTick); #endif + + // Connect new CPU to old CPU's memory only if new CPU isn't + // connected to anything. Also connect old CPU's memory to new + // CPU. + Port *peer; + if (ic->getPeer() == NULL) { + peer = oldCPU->getPort("icache_port")->getPeer(); + ic->setPeer(peer); + } else { + peer = ic->getPeer(); + } + peer->setPeer(ic); + + if (dc->getPeer() == NULL) { + peer = oldCPU->getPort("dcache_port")->getPeer(); + dc->setPeer(peer); + } else { + peer = dc->getPeer(); + } + peer->setPeer(dc); } diff --git a/src/cpu/base.hh b/src/cpu/base.hh index d4213887d..7167bfde0 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -196,7 +196,7 @@ class BaseCPU : public MemObject /// Take over execution from the given CPU. Used for warm-up and /// sampling. - virtual void takeOverFrom(BaseCPU *); + virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc); /** * Number of threads we're actually simulating (<= SMT_MAX_THREADS). diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 785165636..38e6a0b5b 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -557,12 +557,6 @@ template void FullO3CPU::activateContext(int tid, int delay) { -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - threadContexts[tid]->connectMemPorts(); -#endif - // Needs to set each stage to running as well. if (delay){ DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " @@ -781,6 +775,18 @@ FullO3CPU::activateWhenReady(int tid) } } +#if FULL_SYSTEM +template +void +FullO3CPU::updateMemPorts() +{ + // Update all ThreadContext's memory ports (Functional/Virtual + // Ports) + for (int i = 0; i < thread.size(); ++i) + thread[i]->connectMemPorts(); +} +#endif + template void FullO3CPU::serialize(std::ostream &os) @@ -941,7 +947,7 @@ FullO3CPU::takeOverFrom(BaseCPU *oldCPU) activityRec.reset(); - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); fetch.takeOverFrom(); decode.takeOverFrom(); @@ -978,25 +984,6 @@ FullO3CPU::takeOverFrom(BaseCPU *oldCPU) } if (!tickEvent.scheduled()) tickEvent.schedule(curTick); - - Port *peer; - Port *icachePort = fetch.getIcachePort(); - if (icachePort->getPeer() == NULL) { - peer = oldCPU->getPort("icache_port")->getPeer(); - icachePort->setPeer(peer); - } else { - peer = icachePort->getPeer(); - } - peer->setPeer(icachePort); - - Port *dcachePort = iew.getDcachePort(); - if (dcachePort->getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); - dcachePort->setPeer(peer); - } else { - peer = dcachePort->getPeer(); - } - peer->setPeer(dcachePort); } template diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index d217a3e85..ea374dd57 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -357,6 +357,10 @@ class FullO3CPU : public BaseO3CPU { return globalSeqNum++; } #if FULL_SYSTEM + /** Update the Virt and Phys ports of all ThreadContexts to + * reflect change in memory connections. */ + void updateMemPorts(); + /** Check if this address is a valid instruction address. */ bool validInstAddr(Addr addr) { return true; } diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index e68085cfd..80f53a726 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -300,6 +300,8 @@ class LSQ { bool snoopRangeSent; + virtual void setPeer(Port *port); + protected: /** Atomic version of receive. Panics. */ virtual Tick recvAtomic(PacketPtr pkt); @@ -327,6 +329,11 @@ class LSQ { /** D-cache port. */ DcachePort dcachePort; +#if FULL_SYSTEM + /** Tell the CPU to update the Phys and Virt ports. */ + void updateMemPorts() { cpu->updateMemPorts(); } +#endif + protected: /** The LSQ policy for SMT mode. */ LSQPolicy lsqPolicy; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index fb738f7c9..d4994fcb7 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -34,6 +34,19 @@ #include "cpu/o3/lsq.hh" +template +void +LSQ::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + lsq->updateMemPorts(); +#endif +} + template Tick LSQ::DcachePort::recvAtomic(PacketPtr pkt) diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index df7e780e6..ca4627bbf 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -126,6 +126,17 @@ AtomicSimpleCPU::CpuPort::recvRetry() panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); } +void +AtomicSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} AtomicSimpleCPU::AtomicSimpleCPU(Params *p) : BaseSimpleCPU(p), tickEvent(this), @@ -211,7 +222,7 @@ AtomicSimpleCPU::switchOut() void AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); assert(!tickEvent.scheduled()); @@ -242,12 +253,6 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - tc->connectMemPorts(); -#endif - //Make sure ticks are still on multiples of cycles tickEvent.schedule(nextCycle(curTick + cycles(delay))); _status = Running; diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 5bffb7666..ad4aa4708 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -81,9 +81,6 @@ class AtomicSimpleCPU : public BaseSimpleCPU class CpuPort : public Port { - - AtomicSimpleCPU *cpu; - public: CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu) @@ -94,6 +91,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU protected: + AtomicSimpleCPU *cpu; + virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt); @@ -110,7 +109,17 @@ class AtomicSimpleCPU : public BaseSimpleCPU }; CpuPort icachePort; - CpuPort dcachePort; + + class DcachePort : public CpuPort + { + public: + DcachePort(const std::string &_name, AtomicSimpleCPU *_cpu) + : CpuPort(_name, _cpu) + { } + + virtual void setPeer(Port *port); + }; + DcachePort dcachePort; Request *ifetch_req; PacketPtr ifetch_pkt; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 7f857c68d..6f3604678 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -194,7 +194,7 @@ TimingSimpleCPU::switchOut() void TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); // if any of this CPU's ThreadContexts are active, mark the CPU as // running and schedule its tick event. @@ -209,23 +209,6 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) if (_status != Running) { _status = Idle; } - - Port *peer; - if (icachePort.getPeer() == NULL) { - peer = oldCPU->getPort("icache_port")->getPeer(); - icachePort.setPeer(peer); - } else { - peer = icachePort.getPeer(); - } - peer->setPeer(&icachePort); - - if (dcachePort.getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); - dcachePort.setPeer(peer); - } else { - peer = dcachePort.getPeer(); - } - peer->setPeer(&dcachePort); } @@ -240,12 +223,6 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; _status = Running; -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - tc->connectMemPorts(); -#endif - // kick things off by initiating the fetch of the next instruction fetchEvent = new EventWrapper(this, false); @@ -649,6 +626,18 @@ TimingSimpleCPU::completeDrain() drainEvent->process(); } +void +TimingSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} + bool TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index abcb224bf..ef062d24a 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -144,6 +144,8 @@ class TimingSimpleCPU : public BaseSimpleCPU : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu) { } + virtual void setPeer(Port *port); + protected: virtual bool recvTiming(PacketPtr pkt); diff --git a/src/mem/port.hh b/src/mem/port.hh index 52162bf76..6296b42ca 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -120,7 +120,7 @@ class Port { portName = name; } /** Function to set the pointer for the peer port. */ - void setPeer(Port *port); + virtual void setPeer(Port *port); /** Function to get the pointer to the peer port. */ Port *getPeer() { return peer; } -- cgit v1.2.3 From 58f69391cac4dcc3696470d08756d0c5ff308963 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 9 Mar 2007 16:56:39 -0500 Subject: implement ipi stufff for SPARC src/arch/alpha/utility.hh: src/arch/mips/utility.hh: src/arch/sparc/utility.hh: src/arch/x86/utility.hh: add hook for system to startup the cpu or not... in the case of FS sparc, only the first cpu would get spunup.. the rest sit in an idle state until they get an ipi src/arch/sparc/isa/decoder.isa: handle writable bits of strandstatus register in miscregfile src/arch/sparc/miscregfile.hh: some constants for the strand status register src/arch/sparc/ua2005.cc: properly implement the strand status register src/dev/sparc/iob.cc: implement ipi generation properly src/sim/system.cc: call into the ISA to start the CPU (or not) --HG-- extra : convert_revision : 0003b2032337d8a031a9fc044da726dbb2a9e36f --- src/arch/alpha/utility.hh | 3 +++ src/arch/mips/utility.hh | 7 ++++++ src/arch/sparc/isa/decoder.isa | 4 ---- src/arch/sparc/miscregfile.hh | 17 ++++++++++++++ src/arch/sparc/ua2005.cc | 50 ++++++++++++++++++++++++++++++++++++++++-- src/arch/sparc/utility.hh | 15 ++++++++++++- src/arch/x86/utility.hh | 5 +++++ src/dev/sparc/iob.cc | 29 +++++++++++++++++++----- src/sim/system.cc | 3 ++- 9 files changed, 120 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index c8a50e8a2..b7844c7eb 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -123,6 +123,9 @@ namespace AlphaISA // Alpha IPR register accessors inline bool PcPAL(Addr addr) { return addr & 0x3; } + inline void startupCPU(ThreadContext *tc, int cpuId) { + tc->activate(0); + } #if FULL_SYSTEM //////////////////////////////////////////////////////////////////////// diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index 56689ba4d..b5c1e31e1 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,6 +28,7 @@ * * Authors: Nathan Binkert * Steve Reinhardt + * Korey Sewell */ #ifndef __ARCH_MIPS_UTILITY_HH__ @@ -98,6 +100,11 @@ namespace MipsISA { return ExtMachInst(inst); #endif } + + inline void startupCPU(ThreadContext *tc, int cpuId) + { + tc->activate(0); + } }; diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 2e85e1274..70afe19b6 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -620,10 +620,6 @@ decode OP default Unknown::unknown() }}); 0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}}); 0x1A: Priv::wrstrand_sts_reg({{ - if(Pstate<2:> && !Hpstate<2:>) - StrandStsReg = StrandStsReg<63:1> | - (Rs1 ^ Rs2_or_imm13)<0:>; - else StrandStsReg = Rs1 ^ Rs2_or_imm13; }}); //0x1A is supposed to be reserved, but it writes the strand diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 6063c21c8..867f959e1 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -163,6 +163,23 @@ namespace SparcISA const static int ie = 0x2; }; + struct STS { + const static int st_idle = 0x00; + const static int st_wait = 0x01; + const static int st_halt = 0x02; + const static int st_run = 0x05; + const static int st_spec_run = 0x07; + const static int st_spec_rdy = 0x13; + const static int st_ready = 0x19; + const static int active = 0x01; + const static int speculative = 0x04; + const static int shft_id = 8; + const static int shft_fsm0 = 31; + const static int shft_fsm1 = 26; + const static int shft_fsm2 = 21; + const static int shft_fsm3 = 16; + }; + const int NumMiscArchRegs = MISCREG_NUMMISCREGS; const int NumMiscRegs = MISCREG_NUMMISCREGS; diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 6c8a987fe..439f38457 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -26,11 +26,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/sparc/kernel_stats.hh" #include "arch/sparc/miscregfile.hh" #include "base/bitfield.hh" #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" +#include "sim/system.hh" using namespace SparcISA; @@ -185,10 +187,21 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) #endif break; case MISCREG_HTSTATE: - case MISCREG_STRAND_STS_REG: setRegNoEffect(miscReg, val); break; + case MISCREG_STRAND_STS_REG: + if (bits(val,2,2)) + panic("No support for setting spec_en bit\n"); + setRegNoEffect(miscReg, bits(val,0,0)); + if (!bits(val,0,0)) { + // Time to go to sleep + tc->suspend(); + if (tc->getKernelStats()) + tc->getKernelStats()->quiesce(); + } + break; + default: panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg)); } @@ -197,6 +210,8 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) MiscReg MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) { + uint64_t temp; + switch (miscReg) { /* Privileged registers. */ case MISCREG_QUEUE_CPU_MONDO_HEAD: @@ -214,7 +229,6 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) case MISCREG_HPSTATE: case MISCREG_HINTP: case MISCREG_HTSTATE: - case MISCREG_STRAND_STS_REG: case MISCREG_HSTICK_CMPR: return readRegNoEffect(miscReg) ; @@ -223,6 +237,38 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) case MISCREG_HVER: return NWindows | MaxTL << 8 | MaxGL << 16; + case MISCREG_STRAND_STS_REG: + System *sys; + int x; + sys = tc->getSystemPtr(); + + temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative); + // Check that the CPU array is fully populated (by calling getNumCPus()) + assert(sys->getNumCPUs() > tc->readCpuId()); + + temp |= tc->readCpuId() << STS::shft_id; + + for (x = tc->readCpuId() & ~3; x < sys->threadContexts.size(); x++) { + switch (sys->threadContexts[x]->status()) { + case ThreadContext::Active: + temp |= STS::st_run << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + case ThreadContext::Suspended: + // should this be idle? + temp |= STS::st_idle << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + case ThreadContext::Halted: + temp |= STS::st_halt << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + default: + panic("What state are we in?!\n"); + } // switch + } // for + + return temp; default: panic("Invalid read to FS misc register\n"); } diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 64b91695e..dc9201401 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -112,7 +112,20 @@ namespace SparcISA inline void initCPU(ThreadContext *tc, int cpuId) { static Fault por = new PowerOnReset(); - por->invoke(tc); + if (cpuId == 0) + por->invoke(tc); + + } + + inline void startupCPU(ThreadContext *tc, int cpuId) + { +#if FULL_SYSTEM + // Other CPUs will get activated by IPIs + if (cpuId == 0) + tc->activate(0); +#else + tc->activate(0); +#endif } } // namespace SparcISA diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index 1d9d8d3d5..1fbe1fffe 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -126,6 +126,11 @@ namespace X86ISA { panic("initCPU not implemented!\n"); } + + inline void startupCPU(ThreadContext *tc, int cpuId) + { + tc->activate(0); + } }; #endif // __ARCH_X86_UTILITY_HH__ diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc index 2cff02a99..6bd40b631 100644 --- a/src/dev/sparc/iob.cc +++ b/src/dev/sparc/iob.cc @@ -38,6 +38,7 @@ #include #include "arch/sparc/isa_traits.hh" +#include "arch/sparc/faults.hh" #include "base/trace.hh" #include "cpu/intr_control.hh" #include "dev/sparc/iob.hh" @@ -45,6 +46,7 @@ #include "mem/port.hh" #include "mem/packet_access.hh" #include "sim/builder.hh" +#include "sim/faults.hh" #include "sim/system.hh" Iob::Iob(Params *p) @@ -261,13 +263,30 @@ Iob::receiveDeviceInterrupt(DeviceId devid) void Iob::generateIpi(Type type, int cpu_id, int vector) { - // Only handle interrupts for the moment... Cpu Idle/reset/resume will be - // later - if (type != 0) + SparcISA::SparcFault *por = new SparcISA::PowerOnReset(); + if (cpu_id >= sys->getNumCPUs()) return; - assert(type == 0); - ic->post(cpu_id, SparcISA::IT_INT_VEC, vector); + switch (type) { + case 0: // interrupt + ic->post(cpu_id, SparcISA::IT_INT_VEC, vector); + break; + case 1: // reset + warn("Sending reset to CPU: %d\n", cpu_id); + if (vector != por->trapType()) + panic("Don't know how to set non-POR reset to cpu\n"); + por->invoke(sys->threadContexts[cpu_id]); + sys->threadContexts[cpu_id]->activate(); + break; + case 2: // idle -- this means stop executing and don't wake on interrupts + sys->threadContexts[cpu_id]->halt(); + break; + case 3: // resume + sys->threadContexts[cpu_id]->activate(); + break; + default: + panic("Invalid type to generate ipi\n"); + } } bool diff --git a/src/sim/system.cc b/src/sim/system.cc index 1a87e1754..2d0eaaf5b 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -33,6 +33,7 @@ #include "arch/isa_traits.hh" #include "arch/remote_gdb.hh" +#include "arch/utility.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" @@ -203,7 +204,7 @@ System::startup() { int i; for (i = 0; i < threadContexts.size(); i++) - threadContexts[i]->activate(0); + TheISA::startupCPU(threadContexts[i], i); } void -- cgit v1.2.3