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.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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
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;
|
||||||
|
|
|
@ -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);
|
||||||
unscheduleTickEvent();
|
deactivateThread(tid);
|
||||||
|
if (activeThreads.size() == 0)
|
||||||
|
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 §ion)
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 (!dcachePort->sendTiming(data_pkt)) {
|
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;
|
++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)
|
||||||
|
|
|
@ -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, "
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -128,6 +128,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
||||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
virtual void resume();
|
virtual void resume();
|
||||||
|
|
||||||
|
virtual void resume();
|
||||||
void switchOut();
|
void switchOut();
|
||||||
void takeOverFrom(BaseCPU *oldCPU);
|
void takeOverFrom(BaseCPU *oldCPU);
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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 §ion)
|
||||||
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
|
||||||
|
|
|
@ -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 §ion);
|
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 resume();
|
||||||
virtual void setMemoryMode(State new_mode);
|
|
||||||
|
|
||||||
void switchOut();
|
void switchOut();
|
||||||
void takeOverFrom(BaseCPU *oldCPU);
|
void takeOverFrom(BaseCPU *oldCPU);
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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,13 +70,23 @@ 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))
|
||||||
return;
|
if (port->transmitList.size() == 0 && port->drainEvent) {
|
||||||
|
port->drainEvent->process();
|
||||||
|
port->drainEvent = NULL;
|
||||||
|
}
|
||||||
|
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,51 +277,54 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
|
||||||
pendingCount++;
|
pendingCount++;
|
||||||
sendDma(pkt);
|
sendDma(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DmaPort::sendDma(Packet *pkt, bool front)
|
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();
|
||||||
DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
|
if (state == System::Timing) {
|
||||||
pkt, pkt->getAddr());
|
DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
|
||||||
if (transmitList.size() || !sendTiming(pkt)) {
|
pkt, pkt->getAddr());
|
||||||
if (front)
|
if (transmitList.size() || !sendTiming(pkt)) {
|
||||||
transmitList.push_front(pkt);
|
if (front)
|
||||||
else
|
transmitList.push_front(pkt);
|
||||||
transmitList.push_back(pkt);
|
else
|
||||||
DPRINTF(DMA, "-- Failed: queued\n");
|
transmitList.push_back(pkt);
|
||||||
} else {
|
DPRINTF(DMA, "-- Failed: queued\n");
|
||||||
DPRINTF(DMA, "-- Done\n");
|
} else {
|
||||||
}
|
DPRINTF(DMA, "-- Done\n");
|
||||||
/* } else if (state == Atomic) {
|
}
|
||||||
sendAtomic(pkt);
|
} else if (state == System::Atomic) {
|
||||||
if (pkt->senderState) {
|
Tick lat;
|
||||||
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
lat = sendAtomic(pkt);
|
||||||
assert(state);
|
assert(pkt->senderState);
|
||||||
state->completionEvent->schedule(curTick + (pkt->time -
|
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||||
pkt->req->getTime()) +1);
|
assert(state);
|
||||||
delete state;
|
|
||||||
}
|
state->numBytes += pkt->req->getSize();
|
||||||
pendingCount--;
|
if (state->totBytes == state->numBytes) {
|
||||||
assert(pendingCount >= 0);
|
state->completionEvent->schedule(curTick + lat);
|
||||||
delete pkt->req;
|
delete state;
|
||||||
delete pkt;
|
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
|
} else
|
||||||
panic("Unknown memory command state.");
|
panic("Unknown memory command state.");
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DmaDevice::~DmaDevice()
|
DmaDevice::~DmaDevice()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -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 §ion);
|
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
|
|
||||||
|
virtual void resume();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void regStats();
|
void regStats();
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 §ion);
|
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)
|
virtual Port *getPort(const std::string &if_name, int idx = -1)
|
||||||
{
|
{
|
||||||
if (if_name == "config") {
|
if (if_name == "config") {
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
//=====================================================================
|
//=====================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue