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
This commit is contained in:
Kevin Lim 2006-07-14 17:54:43 -04:00
commit 31ac8e7337
42 changed files with 528 additions and 299 deletions

View file

@ -2,41 +2,39 @@ import os, sys
from os.path import isdir, join as joinpath from os.path import isdir, join as joinpath
from os import environ as env from os import environ as env
systemdir = None def disk(file):
bindir = None system()
diskdir = None return joinpath(disk.dir, file)
scriptdir = None
def load_defaults(): def binary(file):
global systemdir, bindir, diskdir, scriptdir system()
if not systemdir: return joinpath(binary.dir, file)
def script(file):
system()
return joinpath(script.dir, file)
def system():
if not system.dir:
try: try:
path = env['M5_PATH'].split(':') path = env['M5_PATH'].split(':')
except KeyError: except KeyError:
path = [ '/dist/m5/system', '/n/poolfs/z/dist/m5/system' ] path = [ '/dist/m5/system', '/n/poolfs/z/dist/m5/system' ]
for systemdir in path: for system.dir in path:
if os.path.isdir(systemdir): if os.path.isdir(system.dir):
break break
else: else:
raise ImportError, "Can't find a path to system files." raise ImportError, "Can't find a path to system files."
if not bindir: if not binary.dir:
bindir = joinpath(systemdir, 'binaries') binary.dir = joinpath(system.dir, 'binaries')
if not diskdir: if not disk.dir:
diskdir = joinpath(systemdir, 'disks') disk.dir = joinpath(system.dir, 'disks')
if not scriptdir: if not script.dir:
scriptdir = joinpath(systemdir, 'boot') script.dir = joinpath(system.dir, 'boot')
def disk(file):
load_defaults()
return joinpath(diskdir, file)
def binary(file):
load_defaults()
return joinpath(bindir, file)
def script(file):
load_defaults()
return joinpath(scriptdir, file)
system.dir = None
binary.dir = None
disk.dir = None
script.dir = None

View file

@ -22,6 +22,8 @@ if args:
# Base for tests is directory containing this file. # Base for tests is directory containing this file.
test_base = os.path.dirname(__file__) test_base = os.path.dirname(__file__)
script.dir = '/z/saidi/work/m5.newmem/configs/boot'
linux_image = env.get('LINUX_IMAGE', disk('linux-latest.img')) linux_image = env.get('LINUX_IMAGE', disk('linux-latest.img'))
class CowIdeDisk(IdeDisk): class CowIdeDisk(IdeDisk):
@ -65,6 +67,7 @@ class MyLinuxAlphaSystem(LinuxAlphaSystem):
cpu = DetailedO3CPU() cpu = DetailedO3CPU()
elif options.timing: elif options.timing:
cpu = TimingSimpleCPU() cpu = TimingSimpleCPU()
mem_mode = 'timing'
else: else:
cpu = AtomicSimpleCPU() cpu = AtomicSimpleCPU()
cpu.mem = membus cpu.mem = membus
@ -72,6 +75,7 @@ class MyLinuxAlphaSystem(LinuxAlphaSystem):
cpu.dcache_port = membus.port cpu.dcache_port = membus.port
cpu.itb = AlphaITB() cpu.itb = AlphaITB()
cpu.dtb = AlphaDTB() cpu.dtb = AlphaDTB()
cpu.clock = '2GHz'
sim_console = SimConsole(listener=ConsoleListener(port=3456)) sim_console = SimConsole(listener=ConsoleListener(port=3456))
kernel = binary('vmlinux') kernel = binary('vmlinux')
pal = binary('ts_osfpal') pal = binary('ts_osfpal')
@ -90,7 +94,7 @@ def DualRoot(clientSystem, serverSystem):
self.etherlink = EtherLink(int1 = Parent.client.tsunami.etherint[0], self.etherlink = EtherLink(int1 = Parent.client.tsunami.etherint[0],
int2 = Parent.server.tsunami.etherint[0], int2 = Parent.server.tsunami.etherint[0],
dump = Parent.etherdump) dump = Parent.etherdump)
self.clock = '5GHz' self.clock = '1THz'
return self return self
if options.dual: if options.dual:
@ -102,6 +106,14 @@ else:
m5.instantiate(root) m5.instantiate(root)
#exit_event = m5.simulate(2600000000000)
#if exit_event.getCause() != "user interrupt received":
# m5.checkpoint(root, 'cpt')
# exit_event = m5.simulate(300000000000)
# if exit_event.getCause() != "user interrupt received":
# m5.checkpoint(root, 'cptA')
if options.maxtick: if options.maxtick:
exit_event = m5.simulate(options.maxtick) exit_event = m5.simulate(options.maxtick)
else: else:

View file

@ -38,6 +38,11 @@ if options.detailed:
cpu.workload = process cpu.workload = process
if options.timing or options.detailed:
system.mem_mode = 'timing'
# instantiate configuration # instantiate configuration
m5.instantiate(root) m5.instantiate(root)

View file

@ -97,6 +97,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
Param<Tick> boot_cpu_frequency; Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem; SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel; Param<string> kernel;
Param<string> console; 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(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"), 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(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"), INIT_PARAM(pal, "file that contains palcode"),
@ -133,6 +136,7 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem)
p->name = getInstanceName(); p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency; p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem; p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel; p->kernel_path = kernel;
p->console_path = console; p->console_path = console;
p->palcode = pal; p->palcode = pal;

View file

@ -191,6 +191,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
Param<Tick> boot_cpu_frequency; Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem; SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel; Param<string> kernel;
Param<string> console; 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(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"), 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(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"), INIT_PARAM(pal, "file that contains palcode"),
@ -227,6 +230,7 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem)
p->name = getInstanceName(); p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency; p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem; p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel; p->kernel_path = kernel;
p->console_path = console; p->console_path = console;
p->palcode = pal; p->palcode = pal;

View file

@ -221,6 +221,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
Param<Tick> boot_cpu_frequency; Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem; SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel; Param<std::string> kernel;
Param<std::string> console; 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(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"), 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(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"), INIT_PARAM(pal, "file that contains palcode"),
@ -257,6 +260,7 @@ CREATE_SIM_OBJECT(AlphaSystem)
p->name = getInstanceName(); p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency; p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem; p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel; p->kernel_path = kernel;
p->console_path = console; p->console_path = console;
p->palcode = pal; p->palcode = pal;

View file

@ -95,6 +95,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
Param<Tick> boot_cpu_frequency; Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem; SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel; Param<string> kernel;
Param<string> console; 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(boot_cpu_frequency, "frequency of the boot cpu"),
INIT_PARAM(physmem, "phsyical memory"), 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(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"), INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"), INIT_PARAM(pal, "file that contains palcode"),
@ -131,6 +134,7 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem)
p->name = getInstanceName(); p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency; p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem; p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel; p->kernel_path = kernel;
p->console_path = console; p->console_path = console;
p->palcode = pal; p->palcode = pal;

View file

@ -45,6 +45,12 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
panic("Copy Regs Not Implemented Yet\n"); panic("Copy Regs Not Implemented Yet\n");
} }
void
MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
panic("Copy Misc. Regs Not Implemented Yet\n");
}
void void
MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc) MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc)
{ {

View file

@ -129,7 +129,7 @@ namespace MipsISA
template <class TC> template <class TC>
void zeroRegisters(TC *tc); void zeroRegisters(TC *tc);
const Addr MaxAddr = (Addr)-1; // const Addr MaxAddr = (Addr)-1;
void copyRegs(ThreadContext *src, ThreadContext *dest); void copyRegs(ThreadContext *src, ThreadContext *dest);

View file

@ -41,6 +41,8 @@
using namespace std; using namespace std;
using namespace MipsISA; using namespace MipsISA;
Addr MipsLiveProcess::stack_start = 0x7FFFFFFF;
MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile, MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
System *_system, int stdin_fd, int stdout_fd, int stderr_fd, System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv, std::vector<std::string> &envp) 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 // Set up stack. On MIPS, stack starts at the top of kuseg
// user address space. MIPS stack grows down from here // 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. // Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024); next_thread_stack_base = stack_base - (8 * 1024 * 1024);
stack_start = next_thread_stack_base;
// Set up break point (Top of Heap) // Set up break point (Top of Heap)
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();

View file

@ -50,6 +50,9 @@ class MipsLiveProcess : public LiveProcess
std::vector<std::string> &envp); std::vector<std::string> &envp);
void startup(); void startup();
static Addr stack_start;
}; };

View file

@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
SimObjectParam<PhysicalMemory *> physmem; SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel; Param<std::string> kernel;
Param<std::string> reset_bin; 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(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"), 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(kernel, "file that contains the kernel code"),
INIT_PARAM(reset_bin, "file that contains the reset code"), INIT_PARAM(reset_bin, "file that contains the reset code"),
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
@ -183,6 +186,7 @@ CREATE_SIM_OBJECT(SparcSystem)
p->name = getInstanceName(); p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency; p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem; p->physmem = physmem;
p->mem_mode = mem_mode;
p->kernel_path = kernel; p->kernel_path = kernel;
p->reset_bin = reset_bin; p->reset_bin = reset_bin;
p->hypervisor_bin = hypervisor_bin; p->hypervisor_bin = hypervisor_bin;

View file

@ -441,7 +441,7 @@ FullO3CPU<Impl>::tick()
if (!tickEvent.scheduled()) { if (!tickEvent.scheduled()) {
if (_status == SwitchedOut || if (_status == SwitchedOut ||
getState() == SimObject::DrainedTiming) { getState() == SimObject::Drained) {
// increment stat // increment stat
lastRunningCycle = curTick; lastRunningCycle = curTick;
} else if (!activityRec.active()) { } else if (!activityRec.active()) {
@ -577,39 +577,19 @@ void
FullO3CPU<Impl>::suspendContext(int tid) FullO3CPU<Impl>::suspendContext(int tid)
{ {
DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
deactivateThread(tid);
if (activeThreads.size() == 0)
unscheduleTickEvent(); unscheduleTickEvent();
_status = Idle; _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> template <class Impl>
void void
FullO3CPU<Impl>::haltContext(int tid) FullO3CPU<Impl>::haltContext(int tid)
{ {
DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid); //For now, this is the same as deallocate
/* DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
//Remove From Active List, if Active deallocateContext(tid, 1);
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);
}
*/
} }
template <class Impl> template <class Impl>
@ -805,7 +785,7 @@ FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
} }
template <class Impl> template <class Impl>
bool unsigned int
FullO3CPU<Impl>::drain(Event *drain_event) FullO3CPU<Impl>::drain(Event *drain_event)
{ {
drainCount = 0; drainCount = 0;
@ -817,7 +797,7 @@ FullO3CPU<Impl>::drain(Event *drain_event)
// Wake the CPU and record activity so everything can drain out if // Wake the CPU and record activity so everything can drain out if
// the CPU was not able to immediately drain. // 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() // A bit of a hack...set the drainEvent after all the drain()
// calls have been made, that way if all of the stages drain // calls have been made, that way if all of the stages drain
// immediately, the signalDrained() function knows not to call // immediately, the signalDrained() function knows not to call
@ -827,9 +807,9 @@ FullO3CPU<Impl>::drain(Event *drain_event)
wakeCPU(); wakeCPU();
activityRec.activity(); activityRec.activity();
return false; return 1;
} else { } else {
return true; return 0;
} }
} }
@ -837,19 +817,21 @@ template <class Impl>
void void
FullO3CPU<Impl>::resume() FullO3CPU<Impl>::resume()
{ {
assert(system->getMemoryMode() == System::Timing);
fetch.resume(); fetch.resume();
decode.resume(); decode.resume();
rename.resume(); rename.resume();
iew.resume(); iew.resume();
commit.resume(); commit.resume();
changeState(SimObject::Running);
if (_status == SwitchedOut || _status == Idle) if (_status == SwitchedOut || _status == Idle)
return; return;
if (!tickEvent.scheduled()) if (!tickEvent.scheduled())
tickEvent.schedule(curTick); tickEvent.schedule(curTick);
_status = Running; _status = Running;
changeState(SimObject::Timing);
} }
template <class Impl> template <class Impl>
@ -860,7 +842,7 @@ FullO3CPU<Impl>::signalDrained()
if (tickEvent.scheduled()) if (tickEvent.scheduled())
tickEvent.squash(); tickEvent.squash();
changeState(SimObject::DrainedTiming); changeState(SimObject::Drained);
if (drainEvent) { if (drainEvent) {
drainEvent->process(); drainEvent->process();

View file

@ -330,7 +330,7 @@ class FullO3CPU : public BaseO3CPU
/** Starts draining the CPU's pipeline of all instructions in /** Starts draining the CPU's pipeline of all instructions in
* order to stop all memory accesses. */ * order to stop all memory accesses. */
virtual bool drain(Event *drain_event); virtual unsigned int drain(Event *drain_event);
/** Resumes execution after a drain. */ /** Resumes execution after a drain. */
virtual void resume(); virtual void resume();

View file

@ -407,6 +407,9 @@ class DefaultFetch
/** The PC of the cacheline that has been loaded. */ /** The PC of the cacheline that has been loaded. */
Addr cacheDataPC[Impl::MaxThreads]; Addr cacheDataPC[Impl::MaxThreads];
/** Whether or not the cache data is valid. */
bool cacheDataValid[Impl::MaxThreads];
/** Size of instructions. */ /** Size of instructions. */
int instSize; int instSize;

View file

@ -162,6 +162,8 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
// Create space to store a cache line. // Create space to store a cache line.
cacheData[tid] = new uint8_t[cacheBlkSize]; cacheData[tid] = new uint8_t[cacheBlkSize];
cacheDataPC[tid] = 0;
cacheDataValid[tid] = false;
stalls[tid].decode = 0; stalls[tid].decode = 0;
stalls[tid].rename = 0; stalls[tid].rename = 0;
@ -358,6 +360,7 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
} }
memcpy(cacheData[tid], pkt->getPtr<uint8_t *>(), cacheBlkSize); memcpy(cacheData[tid], pkt->getPtr<uint8_t *>(), cacheBlkSize);
cacheDataValid[tid] = true;
if (!drainPending) { if (!drainPending) {
// Wake up the CPU (if it went to sleep and was waiting on // 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); fetch_PC = icacheBlockAlignPC(fetch_PC);
// If we've already got the block, no need to try to fetch it again. // 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; return true;
} }
@ -555,9 +558,10 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Build packet here. // Build packet here.
PacketPtr data_pkt = new Packet(mem_req, PacketPtr data_pkt = new Packet(mem_req,
Packet::ReadReq, Packet::Broadcast); Packet::ReadReq, Packet::Broadcast);
data_pkt->dataDynamic(new uint8_t[cacheBlkSize]); data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]);
cacheDataPC[tid] = fetch_PC; cacheDataPC[tid] = fetch_PC;
cacheDataValid[tid] = false;
DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); DPRINTF(Fetch, "Fetch: Doing instruction read.\n");

View file

@ -70,7 +70,7 @@ class LSQ {
* to work. For now it just returns the port from one of the * to work. For now it just returns the port from one of the
* threads. * threads.
*/ */
Port *getDcachePort() { return thread[0].getDcachePort(); } Port *getDcachePort() { return &dcachePort; }
/** Sets the pointer to the list of active threads. */ /** Sets the pointer to the list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr); void setActiveThreads(std::list<unsigned> *at_ptr);
@ -258,6 +258,15 @@ class LSQ {
bool willWB(unsigned tid) bool willWB(unsigned tid)
{ return thread[tid].willWB(); } { 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. */ /** Debugging function to print out all instructions. */
void dumpInsts(); void dumpInsts();
/** Debugging function to print out instructions from a specific thread. */ /** Debugging function to print out instructions from a specific thread. */
@ -274,7 +283,49 @@ class LSQ {
template <class T> template <class T>
Fault write(RequestPtr req, T &data, int store_idx); 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. */ /** The LSQ policy for SMT mode. */
LSQPolicy lsqPolicy; LSQPolicy lsqPolicy;
@ -303,6 +354,10 @@ class LSQ {
/** Number of Threads. */ /** Number of Threads. */
unsigned numThreads; unsigned numThreads;
/** The thread id of the LSQ Unit that is currently waiting for a
* retry. */
int retryTid;
}; };
template <class Impl> template <class Impl>

View file

@ -35,10 +35,54 @@
using namespace std; 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> template <class Impl>
LSQ<Impl>::LSQ(Params *params) LSQ<Impl>::LSQ(Params *params)
: LQEntries(params->LQEntries), SQEntries(params->SQEntries), : dcachePort(this), LQEntries(params->LQEntries),
numThreads(params->numberOfThreads) SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
retryTid(-1)
{ {
DPRINTF(LSQ, "Creating LSQ object.\n"); DPRINTF(LSQ, "Creating LSQ object.\n");
@ -94,7 +138,8 @@ LSQ<Impl>::LSQ(Params *params)
//Initialize LSQs //Initialize LSQs
for (int tid=0; tid < numThreads; tid++) { 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; cpu = cpu_ptr;
dcachePort.setName(name());
for (int tid=0; tid < numThreads; tid++) { for (int tid=0; tid < numThreads; tid++) {
thread[tid].setCPU(cpu_ptr); thread[tid].setCPU(cpu_ptr);
} }

View file

@ -64,6 +64,7 @@ class LSQUnit {
typedef typename Impl::O3CPU O3CPU; typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::CPUPol::IEW IEW; typedef typename Impl::CPUPol::IEW IEW;
typedef typename Impl::CPUPol::LSQ LSQ;
typedef typename Impl::CPUPol::IssueStruct IssueStruct; typedef typename Impl::CPUPol::IssueStruct IssueStruct;
public: public:
@ -71,17 +72,12 @@ class LSQUnit {
LSQUnit(); LSQUnit();
/** Initializes the LSQ unit with the specified number of entries. */ /** 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); unsigned maxSQEntries, unsigned id);
/** Returns the name of the LSQ unit. */ /** Returns the name of the LSQ unit. */
std::string name() const; 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. */ /** Registers statistics. */
void regStats(); void regStats();
@ -92,6 +88,10 @@ class LSQUnit {
void setIEW(IEW *iew_ptr) void setIEW(IEW *iew_ptr)
{ iewStage = iew_ptr; } { iewStage = iew_ptr; }
/** Sets the pointer to the dcache port. */
void setDcachePort(Port *dcache_port)
{ dcachePort = dcache_port; }
/** Switches out LSQ unit. */ /** Switches out LSQ unit. */
void switchOut(); void switchOut();
@ -211,6 +211,9 @@ class LSQUnit {
!storeQueue[storeWBIdx].completed && !storeQueue[storeWBIdx].completed &&
!isStoreBlocked; } !isStoreBlocked; }
/** Handles doing the retry. */
void recvRetry();
private: private:
/** Writes back the instruction, sending it to IEW. */ /** Writes back the instruction, sending it to IEW. */
void writeback(DynInstPtr &inst, PacketPtr pkt); void writeback(DynInstPtr &inst, PacketPtr pkt);
@ -221,9 +224,6 @@ class LSQUnit {
/** Completes the store at the specified index. */ /** Completes the store at the specified index. */
void completeStore(int store_idx); void completeStore(int store_idx);
/** Handles doing the retry. */
void recvRetry();
/** Increments the given store index (circular queue). */ /** Increments the given store index (circular queue). */
inline void incrStIdx(int &store_idx); inline void incrStIdx(int &store_idx);
/** Decrements the given store index (circular queue). */ /** Decrements the given store index (circular queue). */
@ -244,54 +244,11 @@ class LSQUnit {
/** Pointer to the IEW stage. */ /** Pointer to the IEW stage. */
IEW *iewStage; IEW *iewStage;
/** Pointer to memory object. */ /** Pointer to the LSQ. */
MemObject *mem; LSQ *lsq;
/** DcachePort class for this LSQ Unit. Handles doing the /** Pointer to the dcache port. Used only for sending. */
* communication with the cache/memory. Port *dcachePort;
* @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;
/** Derived class to hold any sender state the LSQ needs. */ /** Derived class to hold any sender state the LSQ needs. */
class LSQSenderState : public Packet::SenderState 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 // 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()); load_inst->seqNum, load_inst->readPC());
assert(!load_inst->memData); assert(!load_inst->memData);
@ -666,9 +623,6 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
++usedPorts; ++usedPorts;
DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
load_inst->readPC());
PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(load_inst->memData); data_pkt->dataStatic(load_inst->memData);
@ -678,8 +632,18 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
state->inst = load_inst; state->inst = load_inst;
data_pkt->senderState = state; data_pkt->senderState = state;
// if we have a cache, do cache access too // if we the cache is not blocked, do cache access
if (!lsq->cacheBlocked()) {
if (!dcachePort->sendTiming(data_pkt)) { 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; ++lsqCacheBlocked;
// There's an older load that's already going to squash. // There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)

View file

@ -31,6 +31,7 @@
#include "config/use_checker.hh" #include "config/use_checker.hh"
#include "cpu/o3/lsq.hh"
#include "cpu/o3/lsq_unit.hh" #include "cpu/o3/lsq_unit.hh"
#include "base/str.hh" #include "base/str.hh"
#include "mem/packet.hh" #include "mem/packet.hh"
@ -95,46 +96,6 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
delete pkt; delete 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> template <class Impl>
LSQUnit<Impl>::LSQUnit() LSQUnit<Impl>::LSQUnit()
: loads(0), stores(0), storesToWB(0), stalled(false), : loads(0), stores(0), storesToWB(0), stalled(false),
@ -145,13 +106,15 @@ LSQUnit<Impl>::LSQUnit()
template<class Impl> template<class Impl>
void void
LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
unsigned maxSQEntries, unsigned id) unsigned maxSQEntries, unsigned id)
{ {
DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
switchedOut = false; switchedOut = false;
lsq = lsq_ptr;
lsqID = id; lsqID = id;
// Add 1 for the sentinel entry (they are circular queues). // Add 1 for the sentinel entry (they are circular queues).
@ -168,8 +131,6 @@ LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
usedPorts = 0; usedPorts = 0;
cachePorts = params->cachePorts; cachePorts = params->cachePorts;
mem = params->mem;
memDepViolator = NULL; memDepViolator = NULL;
blockedLoadSeqNum = 0; blockedLoadSeqNum = 0;
@ -180,7 +141,6 @@ void
LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr) LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
{ {
cpu = cpu_ptr; cpu = cpu_ptr;
dcachePort = new DcachePort(cpu, this);
#if USE_CHECKER #if USE_CHECKER
if (cpu->checker) { if (cpu->checker) {
@ -588,7 +548,7 @@ LSQUnit<Impl>::writebackStores()
storeQueue[storeWBIdx].canWB && storeQueue[storeWBIdx].canWB &&
usedPorts < cachePorts) { usedPorts < cachePorts) {
if (isStoreBlocked) { if (isStoreBlocked || lsq->cacheBlocked()) {
DPRINTF(LSQUnit, "Unable to write back any more stores, cache" DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
" is blocked!\n"); " is blocked!\n");
break; break;
@ -911,6 +871,7 @@ LSQUnit<Impl>::recvRetry()
} else { } else {
// Still blocked! // Still blocked!
++lsqCacheBlocked; ++lsqCacheBlocked;
lsq->setRetryTid(lsqID);
} }
} else if (isLoadBlocked) { } else if (isLoadBlocked) {
DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "

View file

@ -33,6 +33,7 @@
#include "cpu/simple/atomic.hh" #include "cpu/simple/atomic.hh"
#include "mem/packet_impl.hh" #include "mem/packet_impl.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/system.hh"
using namespace std; using namespace std;
using namespace TheISA; using namespace TheISA;
@ -183,6 +184,13 @@ AtomicSimpleCPU::resume()
} }
} }
void
AtomicSimpleCPU::resume()
{
assert(system->getMemoryMode() == System::Atomic);
changeState(SimObject::Running);
}
void void
AtomicSimpleCPU::switchOut() AtomicSimpleCPU::switchOut()
{ {
@ -462,11 +470,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
Param<Counter> max_loads_any_thread; Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads; Param<Counter> max_loads_all_threads;
SimObjectParam<MemObject *> mem; SimObjectParam<MemObject *> mem;
SimObjectParam<System *> system;
#if FULL_SYSTEM #if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb; SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb; SimObjectParam<AlphaDTB *> dtb;
SimObjectParam<System *> system;
Param<int> cpu_id; Param<int> cpu_id;
Param<Tick> profile; Param<Tick> profile;
#else #else
@ -494,11 +502,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
INIT_PARAM(max_loads_all_threads, INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"), "terminate when all threads have reached this load count"),
INIT_PARAM(mem, "memory"), INIT_PARAM(mem, "memory"),
INIT_PARAM(system, "system object"),
#if FULL_SYSTEM #if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"), INIT_PARAM(dtb, "Data TLB"),
INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"), INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""), INIT_PARAM(profile, ""),
#else #else
@ -531,11 +539,11 @@ CREATE_SIM_OBJECT(AtomicSimpleCPU)
params->width = width; params->width = width;
params->simulate_stalls = simulate_stalls; params->simulate_stalls = simulate_stalls;
params->mem = mem; params->mem = mem;
params->system = system;
#if FULL_SYSTEM #if FULL_SYSTEM
params->itb = itb; params->itb = itb;
params->dtb = dtb; params->dtb = dtb;
params->system = system;
params->cpu_id = cpu_id; params->cpu_id = cpu_id;
params->profile = profile; params->profile = profile;
#else #else

View file

@ -128,6 +128,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
virtual void resume(); virtual void resume();
virtual void resume();
void switchOut(); void switchOut();
void takeOverFrom(BaseCPU *oldCPU); void takeOverFrom(BaseCPU *oldCPU);

View file

@ -55,10 +55,10 @@
#include "sim/sim_events.hh" #include "sim/sim_events.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
#include "sim/stats.hh" #include "sim/stats.hh"
#include "sim/system.hh"
#if FULL_SYSTEM #if FULL_SYSTEM
#include "base/remote_gdb.hh" #include "base/remote_gdb.hh"
#include "sim/system.hh"
#include "arch/tlb.hh" #include "arch/tlb.hh"
#include "arch/stacktrace.hh" #include "arch/stacktrace.hh"
#include "arch/vtophys.hh" #include "arch/vtophys.hh"

View file

@ -33,6 +33,7 @@
#include "cpu/simple/timing.hh" #include "cpu/simple/timing.hh"
#include "mem/packet_impl.hh" #include "mem/packet_impl.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/system.hh"
using namespace std; using namespace std;
using namespace TheISA; using namespace TheISA;
@ -91,7 +92,7 @@ TimingSimpleCPU::TimingSimpleCPU(Params *p)
ifetch_pkt = dcache_pkt = NULL; ifetch_pkt = dcache_pkt = NULL;
drainEvent = NULL; drainEvent = NULL;
fetchEvent = NULL; fetchEvent = NULL;
state = SimObject::Timing; changeState(SimObject::Running);
} }
@ -115,18 +116,18 @@ TimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
BaseSimpleCPU::unserialize(cp, section); BaseSimpleCPU::unserialize(cp, section);
} }
bool unsigned int
TimingSimpleCPU::drain(Event *drain_event) TimingSimpleCPU::drain(Event *drain_event)
{ {
// TimingSimpleCPU is ready to drain if it's not waiting for // TimingSimpleCPU is ready to drain if it's not waiting for
// an access to complete. // an access to complete.
if (status() == Idle || status() == Running || status() == SwitchedOut) { if (status() == Idle || status() == Running || status() == SwitchedOut) {
changeState(SimObject::DrainedTiming); changeState(SimObject::Drained);
return true; return 0;
} else { } else {
changeState(SimObject::Draining); changeState(SimObject::Draining);
drainEvent = drain_event; drainEvent = drain_event;
return false; return 1;
} }
} }
@ -146,12 +147,9 @@ TimingSimpleCPU::resume()
new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false); new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);
fetchEvent->schedule(curTick); fetchEvent->schedule(curTick);
} }
}
void assert(system->getMemoryMode() == System::Timing);
TimingSimpleCPU::setMemoryMode(State new_mode) changeState(SimObject::Running);
{
assert(new_mode == SimObject::Timing);
} }
void void
@ -518,7 +516,7 @@ void
TimingSimpleCPU::completeDrain() TimingSimpleCPU::completeDrain()
{ {
DPRINTF(Config, "Done draining\n"); DPRINTF(Config, "Done draining\n");
changeState(SimObject::DrainedTiming); changeState(SimObject::Drained);
drainEvent->process(); drainEvent->process();
} }
@ -555,11 +553,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
Param<Counter> max_loads_any_thread; Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads; Param<Counter> max_loads_all_threads;
SimObjectParam<MemObject *> mem; SimObjectParam<MemObject *> mem;
SimObjectParam<System *> system;
#if FULL_SYSTEM #if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb; SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb; SimObjectParam<AlphaDTB *> dtb;
SimObjectParam<System *> system;
Param<int> cpu_id; Param<int> cpu_id;
Param<Tick> profile; Param<Tick> profile;
#else #else
@ -587,11 +585,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
INIT_PARAM(max_loads_all_threads, INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"), "terminate when all threads have reached this load count"),
INIT_PARAM(mem, "memory"), INIT_PARAM(mem, "memory"),
INIT_PARAM(system, "system object"),
#if FULL_SYSTEM #if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"), INIT_PARAM(dtb, "Data TLB"),
INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"), INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""), INIT_PARAM(profile, ""),
#else #else
@ -622,11 +620,11 @@ CREATE_SIM_OBJECT(TimingSimpleCPU)
params->functionTrace = function_trace; params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start; params->functionTraceStart = function_trace_start;
params->mem = mem; params->mem = mem;
params->system = system;
#if FULL_SYSTEM #if FULL_SYSTEM
params->itb = itb; params->itb = itb;
params->dtb = dtb; params->dtb = dtb;
params->system = system;
params->cpu_id = cpu_id; params->cpu_id = cpu_id;
params->profile = profile; params->profile = profile;
#else #else

View file

@ -137,9 +137,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); 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 resume();
virtual void setMemoryMode(State new_mode);
void switchOut(); void switchOut();
void takeOverFrom(BaseCPU *oldCPU); void takeOverFrom(BaseCPU *oldCPU);

