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:
commit
31ac8e7337
42 changed files with 528 additions and 299 deletions
|
@ -2,41 +2,39 @@ import os, sys
|
|||
from os.path import isdir, join as joinpath
|
||||
from os import environ as env
|
||||
|
||||
systemdir = None
|
||||
bindir = None
|
||||
diskdir = None
|
||||
scriptdir = None
|
||||
def disk(file):
|
||||
system()
|
||||
return joinpath(disk.dir, file)
|
||||
|
||||
def load_defaults():
|
||||
global systemdir, bindir, diskdir, scriptdir
|
||||
if not systemdir:
|
||||
def binary(file):
|
||||
system()
|
||||
return joinpath(binary.dir, file)
|
||||
|
||||
def script(file):
|
||||
system()
|
||||
return joinpath(script.dir, file)
|
||||
|
||||
def system():
|
||||
if not system.dir:
|
||||
try:
|
||||
path = env['M5_PATH'].split(':')
|
||||
except KeyError:
|
||||
path = [ '/dist/m5/system', '/n/poolfs/z/dist/m5/system' ]
|
||||
|
||||
for systemdir in path:
|
||||
if os.path.isdir(systemdir):
|
||||
for system.dir in path:
|
||||
if os.path.isdir(system.dir):
|
||||
break
|
||||
else:
|
||||
raise ImportError, "Can't find a path to system files."
|
||||
|
||||
if not bindir:
|
||||
bindir = joinpath(systemdir, 'binaries')
|
||||
if not diskdir:
|
||||
diskdir = joinpath(systemdir, 'disks')
|
||||
if not scriptdir:
|
||||
scriptdir = joinpath(systemdir, '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)
|
||||
if not binary.dir:
|
||||
binary.dir = joinpath(system.dir, 'binaries')
|
||||
if not disk.dir:
|
||||
disk.dir = joinpath(system.dir, 'disks')
|
||||
if not script.dir:
|
||||
script.dir = joinpath(system.dir, 'boot')
|
||||
|
||||
system.dir = None
|
||||
binary.dir = None
|
||||
disk.dir = None
|
||||
script.dir = None
|
||||
|
|
|
@ -22,6 +22,8 @@ if args:
|
|||
# Base for tests is directory containing this 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'))
|
||||
|
||||
class CowIdeDisk(IdeDisk):
|
||||
|
@ -65,6 +67,7 @@ class MyLinuxAlphaSystem(LinuxAlphaSystem):
|
|||
cpu = DetailedO3CPU()
|
||||
elif options.timing:
|
||||
cpu = TimingSimpleCPU()
|
||||
mem_mode = 'timing'
|
||||
else:
|
||||
cpu = AtomicSimpleCPU()
|
||||
cpu.mem = membus
|
||||
|
@ -72,6 +75,7 @@ class MyLinuxAlphaSystem(LinuxAlphaSystem):
|
|||
cpu.dcache_port = membus.port
|
||||
cpu.itb = AlphaITB()
|
||||
cpu.dtb = AlphaDTB()
|
||||
cpu.clock = '2GHz'
|
||||
sim_console = SimConsole(listener=ConsoleListener(port=3456))
|
||||
kernel = binary('vmlinux')
|
||||
pal = binary('ts_osfpal')
|
||||
|
@ -90,7 +94,7 @@ def DualRoot(clientSystem, serverSystem):
|
|||
self.etherlink = EtherLink(int1 = Parent.client.tsunami.etherint[0],
|
||||
int2 = Parent.server.tsunami.etherint[0],
|
||||
dump = Parent.etherdump)
|
||||
self.clock = '5GHz'
|
||||
self.clock = '1THz'
|
||||
return self
|
||||
|
||||
if options.dual:
|
||||
|
@ -102,6 +106,14 @@ else:
|
|||
|
||||
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:
|
||||
exit_event = m5.simulate(options.maxtick)
|
||||
else:
|
||||
|
|
|
@ -38,6 +38,11 @@ if options.detailed:
|
|||
|
||||
cpu.workload = process
|
||||
|
||||
if options.timing or options.detailed:
|
||||
system.mem_mode = 'timing'
|
||||
|
||||
|
||||
|
||||
# instantiate configuration
|
||||
m5.instantiate(root)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -45,6 +45,12 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
|
|||
panic("Copy Regs Not Implemented Yet\n");
|
||||
}
|
||||
|
||||
void
|
||||
MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
|
||||
{
|
||||
panic("Copy Misc. Regs Not Implemented Yet\n");
|
||||
}
|
||||
|
||||
void
|
||||
MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -50,6 +50,9 @@ class MipsLiveProcess : public LiveProcess
|
|||
std::vector<std::string> &envp);
|
||||
|
||||
void startup();
|
||||
|
||||
|
||||
static Addr stack_start;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
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;
|
||||
|
|
|
@ -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 §ion)
|
|||
}
|
||||
|
||||
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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -35,10 +35,54 @@
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
@ -95,46 +96,6 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr 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>
|
||||
LSQUnit<Impl>::LSQUnit()
|
||||
: loads(0), stores(0), storesToWB(0), stalled(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, "
|
||||
|
|
|
@ -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;
|
||||
|
@ -183,6 +184,13 @@ AtomicSimpleCPU::resume()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
AtomicSimpleCPU::resume()
|
||||
{
|
||||
assert(system->getMemoryMode() == System::Atomic);
|
||||
changeState(SimObject::Running);
|
||||
}
|
||||
|
||||
void
|
||||
AtomicSimpleCPU::switchOut()
|
||||
{
|
||||
|
@ -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
|
||||
|
|
|
@ -128,6 +128,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
|||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
virtual void resume();
|
||||
|
||||
virtual void resume();
|
||||
void switchOut();
|
||||
void takeOverFrom(BaseCPU *oldCPU);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 §ion)
|
|||
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
|
||||
|
|
|
@ -137,9 +137,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
|||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
// some kind of selction between access methods
|
||||
// more work is going to have to be done to make
|
||||
// switching actually work
|
||||
|
||||
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;
|
||||
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 if (state == Functional) {
|
||||
sendFunctional(pkt);
|
||||
// Is this correct???
|
||||
completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime);
|
||||
completionEvent == NULL;
|
||||
} else
|
||||
panic("Unknown memory command state.");
|
||||
*/
|
||||
}
|
||||
|
||||
DmaDevice::~DmaDevice()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -391,6 +391,8 @@ class NSGigE : public PciDev
|
|||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
virtual void resume();
|
||||
|
||||
public:
|
||||
void regStats();
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 §ion);
|
||||
|
||||
|
||||
virtual unsigned int drain(Event *de);
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1)
|
||||
{
|
||||
if (if_name == "config") {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue