From f85286b3debf4a4a94d3b959e5bb880be81bd692 Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Tue, 17 Jan 2012 12:55:08 -0600 Subject: MEM: Add port proxies instead of non-structural ports Port proxies are used to replace non-structural ports, and thus enable all ports in the system to correspond to a structural entity. This has the advantage of accessing memory through the normal memory subsystem and thus allowing any constellation of distributed memories, address maps, etc. Most accesses are done through the "system port" that is used for loading binaries, debugging etc. For the entities that belong to the CPU, e.g. threads and thread contexts, they wrap the CPU data port in a port proxy. The following replacements are made: FunctionalPort > PortProxy TranslatingPort > SETranslatingPortProxy VirtualPort > FSTranslatingPortProxy --HG-- rename : src/mem/vport.cc => src/mem/fs_translating_port_proxy.cc rename : src/mem/vport.hh => src/mem/fs_translating_port_proxy.hh rename : src/mem/translating_port.cc => src/mem/se_translating_port_proxy.cc rename : src/mem/translating_port.hh => src/mem/se_translating_port_proxy.hh --- src/cpu/o3/cpu.cc | 12 ++---------- src/cpu/o3/cpu.hh | 4 ---- src/cpu/o3/lsq.hh | 7 ------- src/cpu/o3/lsq_impl.hh | 13 ------------- src/cpu/o3/thread_context.hh | 10 ++++++---- src/cpu/o3/thread_context_impl.hh | 6 +++--- 6 files changed, 11 insertions(+), 41 deletions(-) (limited to 'src/cpu/o3') diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 94fc5cdf3..ee0c3a88a 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -610,6 +610,8 @@ FullO3CPU::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()); } #endif @@ -974,16 +976,6 @@ FullO3CPU::processInterrupts(Fault interrupt) this->trap(interrupt, 0, NULL); } -template -void -FullO3CPU::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()); -} #endif template diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index b2606c1e2..652e6d99a 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -395,10 +395,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; } diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 14917bc16..d01a6b0a4 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -305,8 +305,6 @@ class LSQ { bool snoopRangeSent; - virtual void setPeer(Port *port); - protected: /** Atomic version of receive. Panics. */ virtual Tick recvAtomic(PacketPtr pkt); @@ -334,11 +332,6 @@ 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 ef9167d8c..61dced14f 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -40,19 +40,6 @@ using namespace std; -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/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 38c94439a..6ac745770 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -97,13 +97,15 @@ class O3ThreadContext : public ThreadContext virtual TheISA::Kernel::Statistics *getKernelStats() { return thread->kernelStats; } - virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); } + virtual PortProxy* getPhysProxy() { return thread->getPhysProxy(); } - virtual VirtualPort *getVirtPort(); + virtual FSTranslatingPortProxy* getVirtProxy(); - virtual void connectMemPorts(ThreadContext *tc) { thread->connectMemPorts(tc); } + virtual void initMemProxies(ThreadContext *tc) + { thread->initMemProxies(tc); } #else - virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } + virtual SETranslatingPortProxy* getMemProxy() + { return thread->getMemProxy(); } /** Returns a pointer to this thread's process. */ virtual Process *getProcessPtr() { return thread->getProcessPtr(); } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 4888cf92e..4c2fee22d 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -49,10 +49,10 @@ #if FULL_SYSTEM template -VirtualPort * -O3ThreadContext::getVirtPort() +FSTranslatingPortProxy* +O3ThreadContext::getVirtProxy() { - return thread->getVirtPort(); + return thread->getVirtProxy(); } template -- cgit v1.2.3 From b3f930c884ef23e4d784553fdccc91a772334fd7 Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Tue, 17 Jan 2012 12:55:08 -0600 Subject: CPU: Moving towards a more general port across CPU models This patch performs minimal changes to move the instruction and data ports from specialised subclasses to the base CPU (to the largest degree possible). Ultimately it servers to make the CPU(s) have a well-defined interface to the memory sub-system. --- src/cpu/o3/O3CPU.py | 3 -- src/cpu/o3/cpu.cc | 65 ++++++++++++++++++++++-- src/cpu/o3/cpu.hh | 87 +++++++++++++++++++++++++++++++- src/cpu/o3/fetch.hh | 56 ++------------------ src/cpu/o3/fetch_impl.hh | 87 ++++---------------------------- src/cpu/o3/iew.hh | 3 -- src/cpu/o3/lsq.hh | 76 +++++++++------------------- src/cpu/o3/lsq_impl.hh | 129 ++++++++++++++++++++--------------------------- 8 files changed, 243 insertions(+), 263 deletions(-) (limited to 'src/cpu/o3') diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index 2a5b6782f..9dfcc8b9e 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -53,9 +53,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 ee0c3a88a..7e0b4cee7 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. @@ -79,6 +91,42 @@ BaseO3CPU::regStats() BaseCPU::regStats(); } +template +bool +FullO3CPU::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 +void +FullO3CPU::IcachePort::recvRetry() +{ + fetch->recvRetry(); +} + +template +bool +FullO3CPU::DcachePort::recvTiming(PacketPtr pkt) +{ + return lsq->recvTiming(pkt); +} + +template +void +FullO3CPU::DcachePort::recvRetry() +{ + lsq->recvRetry(); +} + template FullO3CPU::TickEvent::TickEvent(FullO3CPU *c) : Event(CPU_Tick_Pri), cpu(c) @@ -194,6 +242,9 @@ FullO3CPU::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), @@ -218,6 +269,7 @@ FullO3CPU::FullO3CPU(DerivO3CPUParams *params) if (params->checker) { BaseCPU *temp_checker = params->checker; checker = dynamic_cast *>(temp_checker); + checker->setIcachePort(&icachePort); #if FULL_SYSTEM checker->setSystem(params->system); #endif @@ -528,9 +580,9 @@ Port * FullO3CPU::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"); } @@ -606,6 +658,13 @@ FullO3CPU::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 FULL_SYSTEM for (ThreadID tid = 0; tid < numThreads; tid++) { ThreadContext *src_tc = threadContexts[tid]; @@ -1170,7 +1229,7 @@ FullO3CPU::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 652e6d99a..1dd49a4f3 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. @@ -118,6 +130,70 @@ class FullO3CPU : public BaseO3CPU Status _threadStatus[Impl::MaxThreads]; private: + + /** + * IcachePort class for instruction fetch. + */ + class IcachePort : public CpuPort + { + protected: + /** Pointer to fetch. */ + DefaultFetch *fetch; + + public: + /** Default constructor. */ + IcachePort(DefaultFetch *_fetch, FullO3CPU* _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 *lsq; + + public: + /** Default constructor. */ + DcachePort(LSQ *_lsq, FullO3CPU* _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. + * + * @param resp list of ranges this port responds to + * @param snoop indicating if the port snoops or not + */ + virtual void getDeviceAddressRanges(AddrRangeList& resp, + bool& snoop) + { resp.clear(); snoop = true; } + }; + class TickEvent : public Event { private: @@ -566,6 +642,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 @@ -704,8 +786,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 *fetch; - - public: - /** Default constructor. */ - IcachePort(DefaultFetch *_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 *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::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 ccab47d2f..d145fb099 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 @@ -70,68 +70,6 @@ using namespace std; -template -void -DefaultFetch::IcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - fetch->setIcache(); -} - -template -Tick -DefaultFetch::IcachePort::recvAtomic(PacketPtr pkt) -{ - panic("DefaultFetch doesn't expect recvAtomic callback!"); - return curTick(); -} - -template -void -DefaultFetch::IcachePort::recvFunctional(PacketPtr pkt) -{ - DPRINTF(Fetch, "DefaultFetch doesn't update its state from a " - "functional call.\n"); -} - -template -void -DefaultFetch::IcachePort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("DefaultFetch doesn't expect recvStatusChange callback!"); -} - -template -bool -DefaultFetch::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 -void -DefaultFetch::IcachePort::recvRetry() -{ - fetch->recvRetry(); -} - template DefaultFetch::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) : cpu(_cpu), @@ -191,17 +129,6 @@ DefaultFetch::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 @@ -404,8 +331,10 @@ template void DefaultFetch::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); @@ -496,6 +425,10 @@ template void DefaultFetch::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; @@ -686,7 +619,7 @@ DefaultFetch::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); @@ -1405,7 +1338,7 @@ DefaultFetch::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 113d0756e..c58361cd6 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -139,9 +139,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 *tb_ptr); diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index d01a6b0a4..731c67ae6 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. * @@ -66,13 +78,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 *at_ptr); /** Switches out the LSQ. */ @@ -282,56 +287,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; - - 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; - 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 61dced14f..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,85 +52,14 @@ using namespace std; -template -Tick -LSQ::DcachePort::recvAtomic(PacketPtr pkt) -{ - panic("O3CPU model does not work with atomic mode!"); - return curTick(); -} - -template -void -LSQ::DcachePort::recvFunctional(PacketPtr pkt) -{ - DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.\n"); -} - -template -void -LSQ::DcachePort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - panic("O3CPU doesn't expect recvStatusChange callback!"); -} - -template -bool -LSQ::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 -void -LSQ::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 LSQ::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 ***********/ //**********************************************/ @@ -170,7 +111,7 @@ LSQ::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()); } } @@ -360,6 +301,48 @@ LSQ::violation() return false; } +template +void +LSQ::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 +bool +LSQ::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 int LSQ::getCount() -- cgit v1.2.3 From 07cf9d914b292008ead7021182ec2ef8fc4671f1 Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Tue, 17 Jan 2012 12:55:09 -0600 Subject: MEM: Separate queries for snooping and address ranges This patch simplifies the address-range determination mechanism and also unifies the naming across ports and devices. It further splits the queries for determining if a port is snooping and what address ranges it responds to (aiming towards a separation of cache-maintenance ports and pure memory-mapped ports). Default behaviours are such that most ports do not have to define isSnooping, and master ports need not implement getAddrRanges. --- src/cpu/o3/cpu.hh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/cpu/o3') diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 1dd49a4f3..121253475 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -186,12 +186,10 @@ class FullO3CPU : public BaseO3CPU * As this CPU requires snooping to maintain the load store queue * change the behaviour from the base CPU port. * - * @param resp list of ranges this port responds to - * @param snoop indicating if the port snoops or not + * @return true since we have to snoop */ - virtual void getDeviceAddressRanges(AddrRangeList& resp, - bool& snoop) - { resp.clear(); snoop = true; } + virtual bool isSnooping() + { return true; } }; class TickEvent : public Event -- cgit v1.2.3