View file

@ -318,7 +318,7 @@ IdeDisk::doDmaTransfer()
panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n", panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
dmaState, devState); dmaState, devState);
if (ctrl->dmaPending()) { if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD); dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return; return;
} else } else
@ -398,8 +398,7 @@ IdeDisk::doDmaRead()
curPrd.getByteCount(), TheISA::PageBytes); curPrd.getByteCount(), TheISA::PageBytes);
} }
if (ctrl->dmaPending()) { if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
panic("shouldn't be reentant??");
dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return; return;
} else if (!dmaReadCG->done()) { } else if (!dmaReadCG->done()) {
@ -474,8 +473,7 @@ IdeDisk::doDmaWrite()
dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(), dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
curPrd.getByteCount(), TheISA::PageBytes); curPrd.getByteCount(), TheISA::PageBytes);
} }
if (ctrl->dmaPending()) { if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
panic("shouldn't be reentant??");
dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return; return;
} else if (!dmaWriteCG->done()) { } else if (!dmaWriteCG->done()) {

View file

@ -32,10 +32,12 @@
#include "base/trace.hh" #include "base/trace.hh"
#include "dev/io_device.hh" #include "dev/io_device.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/system.hh"
PioPort::PioPort(PioDevice *dev, Platform *p, std::string pname) PioPort::PioPort(PioDevice *dev, System *s, std::string pname)
: Port(dev->name() + pname), device(dev), platform(p) : Port(dev->name() + pname), device(dev), sys(s),
outTiming(0), drainEvent(NULL)
{ } { }
@ -68,12 +70,22 @@ PioPort::recvRetry()
if (result) if (result)
transmitList.pop_front(); transmitList.pop_front();
} }
if (transmitList.size() == 0 && drainEvent) {
drainEvent->process();
drainEvent = NULL;
}
} }
void void
PioPort::SendEvent::process() PioPort::SendEvent::process()
{ {
port->outTiming--;
assert(port->outTiming >= 0);
if (port->Port::sendTiming(packet)) if (port->Port::sendTiming(packet))
if (port->transmitList.size() == 0 && port->drainEvent) {
port->drainEvent->process();
port->drainEvent = NULL;
}
return; return;
port->transmitList.push_back(packet); port->transmitList.push_back(packet);
@ -105,6 +117,15 @@ PioPort::recvTiming(Packet *pkt)
return true; return true;
} }
unsigned int
PioPort::drain(Event *de)
{
if (outTiming == 0 && transmitList.size() == 0)
return 0;
drainEvent = de;
return 1;
}
PioDevice::~PioDevice() PioDevice::~PioDevice()
{ {
if (pioPort) if (pioPort)
@ -119,6 +140,19 @@ PioDevice::init()
pioPort->sendStatusChange(Port::RangeChange); 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 void
BasicPioDevice::addressRanges(AddrRangeList &range_list) BasicPioDevice::addressRanges(AddrRangeList &range_list)
{ {
@ -128,8 +162,9 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
} }
DmaPort::DmaPort(DmaDevice *dev, Platform *p) DmaPort::DmaPort(DmaDevice *dev, System *s)
: Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0) : Port(dev->name() + "-dmaport"), device(dev), sys(s), pendingCount(0),
actionInProgress(0), drainEvent(NULL)
{ } { }
bool bool
@ -159,6 +194,11 @@ DmaPort::recvTiming(Packet *pkt)
} }
delete pkt->req; delete pkt->req;
delete pkt; delete pkt;
if (pendingCount == 0 && drainEvent) {
drainEvent->process();
drainEvent = NULL;
}
} else { } else {
panic("Got packet without sender state... huh?\n"); panic("Got packet without sender state... huh?\n");
} }
@ -170,6 +210,29 @@ DmaDevice::DmaDevice(Params *p)
: PioDevice(p), dmaPort(NULL) : 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 void
DmaPort::recvRetry() DmaPort::recvRetry()
{ {
@ -195,6 +258,8 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
{ {
assert(event); assert(event);
assert(device->getState() == SimObject::Running);
DmaReqState *reqState = new DmaReqState(event, this, size); DmaReqState *reqState = new DmaReqState(event, this, size);
for (ChunkGenerator gen(addr, size, peerBlockSize()); for (ChunkGenerator gen(addr, size, peerBlockSize());
@ -212,6 +277,7 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
pendingCount++; pendingCount++;
sendDma(pkt); sendDma(pkt);
} }
} }
@ -221,9 +287,9 @@ DmaPort::sendDma(Packet *pkt, bool front)
// some kind of selction between access methods // some kind of selction between access methods
// more work is going to have to be done to make // more work is going to have to be done to make
// switching actually work // switching actually work
/* MemState state = device->platform->system->memState;
if (state == Timing) { */ System::MemoryMode state = sys->getMemoryMode();
if (state == System::Timing) {
DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n", DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
pkt, pkt->getAddr()); pkt, pkt->getAddr());
if (transmitList.size() || !sendTiming(pkt)) { if (transmitList.size() || !sendTiming(pkt)) {
@ -235,28 +301,30 @@ DmaPort::sendDma(Packet *pkt, bool front)
} else { } else {
DPRINTF(DMA, "-- Done\n"); DPRINTF(DMA, "-- Done\n");
} }
/* } else if (state == Atomic) { } else if (state == System::Atomic) {
sendAtomic(pkt); Tick lat;
if (pkt->senderState) { lat = sendAtomic(pkt);
assert(pkt->senderState);
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState); DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
assert(state); assert(state);
state->completionEvent->schedule(curTick + (pkt->time -
pkt->req->getTime()) +1); state->numBytes += pkt->req->getSize();
if (state->totBytes == state->numBytes) {
state->completionEvent->schedule(curTick + lat);
delete state; delete state;
delete pkt->req;
} }
pendingCount--; pendingCount--;
assert(pendingCount >= 0); assert(pendingCount >= 0);
delete pkt->req;
delete pkt; delete pkt;
} else if (state == Functional) { if (pendingCount == 0 && drainEvent) {
sendFunctional(pkt); drainEvent->process();
// Is this correct??? drainEvent = NULL;
completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime); }
completionEvent == NULL;
} else } else
panic("Unknown memory command state."); panic("Unknown memory command state.");
*/
} }
DmaDevice::~DmaDevice() DmaDevice::~DmaDevice()

