diff options
Diffstat (limited to 'src/cpu')
42 files changed, 510 insertions, 744 deletions
diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 50a8501e2..19464acbc 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -138,9 +138,12 @@ class BaseCPU(MemObject): tracer = Param.InstTracer(default_tracer, "Instruction tracer") - _cached_ports = [] + icache_port = Port("Instruction Port") + dcache_port = Port("Data Port") + _cached_ports = ['icache_port', 'dcache_port'] + if buildEnv['TARGET_ISA'] in ['x86', 'arm']: - _cached_ports = ["itb.walker.port", "dtb.walker.port"] + _cached_ports += ["itb.walker.port", "dtb.walker.port"] _uncached_ports = [] if buildEnv['TARGET_ISA'] == 'x86': diff --git a/src/cpu/base.cc b/src/cpu/base.cc index a0785ac10..d174995a9 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -470,3 +482,36 @@ BaseCPU::traceFunctionsInternal(Addr pc) functionEntryTick = curTick(); } } + +bool +BaseCPU::CpuPort::recvTiming(PacketPtr pkt) +{ + panic("BaseCPU doesn't expect recvTiming callback!"); + return true; +} + +void +BaseCPU::CpuPort::recvRetry() +{ + panic("BaseCPU doesn't expect recvRetry callback!"); +} + +Tick +BaseCPU::CpuPort::recvAtomic(PacketPtr pkt) +{ + panic("BaseCPU doesn't expect recvAtomic callback!"); + return curTick(); +} + +void +BaseCPU::CpuPort::recvFunctional(PacketPtr pkt) +{ + // No internal storage to update (in the general case). In the + // long term this should never be called, but that assumed a split + // into master/slave and request/response. +} + +void +BaseCPU::CpuPort::recvRangeChange() +{ +} diff --git a/src/cpu/base.hh b/src/cpu/base.hh index a4ffb4716..41c79dff6 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -92,6 +104,42 @@ class BaseCPU : public MemObject // therefore no setCpuId() method is provided int _cpuId; + /** + * Define a base class for the CPU ports (instruction and data) + * that is refined in the subclasses. This class handles the + * common cases, i.e. the functional accesses and the status + * changes and address range queries. The default behaviour for + * both atomic and timing access is to panic and the corresponding + * subclasses have to override these methods. + */ + class CpuPort : public Port + { + public: + + /** + * Create a CPU port with a name and a structural owner. + * + * @param _name port name including the owner + * @param _name structural owner of this port + */ + CpuPort(const std::string& _name, MemObject* _owner) : + Port(_name, _owner) + { } + + protected: + + virtual bool recvTiming(PacketPtr pkt); + + virtual Tick recvAtomic(PacketPtr pkt); + + virtual void recvRetry(); + + void recvFunctional(PacketPtr pkt); + + void recvRangeChange(); + + }; + public: /** Reads this CPU's ID. */ int cpuId() { return _cpuId; } diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 6c3c50a9c..178ded80e 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -98,12 +98,12 @@ class CheckerThreadContext : public ThreadContext Process *getProcessPtr() { return actualTC->getProcessPtr(); } - TranslatingPort *getMemPort() { return actualTC->getMemPort(); } + PortProxy* getPhysProxy() { return actualTC->getPhysProxy(); } - VirtualPort *getVirtPort() - { return actualTC->getVirtPort(); } + FSTranslatingPortProxy* getVirtProxy() + { return actualTC->getVirtProxy(); } - FunctionalPort *getPhysPort() { return actualTC->getPhysPort(); } + SETranslatingPortProxy* getMemProxy() { return actualTC->getMemProxy(); } Status status() const { return actualTC->status(); } diff --git a/src/cpu/inorder/InOrderCPU.py b/src/cpu/inorder/InOrderCPU.py index 4766a1ac1..40af48b19 100644 --- a/src/cpu/inorder/InOrderCPU.py +++ b/src/cpu/inorder/InOrderCPU.py @@ -44,9 +44,6 @@ class InOrderCPU(BaseCPU): fetchMemPort = Param.String("icache_port" , "Name of Memory Port to get instructions from") dataMemPort = Param.String("dcache_port" , "Name of Memory Port to get data from") - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") - _cached_ports = ['icache_port', 'dcache_port'] fetchBuffSize = Param.Unsigned(4, "Fetch Buffer Size (Number of Cache Blocks Stored)") memBlockSize = Param.Unsigned(64, "Memory Block Size") diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 010bdb512..5a14e92a7 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -54,7 +54,6 @@ #include "debug/RefCount.hh" #include "debug/SkedCache.hh" #include "debug/Quiesce.hh" -#include "mem/translating_port.hh" #include "params/InOrderCPU.hh" #include "sim/full_system.hh" #include "sim/process.hh" @@ -758,6 +757,8 @@ InOrderCPU::init() for (ThreadID tid = 0; tid < numThreads; tid++) { ThreadContext *src_tc = threadContexts[tid]; TheISA::initCPU(src_tc, src_tc->contextId()); + // Initialise the ThreadContext's memory proxies + thread[tid]->initMemProxies(thread[tid]->getTC()); } } @@ -860,7 +861,6 @@ InOrderCPU::getInterrupts() return interrupts->getInterrupt(threadContexts[0]); } - void InOrderCPU::processInterrupts(Fault interrupt) { @@ -880,16 +880,6 @@ InOrderCPU::processInterrupts(Fault interrupt) } void -InOrderCPU::updateMemPorts() -{ - // Update all ThreadContext's memory ports (Functional/Virtual - // Ports) - ThreadID size = thread.size(); - for (ThreadID i = 0; i < size; ++i) - thread[i]->connectMemPorts(thread[i]->getTC()); -} - -void InOrderCPU::trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay) { scheduleCpuEvent(Trap, fault, tid, inst, delay); diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index bbd02e027..7d22bc902 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -428,10 +428,6 @@ class InOrderCPU : public BaseCPU /** Halts the CPU. */ void halt() { panic("Halt not implemented!\n"); } - /** 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/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 90ed83d68..0ab9f0579 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -82,17 +82,8 @@ CacheUnit::CachePort::recvFunctional(PacketPtr pkt) } void -CacheUnit::CachePort::recvStatusChange(Status status) +CacheUnit::CachePort::recvRangeChange() { - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("CacheUnit::CachePort doesn't expect recvStatusChange callback!"); } bool @@ -145,18 +136,6 @@ CacheUnit::tlb() } -void -CacheUnit::CachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - // Update the ThreadContext's memory ports (Functional/Virtual - // Ports) - if (cachePortUnit->resName == "dcache_port") { - cachePortUnit->cpu->updateMemPorts(); - } -} - Port * CacheUnit::getPort(const string &if_name, int idx) { diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh index a8dde512b..2155c920c 100644 --- a/src/cpu/inorder/resources/cache_unit.hh +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -90,13 +90,9 @@ class CacheUnit : public Resource CachePort(CacheUnit *_cachePortUnit) : Port(_cachePortUnit->name() + "-cache-port", (MemObject*)_cachePortUnit->cpu), - cachePortUnit(_cachePortUnit), snoopRangeSent(false) + cachePortUnit(_cachePortUnit) { } - bool snoopRangeSent; - - void setPeer(Port *port); - protected: /** Atomic version of receive. Panics. */ Tick recvAtomic(PacketPtr pkt); @@ -104,13 +100,8 @@ class CacheUnit : public Resource /** Functional version of receive.*/ void recvFunctional(PacketPtr pkt); - /** Receives status change. Other than range changing, panics. */ - void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } + /** Receives range changes. */ + void recvRangeChange(); /** Timing version of receive */ bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index 5f141a1b3..acfcf0939 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -38,10 +38,10 @@ using namespace TheISA; -VirtualPort * -InOrderThreadContext::getVirtPort() +FSTranslatingPortProxy* +InOrderThreadContext::getVirtProxy() { - return thread->getVirtPort(); + return thread->getVirtProxy(); } void diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 84d62137e..7fe0fb5ef 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -117,8 +117,12 @@ class InOrderThreadContext : public ThreadContext TheISA::Kernel::Statistics *getKernelStats() { return thread->kernelStats; } - void connectMemPorts(ThreadContext *tc) - { thread->connectMemPorts(tc); } + PortProxy* getPhysProxy() { return thread->getPhysProxy(); } + + FSTranslatingPortProxy* getVirtProxy(); + + void initMemProxies(ThreadContext *tc) + { thread->initMemProxies(tc); } /** Dumps the function profiling information. * @todo: Implement. @@ -142,14 +146,11 @@ class InOrderThreadContext : public ThreadContext return this->thread->quiesceEvent; } + SETranslatingPortProxy* getMemProxy() { return thread->getMemProxy(); } + /** Returns a pointer to this thread's process. */ Process *getProcessPtr() { return thread->getProcessPtr(); } - TranslatingPort *getMemPort() { return thread->getMemPort(); } - - VirtualPort *getVirtPort(); - FunctionalPort *getPhysPort() { return thread->getPhysPort(); } - /** Returns this thread's status. */ Status status() const { return thread->status(); } diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index 1d8950a73..ffc817e81 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -49,9 +49,6 @@ class DerivO3CPU(BaseCPU): checker.dtb = Parent.dtb cachePorts = Param.Unsigned(200, "Cache Ports") - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") - _cached_ports = BaseCPU._cached_ports + ['icache_port', 'dcache_port'] decodeToFetchDelay = Param.Unsigned(1, "Decode to fetch delay") renameToFetchDelay = Param.Unsigned(1 ,"Rename to fetch delay") diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 5d3af6c70..ef08c96f4 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2006 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -76,6 +88,42 @@ BaseO3CPU::regStats() BaseCPU::regStats(); } +template<class Impl> +bool +FullO3CPU<Impl>::IcachePort::recvTiming(PacketPtr pkt) +{ + DPRINTF(O3CPU, "Fetch unit received timing\n"); + if (pkt->isResponse()) { + // We shouldn't ever get a block in ownership state + assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); + + fetch->processCacheCompletion(pkt); + } + //else Snooped a coherence request, just return + return true; +} + +template<class Impl> +void +FullO3CPU<Impl>::IcachePort::recvRetry() +{ + fetch->recvRetry(); +} + +template <class Impl> +bool +FullO3CPU<Impl>::DcachePort::recvTiming(PacketPtr pkt) +{ + return lsq->recvTiming(pkt); +} + +template <class Impl> +void +FullO3CPU<Impl>::DcachePort::recvRetry() +{ + lsq->recvRetry(); +} + template <class Impl> FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) : Event(CPU_Tick_Pri), cpu(c) @@ -191,6 +239,9 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) TheISA::NumMiscRegs * numThreads, TheISA::ZeroReg), + icachePort(&fetch, this), + dcachePort(&iew.ldstQueue, this), + timeBuffer(params->backComSize, params->forwardComSize), fetchQueue(params->backComSize, params->forwardComSize), decodeQueue(params->backComSize, params->forwardComSize), @@ -215,6 +266,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) if (params->checker) { BaseCPU *temp_checker = params->checker; checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); + checker->setIcachePort(&icachePort); checker->setSystem(params->system); } else { checker = NULL; @@ -524,9 +576,9 @@ Port * FullO3CPU<Impl>::getPort(const std::string &if_name, int idx) { if (if_name == "dcache_port") - return iew.getDcachePort(); + return &dcachePort; else if (if_name == "icache_port") - return fetch.getIcachePort(); + return &icachePort; else panic("No Such Port\n"); } @@ -600,10 +652,19 @@ FullO3CPU<Impl>::init() for (ThreadID tid = 0; tid < numThreads; ++tid) thread[tid]->inSyscall = true; + // this CPU could still be unconnected if we are restoring from a + // checkpoint and this CPU is to be switched in, thus we can only + // do this here if the instruction port is actually connected, if + // not we have to do it as part of takeOverFrom + if (icachePort.isConnected()) + fetch.setIcache(); + if (FullSystem) { for (ThreadID tid = 0; tid < numThreads; tid++) { ThreadContext *src_tc = threadContexts[tid]; TheISA::initCPU(src_tc, src_tc->contextId()); + // Initialise the ThreadContext's memory proxies + thread[tid]->initMemProxies(thread[tid]->getTC()); } } @@ -969,17 +1030,6 @@ FullO3CPU<Impl>::processInterrupts(Fault interrupt) template <class Impl> void -FullO3CPU<Impl>::updateMemPorts() -{ - // Update all ThreadContext's memory ports (Functional/Virtual - // Ports) - ThreadID size = thread.size(); - for (ThreadID i = 0; i < size; ++i) - thread[i]->connectMemPorts(thread[i]->getTC()); -} - -template <class Impl> -void FullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst) { // Pass the thread's TC into the invoke method. @@ -1166,7 +1216,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) activityRec.reset(); - BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); fetch.takeOverFrom(); decode.takeOverFrom(); diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 7580106ad..165144c1b 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -117,6 +129,68 @@ class FullO3CPU : public BaseO3CPU Status _threadStatus[Impl::MaxThreads]; private: + + /** + * IcachePort class for instruction fetch. + */ + class IcachePort : public CpuPort + { + protected: + /** Pointer to fetch. */ + DefaultFetch<Impl> *fetch; + + public: + /** Default constructor. */ + IcachePort(DefaultFetch<Impl> *_fetch, FullO3CPU<Impl>* _cpu) + : CpuPort(_fetch->name() + "-iport", _cpu), fetch(_fetch) + { } + + protected: + + /** Timing version of receive. Handles setting fetch to the + * proper status to start fetching. */ + virtual bool recvTiming(PacketPtr pkt); + + /** Handles doing a retry of a failed fetch. */ + virtual void recvRetry(); + }; + + /** + * DcachePort class for the load/store queue. + */ + class DcachePort : public CpuPort + { + protected: + + /** Pointer to LSQ. */ + LSQ<Impl> *lsq; + + public: + /** Default constructor. */ + DcachePort(LSQ<Impl> *_lsq, FullO3CPU<Impl>* _cpu) + : CpuPort(_lsq->name() + "-dport", _cpu), lsq(_lsq) + { } + + protected: + + /** Timing version of receive. Handles writing back and + * completing the load or store that has returned from + * memory. */ + virtual bool recvTiming(PacketPtr pkt); + + /** Handles doing a retry of the previous send. */ + virtual void recvRetry(); + + /** + * As this CPU requires snooping to maintain the load store queue + * change the behaviour from the base CPU port. + * + * @return true since we have to snoop + */ + virtual bool isSnooping() + { return true; } + }; + class TickEvent : public Event { private: @@ -391,10 +465,6 @@ class FullO3CPU : public BaseO3CPU /** Halts the CPU. */ void halt() { panic("Halt not implemented!\n"); } - /** 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; } @@ -565,6 +635,12 @@ class FullO3CPU : public BaseO3CPU TheISA::ISA isa[Impl::MaxThreads]; + /** Instruction port. Note that it has to appear after the fetch stage. */ + IcachePort icachePort; + + /** Data port. Note that it has to appear after the iew stages */ + DcachePort dcachePort; + public: /** Enum to give each stage a specific index, so when calling * activateStage() or deactivateStage(), they can specify which stage @@ -701,8 +777,11 @@ class FullO3CPU : public BaseO3CPU data, store_idx); } + /** Used by the fetch unit to get a hold of the instruction port. */ + Port* getIcachePort() { return &icachePort; } + /** Get the dcache port (used to find block size for translations). */ - Port *getDcachePort() { return this->iew.ldstQueue.getDcachePort(); } + Port* getDcachePort() { return &dcachePort; } Addr lockAddr; diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index d09d7f680..f5d275593 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2011 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -85,48 +85,6 @@ class DefaultFetch typedef TheISA::MachInst MachInst; typedef TheISA::ExtMachInst ExtMachInst; - /** IcachePort class for DefaultFetch. Handles doing the - * communication with the cache/memory. - */ - class IcachePort : public Port - { - protected: - /** Pointer to fetch. */ - DefaultFetch<Impl> *fetch; - - public: - /** Default constructor. */ - IcachePort(DefaultFetch<Impl> *_fetch) - : Port(_fetch->name() + "-iport", _fetch->cpu), fetch(_fetch) - { } - - bool snoopRangeSent; - - virtual void setPeer(Port *port); - - protected: - /** Atomic version of receive. Panics. */ - virtual Tick recvAtomic(PacketPtr pkt); - - /** Functional version of receive. Panics. */ - virtual void recvFunctional(PacketPtr pkt); - - /** Receives status change. Other than range changing, panics. */ - virtual void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } - - /** Timing version of receive. Handles setting fetch to the - * proper status to start fetching. */ - virtual bool recvTiming(PacketPtr pkt); - - /** Handles doing a retry of a failed fetch. */ - virtual void recvRetry(); - }; - class FetchTranslation : public BaseTLB::Translation { protected: @@ -248,9 +206,6 @@ class DefaultFetch /** Registers statistics. */ void regStats(); - /** Returns the icache port. */ - Port *getIcachePort() { return icachePort; } - /** Sets the main backwards communication time buffer pointer. */ void setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer); @@ -266,6 +221,9 @@ class DefaultFetch /** Tells the fetch stage that the Icache is set. */ void setIcache(); + /** Handles retrying the fetch access. */ + void recvRetry(); + /** Processes cache completion event. */ void processCacheCompletion(PacketPtr pkt); @@ -389,9 +347,6 @@ class DefaultFetch StaticInstPtr curMacroop, TheISA::PCState thisPC, TheISA::PCState nextPC, bool trace); - /** Handles retrying the fetch access. */ - void recvRetry(); - /** Returns the appropriate thread to fetch, given the fetch policy. */ ThreadID getFetchingThread(FetchPriority &fetch_priority); @@ -440,9 +395,6 @@ class DefaultFetch /** Wire used to write any information heading to decode. */ typename TimeBuffer<FetchStruct>::wire toDecode; - /** Icache interface. */ - IcachePort *icachePort; - /** BPredUnit. */ BPredUnit branchPred; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 28fd434fe..1b82f8a4c 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2011 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -69,68 +69,6 @@ using namespace std; template<class Impl> -void -DefaultFetch<Impl>::IcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - fetch->setIcache(); -} - -template<class Impl> -Tick -DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt) -{ - panic("DefaultFetch doesn't expect recvAtomic callback!"); - return curTick(); -} - -template<class Impl> -void -DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt) -{ - DPRINTF(Fetch, "DefaultFetch doesn't update its state from a " - "functional call.\n"); -} - -template<class Impl> -void -DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("DefaultFetch doesn't expect recvStatusChange callback!"); -} - -template<class Impl> -bool -DefaultFetch<Impl>::IcachePort::recvTiming(PacketPtr pkt) -{ - DPRINTF(Fetch, "Received timing\n"); - if (pkt->isResponse()) { - // We shouldn't ever get a block in ownership state - assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); - - fetch->processCacheCompletion(pkt); - } - //else Snooped a coherence request, just return - return true; -} - -template<class Impl> -void -DefaultFetch<Impl>::IcachePort::recvRetry() -{ - fetch->recvRetry(); -} - -template<class Impl> DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) : cpu(_cpu), branchPred(params), @@ -189,17 +127,6 @@ DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) // Get the size of an instruction. instSize = sizeof(TheISA::MachInst); - - // Name is finally available, so create the port. - icachePort = new IcachePort(this); - - icachePort->snoopRangeSent = false; - -#if USE_CHECKER - if (cpu->checker) { - cpu->checker->setIcachePort(icachePort); - } -#endif } template <class Impl> @@ -402,8 +329,10 @@ template<class Impl> void DefaultFetch<Impl>::setIcache() { + assert(cpu->getIcachePort()->isConnected()); + // Size of cache block. - cacheBlkSize = icachePort->peerBlockSize(); + cacheBlkSize = cpu->getIcachePort()->peerBlockSize(); // Create mask to get rid of offset bits. cacheBlkMask = (cacheBlkSize - 1); @@ -494,6 +423,10 @@ template <class Impl> void DefaultFetch<Impl>::takeOverFrom() { + // the instruction port is now connected so we can get the block + // size + setIcache(); + // Reset all state for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { stalls[i].decode = 0; @@ -684,7 +617,7 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req) fetchedCacheLines++; // Access the cache. - if (!icachePort->sendTiming(data_pkt)) { + if (!cpu->getIcachePort()->sendTiming(data_pkt)) { assert(retryPkt == NULL); assert(retryTid == InvalidThreadID); DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); @@ -1403,7 +1336,7 @@ DefaultFetch<Impl>::recvRetry() assert(retryTid != InvalidThreadID); assert(fetchStatus[retryTid] == IcacheWaitRetry); - if (icachePort->sendTiming(retryPkt)) { + if (cpu->getIcachePort()->sendTiming(retryPkt)) { fetchStatus[retryTid] = IcacheWaitResponse; retryPkt = NULL; retryTid = InvalidThreadID; diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh index 2c5858a51..0d7e0f68f 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -138,9 +138,6 @@ class DefaultIEW /** Initializes stage; sends back the number of free IQ and LSQ entries. */ void initStage(); - /** Returns the dcache port. */ - Port *getDcachePort() { return ldstQueue.getDcachePort(); } - /** Sets main time buffer used for backwards communication. */ void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr); diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 1974af08f..db127a2da 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * @@ -65,13 +77,6 @@ class LSQ { /** Registers statistics of each LSQ unit. */ void regStats(); - /** Returns dcache port. - * @todo: Dcache port needs to be moved up to this level for SMT - * to work. For now it just returns the port from one of the - * threads. - */ - Port *getDcachePort() { return &dcachePort; } - /** Sets the pointer to the list of active threads. */ void setActiveThreads(std::list<ThreadID> *at_ptr); /** Switches out the LSQ. */ @@ -281,61 +286,25 @@ class LSQ { Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh, uint8_t *data, int store_idx); + /** + * Retry the previous send that failed. + */ + void recvRetry(); + + /** + * Handles writing back and completing the load or store that has + * returned from memory. + * + * @param pkt Response packet from the memory sub-system + */ + bool recvTiming(PacketPtr pkt); + /** The CPU pointer. */ O3CPU *cpu; /** The IEW stage pointer. */ IEW *iewStage; - /** DcachePort class for this LSQ. Handles doing the - * communication with the cache/memory. - */ - class DcachePort : public Port - { - protected: - /** Pointer to LSQ. */ - LSQ *lsq; - - public: - /** Default constructor. */ - DcachePort(LSQ *_lsq) - : Port(_lsq->name() + "-dport", _lsq->cpu), lsq(_lsq) - { } - - bool snoopRangeSent; - - virtual void setPeer(Port *port); - - protected: - /** Atomic version of receive. Panics. */ - virtual Tick recvAtomic(PacketPtr pkt); - - /** Functional version of receive. Panics. */ - virtual void recvFunctional(PacketPtr pkt); - - /** Receives status change. Other than range changing, panics. */ - virtual void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } - - /** Timing version of receive. Handles writing back and - * completing the load or store that has returned from - * memory. */ - virtual bool recvTiming(PacketPtr pkt); - - /** Handles doing a retry of the previous send. */ - virtual void recvRetry(); - }; - - /** D-cache port. */ - DcachePort dcachePort; - - /** Tell the CPU to update the Phys and Virt ports. */ - void updateMemPorts() { cpu->updateMemPorts(); } - 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 8b1638c70..f1642be9c 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2005-2006 The Regents of The University of Michigan * All rights reserved. * @@ -40,96 +52,14 @@ using namespace std; -template<class Impl> -void -LSQ<Impl>::DcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - // Update the ThreadContext's memory ports (Functional/Virtual - // Ports) - lsq->updateMemPorts(); -} - -template <class Impl> -Tick -LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) -{ - panic("O3CPU model does not work with atomic mode!"); - return curTick(); -} - -template <class Impl> -void -LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) -{ - DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.\n"); -} - -template <class Impl> -void -LSQ<Impl>::DcachePort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - panic("O3CPU doesn't expect recvStatusChange callback!"); -} - -template <class Impl> -bool -LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) -{ - if (pkt->isError()) - DPRINTF(LSQ, "Got error packet back for address: %#X\n", pkt->getAddr()); - if (pkt->isResponse()) { - lsq->thread[pkt->req->threadId()].completeDataAccess(pkt); - } else { - DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(), - pkt->cmdString()); - - // must be a snoop - if (pkt->isInvalidate()) { - DPRINTF(LSQ, "received invalidation for addr:%#x\n", pkt->getAddr()); - for (ThreadID tid = 0; tid < lsq->numThreads; tid++) { - lsq->thread[tid].checkSnoop(pkt); - } - } - // to provide stronger consistency model - } - return true; -} - -template <class Impl> -void -LSQ<Impl>::DcachePort::recvRetry() -{ - if (lsq->retryTid == -1) - { - //Squashed, so drop it - return; - } - int curr_retry_tid = lsq->retryTid; - // Speculatively clear the retry Tid. This will get set again if - // the LSQUnit was unable to complete its access. - lsq->retryTid = -1; - lsq->thread[curr_retry_tid].recvRetry(); -} - template <class Impl> LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) - : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this), + : cpu(cpu_ptr), iewStage(iew_ptr), LQEntries(params->LQEntries), SQEntries(params->SQEntries), numThreads(params->numThreads), retryTid(-1) { - dcachePort.snoopRangeSent = false; - //**********************************************/ //************ Handle SMT Parameters ***********/ //**********************************************/ @@ -181,7 +111,7 @@ LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) for (ThreadID tid = 0; tid < numThreads; tid++) { thread[tid].init(cpu, iew_ptr, params, this, maxLQEntries, maxSQEntries, tid); - thread[tid].setDcachePort(&dcachePort); + thread[tid].setDcachePort(cpu_ptr->getDcachePort()); } } @@ -371,6 +301,48 @@ LSQ<Impl>::violation() return false; } +template <class Impl> +void +LSQ<Impl>::recvRetry() +{ + if (retryTid == InvalidThreadID) + { + //Squashed, so drop it + return; + } + int curr_retry_tid = retryTid; + // Speculatively clear the retry Tid. This will get set again if + // the LSQUnit was unable to complete its access. + retryTid = -1; + thread[curr_retry_tid].recvRetry(); +} + +template <class Impl> +bool +LSQ<Impl>::recvTiming(PacketPtr pkt) +{ + if (pkt->isError()) + DPRINTF(LSQ, "Got error packet back for address: %#X\n", + pkt->getAddr()); + if (pkt->isResponse()) { + thread[pkt->req->threadId()].completeDataAccess(pkt); + } else { + DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(), + pkt->cmdString()); + + // must be a snoop + if (pkt->isInvalidate()) { + DPRINTF(LSQ, "received invalidation for addr:%#x\n", + pkt->getAddr()); + for (ThreadID tid = 0; tid < numThreads; tid++) { + thread[tid].checkSnoop(pkt); + } + } + // to provide stronger consistency model + } + return true; +} + template<class Impl> int LSQ<Impl>::getCount() diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 815c9cb64..ff6ca0093 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -96,17 +96,18 @@ class O3ThreadContext : public ThreadContext virtual TheISA::Kernel::Statistics *getKernelStats() { return thread->kernelStats; } - virtual void connectMemPorts(ThreadContext *tc) - { thread->connectMemPorts(tc); } - /** Returns a pointer to this thread's process. */ virtual Process *getProcessPtr() { return thread->getProcessPtr(); } - virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } + virtual PortProxy* getPhysProxy() { return thread->getPhysProxy(); } + + virtual FSTranslatingPortProxy* getVirtProxy(); - virtual VirtualPort *getVirtPort(); + virtual void initMemProxies(ThreadContext *tc) + { thread->initMemProxies(tc); } - virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); } + virtual SETranslatingPortProxy* getMemProxy() + { return thread->getMemProxy(); } /** Returns this thread's status. */ virtual Status status() const { return thread->status(); } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 15fc397dc..5ba454458 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -49,10 +49,10 @@ #include "debug/O3CPU.hh" template <class Impl> -VirtualPort * -O3ThreadContext<Impl>::getVirtPort() +FSTranslatingPortProxy* +O3ThreadContext<Impl>::getVirtProxy() { - return thread->getVirtPort(); + return thread->getVirtProxy(); } template <class Impl> diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 36df58ab5..ff43ad6cb 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -114,12 +114,12 @@ class OzoneCPU : public BaseCPU Process *getProcessPtr() { return thread->getProcessPtr(); } - TranslatingPort *getMemPort() { return thread->getMemPort(); } + PortProxy* getPhysProxy() { return thread->getPhysProxy(); } - VirtualPort *getVirtPort() - { return thread->getVirtPort(); } + FSTranslatingPortProxy* getVirtProxy() + { return thread->getVirtProxy(); } - FunctionalPort *getPhysPort() { return thread->getPhysPort(); } + SETranslatingPortProxy* getMemProxy() { return thread->getMemProxy(); } Status status() const { return thread->status(); } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index e2f5dc10c..f532078fe 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -186,25 +186,7 @@ OzoneCPU<Impl>::OzoneCPU(Params *p) frontEnd->renameTable.copyFrom(thread.renameTable); backEnd->renameTable.copyFrom(thread.renameTable); - if (FullSystem) { - Port *mem_port; - FunctionalPort *phys_port; - VirtualPort *virt_port; - phys_port = new FunctionalPort(csprintf("%s-%d-funcport", - name(), 0)); - mem_port = system->physmem->getPort("functional"); - mem_port->setPeer(phys_port); - phys_port->setPeer(mem_port); - - virt_port = new VirtualPort(csprintf("%s-%d-vport", - name(), 0)); - mem_port = system->physmem->getPort("functional"); - mem_port->setPeer(virt_port); - virt_port->setPeer(mem_port); - - thread.setPhysPort(phys_port); - thread.setVirtPort(virt_port); - } + thread.connectMemPorts(tc); DPRINTF(OzoneCPU, "OzoneCPU: Created Ozone cpu object.\n"); } diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index 1d200ef7d..41b86aab8 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -87,13 +87,8 @@ class FrontEnd /** Functional version of receive. Panics. */ virtual void recvFunctional(PacketPtr pkt); - /** Receives status change. Other than range changing, panics. */ - virtual void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } + /** Receives range change. */ + virtual void recvRangeChange(); /** Timing version of receive. Handles setting fetch to the * proper status to start fetching. */ diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 88576de3d..e7255d75f 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -64,12 +64,8 @@ FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt) template<class Impl> void -FrontEnd<Impl>::IcachePort::recvStatusChange(Status status) +FrontEnd<Impl>::IcachePort::recvRangeChange() { - if (status == RangeChange) - return; - - panic("FrontEnd doesn't expect recvStatusChange callback!"); } template<class Impl> diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 34461b9d0..dd573e5e0 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -255,11 +255,13 @@ class OzoneLWLSQ { virtual void recvFunctional(PacketPtr pkt); - virtual void recvStatusChange(Status status); + virtual void recvRangeChange(); - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } + /** + * Is a snooper due to LSQ maintenance + */ + virtual bool isSnooping() + { return true; } virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index 3bee83176..811d66567 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -77,12 +77,8 @@ OzoneLWLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) template <class Impl> void -OzoneLWLSQ<Impl>::DcachePort::recvStatusChange(Status status) +OzoneLWLSQ<Impl>::DcachePort::recvRangeChange() { - if (status == RangeChange) - return; - - panic("O3CPU doesn't expect recvStatusChange callback!"); } template <class Impl> diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index a4d807f86..93cd02ba7 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -34,8 +34,4 @@ class AtomicSimpleCPU(BaseSimpleCPU): width = Param.Int(1, "CPU width") simulate_data_stalls = Param.Bool(False, "Simulate dcache stall cycles") simulate_inst_stalls = Param.Bool(False, "Simulate icache stall cycles") - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") physmem_port = Port("Physical Memory Port") - _cached_ports = BaseSimpleCPU._cached_ports + \ - ['icache_port', 'dcache_port'] diff --git a/src/cpu/simple/TimingSimpleCPU.py b/src/cpu/simple/TimingSimpleCPU.py index 8d6888f72..61491b087 100644 --- a/src/cpu/simple/TimingSimpleCPU.py +++ b/src/cpu/simple/TimingSimpleCPU.py @@ -31,6 +31,3 @@ from BaseSimpleCPU import BaseSimpleCPU class TimingSimpleCPU(BaseSimpleCPU): type = 'TimingSimpleCPU' - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") - _cached_ports = BaseSimpleCPU._cached_ports + ['icache_port', 'dcache_port'] diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index fed94ffd8..2c12b244b 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -92,10 +92,12 @@ AtomicSimpleCPU::init() TheISA::initCPU(tc, tc->contextId()); } } + + // Initialise the ThreadContext's memory proxies + tcBase()->initMemProxies(tcBase()); + if (hasPhysMemPort) { - bool snoop = false; - AddrRangeList pmAddrList; - physmemPort.getPeerAddressRanges(pmAddrList, snoop); + AddrRangeList pmAddrList = physmemPort.getPeer()->getAddrRanges(); physMemAddr = *pmAddrList.begin(); } // Atomic doesn't do MT right now, so contextId == threadId @@ -104,59 +106,6 @@ AtomicSimpleCPU::init() data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too } -bool -AtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt) -{ - panic("AtomicSimpleCPU doesn't expect recvTiming callback!"); - return true; -} - -Tick -AtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) -{ - //Snooping a coherence request, just return - return 0; -} - -void -AtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) -{ - //No internal storage to update, just return - return; -} - -void -AtomicSimpleCPU::CpuPort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!"); -} - -void -AtomicSimpleCPU::CpuPort::recvRetry() -{ - panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); -} - -void -AtomicSimpleCPU::DcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - if (FullSystem) { - // Update the ThreadContext's memory ports (Functional/Virtual - // Ports) - cpu->tcBase()->connectMemPorts(cpu->tcBase()); - } -} - AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false), simulate_data_stalls(p->simulate_data_stalls), @@ -165,10 +114,6 @@ AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) physmemPort(name() + "-iport", this), hasPhysMemPort(false) { _status = Idle; - - icachePort.snoopRangeSent = false; - dcachePort.snoopRangeSent = false; - } diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 246afa0b2..77a9d6b0d 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -64,47 +64,31 @@ class AtomicSimpleCPU : public BaseSimpleCPU // main simulation loop (one cycle) void tick(); - class CpuPort : public Port + /** + * An AtomicCPUPort overrides the default behaviour of the + * recvAtomic and ignores the packet instead of panicking. + */ + class AtomicCPUPort : public CpuPort { + public: - CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu) - : Port(_name, _cpu), cpu(_cpu) + AtomicCPUPort(const std::string &_name, BaseCPU* _cpu) + : CpuPort(_name, _cpu) { } - bool snoopRangeSent; - protected: - AtomicSimpleCPU *cpu; - - virtual bool recvTiming(PacketPtr pkt); - - virtual Tick recvAtomic(PacketPtr pkt); - - virtual void recvFunctional(PacketPtr pkt); - - virtual void recvStatusChange(Status status); - - virtual void recvRetry(); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } + virtual Tick recvAtomic(PacketPtr pkt) + { + // Snooping a coherence request, just return + return 0; + } }; - CpuPort icachePort; - class DcachePort : public CpuPort - { - public: - DcachePort(const std::string &_name, AtomicSimpleCPU *_cpu) - : CpuPort(_name, _cpu) - { } - - virtual void setPeer(Port *port); - }; - DcachePort dcachePort; + AtomicCPUPort icachePort; + AtomicCPUPort dcachePort; CpuPort physmemPort; bool hasPhysMemPort; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 983672c27..fd02e8300 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -82,53 +82,24 @@ TimingSimpleCPU::init() TheISA::initCPU(tc, _cpuId); } } -} - -Tick -TimingSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) -{ - panic("TimingSimpleCPU doesn't expect recvAtomic callback!"); - return curTick(); -} -void -TimingSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) -{ - //No internal storage to update, jusst return - return; + // Initialise the ThreadContext's memory proxies + tcBase()->initMemProxies(tcBase()); } void -TimingSimpleCPU::CpuPort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("TimingSimpleCPU doesn't expect recvStatusChange callback!"); -} - - -void -TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) +TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t) { pkt = _pkt; cpu->schedule(this, t); } TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) - : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock), - dcachePort(this, p->clock), fetchEvent(this) + : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this), + dcachePort(this), fetchEvent(this) { _status = Idle; - icachePort.snoopRangeSent = false; - dcachePort.snoopRangeSent = false; - ifetch_pkt = dcache_pkt = NULL; drainEvent = NULL; previousTick = 0; @@ -874,18 +845,6 @@ TimingSimpleCPU::completeDrain() drainEvent->process(); } -void -TimingSimpleCPU::DcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - if (FullSystem) { - // Update the ThreadContext's memory ports (Functional/Virtual - // Ports) - cpu->tcBase()->connectMemPorts(cpu->tcBase()); - } -} - bool TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { @@ -903,7 +862,7 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) // faster than a CPU we could get two responses before // next_tick expires if (!retryEvent.scheduled()) - schedule(retryEvent, next_tick); + cpu->schedule(retryEvent, next_tick); return false; } } diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 4301dfca7..dce3c58ff 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -137,31 +137,23 @@ class TimingSimpleCPU : public BaseSimpleCPU // This function always implicitly uses dcache_pkt. bool handleWritePacket(); - class CpuPort : public Port + /** + * A TimingCPUPort overrides the default behaviour of the + * recvTiming and recvRetry and implements events for the + * scheduling of handling of incoming packets in the following + * cycle. + */ + class TimingCPUPort : public CpuPort { - protected: - TimingSimpleCPU *cpu; - Tick lat; - public: - CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat) - : Port(_name, _cpu), cpu(_cpu), lat(_lat), retryEvent(this) + TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu) + : CpuPort(_name, _cpu), cpu(_cpu), retryEvent(this) { } - bool snoopRangeSent; - protected: - virtual Tick recvAtomic(PacketPtr pkt); - - virtual void recvFunctional(PacketPtr pkt); - - virtual void recvStatusChange(Status status); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = false; } + TimingSimpleCPU* cpu; struct TickEvent : public Event { @@ -169,7 +161,7 @@ class TimingSimpleCPU : public BaseSimpleCPU TimingSimpleCPU *cpu; CpuPort *port; - TickEvent(TimingSimpleCPU *_cpu) : cpu(_cpu) {} + TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {} const char *description() const { return "Timing CPU tick"; } void schedule(PacketPtr _pkt, Tick t); }; @@ -177,12 +169,13 @@ class TimingSimpleCPU : public BaseSimpleCPU EventWrapper<Port, &Port::sendRetry> retryEvent; }; - class IcachePort : public CpuPort + class IcachePort : public TimingCPUPort { public: - IcachePort(TimingSimpleCPU *_cpu, Tick _lat) - : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu) + IcachePort(TimingSimpleCPU *_cpu) + : TimingCPUPort(_cpu->name() + "-iport", _cpu), + tickEvent(_cpu) { } protected: @@ -204,16 +197,14 @@ class TimingSimpleCPU : public BaseSimpleCPU }; - class DcachePort : public CpuPort + class DcachePort : public TimingCPUPort { public: - DcachePort(TimingSimpleCPU *_cpu, Tick _lat) - : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu) + DcachePort(TimingSimpleCPU *_cpu) + : TimingCPUPort(_cpu->name() + "-dport", _cpu), tickEvent(_cpu) { } - virtual void setPeer(Port *port); - protected: virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index edde884e7..a12ab8e8a 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -47,13 +47,14 @@ #include "cpu/quiesce_event.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" -#include "mem/translating_port.hh" -#include "mem/vport.hh" #include "params/BaseCPU.hh" +#include "mem/fs_translating_port_proxy.hh" +#include "mem/se_translating_port_proxy.hh" #include "sim/full_system.hh" #include "sim/process.hh" #include "sim/serialize.hh" #include "sim/sim_exit.hh" +#include "sim/process.hh" #include "sim/system.hh" using namespace std; @@ -106,8 +107,6 @@ SimpleThread::SimpleThread() SimpleThread::~SimpleThread() { - delete physPort; - delete virtPort; delete tc; } diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index ffa89a967..f2132dc36 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -57,7 +57,6 @@ class BaseCPU; class FunctionProfile; class ProfileNode; -class FunctionalPort; class PhysicalPort; class TranslatingPort; @@ -195,13 +194,13 @@ class SimpleThread : public ThreadState System *getSystemPtr() { return system; } - FunctionalPort *getPhysPort() { return physPort; } + PortProxy* getPhysProxy() { return physProxy; } /** Return a virtual port. This port cannot be cached locally in an object. * After a CPU switch it may point to the wrong memory object which could * mean stale data. */ - VirtualPort *getVirtPort() { return virtPort; } + FSTranslatingPortProxy* getVirtProxy() { return virtProxy; } Status status() const { return _status; } diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc index ef23825cd..d70dc96e6 100644 --- a/src/cpu/testers/memtest/memtest.cc +++ b/src/cpu/testers/memtest/memtest.cc @@ -84,17 +84,8 @@ MemTest::CpuPort::recvFunctional(PacketPtr pkt) } void -MemTest::CpuPort::recvStatusChange(Status status) +MemTest::CpuPort::recvRangeChange() { - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("MemTest doesn't expect recvStatusChange callback!"); } void @@ -149,9 +140,6 @@ MemTest::MemTest(const Params *p) atomic(p->atomic), suppress_func_warnings(p->suppress_func_warnings) { - cachePort.snoopRangeSent = false; - funcPort.snoopRangeSent = true; - id = TESTER_ALLOCATOR++; // Needs to be masked off once we know the block size. diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh index 292e7d83d..1a59914fd 100644 --- a/src/cpu/testers/memtest/memtest.hh +++ b/src/cpu/testers/memtest/memtest.hh @@ -93,8 +93,6 @@ class MemTest : public MemObject : Port(_name, _memtest), memtest(_memtest) { } - bool snoopRangeSent; - protected: virtual bool recvTiming(PacketPtr pkt); @@ -103,20 +101,14 @@ class MemTest : public MemObject virtual void recvFunctional(PacketPtr pkt); - virtual void recvStatusChange(Status status); + virtual void recvRangeChange(); virtual void recvRetry(); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = false; } }; CpuPort cachePort; CpuPort funcPort; - bool snoopRangeSent; - class MemTestSenderState : public Packet::SenderState, public FastAlloc { public: diff --git a/src/cpu/testers/networktest/networktest.cc b/src/cpu/testers/networktest/networktest.cc index d78f976be..56fcc46c4 100644 --- a/src/cpu/testers/networktest/networktest.cc +++ b/src/cpu/testers/networktest/networktest.cc @@ -81,17 +81,8 @@ NetworkTest::CpuPort::recvFunctional(PacketPtr pkt) } void -NetworkTest::CpuPort::recvStatusChange(Status status) +NetworkTest::CpuPort::recvRangeChange() { - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("NetworkTest doesn't expect recvStatusChange callback!"); } void @@ -124,8 +115,6 @@ NetworkTest::NetworkTest(const Params *p) injRate(p->inj_rate), precision(p->precision) { - cachePort.snoopRangeSent = false; - // set up counters noResponseCycles = 0; schedule(tickEvent, 0); diff --git a/src/cpu/testers/networktest/networktest.hh b/src/cpu/testers/networktest/networktest.hh index 6d9d1edad..c277cfbab 100644 --- a/src/cpu/testers/networktest/networktest.hh +++ b/src/cpu/testers/networktest/networktest.hh @@ -89,8 +89,6 @@ class NetworkTest : public MemObject : Port(_name, _networktest), networktest(_networktest) { } - bool snoopRangeSent; - protected: virtual bool recvTiming(PacketPtr pkt); @@ -99,19 +97,13 @@ class NetworkTest : public MemObject virtual void recvFunctional(PacketPtr pkt); - virtual void recvStatusChange(Status status); + virtual void recvRangeChange(); virtual void recvRetry(); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = false; } }; CpuPort cachePort; - bool snoopRangeSent; - class NetworkTestSenderState : public Packet::SenderState, public FastAlloc { public: diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index f7879ea60..261ace7cf 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -49,9 +49,9 @@ class BaseCPU; class Checkpoint; class Decoder; class EndQuiesceEvent; -class TranslatingPort; -class FunctionalPort; -class VirtualPort; +class SETranslatingPortProxy; +class FSTranslatingPortProxy; +class PortProxy; class Process; class System; namespace TheISA { @@ -126,15 +126,21 @@ class ThreadContext virtual TheISA::Kernel::Statistics *getKernelStats() = 0; - virtual void connectMemPorts(ThreadContext *tc) = 0; + virtual PortProxy* getPhysProxy() = 0; - virtual Process *getProcessPtr() = 0; + virtual FSTranslatingPortProxy* getVirtProxy() = 0; - virtual TranslatingPort *getMemPort() = 0; + /** + * Initialise the physical and virtual port proxies and tie them to + * the data port of the CPU. + * + * tc ThreadContext for the virtual-to-physical translation + */ + virtual void initMemProxies(ThreadContext *tc) = 0; - virtual VirtualPort *getVirtPort() = 0; + virtual SETranslatingPortProxy *getMemProxy() = 0; - virtual FunctionalPort *getPhysPort() = 0; + virtual Process *getProcessPtr() = 0; virtual Status status() const = 0; @@ -288,15 +294,15 @@ class ProxyThreadContext : public ThreadContext TheISA::Kernel::Statistics *getKernelStats() { return actualTC->getKernelStats(); } - void connectMemPorts(ThreadContext *tc) { actualTC->connectMemPorts(tc); } + PortProxy* getPhysProxy() { return actualTC->getPhysProxy(); } - Process *getProcessPtr() { return actualTC->getProcessPtr(); } + FSTranslatingPortProxy* getVirtProxy() { return actualTC->getVirtProxy(); } - TranslatingPort *getMemPort() { return actualTC->getMemPort(); } + void initMemProxies(ThreadContext *tc) { actualTC->initMemProxies(tc); } - VirtualPort *getVirtPort() { return actualTC->getVirtPort(); } + SETranslatingPortProxy* getMemProxy() { return actualTC->getMemProxy(); } - FunctionalPort *getPhysPort() { return actualTC->getPhysPort(); } + Process *getProcessPtr() { return actualTC->getProcessPtr(); } Status status() const { return actualTC->status(); } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index ef81271a8..574be7b6d 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -34,27 +34,31 @@ #include "cpu/profile.hh" #include "cpu/quiesce_event.hh" #include "cpu/thread_state.hh" +#include "mem/fs_translating_port_proxy.hh" #include "mem/port.hh" -#include "mem/translating_port.hh" -#include "mem/vport.hh" +#include "mem/port_proxy.hh" +#include "mem/se_translating_port_proxy.hh" #include "sim/full_system.hh" #include "sim/serialize.hh" +#include "sim/system.hh" ThreadState::ThreadState(BaseCPU *cpu, ThreadID _tid, Process *_process) : numInst(0), numLoad(0), _status(ThreadContext::Halted), baseCpu(cpu), _threadId(_tid), lastActivate(0), lastSuspend(0), profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL), - kernelStats(NULL), process(_process), port(NULL), virtPort(NULL), - physPort(NULL), funcExeInst(0), storeCondFailures(0) + kernelStats(NULL), process(_process), physProxy(NULL), virtProxy(NULL), + proxy(NULL), funcExeInst(0), storeCondFailures(0) { } ThreadState::~ThreadState() { - if (port) { - delete port->getPeer(); - delete port; - } + if (physProxy != NULL) + delete physProxy; + if (virtProxy != NULL) + delete virtProxy; + if (proxy != NULL) + delete proxy; } void @@ -93,38 +97,16 @@ ThreadState::unserialize(Checkpoint *cp, const std::string §ion) } void -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. - if (physPort) - physPort->removeConn(); - else - physPort = new FunctionalPort(csprintf("%s-%d-funcport", - baseCpu->name(), _threadId)); - connectToMemFunc(physPort); -} - -void -ThreadState::connectVirtPort(ThreadContext *tc) -{ - // @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. - if (virtPort) - virtPort->removeConn(); - else - virtPort = new VirtualPort(csprintf("%s-%d-vport", - baseCpu->name(), _threadId), tc); - connectToMemFunc(virtPort); -} - -void -ThreadState::connectMemPorts(ThreadContext *tc) +ThreadState::initMemProxies(ThreadContext *tc) { - connectPhysPort(); - connectVirtPort(tc); + // Note that this only refers to the port on the CPU side and can + // safely be done at init() time even if the CPU is not connected + // (i.e. due to restoring from a checkpoint and later switching + // in. + if (physProxy == NULL) + physProxy = new PortProxy(*baseCpu->getPort("dcache_port")); + if (virtProxy == NULL) + virtProxy = new FSTranslatingPortProxy(tc); } void @@ -141,35 +123,16 @@ ThreadState::profileSample() profile->sample(profileNode, profilePC); } -TranslatingPort * -ThreadState::getMemPort() +SETranslatingPortProxy * +ThreadState::getMemProxy() { - if (port != NULL) - return port; - - /* Use this port to for syscall emulation writes to memory. */ - port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), - _threadId), process, TranslatingPort::NextPage); - - connectToMemFunc(port); - - return port; -} - -void -ThreadState::connectToMemFunc(Port *port) -{ - Port *dcache_port, *func_mem_port; - - dcache_port = baseCpu->getPort("dcache_port"); - assert(dcache_port != NULL); - - MemObject *mem_object = dcache_port->getPeer()->getOwner(); - assert(mem_object != NULL); + if (proxy != NULL) + return proxy; - func_mem_port = mem_object->getPort("functional"); - assert(func_mem_port != NULL); + /* Use this port proxy to for syscall emulation writes to memory. */ + proxy = new SETranslatingPortProxy(*process->system->getSystemPort(), + process, + SETranslatingPortProxy::NextPage); - func_mem_port->setPeer(port); - port->setPeer(func_mem_port); + return proxy; } diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 972ca895d..30bb64ed7 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -49,8 +49,9 @@ namespace TheISA { }; class Checkpoint; -class Port; -class TranslatingPort; +class PortProxy; +class SETranslatingPort; +class FSTranslatingPort; /** * Struct for holding general thread state that is needed across CPU @@ -83,11 +84,13 @@ struct ThreadState { Tick readLastSuspend() { return lastSuspend; } - void connectPhysPort(); - - void connectVirtPort(ThreadContext *tc); - - void connectMemPorts(ThreadContext *tc); + /** + * Initialise the physical and virtual port proxies and tie them to + * the data port of the CPU. + * + * tc ThreadContext for the virtual-to-physical translation + */ + void initMemProxies(ThreadContext *tc); void dumpFuncProfile(); @@ -99,17 +102,13 @@ struct ThreadState { TheISA::Kernel::Statistics *getKernelStats() { return kernelStats; } - Process *getProcessPtr() { return process; } - - TranslatingPort *getMemPort(); + PortProxy* getPhysProxy() { return physProxy; } - void setMemPort(TranslatingPort *_port) { port = _port; } + FSTranslatingPortProxy* getVirtProxy() { return virtProxy; } - VirtualPort *getVirtPort() { return virtPort; } - - FunctionalPort *getPhysPort() { return physPort; } + Process *getProcessPtr() { return process; } - void setPhysPort(FunctionalPort *port) { physPort = port; } + SETranslatingPortProxy* getMemProxy(); /** Reads the number of instructions functionally executed and * committed. @@ -128,9 +127,6 @@ struct ThreadState { void setStatus(Status new_status) { _status = new_status; } public: - /** Connects port to the functional port of the memory object - * below the CPU. */ - void connectToMemFunc(Port *port); /** Number of instructions committed. */ Counter numInst; @@ -177,15 +173,14 @@ struct ThreadState { protected: Process *process; - TranslatingPort *port; - - /** A functional port, outgoing only, for functional accesse to virtual - * addresses. */ - VirtualPort *virtPort; - - /** A functional port outgoing only for functional accesses to physical + /** A port proxy outgoing only for functional accesses to physical * addresses.*/ - FunctionalPort *physPort; + PortProxy *physProxy; + + /** A translating port proxy, outgoing only, for functional + * accesse to virtual addresses. */ + FSTranslatingPortProxy* virtProxy; + SETranslatingPortProxy* proxy; public: /* |