summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2006-07-14 17:54:43 -0400
committerKevin Lim <ktlim@umich.edu>2006-07-14 17:54:43 -0400
commit31ac8e733765ee37411d92ea3b7c308affef087a (patch)
treef2b677c660d83978d9a9a83ca934c3d9bb1215ba /src
parent138a4faf2894ff7d22585b8398ae87f8e6aad9a1 (diff)
parent07186de5a1b1df55a31329b2ca9c53ad168438ff (diff)
downloadgem5-31ac8e733765ee37411d92ea3b7c308affef087a.tar.xz
Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/newmem-merge configs/test/fs.py: configs/test/test.py: SCCS merged --HG-- extra : convert_revision : 7b2dbcd5881fac01dec38001c4131e73b5be52b5
Diffstat (limited to 'src')
-rw-r--r--src/arch/alpha/freebsd/system.cc4
-rw-r--r--src/arch/alpha/linux/system.cc4
-rw-r--r--src/arch/alpha/system.cc4
-rw-r--r--src/arch/alpha/tru64/system.cc4
-rw-r--r--src/arch/mips/isa_traits.cc6
-rw-r--r--src/arch/mips/isa_traits.hh2
-rw-r--r--src/arch/mips/process.cc5
-rw-r--r--src/arch/mips/process.hh3
-rw-r--r--src/arch/sparc/system.cc4
-rw-r--r--src/cpu/o3/cpu.cc48
-rw-r--r--src/cpu/o3/cpu.hh2
-rw-r--r--src/cpu/o3/fetch.hh3
-rw-r--r--src/cpu/o3/fetch_impl.hh8
-rw-r--r--src/cpu/o3/lsq.hh59
-rw-r--r--src/cpu/o3/lsq_impl.hh53
-rw-r--r--src/cpu/o3/lsq_unit.hh88
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh51
-rw-r--r--src/cpu/simple/atomic.cc14
-rw-r--r--src/cpu/simple/atomic.hh1
-rw-r--r--src/cpu/simple/base.cc2
-rw-r--r--src/cpu/simple/timing.cc26
-rw-r--r--src/cpu/simple/timing.hh3
-rw-r--r--src/dev/ide_disk.cc8
-rw-r--r--src/dev/io_device.cc152
-rw-r--r--src/dev/io_device.hh49
-rw-r--r--src/dev/ns_gige.cc22
-rw-r--r--src/dev/ns_gige.hh2
-rw-r--r--src/dev/pcidev.cc16
-rw-r--r--src/dev/pcidev.hh5
-rw-r--r--src/dev/sinic.cc16
-rw-r--r--src/dev/sinic.hh1
-rw-r--r--src/python/m5/config.py5
-rw-r--r--src/python/m5/main.py2
-rw-r--r--src/python/m5/objects/BaseCPU.py2
-rw-r--r--src/python/m5/objects/System.py3
-rw-r--r--src/sim/sim_object.cc29
-rw-r--r--src/sim/sim_object.hh15
-rw-r--r--src/sim/system.cc19
-rw-r--r--src/sim/system.hh20
39 files changed, 487 insertions, 273 deletions
diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc
index 7cf68e0db..8d50e1612 100644
--- a/src/arch/alpha/freebsd/system.cc
+++ b/src/arch/alpha/freebsd/system.cc
@@ -97,6 +97,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -115,6 +116,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -133,6 +136,7 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;
diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc
index 9fe63c390..ef4e18cb5 100644
--- a/src/arch/alpha/linux/system.cc
+++ b/src/arch/alpha/linux/system.cc
@@ -191,6 +191,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -209,6 +210,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -227,6 +230,7 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;
diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc
index dce7365aa..a7e615531 100644
--- a/src/arch/alpha/system.cc
+++ b/src/arch/alpha/system.cc
@@ -221,6 +221,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel;
Param<std::string> console;
@@ -239,6 +240,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -257,6 +260,7 @@ CREATE_SIM_OBJECT(AlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;
diff --git a/src/arch/alpha/tru64/system.cc b/src/arch/alpha/tru64/system.cc
index 6c0edc1ee..3ef1e4d3c 100644
--- a/src/arch/alpha/tru64/system.cc
+++ b/src/arch/alpha/tru64/system.cc
@@ -95,6 +95,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -113,6 +114,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -131,6 +134,7 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;
diff --git a/src/arch/mips/isa_traits.cc b/src/arch/mips/isa_traits.cc
index 85acc4e8c..a8b41270e 100644
--- a/src/arch/mips/isa_traits.cc
+++ b/src/arch/mips/isa_traits.cc
@@ -46,6 +46,12 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
}
void
+MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
+{
+ panic("Copy Misc. Regs Not Implemented Yet\n");
+}
+
+void
MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc)
{
panic("Copy Misc. Regs Not Implemented Yet\n");
diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh
index ff994bef9..2f485c7fd 100644
--- a/src/arch/mips/isa_traits.hh
+++ b/src/arch/mips/isa_traits.hh
@@ -129,7 +129,7 @@ namespace MipsISA
template <class TC>
void zeroRegisters(TC *tc);
- const Addr MaxAddr = (Addr)-1;
+// const Addr MaxAddr = (Addr)-1;
void copyRegs(ThreadContext *src, ThreadContext *dest);
diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc
index 031c2030e..cb847fe04 100644
--- a/src/arch/mips/process.cc
+++ b/src/arch/mips/process.cc
@@ -41,6 +41,8 @@
using namespace std;
using namespace MipsISA;
+Addr MipsLiveProcess::stack_start = 0x7FFFFFFF;
+
MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv, std::vector<std::string> &envp)
@@ -49,10 +51,11 @@ MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
{
// Set up stack. On MIPS, stack starts at the top of kuseg
// user address space. MIPS stack grows down from here
- stack_base = 0x7FFFFFFF;
+ stack_base = stack_start;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+ stack_start = next_thread_stack_base;
// Set up break point (Top of Heap)
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh
index b0ef20399..4baee134b 100644
--- a/src/arch/mips/process.hh
+++ b/src/arch/mips/process.hh
@@ -50,6 +50,9 @@ class MipsLiveProcess : public LiveProcess
std::vector<std::string> &envp);
void startup();
+
+
+ static Addr stack_start;
};
diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc
index e197e7918..63cbbe057 100644
--- a/src/arch/sparc/system.cc
+++ b/src/arch/sparc/system.cc
@@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel;
Param<std::string> reset_bin;
@@ -161,6 +162,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(reset_bin, "file that contains the reset code"),
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
@@ -183,6 +186,7 @@ CREATE_SIM_OBJECT(SparcSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->reset_bin = reset_bin;
p->hypervisor_bin = hypervisor_bin;
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index de87ee2ef..c43cc2cf8 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -441,7 +441,7 @@ FullO3CPU<Impl>::tick()
if (!tickEvent.scheduled()) {
if (_status == SwitchedOut ||
- getState() == SimObject::DrainedTiming) {
+ getState() == SimObject::Drained) {
// increment stat
lastRunningCycle = curTick;
} else if (!activityRec.active()) {
@@ -577,39 +577,19 @@ void
FullO3CPU<Impl>::suspendContext(int tid)
{
DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
- unscheduleTickEvent();
+ deactivateThread(tid);
+ if (activeThreads.size() == 0)
+ unscheduleTickEvent();
_status = Idle;
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
- }
-*/
}
template <class Impl>
void
FullO3CPU<Impl>::haltContext(int tid)
{
- DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid);
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
-
- removeThread(tid);
- }
-*/
+ //For now, this is the same as deallocate
+ DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
+ deallocateContext(tid, 1);
}
template <class Impl>
@@ -805,7 +785,7 @@ FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
}
template <class Impl>
-bool
+unsigned int
FullO3CPU<Impl>::drain(Event *drain_event)
{
drainCount = 0;
@@ -817,7 +797,7 @@ FullO3CPU<Impl>::drain(Event *drain_event)
// Wake the CPU and record activity so everything can drain out if
// the CPU was not able to immediately drain.
- if (getState() != SimObject::DrainedTiming) {
+ if (getState() != SimObject::Drained) {
// A bit of a hack...set the drainEvent after all the drain()
// calls have been made, that way if all of the stages drain
// immediately, the signalDrained() function knows not to call
@@ -827,9 +807,9 @@ FullO3CPU<Impl>::drain(Event *drain_event)
wakeCPU();
activityRec.activity();
- return false;
+ return 1;
} else {
- return true;
+ return 0;
}
}
@@ -837,19 +817,21 @@ template <class Impl>
void
FullO3CPU<Impl>::resume()
{
+ assert(system->getMemoryMode() == System::Timing);
fetch.resume();
decode.resume();
rename.resume();
iew.resume();
commit.resume();
+ changeState(SimObject::Running);
+
if (_status == SwitchedOut || _status == Idle)
return;
if (!tickEvent.scheduled())
tickEvent.schedule(curTick);
_status = Running;
- changeState(SimObject::Timing);
}
template <class Impl>
@@ -860,7 +842,7 @@ FullO3CPU<Impl>::signalDrained()
if (tickEvent.scheduled())
tickEvent.squash();
- changeState(SimObject::DrainedTiming);
+ changeState(SimObject::Drained);
if (drainEvent) {
drainEvent->process();
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index 2fbd013ac..83cb966e3 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -330,7 +330,7 @@ class FullO3CPU : public BaseO3CPU
/** Starts draining the CPU's pipeline of all instructions in
* order to stop all memory accesses. */
- virtual bool drain(Event *drain_event);
+ virtual unsigned int drain(Event *drain_event);
/** Resumes execution after a drain. */
virtual void resume();
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 0331cf07f..931919af8 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -407,6 +407,9 @@ class DefaultFetch
/** The PC of the cacheline that has been loaded. */
Addr cacheDataPC[Impl::MaxThreads];
+ /** Whether or not the cache data is valid. */
+ bool cacheDataValid[Impl::MaxThreads];
+
/** Size of instructions. */
int instSize;
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 4045492ca..4184e1867 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -162,6 +162,8 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
// Create space to store a cache line.
cacheData[tid] = new uint8_t[cacheBlkSize];
+ cacheDataPC[tid] = 0;
+ cacheDataValid[tid] = false;
stalls[tid].decode = 0;
stalls[tid].rename = 0;
@@ -358,6 +360,7 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
}
memcpy(cacheData[tid], pkt->getPtr<uint8_t *>(), cacheBlkSize);
+ cacheDataValid[tid] = true;
if (!drainPending) {
// Wake up the CPU (if it went to sleep and was waiting on
@@ -520,7 +523,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
fetch_PC = icacheBlockAlignPC(fetch_PC);
// If we've already got the block, no need to try to fetch it again.
- if (fetch_PC == cacheDataPC[tid]) {
+ if (cacheDataValid[tid] && fetch_PC == cacheDataPC[tid]) {
return true;
}
@@ -555,9 +558,10 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Build packet here.
PacketPtr data_pkt = new Packet(mem_req,
Packet::ReadReq, Packet::Broadcast);
- data_pkt->dataDynamic(new uint8_t[cacheBlkSize]);
+ data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]);
cacheDataPC[tid] = fetch_PC;
+ cacheDataValid[tid] = false;
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh
index d5890950f..190734dc2 100644
--- a/src/cpu/o3/lsq.hh
+++ b/src/cpu/o3/lsq.hh
@@ -70,7 +70,7 @@ class LSQ {
* to work. For now it just returns the port from one of the
* threads.
*/
- Port *getDcachePort() { return thread[0].getDcachePort(); }
+ Port *getDcachePort() { return &dcachePort; }
/** Sets the pointer to the list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr);
@@ -258,6 +258,15 @@ class LSQ {
bool willWB(unsigned tid)
{ return thread[tid].willWB(); }
+ /** Returns if the cache is currently blocked. */
+ bool cacheBlocked()
+ { return retryTid != -1; }
+
+ /** Sets the retry thread id, indicating that one of the LSQUnits
+ * tried to access the cache but the cache was blocked. */
+ void setRetryTid(int tid)
+ { retryTid = tid; }
+
/** Debugging function to print out all instructions. */
void dumpInsts();
/** Debugging function to print out instructions from a specific thread. */
@@ -274,7 +283,49 @@ class LSQ {
template <class T>
Fault write(RequestPtr req, T &data, int store_idx);
- private:
+ /** 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)
+ : lsq(_lsq)
+ { }
+
+ 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,
+ AddrRangeList &snoop)
+ { resp.clear(); snoop.clear(); }
+
+ /** 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;
@@ -303,6 +354,10 @@ class LSQ {
/** Number of Threads. */
unsigned numThreads;
+
+ /** The thread id of the LSQ Unit that is currently waiting for a
+ * retry. */
+ int retryTid;
};
template <class Impl>
diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh
index 89fd1a71d..4e3957029 100644
--- a/src/cpu/o3/lsq_impl.hh
+++ b/src/cpu/o3/lsq_impl.hh
@@ -36,9 +36,53 @@
using namespace std;
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)
+{
+ panic("O3CPU doesn't expect recvFunctional callback!");
+}
+
+template <class Impl>
+void
+LSQ<Impl>::DcachePort::recvStatusChange(Status status)
+{
+ if (status == RangeChange)
+ return;
+
+ panic("O3CPU doesn't expect recvStatusChange callback!");
+}
+
+template <class Impl>
+bool
+LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
+{
+ lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);
+ return true;
+}
+
+template <class Impl>
+void
+LSQ<Impl>::DcachePort::recvRetry()
+{
+ lsq->thread[lsq->retryTid].recvRetry();
+ // Speculatively clear the retry Tid. This will get set again if
+ // the LSQUnit was unable to complete its access.
+ lsq->retryTid = -1;
+}
+
+template <class Impl>
LSQ<Impl>::LSQ(Params *params)
- : LQEntries(params->LQEntries), SQEntries(params->SQEntries),
- numThreads(params->numberOfThreads)
+ : dcachePort(this), LQEntries(params->LQEntries),
+ SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
+ retryTid(-1)
{
DPRINTF(LSQ, "Creating LSQ object.\n");
@@ -94,7 +138,8 @@ LSQ<Impl>::LSQ(Params *params)
//Initialize LSQs
for (int tid=0; tid < numThreads; tid++) {
- thread[tid].init(params, maxLQEntries, maxSQEntries, tid);
+ thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
+ thread[tid].setDcachePort(&dcachePort);
}
}
@@ -130,6 +175,8 @@ LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
{
cpu = cpu_ptr;
+ dcachePort.setName(name());
+
for (int tid=0; tid < numThreads; tid++) {
thread[tid].setCPU(cpu_ptr);
}
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index 4d7a8350b..a76a73f0c 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -64,6 +64,7 @@ class LSQUnit {
typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::CPUPol::IEW IEW;
+ typedef typename Impl::CPUPol::LSQ LSQ;
typedef typename Impl::CPUPol::IssueStruct IssueStruct;
public:
@@ -71,17 +72,12 @@ class LSQUnit {
LSQUnit();
/** Initializes the LSQ unit with the specified number of entries. */
- void init(Params *params, unsigned maxLQEntries,
+ void init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
unsigned maxSQEntries, unsigned id);
/** Returns the name of the LSQ unit. */
std::string name() const;
- /** Returns the dcache port.
- * @todo: Remove this once the port moves up to the LSQ level.
- */
- Port *getDcachePort() { return dcachePort; }
-
/** Registers statistics. */
void regStats();
@@ -92,6 +88,10 @@ class LSQUnit {
void setIEW(IEW *iew_ptr)
{ iewStage = iew_ptr; }
+ /** Sets the pointer to the dcache port. */
+ void setDcachePort(Port *dcache_port)
+ { dcachePort = dcache_port; }
+
/** Switches out LSQ unit. */
void switchOut();
@@ -211,6 +211,9 @@ class LSQUnit {
!storeQueue[storeWBIdx].completed &&
!isStoreBlocked; }
+ /** Handles doing the retry. */
+ void recvRetry();
+
private:
/** Writes back the instruction, sending it to IEW. */
void writeback(DynInstPtr &inst, PacketPtr pkt);
@@ -221,9 +224,6 @@ class LSQUnit {
/** Completes the store at the specified index. */
void completeStore(int store_idx);
- /** Handles doing the retry. */
- void recvRetry();
-
/** Increments the given store index (circular queue). */
inline void incrStIdx(int &store_idx);
/** Decrements the given store index (circular queue). */
@@ -244,54 +244,11 @@ class LSQUnit {
/** Pointer to the IEW stage. */
IEW *iewStage;
- /** Pointer to memory object. */
- MemObject *mem;
+ /** Pointer to the LSQ. */
+ LSQ *lsq;
- /** DcachePort class for this LSQ Unit. Handles doing the
- * communication with the cache/memory.
- * @todo: Needs to be moved to the LSQ level and have some sort
- * of arbitration.
- */
- class DcachePort : public Port
- {
- protected:
- /** Pointer to CPU. */
- O3CPU *cpu;
- /** Pointer to LSQ. */
- LSQUnit *lsq;
-
- public:
- /** Default constructor. */
- DcachePort(O3CPU *_cpu, LSQUnit *_lsq)
- : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
- { }
-
- 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,
- AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); }
-
- /** 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();
- };
-
- /** Pointer to the D-cache. */
- DcachePort *dcachePort;
+ /** Pointer to the dcache port. Used only for sending. */
+ Port *dcachePort;
/** Derived class to hold any sender state the LSQ needs. */
class LSQSenderState : public Packet::SenderState
@@ -658,7 +615,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
}
// If there's no forwarding case, then go access memory
- DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n",
+ DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
load_inst->seqNum, load_inst->readPC());
assert(!load_inst->memData);
@@ -666,9 +623,6 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
++usedPorts;
- DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
- load_inst->readPC());
-
PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(load_inst->memData);
@@ -678,8 +632,18 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
state->inst = load_inst;
data_pkt->senderState = state;
- // if we have a cache, do cache access too
- if (!dcachePort->sendTiming(data_pkt)) {
+ // if we the cache is not blocked, do cache access
+ if (!lsq->cacheBlocked()) {
+ if (!dcachePort->sendTiming(data_pkt)) {
+ // If the access didn't succeed, tell the LSQ by setting
+ // the retry thread id.
+ lsq->setRetryTid(lsqID);
+ }
+ }
+
+ // If the cache was blocked, or has become blocked due to the access,
+ // handle it.
+ if (lsq->cacheBlocked()) {
++lsqCacheBlocked;
// There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index 8e951534f..85b150cd9 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -31,6 +31,7 @@
#include "config/use_checker.hh"
+#include "cpu/o3/lsq.hh"
#include "cpu/o3/lsq_unit.hh"
#include "base/str.hh"
#include "mem/packet.hh"
@@ -96,46 +97,6 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
}
template <class Impl>
-Tick
-LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
-{
- panic("O3CPU model does not work with atomic mode!");
- return curTick;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
-{
- panic("O3CPU doesn't expect recvFunctional callback!");
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvStatusChange(Status status)
-{
- if (status == RangeChange)
- return;
-
- panic("O3CPU doesn't expect recvStatusChange callback!");
-}
-
-template <class Impl>
-bool
-LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt)
-{
- lsq->completeDataAccess(pkt);
- return true;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvRetry()
-{
- lsq->recvRetry();
-}
-
-template <class Impl>
LSQUnit<Impl>::LSQUnit()
: loads(0), stores(0), storesToWB(0), stalled(false),
isStoreBlocked(false), isLoadBlocked(false),
@@ -145,13 +106,15 @@ LSQUnit<Impl>::LSQUnit()
template<class Impl>
void
-LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
+LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
unsigned maxSQEntries, unsigned id)
{
DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
switchedOut = false;
+ lsq = lsq_ptr;
+
lsqID = id;
// Add 1 for the sentinel entry (they are circular queues).
@@ -168,8 +131,6 @@ LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
usedPorts = 0;
cachePorts = params->cachePorts;
- mem = params->mem;
-
memDepViolator = NULL;
blockedLoadSeqNum = 0;
@@ -180,7 +141,6 @@ void
LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
{
cpu = cpu_ptr;
- dcachePort = new DcachePort(cpu, this);
#if USE_CHECKER
if (cpu->checker) {
@@ -588,7 +548,7 @@ LSQUnit<Impl>::writebackStores()
storeQueue[storeWBIdx].canWB &&
usedPorts < cachePorts) {
- if (isStoreBlocked) {
+ if (isStoreBlocked || lsq->cacheBlocked()) {
DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
" is blocked!\n");
break;
@@ -911,6 +871,7 @@ LSQUnit<Impl>::recvRetry()
} else {
// Still blocked!
++lsqCacheBlocked;
+ lsq->setRetryTid(lsqID);
}
} else if (isLoadBlocked) {
DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 0580fdd81..6be188a96 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -33,6 +33,7 @@
#include "cpu/simple/atomic.hh"
#include "mem/packet_impl.hh"
#include "sim/builder.hh"
+#include "sim/system.hh"
using namespace std;
using namespace TheISA;
@@ -184,6 +185,13 @@ AtomicSimpleCPU::resume()
}
void
+AtomicSimpleCPU::resume()
+{
+ assert(system->getMemoryMode() == System::Atomic);
+ changeState(SimObject::Running);
+}
+
+void
AtomicSimpleCPU::switchOut()
{
assert(status() == Running || status() == Idle);
@@ -462,11 +470,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
SimObjectParam<MemObject *> mem;
+ SimObjectParam<System *> system;
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<System *> system;
Param<int> cpu_id;
Param<Tick> profile;
#else
@@ -494,11 +502,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"),
INIT_PARAM(mem, "memory"),
+ INIT_PARAM(system, "system object"),
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""),
#else
@@ -531,11 +539,11 @@ CREATE_SIM_OBJECT(AtomicSimpleCPU)
params->width = width;
params->simulate_stalls = simulate_stalls;
params->mem = mem;
+ params->system = system;
#if FULL_SYSTEM
params->itb = itb;
params->dtb = dtb;
- params->system = system;
params->cpu_id = cpu_id;
params->profile = profile;
#else
diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh
index b602af558..895eb5bde 100644
--- a/src/cpu/simple/atomic.hh
+++ b/src/cpu/simple/atomic.hh
@@ -128,6 +128,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
virtual void unserialize(Checkpoint *cp, const std::string &section);
virtual void resume();
+ virtual void resume();
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index 2d0afef65..240696c2b 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -55,10 +55,10 @@
#include "sim/sim_events.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
+#include "sim/system.hh"
#if FULL_SYSTEM
#include "base/remote_gdb.hh"
-#include "sim/system.hh"
#include "arch/tlb.hh"
#include "arch/stacktrace.hh"
#include "arch/vtophys.hh"
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index a98854832..246bcec05 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -33,6 +33,7 @@
#include "cpu/simple/timing.hh"
#include "mem/packet_impl.hh"
#include "sim/builder.hh"
+#include "sim/system.hh"
using namespace std;
using namespace TheISA;
@@ -91,7 +92,7 @@ TimingSimpleCPU::TimingSimpleCPU(Params *p)
ifetch_pkt = dcache_pkt = NULL;
drainEvent = NULL;
fetchEvent = NULL;
- state = SimObject::Timing;
+ changeState(SimObject::Running);
}
@@ -115,18 +116,18 @@ TimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
BaseSimpleCPU::unserialize(cp, section);
}
-bool
+unsigned int
TimingSimpleCPU::drain(Event *drain_event)
{
// TimingSimpleCPU is ready to drain if it's not waiting for
// an access to complete.
if (status() == Idle || status() == Running || status() == SwitchedOut) {
- changeState(SimObject::DrainedTiming);
- return true;
+ changeState(SimObject::Drained);
+ return 0;
} else {
changeState(SimObject::Draining);
drainEvent = drain_event;
- return false;
+ return 1;
}
}
@@ -146,12 +147,9 @@ TimingSimpleCPU::resume()
new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);
fetchEvent->schedule(curTick);
}
-}
-void
-TimingSimpleCPU::setMemoryMode(State new_mode)
-{
- assert(new_mode == SimObject::Timing);
+ assert(system->getMemoryMode() == System::Timing);
+ changeState(SimObject::Running);
}
void
@@ -518,7 +516,7 @@ void
TimingSimpleCPU::completeDrain()
{
DPRINTF(Config, "Done draining\n");
- changeState(SimObject::DrainedTiming);
+ changeState(SimObject::Drained);
drainEvent->process();
}
@@ -555,11 +553,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
SimObjectParam<MemObject *> mem;
+ SimObjectParam<System *> system;
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<System *> system;
Param<int> cpu_id;
Param<Tick> profile;
#else
@@ -587,11 +585,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"),
INIT_PARAM(mem, "memory"),
+ INIT_PARAM(system, "system object"),
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""),
#else
@@ -622,11 +620,11 @@ CREATE_SIM_OBJECT(TimingSimpleCPU)
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;
params->mem = mem;
+ params->system = system;
#if FULL_SYSTEM
params->itb = itb;
params->dtb = dtb;
- params->system = system;
params->cpu_id = cpu_id;
params->profile = profile;
#else
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index 0a3f91e6c..ac36e5c99 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -137,9 +137,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
- virtual bool drain(Event *drain_event);
+ virtual unsigned int drain(Event *drain_event);
virtual void resume();
- virtual void setMemoryMode(State new_mode);
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc
index dc78021f8..12564ddd0 100644
--- a/src/dev/ide_disk.cc
+++ b/src/dev/ide_disk.cc
@@ -318,7 +318,7 @@ IdeDisk::doDmaTransfer()
panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
dmaState, devState);
- if (ctrl->dmaPending()) {
+ if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else
@@ -398,8 +398,7 @@ IdeDisk::doDmaRead()
curPrd.getByteCount(), TheISA::PageBytes);
}
- if (ctrl->dmaPending()) {
- panic("shouldn't be reentant??");
+ if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else if (!dmaReadCG->done()) {
@@ -474,8 +473,7 @@ IdeDisk::doDmaWrite()
dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
curPrd.getByteCount(), TheISA::PageBytes);
}
- if (ctrl->dmaPending()) {
- panic("shouldn't be reentant??");
+ if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else if (!dmaWriteCG->done()) {
diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc
index cb4850108..660efabfd 100644
--- a/src/dev/io_device.cc
+++ b/src/dev/io_device.cc
@@ -32,10 +32,12 @@
#include "base/trace.hh"
#include "dev/io_device.hh"
#include "sim/builder.hh"
+#include "sim/system.hh"
-PioPort::PioPort(PioDevice *dev, Platform *p, std::string pname)
- : Port(dev->name() + pname), device(dev), platform(p)
+PioPort::PioPort(PioDevice *dev, System *s, std::string pname)
+ : Port(dev->name() + pname), device(dev), sys(s),
+ outTiming(0), drainEvent(NULL)
{ }
@@ -68,13 +70,23 @@ PioPort::recvRetry()
if (result)
transmitList.pop_front();
}
+ if (transmitList.size() == 0 && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
}
void
PioPort::SendEvent::process()
{
+ port->outTiming--;
+ assert(port->outTiming >= 0);
if (port->Port::sendTiming(packet))
- return;
+ if (port->transmitList.size() == 0 && port->drainEvent) {
+ port->drainEvent->process();
+ port->drainEvent = NULL;
+ }
+ return;
port->transmitList.push_back(packet);
}
@@ -105,6 +117,15 @@ PioPort::recvTiming(Packet *pkt)
return true;
}
+unsigned int
+PioPort::drain(Event *de)
+{
+ if (outTiming == 0 && transmitList.size() == 0)
+ return 0;
+ drainEvent = de;
+ return 1;
+}
+
PioDevice::~PioDevice()
{
if (pioPort)
@@ -119,6 +140,19 @@ PioDevice::init()
pioPort->sendStatusChange(Port::RangeChange);
}
+
+unsigned int
+PioDevice::drain(Event *de)
+{
+ unsigned int count;
+ count = pioPort->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
+
void
BasicPioDevice::addressRanges(AddrRangeList &range_list)
{
@@ -128,8 +162,9 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
}
-DmaPort::DmaPort(DmaDevice *dev, Platform *p)
- : Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0)
+DmaPort::DmaPort(DmaDevice *dev, System *s)
+ : Port(dev->name() + "-dmaport"), device(dev), sys(s), pendingCount(0),
+ actionInProgress(0), drainEvent(NULL)
{ }
bool
@@ -159,6 +194,11 @@ DmaPort::recvTiming(Packet *pkt)
}
delete pkt->req;
delete pkt;
+
+ if (pendingCount == 0 && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
} else {
panic("Got packet without sender state... huh?\n");
}
@@ -170,6 +210,29 @@ DmaDevice::DmaDevice(Params *p)
: PioDevice(p), dmaPort(NULL)
{ }
+
+unsigned int
+DmaDevice::drain(Event *de)
+{
+ unsigned int count;
+ count = pioPort->drain(de) + dmaPort->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
+
+unsigned int
+DmaPort::drain(Event *de)
+{
+ if (pendingCount == 0)
+ return 0;
+ drainEvent = de;
+ return 1;
+}
+
+
void
DmaPort::recvRetry()
{
@@ -195,6 +258,8 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
{
assert(event);
+ assert(device->getState() == SimObject::Running);
+
DmaReqState *reqState = new DmaReqState(event, this, size);
for (ChunkGenerator gen(addr, size, peerBlockSize());
@@ -212,51 +277,54 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
pendingCount++;
sendDma(pkt);
}
+
}
void
DmaPort::sendDma(Packet *pkt, bool front)
{
- // some kind of selction between access methods
- // more work is going to have to be done to make
- // switching actually work
- /* MemState state = device->platform->system->memState;
-
- if (state == Timing) { */
- DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
- pkt, pkt->getAddr());
- if (transmitList.size() || !sendTiming(pkt)) {
- if (front)
- transmitList.push_front(pkt);
- else
- transmitList.push_back(pkt);
- DPRINTF(DMA, "-- Failed: queued\n");
- } else {
- DPRINTF(DMA, "-- Done\n");
- }
- /* } else if (state == Atomic) {
- sendAtomic(pkt);
- if (pkt->senderState) {
- DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
- assert(state);
- state->completionEvent->schedule(curTick + (pkt->time -
- pkt->req->getTime()) +1);
- delete state;
- }
- pendingCount--;
- assert(pendingCount >= 0);
- delete pkt->req;
- delete pkt;
-
- } else if (state == Functional) {
- sendFunctional(pkt);
- // Is this correct???
- completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime);
- completionEvent == NULL;
+ // some kind of selction between access methods
+ // more work is going to have to be done to make
+ // switching actually work
+
+ System::MemoryMode state = sys->getMemoryMode();
+ if (state == System::Timing) {
+ DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
+ pkt, pkt->getAddr());
+ if (transmitList.size() || !sendTiming(pkt)) {
+ if (front)
+ transmitList.push_front(pkt);
+ else
+ transmitList.push_back(pkt);
+ DPRINTF(DMA, "-- Failed: queued\n");
+ } else {
+ DPRINTF(DMA, "-- Done\n");
+ }
+ } else if (state == System::Atomic) {
+ Tick lat;
+ lat = sendAtomic(pkt);
+ assert(pkt->senderState);
+ DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
+ assert(state);
+
+ state->numBytes += pkt->req->getSize();
+ if (state->totBytes == state->numBytes) {
+ state->completionEvent->schedule(curTick + lat);
+ delete state;
+ delete pkt->req;
+ }
+ pendingCount--;
+ assert(pendingCount >= 0);
+ delete pkt;
+
+ if (pendingCount == 0 && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
+
} else
panic("Unknown memory command state.");
- */
}
DmaDevice::~DmaDevice()
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index 40edf6875..fa3f98247 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -60,9 +60,9 @@ class PioPort : public Port
/** The device that this port serves. */
PioDevice *device;
- /** The platform that device/port are in. This is used to select which mode
+ /** The system that device/port are in. This is used to select which mode
* we are currently operating in. */
- Platform *platform;
+ System *sys;
/** A list of outgoing timing response packets that haven't been serviced
* yet. */
@@ -106,16 +106,27 @@ class PioPort : public Port
friend class PioPort;
};
+ /** Number of timing requests that are emulating the device timing before
+ * attempting to end up on the bus.
+ */
+ int outTiming;
+
+ /** If we need to drain, keep the drain event around until we're done
+ * here.*/
+ Event *drainEvent;
+
/** Schedule a sendTiming() event to be called in the future. */
void sendTiming(Packet *pkt, Tick time)
- { new PioPort::SendEvent(this, pkt, time); }
+ { outTiming++; new PioPort::SendEvent(this, pkt, time); }
/** This function is notification that the device should attempt to send a
* packet again. */
virtual void recvRetry();
public:
- PioPort(PioDevice *dev, Platform *p, std::string pname = "-pioport");
+ PioPort(PioDevice *dev, System *s, std::string pname = "-pioport");
+
+ unsigned int drain(Event *de);
friend class PioPort::SendEvent;
};
@@ -147,13 +158,20 @@ class DmaPort : public Port
DmaDevice *device;
std::list<Packet*> transmitList;
- /** The platform that device/port are in. This is used to select which mode
+ /** The system that device/port are in. This is used to select which mode
* we are currently operating in. */
- Platform *platform;
+ System *sys;
/** Number of outstanding packets the dma port has. */
int pendingCount;
+ /** If a dmaAction is in progress. */
+ int actionInProgress;
+
+ /** If we need to drain, keep the drain event around until we're done
+ * here.*/
+ Event *drainEvent;
+
virtual bool recvTiming(Packet *pkt);
virtual Tick recvAtomic(Packet *pkt)
{ panic("dma port shouldn't be used for pio access."); }
@@ -171,13 +189,14 @@ class DmaPort : public Port
void sendDma(Packet *pkt, bool front = false);
public:
- DmaPort(DmaDevice *dev, Platform *p);
+ DmaPort(DmaDevice *dev, System *s);
void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
uint8_t *data = NULL);
bool dmaPending() { return pendingCount > 0; }
+ unsigned int drain(Event *de);
};
/**
@@ -196,6 +215,8 @@ class PioDevice : public MemObject
* transaction we should perform. */
Platform *platform;
+ System *sys;
+
/** The pioPort that handles the requests for us and provides us requests
* that it sees. */
PioPort *pioPort;
@@ -240,20 +261,22 @@ class PioDevice : public MemObject
const Params *params() const { return _params; }
PioDevice(Params *p)
- : MemObject(p->name), platform(p->platform), pioPort(NULL),
- _params(p)
+ : MemObject(p->name), platform(p->platform), sys(p->system),
+ pioPort(NULL), _params(p)
{}
virtual ~PioDevice();
virtual void init();
+ virtual unsigned int drain(Event *de);
+
virtual Port *getPort(const std::string &if_name, int idx = -1)
{
if (if_name == "pio") {
if (pioPort != NULL)
panic("pio port already connected to.");
- pioPort = new PioPort(this, params()->platform);
+ pioPort = new PioPort(this, sys);
return pioPort;
} else
return NULL;
@@ -310,17 +333,19 @@ class DmaDevice : public PioDevice
bool dmaPending() { return dmaPort->dmaPending(); }
+ virtual unsigned int drain(Event *de);
+
virtual Port *getPort(const std::string &if_name, int idx = -1)
{
if (if_name == "pio") {
if (pioPort != NULL)
panic("pio port already connected to.");
- pioPort = new PioPort(this, params()->platform);
+ pioPort = new PioPort(this, sys);
return pioPort;
} else if (if_name == "dma") {
if (dmaPort != NULL)
panic("dma port already connected to.");
- dmaPort = new DmaPort(this, params()->platform);
+ dmaPort = new DmaPort(this, sys);
return dmaPort;
} else
return NULL;
diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc
index 179a2c62d..bf2279d93 100644
--- a/src/dev/ns_gige.cc
+++ b/src/dev/ns_gige.cc
@@ -1377,7 +1377,7 @@ NSGigE::doRxDmaRead()
assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
rxDmaState = dmaReading;
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
rxDmaState = dmaReadWaiting;
else
dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
@@ -1408,7 +1408,7 @@ NSGigE::doRxDmaWrite()
assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
rxDmaState = dmaWriting;
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
rxDmaState = dmaWriteWaiting;
else
dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
@@ -1826,7 +1826,7 @@ NSGigE::doTxDmaRead()
assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
txDmaState = dmaReading;
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
txDmaState = dmaReadWaiting;
else
dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
@@ -1857,7 +1857,7 @@ NSGigE::doTxDmaWrite()
assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
txDmaState = dmaWriting;
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
txDmaState = dmaWriteWaiting;
else
dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
@@ -2406,6 +2406,20 @@ NSGigE::recvPacket(EthPacketPtr packet)
return true;
}
+
+void
+NSGigE::resume()
+{
+ SimObject::resume();
+
+ // During drain we could have left the state machines in a waiting state and
+ // they wouldn't get out until some other event occured to kick them.
+ // This way they'll get out immediately
+ txKick();
+ rxKick();
+}
+
+
//=====================================================================
//
//
diff --git a/src/dev/ns_gige.hh b/src/dev/ns_gige.hh
index ea7243777..080c0b1f3 100644
--- a/src/dev/ns_gige.hh
+++ b/src/dev/ns_gige.hh
@@ -391,6 +391,8 @@ class NSGigE : public PciDev
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
+ virtual void resume();
+
public:
void regStats();
diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc
index 62a7324ad..e81e0d1ee 100644
--- a/src/dev/pcidev.cc
+++ b/src/dev/pcidev.cc
@@ -56,8 +56,8 @@ using namespace std;
PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid,
int funcid, Platform *p)
- : PioPort(dev,p,"-pciconf"), device(dev), busId(busid), deviceId(devid),
- functionId(funcid)
+ : PioPort(dev,p->system,"-pciconf"), device(dev), platform(p),
+ busId(busid), deviceId(devid), functionId(funcid)
{
configAddr = platform->calcConfigAddr(busId, deviceId, functionId);
}
@@ -132,6 +132,18 @@ PciDev::init()
PioDevice::init();
}
+unsigned int
+PciDev::drain(Event *de)
+{
+ unsigned int count;
+ count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
+
Tick
PciDev::readConfig(Packet *pkt)
{
diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh
index 20ab9364a..847fb07d0 100644
--- a/src/dev/pcidev.hh
+++ b/src/dev/pcidev.hh
@@ -95,6 +95,8 @@ class PciDev : public DmaDevice
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+ Platform *platform;
+
int busId;
int deviceId;
int functionId;
@@ -249,6 +251,9 @@ class PciDev : public DmaDevice
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ virtual unsigned int drain(Event *de);
+
virtual Port *getPort(const std::string &if_name, int idx = -1)
{
if (if_name == "config") {
diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc
index dddda1f1c..815cecca5 100644
--- a/src/dev/sinic.cc
+++ b/src/dev/sinic.cc
@@ -921,7 +921,7 @@ Device::rxKick()
break;
case rxBeginCopy:
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
goto exit;
rxDmaAddr = params()->platform->pciToDma(
@@ -1109,7 +1109,7 @@ Device::txKick()
break;
case txBeginCopy:
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
goto exit;
txDmaAddr = params()->platform->pciToDma(
@@ -1287,6 +1287,18 @@ Device::recvPacket(EthPacketPtr packet)
return true;
}
+void
+Device::resume()
+{
+ SimObject::resume();
+
+ // During drain we could have left the state machines in a waiting state and
+ // they wouldn't get out until some other event occured to kick them.
+ // This way they'll get out immediately
+ txKick();
+ rxKick();
+}
+
//=====================================================================
//
//
diff --git a/src/dev/sinic.hh b/src/dev/sinic.hh
index f6c229039..eece4ba6b 100644
--- a/src/dev/sinic.hh
+++ b/src/dev/sinic.hh
@@ -266,6 +266,7 @@ class Device : public Base
public:
virtual Tick read(Packet *pkt);
virtual Tick write(Packet *pkt);
+ virtual void resume();
void prepareIO(int cpu, int index);
void prepareRead(int cpu, int index);
diff --git a/src/python/m5/config.py b/src/python/m5/config.py
index e7fe7b78f..df4b74cbd 100644
--- a/src/python/m5/config.py
+++ b/src/python/m5/config.py
@@ -547,8 +547,7 @@ class SimObject(object):
count = 0
# ParamContexts don't serialize
if isinstance(self, SimObject) and not isinstance(self, ParamContext):
- if not self._ccObject.drain(drain_event):
- count = 1
+ count += self._ccObject.drain(drain_event)
if recursive:
for child in self._children.itervalues():
count += child.startDrain(drain_event, True)
@@ -561,7 +560,7 @@ class SimObject(object):
child.resume()
def changeTiming(self, mode):
- if isinstance(self, SimObject) and not isinstance(self, ParamContext):
+ if isinstance(self, System):
self._ccObject.setMemoryMode(mode)
for child in self._children.itervalues():
child.changeTiming(mode)
diff --git a/src/python/m5/main.py b/src/python/m5/main.py
index c97390d25..a757aaf1a 100644
--- a/src/python/m5/main.py
+++ b/src/python/m5/main.py
@@ -182,7 +182,7 @@ options = attrdict()
arguments = []
def usage(exitcode=None):
- print parser.help
+ parser.print_help()
if exitcode is not None:
sys.exit(exitcode)
diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py
index 2e78578df..5bf98be9c 100644
--- a/src/python/m5/objects/BaseCPU.py
+++ b/src/python/m5/objects/BaseCPU.py
@@ -6,10 +6,10 @@ class BaseCPU(SimObject):
abstract = True
mem = Param.MemObject("memory")
+ system = Param.System(Parent.any, "system object")
if build_env['FULL_SYSTEM']:
dtb = Param.AlphaDTB("Data TLB")
itb = Param.AlphaITB("Instruction TLB")
- system = Param.System(Parent.any, "system object")
cpu_id = Param.Int(-1, "CPU identifier")
else:
workload = VectorParam.Process("processes to run")
diff --git a/src/python/m5/objects/System.py b/src/python/m5/objects/System.py
index 9a1e1d690..386f39277 100644
--- a/src/python/m5/objects/System.py
+++ b/src/python/m5/objects/System.py
@@ -1,9 +1,12 @@
from m5 import build_env
from m5.config import *
+class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing']
+
class System(SimObject):
type = 'System'
physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
+ mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
if build_env['FULL_SYSTEM']:
boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
"boot processor frequency")
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index a0278dba0..d12b06b7a 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -72,7 +72,7 @@ SimObject::SimObject(Params *p)
doRecordEvent = !Stats::event_ignore.match(name());
simObjectList.push_back(this);
- state = Atomic;
+ state = Running;
}
//
@@ -88,7 +88,7 @@ SimObject::SimObject(const string &_name)
doRecordEvent = !Stats::event_ignore.match(name());
simObjectList.push_back(this);
- state = Atomic;
+ state = Running;
}
void
@@ -269,38 +269,23 @@ SimObject::recordEvent(const std::string &stat)
Stats::recordEvent(stat);
}
-bool
+unsigned int
SimObject::drain(Event *drain_event)
{
- if (state != DrainedAtomic && state != Atomic) {
- panic("Must implement your own drain function if it is to be used "
- "in timing mode!");
- }
- state = DrainedAtomic;
- return true;
+ state = Drained;
+ return 0;
}
void
SimObject::resume()
{
- if (state == DrainedAtomic) {
- state = Atomic;
- } else if (state == DrainedTiming) {
- state = Timing;
- }
+ state = Running;
}
void
SimObject::setMemoryMode(State new_mode)
{
- assert(new_mode == Timing || new_mode == Atomic);
- if (state == DrainedAtomic && new_mode == Timing) {
- state = DrainedTiming;
- } else if (state == DrainedTiming && new_mode == Atomic) {
- state = DrainedAtomic;
- } else {
- state = new_mode;
- }
+ panic("setMemoryMode() should only be called on systems");
}
void
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index 7ecc00958..38f2bdd23 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -60,16 +60,15 @@ class SimObject : public Serializable, protected StartupCallback
};
enum State {
- Atomic,
- Timing,
+ Running,
Draining,
- DrainedAtomic,
- DrainedTiming
+ Drained
};
+ private:
+ State state;
protected:
Params *_params;
- State state;
void changeState(State new_state) { state = new_state; }
@@ -116,8 +115,10 @@ class SimObject : public Serializable, protected StartupCallback
// Methods to drain objects in order to take checkpoints
// Or switch from timing -> atomic memory model
- // Drain returns false if the SimObject cannot drain immediately.
- virtual bool drain(Event *drain_event);
+ // Drain returns 0 if the simobject can drain immediately or
+ // the number of times the drain_event's process function will be called
+ // before the object will be done draining. Normally this should be 1
+ virtual unsigned int drain(Event *drain_event);
virtual void resume();
virtual void setMemoryMode(State new_mode);
virtual void switchOut();
diff --git a/src/sim/system.cc b/src/sim/system.cc
index 89e7b8542..ad70b9b03 100644
--- a/src/sim/system.cc
+++ b/src/sim/system.cc
@@ -63,7 +63,7 @@ System::System(Params *p)
#else
page_ptr(0),
#endif
- _params(p)
+ memoryMode(p->mem_mode), _params(p)
{
// add self to global system list
systemList.push_back(this);
@@ -143,6 +143,14 @@ int rgdb_wait = -1;
#endif // FULL_SYSTEM
+
+void
+System::setMemoryMode(MemoryMode mode)
+{
+ assert(getState() == Drained);
+ memoryMode = mode;
+}
+
int
System::registerThreadContext(ThreadContext *tc, int id)
{
@@ -249,6 +257,9 @@ printSystems()
System::printSystems();
}
+const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
+ "timing"};
+
#if FULL_SYSTEM
// In full system mode, only derived classes (e.g. AlphaLinuxSystem)
@@ -261,12 +272,15 @@ DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
END_DECLARE_SIM_OBJECT_PARAMS(System)
BEGIN_INIT_SIM_OBJECT_PARAMS(System)
- INIT_PARAM(physmem, "physical memory")
+ INIT_PARAM(physmem, "physical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings)
END_INIT_SIM_OBJECT_PARAMS(System)
@@ -275,6 +289,7 @@ CREATE_SIM_OBJECT(System)
System::Params *p = new System::Params;
p->name = getInstanceName();
p->physmem = physmem;
+ p->mem_mode = mem_mode;
return new System(p);
}
diff --git a/src/sim/system.hh b/src/sim/system.hh
index 059dc92dc..a1b53c2eb 100644
--- a/src/sim/system.hh
+++ b/src/sim/system.hh
@@ -61,6 +61,23 @@ class RemoteGDB;
class System : public SimObject
{
public:
+ enum MemoryMode {
+ Invalid=0,
+ Atomic,
+ Timing
+ };
+
+ static const char *MemoryModeStrings[3];
+
+
+ MemoryMode getMemoryMode() { assert(memoryMode); return memoryMode; }
+
+ /** Change the memory mode of the system. This should only be called by the
+ * python!!
+ * @param mode Mode to change to (atomic/timing)
+ */
+ void setMemoryMode(MemoryMode mode);
+
PhysicalMemory *physmem;
PCEventQueue pcEventQueue;
@@ -108,6 +125,8 @@ class System : public SimObject
protected:
+ MemoryMode memoryMode;
+
#if FULL_SYSTEM
/**
* Fix up an address used to match PCs for hooking simulator
@@ -153,6 +172,7 @@ class System : public SimObject
{
std::string name;
PhysicalMemory *physmem;
+ MemoryMode mem_mode;
#if FULL_SYSTEM
Tick boot_cpu_frequency;