View file

@ -60,9 +60,9 @@ class PioPort : public Port
/** The device that this port serves. */ /** The device that this port serves. */
PioDevice *device; 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. */ * we are currently operating in. */
Platform *platform; System *sys;
/** A list of outgoing timing response packets that haven't been serviced /** A list of outgoing timing response packets that haven't been serviced
* yet. */ * yet. */
@ -106,16 +106,27 @@ class PioPort : public Port
friend class PioPort; 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. */ /** Schedule a sendTiming() event to be called in the future. */
void sendTiming(Packet *pkt, Tick time) 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 /** This function is notification that the device should attempt to send a
* packet again. */ * packet again. */
virtual void recvRetry(); virtual void recvRetry();
public: 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; friend class PioPort::SendEvent;
}; };
@ -147,13 +158,20 @@ class DmaPort : public Port
DmaDevice *device; DmaDevice *device;
std::list<Packet*> transmitList; 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. */ * we are currently operating in. */
Platform *platform; System *sys;
/** Number of outstanding packets the dma port has. */ /** Number of outstanding packets the dma port has. */
int pendingCount; 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 bool recvTiming(Packet *pkt);
virtual Tick recvAtomic(Packet *pkt) virtual Tick recvAtomic(Packet *pkt)
{ panic("dma port shouldn't be used for pio access."); } { 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); void sendDma(Packet *pkt, bool front = false);
public: public:
DmaPort(DmaDevice *dev, Platform *p); DmaPort(DmaDevice *dev, System *s);
void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
uint8_t *data = NULL); uint8_t *data = NULL);
bool dmaPending() { return pendingCount > 0; } bool dmaPending() { return pendingCount > 0; }
unsigned int drain(Event *de);
}; };
/** /**
@ -196,6 +215,8 @@ class PioDevice : public MemObject
* transaction we should perform. */ * transaction we should perform. */
Platform *platform; Platform *platform;
System *sys;
/** The pioPort that handles the requests for us and provides us requests /** The pioPort that handles the requests for us and provides us requests
* that it sees. */ * that it sees. */
PioPort *pioPort; PioPort *pioPort;
@ -240,20 +261,22 @@ class PioDevice : public MemObject
const Params *params() const { return _params; } const Params *params() const { return _params; }
PioDevice(Params *p) PioDevice(Params *p)
: MemObject(p->name), platform(p->platform), pioPort(NULL), : MemObject(p->name), platform(p->platform), sys(p->system),
_params(p) pioPort(NULL), _params(p)
{} {}
virtual ~PioDevice(); virtual ~PioDevice();
virtual void init(); virtual void init();
virtual unsigned int drain(Event *de);
virtual Port *getPort(const std::string &if_name, int idx = -1) virtual Port *getPort(const std::string &if_name, int idx = -1)
{ {
if (if_name == "pio") { if (if_name == "pio") {
if (pioPort != NULL) if (pioPort != NULL)
panic("pio port already connected to."); panic("pio port already connected to.");
pioPort = new PioPort(this, params()->platform); pioPort = new PioPort(this, sys);
return pioPort; return pioPort;
} else } else
return NULL; return NULL;
@ -310,17 +333,19 @@ class DmaDevice : public PioDevice
bool dmaPending() { return dmaPort->dmaPending(); } bool dmaPending() { return dmaPort->dmaPending(); }
virtual unsigned int drain(Event *de);
virtual Port *getPort(const std::string &if_name, int idx = -1) virtual Port *getPort(const std::string &if_name, int idx = -1)
{ {
if (if_name == "pio") { if (if_name == "pio") {
if (pioPort != NULL) if (pioPort != NULL)
panic("pio port already connected to."); panic("pio port already connected to.");
pioPort = new PioPort(this, params()->platform); pioPort = new PioPort(this, sys);
return pioPort; return pioPort;
} else if (if_name == "dma") { } else if (if_name == "dma") {
if (dmaPort != NULL) if (dmaPort != NULL)
panic("dma port already connected to."); panic("dma port already connected to.");
dmaPort = new DmaPort(this, params()->platform); dmaPort = new DmaPort(this, sys);
return dmaPort; return dmaPort;
} else } else
return NULL; return NULL;

View file

@ -1377,7 +1377,7 @@ NSGigE::doRxDmaRead()
assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
rxDmaState = dmaReading; rxDmaState = dmaReading;
if (dmaPending()) if (dmaPending() || getState() != Running)
rxDmaState = dmaReadWaiting; rxDmaState = dmaReadWaiting;
else else
dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData); dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
@ -1408,7 +1408,7 @@ NSGigE::doRxDmaWrite()
assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
rxDmaState = dmaWriting; rxDmaState = dmaWriting;
if (dmaPending()) if (dmaPending() || getState() != Running)
rxDmaState = dmaWriteWaiting; rxDmaState = dmaWriteWaiting;
else else
dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData); dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
@ -1826,7 +1826,7 @@ NSGigE::doTxDmaRead()
assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
txDmaState = dmaReading; txDmaState = dmaReading;
if (dmaPending()) if (dmaPending() || getState() != Running)
txDmaState = dmaReadWaiting; txDmaState = dmaReadWaiting;
else else
dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData); dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
@ -1857,7 +1857,7 @@ NSGigE::doTxDmaWrite()
assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
txDmaState = dmaWriting; txDmaState = dmaWriting;
if (dmaPending()) if (dmaPending() || getState() != Running)
txDmaState = dmaWriteWaiting; txDmaState = dmaWriteWaiting;
else else
dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData); dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
@ -2406,6 +2406,20 @@ NSGigE::recvPacket(EthPacketPtr packet)
return true; 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();
}
//===================================================================== //=====================================================================
// //
// //

