Merge ktlim@zizzer:/bk/newmem

into  zamp.eecs.umich.edu:/z/ktlim2/clean/newmem-merge

configs/test/fs.py:
configs/test/test.py:
    SCCS merged

--HG--
extra : convert_revision : 7b2dbcd5881fac01dec38001c4131e73b5be52b5
This commit is contained in:
Kevin Lim 2006-07-14 17:54:43 -04:00
commit 31ac8e7337
42 changed files with 528 additions and 299 deletions

View file

@ -2,41 +2,39 @@ import os, sys
from os.path import isdir, join as joinpath
from os 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

View file

@ -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:

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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)
{

View file

@ -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);

View file

@ -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();

View file

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

View file

@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
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;

View file

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

View file

@ -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();

View file

@ -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;

View file

@ -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");

View file

@ -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>

View file

@ -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);
}

View file

@ -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)

View file

@ -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, "

View file

@ -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

View file

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

View file

@ -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"

View file

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

View file

@ -137,9 +137,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
virtual bool drain(Event *drain_event);
virtual unsigned int drain(Event *drain_event);
virtual void resume();
virtual void setMemoryMode(State new_mode);
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);

View file

@ -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()) {

View file

@ -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()

View file

@ -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;

View file

@ -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();
}
//=====================================================================
//
//

View file

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

View file

@ -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)
{

View file

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

View file

@ -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();
}
//=====================================================================
//
//

View file

@ -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);

View file

@ -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)

View file

@ -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)

View file

@ -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")

View file

@ -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")

View file

@ -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

View file

@ -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();

View file

@ -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);
}

View file

@ -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;