summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2012-01-28 07:24:01 -0800
committerGabe Black <gblack@eecs.umich.edu>2012-01-28 07:24:01 -0800
commitc3d41a2def15cdaf2ac3984315f452dacc6a0884 (patch)
tree5324ebec3add54b934a841eee901983ac3463a7f /src/cpu
parentda2a4acc26ba264c3c4a12495776fd6a1c4fb133 (diff)
parent4acca8a0536d4445ed25b67edf571ae460446ab9 (diff)
downloadgem5-c3d41a2def15cdaf2ac3984315f452dacc6a0884.tar.xz
Merge with the main repo.
--HG-- 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
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/BaseCPU.py7
-rw-r--r--src/cpu/base.cc45
-rw-r--r--src/cpu/base.hh48
-rw-r--r--src/cpu/checker/thread_context.hh8
-rw-r--r--src/cpu/inorder/InOrderCPU.py3
-rw-r--r--src/cpu/inorder/cpu.cc14
-rw-r--r--src/cpu/inorder/cpu.hh4
-rw-r--r--src/cpu/inorder/resources/cache_unit.cc23
-rw-r--r--src/cpu/inorder/resources/cache_unit.hh15
-rw-r--r--src/cpu/inorder/thread_context.cc6
-rw-r--r--src/cpu/inorder/thread_context.hh15
-rw-r--r--src/cpu/o3/O3CPU.py3
-rw-r--r--src/cpu/o3/cpu.cc78
-rw-r--r--src/cpu/o3/cpu.hh89
-rw-r--r--src/cpu/o3/fetch.hh56
-rw-r--r--src/cpu/o3/fetch_impl.hh87
-rw-r--r--src/cpu/o3/iew.hh3
-rw-r--r--src/cpu/o3/lsq.hh81
-rw-r--r--src/cpu/o3/lsq_impl.hh140
-rwxr-xr-xsrc/cpu/o3/thread_context.hh13
-rwxr-xr-xsrc/cpu/o3/thread_context_impl.hh6
-rw-r--r--src/cpu/ozone/cpu.hh8
-rw-r--r--src/cpu/ozone/cpu_impl.hh20
-rw-r--r--src/cpu/ozone/front_end.hh9
-rw-r--r--src/cpu/ozone/front_end_impl.hh6
-rw-r--r--src/cpu/ozone/lw_lsq.hh10
-rw-r--r--src/cpu/ozone/lw_lsq_impl.hh6
-rw-r--r--src/cpu/simple/AtomicSimpleCPU.py4
-rw-r--r--src/cpu/simple/TimingSimpleCPU.py3
-rw-r--r--src/cpu/simple/atomic.cc65
-rw-r--r--src/cpu/simple/atomic.hh46
-rw-r--r--src/cpu/simple/timing.cc53
-rw-r--r--src/cpu/simple/timing.hh45
-rw-r--r--src/cpu/simple_thread.cc7
-rw-r--r--src/cpu/simple_thread.hh5
-rw-r--r--src/cpu/testers/memtest/memtest.cc14
-rw-r--r--src/cpu/testers/memtest/memtest.hh10
-rw-r--r--src/cpu/testers/networktest/networktest.cc13
-rw-r--r--src/cpu/testers/networktest/networktest.hh10
-rw-r--r--src/cpu/thread_context.hh32
-rw-r--r--src/cpu/thread_state.cc97
-rw-r--r--src/cpu/thread_state.hh47
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 &section)
}
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:
/*