View file

@ -391,6 +391,8 @@ class NSGigE : public PciDev
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
virtual void resume();
public: public:
void regStats(); void regStats();

View file

@ -56,8 +56,8 @@ using namespace std;
PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid, PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid,
int funcid, Platform *p) int funcid, Platform *p)
: PioPort(dev,p,"-pciconf"), device(dev), busId(busid), deviceId(devid), : PioPort(dev,p->system,"-pciconf"), device(dev), platform(p),
functionId(funcid) busId(busid), deviceId(devid), functionId(funcid)
{ {
configAddr = platform->calcConfigAddr(busId, deviceId, functionId); configAddr = platform->calcConfigAddr(busId, deviceId, functionId);
} }
@ -132,6 +132,18 @@ PciDev::init()
PioDevice::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 Tick
PciDev::readConfig(Packet *pkt) PciDev::readConfig(Packet *pkt)
{ {

View file

@ -95,6 +95,8 @@ class PciDev : public DmaDevice
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
Platform *platform;
int busId; int busId;
int deviceId; int deviceId;
int functionId; int functionId;
@ -249,6 +251,9 @@ class PciDev : public DmaDevice
*/ */
virtual void unserialize(Checkpoint *cp, const std::string &section); 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) virtual Port *getPort(const std::string &if_name, int idx = -1)
{ {
if (if_name == "config") { if (if_name == "config") {

View file

@ -921,7 +921,7 @@ Device::rxKick()
break; break;
case rxBeginCopy: case rxBeginCopy:
if (dmaPending()) if (dmaPending() || getState() != Running)
goto exit; goto exit;
rxDmaAddr = params()->platform->pciToDma( rxDmaAddr = params()->platform->pciToDma(
@ -1109,7 +1109,7 @@ Device::txKick()
break; break;
case txBeginCopy: case txBeginCopy:
if (dmaPending()) if (dmaPending() || getState() != Running)
goto exit; goto exit;
txDmaAddr = params()->platform->pciToDma( txDmaAddr = params()->platform->pciToDma(
@ -1287,6 +1287,18 @@ Device::recvPacket(EthPacketPtr packet)
return true; 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();
}
//===================================================================== //=====================================================================
// //
// //

View file

@ -266,6 +266,7 @@ class Device : public Base
public: public:
virtual Tick read(Packet *pkt); virtual Tick read(Packet *pkt);
virtual Tick write(Packet *pkt); virtual Tick write(Packet *pkt);
virtual void resume();
void prepareIO(int cpu, int index); void prepareIO(int cpu, int index);
void prepareRead(int cpu, int index); void prepareRead(int cpu, int index);

View file

@ -547,8 +547,7 @@ class SimObject(object):
count = 0 count = 0
# ParamContexts don't serialize # ParamContexts don't serialize
if isinstance(self, SimObject) and not isinstance(self, ParamContext): if isinstance(self, SimObject) and not isinstance(self, ParamContext):
if not self._ccObject.drain(drain_event): count += self._ccObject.drain(drain_event)
count = 1
if recursive: if recursive:
for child in self._children.itervalues(): for child in self._children.itervalues():
count += child.startDrain(drain_event, True) count += child.startDrain(drain_event, True)
@ -561,7 +560,7 @@ class SimObject(object):
child.resume() child.resume()
def changeTiming(self, mode): def changeTiming(self, mode):
if isinstance(self, SimObject) and not isinstance(self, ParamContext): if isinstance(self, System):
self._ccObject.setMemoryMode(mode) self._ccObject.setMemoryMode(mode)
for child in self._children.itervalues(): for child in self._children.itervalues():
child.changeTiming(mode) child.changeTiming(mode)

View file

@ -182,7 +182,7 @@ options = attrdict()
arguments = [] arguments = []
def usage(exitcode=None): def usage(exitcode=None):
print parser.help parser.print_help()
if exitcode is not None: if exitcode is not None:
sys.exit(exitcode) sys.exit(exitcode)

View file

@ -6,10 +6,10 @@ class BaseCPU(SimObject):
abstract = True abstract = True
mem = Param.MemObject("memory") mem = Param.MemObject("memory")
system = Param.System(Parent.any, "system object")
if build_env['FULL_SYSTEM']: if build_env['FULL_SYSTEM']:
dtb = Param.AlphaDTB("Data TLB") dtb = Param.AlphaDTB("Data TLB")
itb = Param.AlphaITB("Instruction TLB") itb = Param.AlphaITB("Instruction TLB")
system = Param.System(Parent.any, "system object")
cpu_id = Param.Int(-1, "CPU identifier") cpu_id = Param.Int(-1, "CPU identifier")
else: else:
workload = VectorParam.Process("processes to run") workload = VectorParam.Process("processes to run")

View file

@ -1,9 +1,12 @@
from m5 import build_env from m5 import build_env
from m5.config import * from m5.config import *
class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing']
class System(SimObject): class System(SimObject):
type = 'System' type = 'System'
physmem = Param.PhysicalMemory(Parent.any, "phsyical memory") physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
if build_env['FULL_SYSTEM']: if build_env['FULL_SYSTEM']:
boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency, boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
"boot processor frequency") "boot processor frequency")

View file

@ -72,7 +72,7 @@ SimObject::SimObject(Params *p)
doRecordEvent = !Stats::event_ignore.match(name()); doRecordEvent = !Stats::event_ignore.match(name());
simObjectList.push_back(this); simObjectList.push_back(this);
state = Atomic; state = Running;
} }
// //
@ -88,7 +88,7 @@ SimObject::SimObject(const string &_name)
doRecordEvent = !Stats::event_ignore.match(name()); doRecordEvent = !Stats::event_ignore.match(name());
simObjectList.push_back(this); simObjectList.push_back(this);
state = Atomic; state = Running;
} }
void void
@ -269,38 +269,23 @@ SimObject::recordEvent(const std::string &stat)
Stats::recordEvent(stat); Stats::recordEvent(stat);
} }
bool unsigned int
SimObject::drain(Event *drain_event) SimObject::drain(Event *drain_event)
{ {
if (state != DrainedAtomic && state != Atomic) { state = Drained;
panic("Must implement your own drain function if it is to be used " return 0;
"in timing mode!");
}
state = DrainedAtomic;
return true;
} }
void void
SimObject::resume() SimObject::resume()
{ {
if (state == DrainedAtomic) { state = Running;
state = Atomic;
} else if (state == DrainedTiming) {
state = Timing;
}
} }
void void
SimObject::setMemoryMode(State new_mode) SimObject::setMemoryMode(State new_mode)
{ {
assert(new_mode == Timing || new_mode == Atomic); panic("setMemoryMode() should only be called on systems");
if (state == DrainedAtomic && new_mode == Timing) {
state = DrainedTiming;
} else if (state == DrainedTiming && new_mode == Atomic) {
state = DrainedAtomic;
} else {
state = new_mode;
}
} }
void void

View file

@ -60,16 +60,15 @@ class SimObject : public Serializable, protected StartupCallback
}; };
enum State { enum State {
Atomic, Running,
Timing,
Draining, Draining,
DrainedAtomic, Drained
DrainedTiming
}; };
private:
State state;
protected: protected:
Params *_params; Params *_params;
State state;
void changeState(State new_state) { state = new_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 // Methods to drain objects in order to take checkpoints
// Or switch from timing -> atomic memory model // Or switch from timing -> atomic memory model
// Drain returns false if the SimObject cannot drain immediately. // Drain returns 0 if the simobject can drain immediately or
virtual bool drain(Event *drain_event); // 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 resume();
virtual void setMemoryMode(State new_mode); virtual void setMemoryMode(State new_mode);
virtual void switchOut(); virtual void switchOut();

View file

@ -63,7 +63,7 @@ System::System(Params *p)
#else #else
page_ptr(0), page_ptr(0),
#endif #endif
_params(p) memoryMode(p->mem_mode), _params(p)
{ {
// add self to global system list // add self to global system list
systemList.push_back(this); systemList.push_back(this);
@ -143,6 +143,14 @@ int rgdb_wait = -1;
#endif // FULL_SYSTEM #endif // FULL_SYSTEM
void
System::setMemoryMode(MemoryMode mode)
{
assert(getState() == Drained);
memoryMode = mode;
}
int int
System::registerThreadContext(ThreadContext *tc, int id) System::registerThreadContext(ThreadContext *tc, int id)
{ {
@ -249,6 +257,9 @@ printSystems()
System::printSystems(); System::printSystems();
} }
const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
"timing"};
#if FULL_SYSTEM #if FULL_SYSTEM
// In full system mode, only derived classes (e.g. AlphaLinuxSystem) // 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) BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
SimObjectParam<PhysicalMemory *> physmem; SimObjectParam<PhysicalMemory *> physmem;
SimpleEnumParam<System::MemoryMode> mem_mode;
END_DECLARE_SIM_OBJECT_PARAMS(System) END_DECLARE_SIM_OBJECT_PARAMS(System)
BEGIN_INIT_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) END_INIT_SIM_OBJECT_PARAMS(System)
@ -275,6 +289,7 @@ CREATE_SIM_OBJECT(System)
System::Params *p = new System::Params; System::Params *p = new System::Params;
p->name = getInstanceName(); p->name = getInstanceName();
p->physmem = physmem; p->physmem = physmem;
p->mem_mode = mem_mode;
return new System(p); return new System(p);
} }

View file

@ -61,6 +61,23 @@ class RemoteGDB;
class System : public SimObject class System : public SimObject
{ {
public: 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; PhysicalMemory *physmem;
PCEventQueue pcEventQueue; PCEventQueue pcEventQueue;
@ -108,6 +125,8 @@ class System : public SimObject
protected: protected:
MemoryMode memoryMode;
#if FULL_SYSTEM #if FULL_SYSTEM
/** /**
* Fix up an address used to match PCs for hooking simulator * Fix up an address used to match PCs for hooking simulator
@ -153,6 +172,7 @@ class System : public SimObject
{ {
std::string name; std::string name;
PhysicalMemory *physmem; PhysicalMemory *physmem;
MemoryMode mem_mode;
#if FULL_SYSTEM #if FULL_SYSTEM
Tick boot_cpu_frequency; Tick boot_cpu_frequency;