Merge stever@zizzer:/bk/m5 into isabel.reinhardt.house:/z/stever/bk/m5
--HG-- extra : convert_revision : b0f93bd35d767fd3a520a9fed70a71d40b0056db
This commit is contained in:
commit
cc9a838f4c
18 changed files with 339 additions and 171 deletions
|
@ -44,9 +44,9 @@ AlphaISA::swap_palshadow(RegFile *regs, bool use_shadow)
|
||||||
// Machine dependent functions
|
// Machine dependent functions
|
||||||
//
|
//
|
||||||
void
|
void
|
||||||
AlphaISA::init(void *mem, RegFile *regs)
|
AlphaISA::initCPU(RegFile *regs)
|
||||||
{
|
{
|
||||||
ipr_init(mem, regs);
|
initIPRs(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -91,7 +91,7 @@ const int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = {
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
void
|
void
|
||||||
AlphaISA::ipr_init(void *mem, RegFile *regs)
|
AlphaISA::initIPRs(RegFile *regs)
|
||||||
{
|
{
|
||||||
uint64_t *ipr = regs->ipr;
|
uint64_t *ipr = regs->ipr;
|
||||||
|
|
||||||
|
|
|
@ -511,14 +511,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
|
|
||||||
case OSF::GSI_MAX_CPU: {
|
case OSF::GSI_MAX_CPU: {
|
||||||
TypedBufferArg<uint32_t> max_cpu(getArg(xc, 1));
|
TypedBufferArg<uint32_t> max_cpu(getArg(xc, 1));
|
||||||
*max_cpu = process->numCpus;
|
*max_cpu = process->numCpus();
|
||||||
max_cpu.copyOut(xc->mem);
|
max_cpu.copyOut(xc->mem);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OSF::GSI_CPUS_IN_BOX: {
|
case OSF::GSI_CPUS_IN_BOX: {
|
||||||
TypedBufferArg<uint32_t> cpus_in_box(getArg(xc, 1));
|
TypedBufferArg<uint32_t> cpus_in_box(getArg(xc, 1));
|
||||||
*cpus_in_box = process->numCpus;
|
*cpus_in_box = process->numCpus();
|
||||||
cpus_in_box.copyOut(xc->mem);
|
cpus_in_box.copyOut(xc->mem);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -534,10 +534,10 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
TypedBufferArg<OSF::cpu_info> infop(getArg(xc, 1));
|
TypedBufferArg<OSF::cpu_info> infop(getArg(xc, 1));
|
||||||
|
|
||||||
infop->current_cpu = 0;
|
infop->current_cpu = 0;
|
||||||
infop->cpus_in_box = process->numCpus;
|
infop->cpus_in_box = process->numCpus();
|
||||||
infop->cpu_type = 57;
|
infop->cpu_type = 57;
|
||||||
infop->ncpus = process->numCpus;
|
infop->ncpus = process->numCpus();
|
||||||
int cpumask = (1 << process->numCpus) - 1;
|
int cpumask = (1 << process->numCpus()) - 1;
|
||||||
infop->cpus_present = infop->cpus_running = cpumask;
|
infop->cpus_present = infop->cpus_running = cpumask;
|
||||||
infop->cpu_binding = 0;
|
infop->cpu_binding = 0;
|
||||||
infop->cpu_ex_binding = 0;
|
infop->cpu_ex_binding = 0;
|
||||||
|
@ -743,7 +743,7 @@ tableFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
elp->si_hz = clk_hz;
|
elp->si_hz = clk_hz;
|
||||||
elp->si_phz = clk_hz;
|
elp->si_phz = clk_hz;
|
||||||
elp->si_boottime = seconds_since_epoch; // seconds since epoch?
|
elp->si_boottime = seconds_since_epoch; // seconds since epoch?
|
||||||
elp->si_max_procs = process->numCpus;
|
elp->si_max_procs = process->numCpus();
|
||||||
elp.copyOut(xc->mem);
|
elp.copyOut(xc->mem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1141,20 +1141,20 @@ nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
cur_addr += sizeof(OSF::nxm_config_info);
|
cur_addr += sizeof(OSF::nxm_config_info);
|
||||||
// next comes the per-cpu state vector
|
// next comes the per-cpu state vector
|
||||||
Addr slot_state_addr = cur_addr;
|
Addr slot_state_addr = cur_addr;
|
||||||
int slot_state_size = process->numCpus * sizeof(OSF::nxm_slot_state_t);
|
int slot_state_size = process->numCpus() * sizeof(OSF::nxm_slot_state_t);
|
||||||
cur_addr += slot_state_size;
|
cur_addr += slot_state_size;
|
||||||
// now the per-RAD state struct (we only support one RAD)
|
// now the per-RAD state struct (we only support one RAD)
|
||||||
cur_addr = 0x14000; // bump up addr for alignment
|
cur_addr = 0x14000; // bump up addr for alignment
|
||||||
Addr rad_state_addr = cur_addr;
|
Addr rad_state_addr = cur_addr;
|
||||||
int rad_state_size =
|
int rad_state_size =
|
||||||
(sizeof(OSF::nxm_shared)
|
(sizeof(OSF::nxm_shared)
|
||||||
+ (process->numCpus-1) * sizeof(OSF::nxm_sched_state));
|
+ (process->numCpus()-1) * sizeof(OSF::nxm_sched_state));
|
||||||
cur_addr += rad_state_size;
|
cur_addr += rad_state_size;
|
||||||
|
|
||||||
// now initialize a config_info struct and copy it out to user space
|
// now initialize a config_info struct and copy it out to user space
|
||||||
TypedBufferArg<OSF::nxm_config_info> config(config_addr);
|
TypedBufferArg<OSF::nxm_config_info> config(config_addr);
|
||||||
|
|
||||||
config->nxm_nslots_per_rad = process->numCpus;
|
config->nxm_nslots_per_rad = process->numCpus();
|
||||||
config->nxm_nrads = 1; // only one RAD in our system!
|
config->nxm_nrads = 1; // only one RAD in our system!
|
||||||
config->nxm_slot_state = slot_state_addr;
|
config->nxm_slot_state = slot_state_addr;
|
||||||
config->nxm_rad[0] = rad_state_addr;
|
config->nxm_rad[0] = rad_state_addr;
|
||||||
|
@ -1164,7 +1164,7 @@ nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
// initialize the slot_state array and copy it out
|
// initialize the slot_state array and copy it out
|
||||||
TypedBufferArg<OSF::nxm_slot_state_t> slot_state(slot_state_addr,
|
TypedBufferArg<OSF::nxm_slot_state_t> slot_state(slot_state_addr,
|
||||||
slot_state_size);
|
slot_state_size);
|
||||||
for (int i = 0; i < process->numCpus; ++i) {
|
for (int i = 0; i < process->numCpus(); ++i) {
|
||||||
// CPU 0 is bound to the calling process; all others are available
|
// CPU 0 is bound to the calling process; all others are available
|
||||||
slot_state[i] = (i == 0) ? OSF::NXM_SLOT_BOUND : OSF::NXM_SLOT_AVAIL;
|
slot_state[i] = (i == 0) ? OSF::NXM_SLOT_BOUND : OSF::NXM_SLOT_AVAIL;
|
||||||
}
|
}
|
||||||
|
@ -1180,7 +1180,7 @@ nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
rad_state->nxm_callback = attrp->nxm_callback;
|
rad_state->nxm_callback = attrp->nxm_callback;
|
||||||
rad_state->nxm_version = attrp->nxm_version;
|
rad_state->nxm_version = attrp->nxm_version;
|
||||||
rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
|
rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
|
||||||
for (int i = 0; i < process->numCpus; ++i) {
|
for (int i = 0; i < process->numCpus(); ++i) {
|
||||||
OSF::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
|
OSF::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
|
||||||
ssp->nxm_u.sigmask = 0;
|
ssp->nxm_u.sigmask = 0;
|
||||||
ssp->nxm_u.sig = 0;
|
ssp->nxm_u.sig = 0;
|
||||||
|
@ -1250,7 +1250,7 @@ nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread_index < 0 | thread_index > process->numCpus) {
|
if (thread_index < 0 | thread_index > process->numCpus()) {
|
||||||
cerr << "nxm_thread_create: bad thread index " << thread_index
|
cerr << "nxm_thread_create: bad thread index " << thread_index
|
||||||
<< endl;
|
<< endl;
|
||||||
abort();
|
abort();
|
||||||
|
@ -1262,7 +1262,7 @@ nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
// back out again.
|
// back out again.
|
||||||
int rad_state_size =
|
int rad_state_size =
|
||||||
(sizeof(OSF::nxm_shared) +
|
(sizeof(OSF::nxm_shared) +
|
||||||
(process->numCpus-1) * sizeof(OSF::nxm_sched_state));
|
(process->numCpus()-1) * sizeof(OSF::nxm_sched_state));
|
||||||
|
|
||||||
TypedBufferArg<OSF::nxm_shared> rad_state(0x14000,
|
TypedBufferArg<OSF::nxm_shared> rad_state(0x14000,
|
||||||
rad_state_size);
|
rad_state_size);
|
||||||
|
@ -1294,7 +1294,7 @@ nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
rad_state.copyOut(xc->mem);
|
rad_state.copyOut(xc->mem);
|
||||||
|
|
||||||
Addr slot_state_addr = 0x12000 + sizeof(OSF::nxm_config_info);
|
Addr slot_state_addr = 0x12000 + sizeof(OSF::nxm_config_info);
|
||||||
int slot_state_size = process->numCpus * sizeof(OSF::nxm_slot_state_t);
|
int slot_state_size = process->numCpus() * sizeof(OSF::nxm_slot_state_t);
|
||||||
|
|
||||||
TypedBufferArg<OSF::nxm_slot_state_t> slot_state(slot_state_addr,
|
TypedBufferArg<OSF::nxm_slot_state_t> slot_state(slot_state_addr,
|
||||||
slot_state_size);
|
slot_state_size);
|
||||||
|
@ -1312,11 +1312,8 @@ nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
|
||||||
slot_state.copyOut(xc->mem);
|
slot_state.copyOut(xc->mem);
|
||||||
|
|
||||||
// Find a free simulator execution context.
|
// Find a free simulator execution context.
|
||||||
list<ExecContext *> &ecList = process->execContexts;
|
for (int i = 0; i < process->numCpus(); ++i) {
|
||||||
list<ExecContext *>::iterator i = ecList.begin();
|
ExecContext *xc = process->execContexts[i];
|
||||||
list<ExecContext *>::iterator end = ecList.end();
|
|
||||||
for (; i != end; ++i) {
|
|
||||||
ExecContext *xc = *i;
|
|
||||||
|
|
||||||
if (xc->status() == ExecContext::Unallocated) {
|
if (xc->status() == ExecContext::Unallocated) {
|
||||||
// inactive context... grab it
|
// inactive context... grab it
|
||||||
|
|
|
@ -217,8 +217,11 @@ bool
|
||||||
IniFile::Section::add(const std::string &assignment)
|
IniFile::Section::add(const std::string &assignment)
|
||||||
{
|
{
|
||||||
string::size_type offset = assignment.find('=');
|
string::size_type offset = assignment.find('=');
|
||||||
if (offset == string::npos) // no '=' found
|
if (offset == string::npos) {
|
||||||
|
// no '=' found
|
||||||
|
cerr << "Can't parse .ini line " << assignment << endl;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// if "+=" rather than just "=" then append value
|
// if "+=" rather than just "=" then append value
|
||||||
bool append = (assignment[offset-1] == '+');
|
bool append = (assignment[offset-1] == '+');
|
||||||
|
|
|
@ -90,6 +90,8 @@ class RemoteGDB
|
||||||
RemoteGDB(System *system, ExecContext *context);
|
RemoteGDB(System *system, ExecContext *context);
|
||||||
~RemoteGDB();
|
~RemoteGDB();
|
||||||
|
|
||||||
|
void replaceExecContext(ExecContext *xc) { context = xc; }
|
||||||
|
|
||||||
void attach(int fd);
|
void attach(int fd);
|
||||||
void detach();
|
void detach();
|
||||||
bool isattached();
|
bool isattached();
|
||||||
|
|
|
@ -846,7 +846,7 @@ DistDisplay(ostream &stream, const string &name, const string &desc,
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
if (flags & nozero && vec[i] == 0.0 ||
|
if (flags & nozero && vec[i] == 0.0 ||
|
||||||
flags & nonan && isnan(vec[i]))
|
flags & nonan && isnan(vec[i]))
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
_min = i * bucket_size + min;
|
_min = i * bucket_size + min;
|
||||||
_pdf = vec[i] / total * 100.0;
|
_pdf = vec[i] / total * 100.0;
|
||||||
|
|
|
@ -52,8 +52,8 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
|
||||||
Counter max_insts_all_threads,
|
Counter max_insts_all_threads,
|
||||||
Counter max_loads_any_thread,
|
Counter max_loads_any_thread,
|
||||||
Counter max_loads_all_threads,
|
Counter max_loads_all_threads,
|
||||||
System *_system, int num, Tick freq)
|
System *_system, Tick freq)
|
||||||
: SimObject(_name), number(num), frequency(freq),
|
: SimObject(_name), frequency(freq),
|
||||||
number_of_threads(_number_of_threads), system(_system)
|
number_of_threads(_number_of_threads), system(_system)
|
||||||
#else
|
#else
|
||||||
BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
|
BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
|
||||||
|
@ -120,27 +120,73 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
|
||||||
max_loads_all_threads, *counter);
|
max_loads_all_threads, *counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
memset(interrupts, 0, sizeof(interrupts));
|
memset(interrupts, 0, sizeof(interrupts));
|
||||||
intstatus = 0;
|
intstatus = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseCPU::regStats()
|
BaseCPU::regStats()
|
||||||
{
|
{
|
||||||
int size = contexts.size();
|
int size = execContexts.size();
|
||||||
if (size > 1) {
|
if (size > 1) {
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
stringstream namestr;
|
stringstream namestr;
|
||||||
ccprintf(namestr, "%s.ctx%d", name(), i);
|
ccprintf(namestr, "%s.ctx%d", name(), i);
|
||||||
contexts[i]->regStats(namestr.str());
|
execContexts[i]->regStats(namestr.str());
|
||||||
}
|
}
|
||||||
} else if (size == 1)
|
} else if (size == 1)
|
||||||
contexts[0]->regStats(name());
|
execContexts[0]->regStats(name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseCPU::registerExecContexts()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < execContexts.size(); ++i) {
|
||||||
|
ExecContext *xc = execContexts[i];
|
||||||
|
int cpu_id;
|
||||||
|
|
||||||
|
#ifdef FULL_SYSTEM
|
||||||
|
cpu_id = system->registerExecContext(xc);
|
||||||
|
#else
|
||||||
|
cpu_id = xc->process->registerExecContext(xc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xc->cpu_id = cpu_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseCPU::switchOut()
|
||||||
|
{
|
||||||
|
// default: do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BaseCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
|
{
|
||||||
|
assert(execContexts.size() == oldCPU->execContexts.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < execContexts.size(); ++i) {
|
||||||
|
ExecContext *newXC = execContexts[i];
|
||||||
|
ExecContext *oldXC = oldCPU->execContexts[i];
|
||||||
|
|
||||||
|
newXC->takeOverFrom(oldXC);
|
||||||
|
assert(newXC->cpu_id == oldXC->cpu_id);
|
||||||
|
#ifdef FULL_SYSTEM
|
||||||
|
system->replaceExecContext(newXC->cpu_id, newXC);
|
||||||
|
#else
|
||||||
|
assert(newXC->process == oldXC->process);
|
||||||
|
newXC->process->replaceExecContext(newXC->cpu_id, newXC);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
void
|
void
|
||||||
BaseCPU::post_interrupt(int int_num, int index)
|
BaseCPU::post_interrupt(int int_num, int index)
|
||||||
|
@ -185,4 +231,10 @@ BaseCPU::clear_interrupts()
|
||||||
|
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
|
|
||||||
|
//
|
||||||
|
// This declaration is not needed now that SamplingCPU provides a
|
||||||
|
// BaseCPUBuilder object.
|
||||||
|
//
|
||||||
|
#if 0
|
||||||
DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
|
DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
|
||||||
|
#endif
|
||||||
|
|
|
@ -47,7 +47,6 @@ class BaseCPU : public SimObject
|
||||||
{
|
{
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
protected:
|
protected:
|
||||||
int number;
|
|
||||||
Tick frequency;
|
Tick frequency;
|
||||||
uint8_t interrupts[NumInterruptLevels];
|
uint8_t interrupts[NumInterruptLevels];
|
||||||
uint64_t intstatus;
|
uint64_t intstatus;
|
||||||
|
@ -71,7 +70,7 @@ class BaseCPU : public SimObject
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<ExecContext *> contexts;
|
std::vector<ExecContext *> execContexts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void execCtxStatusChg() {}
|
virtual void execCtxStatusChg() {}
|
||||||
|
@ -82,8 +81,7 @@ class BaseCPU : public SimObject
|
||||||
BaseCPU(const std::string &_name, int _number_of_threads,
|
BaseCPU(const std::string &_name, int _number_of_threads,
|
||||||
Counter max_insts_any_thread, Counter max_insts_all_threads,
|
Counter max_insts_any_thread, Counter max_insts_all_threads,
|
||||||
Counter max_loads_any_thread, Counter max_loads_all_threads,
|
Counter max_loads_any_thread, Counter max_loads_all_threads,
|
||||||
System *_system,
|
System *_system, Tick freq);
|
||||||
int num, Tick freq);
|
|
||||||
#else
|
#else
|
||||||
BaseCPU(const std::string &_name, int _number_of_threads,
|
BaseCPU(const std::string &_name, int _number_of_threads,
|
||||||
Counter max_insts_any_thread = 0,
|
Counter max_insts_any_thread = 0,
|
||||||
|
@ -96,6 +94,16 @@ class BaseCPU : public SimObject
|
||||||
|
|
||||||
virtual void regStats();
|
virtual void regStats();
|
||||||
|
|
||||||
|
virtual void registerExecContexts();
|
||||||
|
|
||||||
|
/// Prepare for another CPU to take over execution. Called by
|
||||||
|
/// takeOverFrom() on its argument.
|
||||||
|
virtual void switchOut();
|
||||||
|
|
||||||
|
/// Take over execution from the given CPU. Used for warm-up and
|
||||||
|
/// sampling.
|
||||||
|
virtual void takeOverFrom(BaseCPU *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of threads we're actually simulating (<= SMT_MAX_THREADS).
|
* Number of threads we're actually simulating (<= SMT_MAX_THREADS).
|
||||||
* This is a constant for the duration of the simulation.
|
* This is a constant for the duration of the simulation.
|
||||||
|
|
|
@ -43,42 +43,62 @@ using namespace std;
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
|
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
|
||||||
AlphaItb *_itb, AlphaDtb *_dtb,
|
AlphaItb *_itb, AlphaDtb *_dtb,
|
||||||
FunctionalMemory *_mem, int _cpu_id)
|
FunctionalMemory *_mem)
|
||||||
: kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num), mem(_mem),
|
: kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num),
|
||||||
itb(_itb), dtb(_dtb), cpu_id(_cpu_id), system(_sys),
|
cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
|
||||||
memCtrl(_sys->memCtrl), physmem(_sys->physmem)
|
memCtrl(_sys->memCtrl), physmem(_sys->physmem),
|
||||||
|
func_exe_insn(0), storeCondFailures(0)
|
||||||
{
|
{
|
||||||
memset(®s, 0, sizeof(RegFile));
|
memset(®s, 0, sizeof(RegFile));
|
||||||
_status = Active;
|
setStatus(ExecContext::Unallocated);
|
||||||
func_exe_insn = 0;
|
|
||||||
storeCondFailures = 0;
|
|
||||||
system->registerExecContext(this);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
|
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
|
||||||
Process *_process, int _asid)
|
Process *_process, int _asid)
|
||||||
: cpu(_cpu), thread_num(_thread_num), process(_process), asid (_asid)
|
: cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
|
||||||
|
process(_process), asid (_asid),
|
||||||
|
func_exe_insn(0), storeCondFailures(0)
|
||||||
{
|
{
|
||||||
|
setStatus(ExecContext::Unallocated);
|
||||||
// Register with process object. Our 'active' will be set by the
|
|
||||||
// process iff we're the initial context. Others are reserved for
|
|
||||||
// dynamically created threads.
|
|
||||||
process->registerExecContext(this);
|
|
||||||
|
|
||||||
mem = process->getMemory();
|
mem = process->getMemory();
|
||||||
|
|
||||||
func_exe_insn = 0;
|
|
||||||
storeCondFailures = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
|
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
|
||||||
FunctionalMemory *_mem, int _asid)
|
FunctionalMemory *_mem, int _asid)
|
||||||
: cpu(_cpu), thread_num(_thread_num), process(NULL), mem(_mem),
|
: cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
|
||||||
asid(_asid)
|
func_exe_insn(0), storeCondFailures(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ExecContext::takeOverFrom(ExecContext *oldContext)
|
||||||
|
{
|
||||||
|
// some things should already be set up
|
||||||
|
assert(mem == oldContext->mem);
|
||||||
|
#ifdef FULL_SYSTEM
|
||||||
|
assert(system == oldContext->system);
|
||||||
|
#else
|
||||||
|
assert(process == oldContext->process);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// copy over functional state
|
||||||
|
_status = oldContext->_status;
|
||||||
|
#ifdef FULL_SYSTEM
|
||||||
|
kernelStats = oldContext->kernelStats;
|
||||||
|
#endif
|
||||||
|
regs = oldContext->regs;
|
||||||
|
cpu_id = oldContext->cpu_id;
|
||||||
|
func_exe_insn = oldContext->func_exe_insn;
|
||||||
|
|
||||||
|
storeCondFailures = 0;
|
||||||
|
|
||||||
|
oldContext->_status = ExecContext::Unallocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ExecContext::setStatus(Status new_status)
|
ExecContext::setStatus(Status new_status)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,11 @@ class ExecContext
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Status status() const { return _status; }
|
Status status() const { return _status; }
|
||||||
|
|
||||||
|
// Unlike setStatus(), initStatus() has no side effects other than
|
||||||
|
// setting the _status variable.
|
||||||
|
void initStatus(Status init_status) { _status = init_status; }
|
||||||
|
|
||||||
void setStatus(Status new_status);
|
void setStatus(Status new_status);
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
|
@ -83,12 +88,15 @@ class ExecContext
|
||||||
// Index of hardware thread context on the CPU that this represents.
|
// Index of hardware thread context on the CPU that this represents.
|
||||||
int thread_num;
|
int thread_num;
|
||||||
|
|
||||||
|
// ID of this context w.r.t. the System or Process object to which
|
||||||
|
// it belongs. For full-system mode, this is the system CPU ID.
|
||||||
|
int cpu_id;
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
|
|
||||||
FunctionalMemory *mem;
|
FunctionalMemory *mem;
|
||||||
AlphaItb *itb;
|
AlphaItb *itb;
|
||||||
AlphaDtb *dtb;
|
AlphaDtb *dtb;
|
||||||
int cpu_id;
|
|
||||||
System *system;
|
System *system;
|
||||||
|
|
||||||
// the following two fields are redundant, since we can always
|
// the following two fields are redundant, since we can always
|
||||||
|
@ -124,8 +132,7 @@ class ExecContext
|
||||||
// constructor: initialize context from given process structure
|
// constructor: initialize context from given process structure
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
|
ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
|
||||||
AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem,
|
AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem);
|
||||||
int _cpu_id);
|
|
||||||
#else
|
#else
|
||||||
ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
|
ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
|
||||||
ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
|
ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
|
||||||
|
@ -133,6 +140,8 @@ class ExecContext
|
||||||
#endif
|
#endif
|
||||||
virtual ~ExecContext() {}
|
virtual ~ExecContext() {}
|
||||||
|
|
||||||
|
virtual void takeOverFrom(ExecContext *oldContext);
|
||||||
|
|
||||||
void regStats(const std::string &name);
|
void regStats(const std::string &name);
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
|
@ -156,7 +165,6 @@ class ExecContext
|
||||||
return dtb->translate(req, true);
|
return dtb->translate(req, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
bool validInstAddr(Addr addr)
|
bool validInstAddr(Addr addr)
|
||||||
{ return process->validInstAddr(addr); }
|
{ return process->validInstAddr(addr); }
|
||||||
|
@ -244,8 +252,8 @@ class ExecContext
|
||||||
// and all other stores (WH64?). Unsuccessful Store
|
// and all other stores (WH64?). Unsuccessful Store
|
||||||
// Conditionals would have returned above, and wouldn't fall
|
// Conditionals would have returned above, and wouldn't fall
|
||||||
// through.
|
// through.
|
||||||
for (int i = 0; i < system->xcvec.size(); i++){
|
for (int i = 0; i < system->execContexts.size(); i++){
|
||||||
cregs = &system->xcvec[i]->regs.miscRegs;
|
cregs = &system->execContexts[i]->regs.miscRegs;
|
||||||
if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
|
if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
|
||||||
cregs->lock_flag = false;
|
cregs->lock_flag = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,11 +103,11 @@ SimpleCPU::SimpleCPU(const string &_name,
|
||||||
FunctionalMemory *mem,
|
FunctionalMemory *mem,
|
||||||
MemInterface *icache_interface,
|
MemInterface *icache_interface,
|
||||||
MemInterface *dcache_interface,
|
MemInterface *dcache_interface,
|
||||||
int cpu_id, Tick freq)
|
Tick freq)
|
||||||
: BaseCPU(_name, /* number_of_threads */ 1,
|
: BaseCPU(_name, /* number_of_threads */ 1,
|
||||||
max_insts_any_thread, max_insts_all_threads,
|
max_insts_any_thread, max_insts_all_threads,
|
||||||
max_loads_any_thread, max_loads_all_threads,
|
max_loads_any_thread, max_loads_all_threads,
|
||||||
_system, cpu_id, freq),
|
_system, freq),
|
||||||
#else
|
#else
|
||||||
SimpleCPU::SimpleCPU(const string &_name, Process *_process,
|
SimpleCPU::SimpleCPU(const string &_name, Process *_process,
|
||||||
Counter max_insts_any_thread,
|
Counter max_insts_any_thread,
|
||||||
|
@ -122,61 +122,23 @@ SimpleCPU::SimpleCPU(const string &_name, Process *_process,
|
||||||
#endif
|
#endif
|
||||||
tickEvent(this), xc(NULL), cacheCompletionEvent(this)
|
tickEvent(this), xc(NULL), cacheCompletionEvent(this)
|
||||||
{
|
{
|
||||||
#ifdef FULL_SYSTEM
|
|
||||||
xc = new ExecContext(this, 0, system, itb, dtb, mem, cpu_id);
|
|
||||||
|
|
||||||
_status = Running;
|
|
||||||
if (cpu_id != 0) {
|
|
||||||
|
|
||||||
xc->setStatus(ExecContext::Unallocated);
|
|
||||||
|
|
||||||
//Open a GDB debug session on port (7000 + the cpu_id)
|
|
||||||
(new GDBListener(new RemoteGDB(system, xc), 7000 + cpu_id))->listen();
|
|
||||||
|
|
||||||
AlphaISA::init(system->physmem, &xc->regs);
|
|
||||||
|
|
||||||
fault = Reset_Fault;
|
|
||||||
|
|
||||||
IntReg *ipr = xc->regs.ipr;
|
|
||||||
ipr[TheISA::IPR_MCSR] = 0x6;
|
|
||||||
|
|
||||||
AlphaISA::swap_palshadow(&xc->regs, true);
|
|
||||||
|
|
||||||
xc->regs.pc =
|
|
||||||
ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
|
|
||||||
xc->regs.npc = xc->regs.pc + sizeof(MachInst);
|
|
||||||
|
|
||||||
_status = Idle;
|
_status = Idle;
|
||||||
}
|
#ifdef FULL_SYSTEM
|
||||||
else {
|
xc = new ExecContext(this, 0, system, itb, dtb, mem);
|
||||||
system->init(xc);
|
|
||||||
|
|
||||||
// Reset the system
|
TheISA::initCPU(&xc->regs);
|
||||||
//
|
|
||||||
AlphaISA::init(system->physmem, &xc->regs);
|
|
||||||
|
|
||||||
fault = Reset_Fault;
|
|
||||||
|
|
||||||
IntReg *ipr = xc->regs.ipr;
|
IntReg *ipr = xc->regs.ipr;
|
||||||
ipr[TheISA::IPR_MCSR] = 0x6;
|
ipr[TheISA::IPR_MCSR] = 0x6;
|
||||||
|
|
||||||
AlphaISA::swap_palshadow(&xc->regs, true);
|
AlphaISA::swap_palshadow(&xc->regs, true);
|
||||||
|
|
||||||
|
fault = Reset_Fault;
|
||||||
xc->regs.pc = ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
|
xc->regs.pc = ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
|
||||||
xc->regs.npc = xc->regs.pc + sizeof(MachInst);
|
xc->regs.npc = xc->regs.pc + sizeof(MachInst);
|
||||||
|
|
||||||
_status = Running;
|
|
||||||
tickEvent.schedule(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
xc = new ExecContext(this, /* thread_num */ 0, _process, /* asid */ 0);
|
xc = new ExecContext(this, /* thread_num */ 0, _process, /* asid */ 0);
|
||||||
fault = No_Fault;
|
fault = No_Fault;
|
||||||
if (xc->status() == ExecContext::Active) {
|
|
||||||
_status = Running;
|
|
||||||
tickEvent.schedule(0);
|
|
||||||
} else
|
|
||||||
_status = Idle;
|
|
||||||
#endif // !FULL_SYSTEM
|
#endif // !FULL_SYSTEM
|
||||||
|
|
||||||
icacheInterface = icache_interface;
|
icacheInterface = icache_interface;
|
||||||
|
@ -193,13 +155,61 @@ SimpleCPU::SimpleCPU(const string &_name, Process *_process,
|
||||||
lastIcacheStall = 0;
|
lastIcacheStall = 0;
|
||||||
lastDcacheStall = 0;
|
lastDcacheStall = 0;
|
||||||
|
|
||||||
contexts.push_back(xc);
|
execContexts.push_back(xc);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleCPU::~SimpleCPU()
|
SimpleCPU::~SimpleCPU()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SimpleCPU::registerExecContexts()
|
||||||
|
{
|
||||||
|
BaseCPU::registerExecContexts();
|
||||||
|
|
||||||
|
// if any of this CPU's ExecContexts are active, mark the CPU as
|
||||||
|
// running and schedule its tick event.
|
||||||
|
for (int i = 0; i < execContexts.size(); ++i) {
|
||||||
|
ExecContext *xc = execContexts[i];
|
||||||
|
if (xc->status() == ExecContext::Active && _status != Running) {
|
||||||
|
_status = Running;
|
||||||
|
// this should only happen at initialization time
|
||||||
|
assert(curTick == 0);
|
||||||
|
tickEvent.schedule(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SimpleCPU::switchOut()
|
||||||
|
{
|
||||||
|
_status = SwitchedOut;
|
||||||
|
if (tickEvent.scheduled())
|
||||||
|
tickEvent.squash();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SimpleCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
|
{
|
||||||
|
BaseCPU::takeOverFrom(oldCPU);
|
||||||
|
|
||||||
|
assert(!tickEvent.scheduled());
|
||||||
|
|
||||||
|
// if any of this CPU's ExecContexts are active, mark the CPU as
|
||||||
|
// running and schedule its tick event.
|
||||||
|
for (int i = 0; i < execContexts.size(); ++i) {
|
||||||
|
ExecContext *xc = execContexts[i];
|
||||||
|
if (xc->status() == ExecContext::Active && _status != Running) {
|
||||||
|
_status = Running;
|
||||||
|
tickEvent.schedule(curTick + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SimpleCPU::regStats()
|
SimpleCPU::regStats()
|
||||||
{
|
{
|
||||||
|
@ -488,6 +498,11 @@ SimpleCPU::processCacheCompletion()
|
||||||
dcacheStallCycles += curTick - lastDcacheStall;
|
dcacheStallCycles += curTick - lastDcacheStall;
|
||||||
setStatus(Running);
|
setStatus(Running);
|
||||||
break;
|
break;
|
||||||
|
case SwitchedOut:
|
||||||
|
// If this CPU has been switched out due to sampling/warm-up,
|
||||||
|
// ignore any further status changes (e.g., due to cache
|
||||||
|
// misses outstanding at the time of the switch).
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
panic("SimpleCPU::processCacheCompletion: bad state");
|
panic("SimpleCPU::processCacheCompletion: bad state");
|
||||||
break;
|
break;
|
||||||
|
@ -693,7 +708,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
|
||||||
SimObjectParam<AlphaDtb *> dtb;
|
SimObjectParam<AlphaDtb *> dtb;
|
||||||
SimObjectParam<FunctionalMemory *> mem;
|
SimObjectParam<FunctionalMemory *> mem;
|
||||||
SimObjectParam<System *> system;
|
SimObjectParam<System *> system;
|
||||||
Param<int> cpu_id;
|
|
||||||
Param<int> mult;
|
Param<int> mult;
|
||||||
#else
|
#else
|
||||||
SimObjectParam<Process *> workload;
|
SimObjectParam<Process *> workload;
|
||||||
|
@ -702,6 +716,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
|
||||||
SimObjectParam<BaseMem *> icache;
|
SimObjectParam<BaseMem *> icache;
|
||||||
SimObjectParam<BaseMem *> dcache;
|
SimObjectParam<BaseMem *> dcache;
|
||||||
|
|
||||||
|
Param<bool> defer_registration;
|
||||||
|
|
||||||
END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
|
END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
|
||||||
|
|
||||||
BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
|
BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
|
||||||
|
@ -724,39 +740,47 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
|
||||||
INIT_PARAM(dtb, "Data TLB"),
|
INIT_PARAM(dtb, "Data TLB"),
|
||||||
INIT_PARAM(mem, "memory"),
|
INIT_PARAM(mem, "memory"),
|
||||||
INIT_PARAM(system, "system object"),
|
INIT_PARAM(system, "system object"),
|
||||||
INIT_PARAM_DFLT(cpu_id, "CPU identification number", 0),
|
|
||||||
INIT_PARAM_DFLT(mult, "system clock multiplier", 1),
|
INIT_PARAM_DFLT(mult, "system clock multiplier", 1),
|
||||||
#else
|
#else
|
||||||
INIT_PARAM(workload, "processes to run"),
|
INIT_PARAM(workload, "processes to run"),
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
|
|
||||||
INIT_PARAM_DFLT(icache, "L1 instruction cache object", NULL),
|
INIT_PARAM_DFLT(icache, "L1 instruction cache object", NULL),
|
||||||
INIT_PARAM_DFLT(dcache, "L1 data cache object", NULL)
|
INIT_PARAM_DFLT(dcache, "L1 data cache object", NULL),
|
||||||
|
INIT_PARAM_DFLT(defer_registration, "defer registration with system "
|
||||||
|
"(for sampling)", false)
|
||||||
|
|
||||||
END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
|
END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
|
||||||
|
|
||||||
|
|
||||||
CREATE_SIM_OBJECT(SimpleCPU)
|
CREATE_SIM_OBJECT(SimpleCPU)
|
||||||
{
|
{
|
||||||
|
SimpleCPU *cpu;
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
if (mult != 1)
|
if (mult != 1)
|
||||||
panic("processor clock multiplier must be 1\n");
|
panic("processor clock multiplier must be 1\n");
|
||||||
|
|
||||||
return new SimpleCPU(getInstanceName(), system,
|
cpu = new SimpleCPU(getInstanceName(), system,
|
||||||
max_insts_any_thread, max_insts_all_threads,
|
max_insts_any_thread, max_insts_all_threads,
|
||||||
max_loads_any_thread, max_loads_all_threads,
|
max_loads_any_thread, max_loads_all_threads,
|
||||||
itb, dtb, mem,
|
itb, dtb, mem,
|
||||||
(icache) ? icache->getInterface() : NULL,
|
(icache) ? icache->getInterface() : NULL,
|
||||||
(dcache) ? dcache->getInterface() : NULL,
|
(dcache) ? dcache->getInterface() : NULL,
|
||||||
cpu_id, ticksPerSecond * mult);
|
ticksPerSecond * mult);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
return new SimpleCPU(getInstanceName(), workload,
|
cpu = new SimpleCPU(getInstanceName(), workload,
|
||||||
max_insts_any_thread, max_insts_all_threads,
|
max_insts_any_thread, max_insts_all_threads,
|
||||||
max_loads_any_thread, max_loads_all_threads,
|
max_loads_any_thread, max_loads_all_threads,
|
||||||
icache->getInterface(), dcache->getInterface());
|
icache->getInterface(), dcache->getInterface());
|
||||||
|
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
|
|
||||||
|
if (!defer_registration) {
|
||||||
|
cpu->registerExecContexts();
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU)
|
REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU)
|
||||||
|
|
|
@ -92,7 +92,8 @@ class SimpleCPU : public BaseCPU
|
||||||
Idle,
|
Idle,
|
||||||
IcacheMissStall,
|
IcacheMissStall,
|
||||||
IcacheMissComplete,
|
IcacheMissComplete,
|
||||||
DcacheMissStall
|
DcacheMissStall,
|
||||||
|
SwitchedOut
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -117,7 +118,7 @@ class SimpleCPU : public BaseCPU
|
||||||
Counter max_loads_any_thread, Counter max_loads_all_threads,
|
Counter max_loads_any_thread, Counter max_loads_all_threads,
|
||||||
AlphaItb *itb, AlphaDtb *dtb, FunctionalMemory *mem,
|
AlphaItb *itb, AlphaDtb *dtb, FunctionalMemory *mem,
|
||||||
MemInterface *icache_interface, MemInterface *dcache_interface,
|
MemInterface *icache_interface, MemInterface *dcache_interface,
|
||||||
int cpu_id, Tick freq);
|
Tick freq);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -135,6 +136,11 @@ class SimpleCPU : public BaseCPU
|
||||||
// execution context
|
// execution context
|
||||||
ExecContext *xc;
|
ExecContext *xc;
|
||||||
|
|
||||||
|
void registerExecContexts();
|
||||||
|
|
||||||
|
void switchOut();
|
||||||
|
void takeOverFrom(BaseCPU *oldCPU);
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
Addr dbg_vtophys(Addr addr);
|
Addr dbg_vtophys(Addr addr);
|
||||||
|
|
||||||
|
@ -171,6 +177,7 @@ class SimpleCPU : public BaseCPU
|
||||||
CacheCompletionEvent cacheCompletionEvent;
|
CacheCompletionEvent cacheCompletionEvent;
|
||||||
|
|
||||||
Status status() const { return _status; }
|
Status status() const { return _status; }
|
||||||
|
|
||||||
virtual void execCtxStatusChg() {
|
virtual void execCtxStatusChg() {
|
||||||
if (xc) {
|
if (xc) {
|
||||||
if (xc->status() == ExecContext::Active)
|
if (xc->status() == ExecContext::Active)
|
||||||
|
@ -182,6 +189,10 @@ class SimpleCPU : public BaseCPU
|
||||||
|
|
||||||
void setStatus(Status new_status) {
|
void setStatus(Status new_status) {
|
||||||
Status old_status = status();
|
Status old_status = status();
|
||||||
|
|
||||||
|
// We should never even get here if the CPU has been switched out.
|
||||||
|
assert(old_status != SwitchedOut);
|
||||||
|
|
||||||
_status = new_status;
|
_status = new_status;
|
||||||
|
|
||||||
switch (status()) {
|
switch (status()) {
|
||||||
|
|
|
@ -153,7 +153,7 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data)
|
||||||
int cpu = val;
|
int cpu = val;
|
||||||
assert(cpu > 0 && "Must not access primary cpu");
|
assert(cpu > 0 && "Must not access primary cpu");
|
||||||
|
|
||||||
ExecContext *other_xc = req->xc->system->xcvec[cpu];
|
ExecContext *other_xc = req->xc->system->execContexts[cpu];
|
||||||
other_xc->regs.intRegFile[16] = cpu;
|
other_xc->regs.intRegFile[16] = cpu;
|
||||||
other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu;
|
other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu;
|
||||||
other_xc->regs.intRegFile[0] = cpu;
|
other_xc->regs.intRegFile[0] = cpu;
|
||||||
|
|
|
@ -184,24 +184,44 @@ Tru64System::~Tru64System()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
Tru64System::init(ExecContext *xc)
|
Tru64System::registerExecContext(ExecContext *xc)
|
||||||
{
|
{
|
||||||
xc->regs = *initRegs;
|
int xcIndex = System::registerExecContext(xc);
|
||||||
|
|
||||||
remoteGDB = new RemoteGDB(this, xc);
|
if (xcIndex == 0) {
|
||||||
gdbListen = new GDBListener(remoteGDB, 7000);
|
// xc->regs = *initRegs;
|
||||||
gdbListen->listen();
|
xc->initStatus(ExecContext::Active);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xc->initStatus(ExecContext::Unallocated);
|
||||||
|
}
|
||||||
|
|
||||||
// Reset the system
|
RemoteGDB *rgdb = new RemoteGDB(this, xc);
|
||||||
//
|
GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
|
||||||
TheISA::init(physmem, &xc->regs);
|
gdbl->listen();
|
||||||
|
|
||||||
|
if (remoteGDB.size() <= xcIndex) {
|
||||||
|
remoteGDB.resize(xcIndex+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteGDB[xcIndex] = rgdb;
|
||||||
|
|
||||||
|
return xcIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Tru64System::replaceExecContext(ExecContext *xc, int xcIndex)
|
||||||
|
{
|
||||||
|
System::replaceExecContext(xcIndex, xc);
|
||||||
|
remoteGDB[xcIndex]->replaceExecContext(xc);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Tru64System::breakpoint()
|
Tru64System::breakpoint()
|
||||||
{
|
{
|
||||||
return remoteGDB->trap(ALPHA_KENTRY_IF);
|
return remoteGDB[0]->trap(ALPHA_KENTRY_IF);
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
|
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#ifndef __TRU64_SYSTEM_HH__
|
#ifndef __TRU64_SYSTEM_HH__
|
||||||
#define __TRU64_SYSTEM_HH__
|
#define __TRU64_SYSTEM_HH__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
#include "targetarch/isa_traits.hh"
|
#include "targetarch/isa_traits.hh"
|
||||||
|
|
||||||
|
@ -48,8 +50,6 @@ class AlphaArguments;
|
||||||
class Tru64System : public System
|
class Tru64System : public System
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
ExecContext *xc;
|
|
||||||
|
|
||||||
EcoffObject *kernel;
|
EcoffObject *kernel;
|
||||||
EcoffObject *console;
|
EcoffObject *console;
|
||||||
|
|
||||||
|
@ -74,8 +74,8 @@ class Tru64System : public System
|
||||||
Addr kernelEntry;
|
Addr kernelEntry;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoteGDB *remoteGDB;
|
std::vector<RemoteGDB *> remoteGDB;
|
||||||
GDBListener *gdbListen;
|
std::vector<GDBListener *> gdbListen;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Tru64System(const std::string _name,
|
Tru64System(const std::string _name,
|
||||||
|
@ -88,7 +88,8 @@ class Tru64System : public System
|
||||||
const std::string &boot_osflags);
|
const std::string &boot_osflags);
|
||||||
~Tru64System();
|
~Tru64System();
|
||||||
|
|
||||||
void init(ExecContext *xc);
|
int registerExecContext(ExecContext *xc);
|
||||||
|
void replaceExecContext(ExecContext *xc, int xcIndex);
|
||||||
|
|
||||||
Addr getKernelStart() const { return kernelStart; }
|
Addr getKernelStart() const { return kernelStart; }
|
||||||
Addr getKernelEnd() const { return kernelEnd; }
|
Addr getKernelEnd() const { return kernelEnd; }
|
||||||
|
|
36
sim/prog.cc
36
sim/prog.cc
|
@ -85,8 +85,6 @@ Process::Process(const string &name,
|
||||||
fd_map[i] = -1;
|
fd_map[i] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
numCpus = 0;
|
|
||||||
|
|
||||||
num_syscalls = 0;
|
num_syscalls = 0;
|
||||||
|
|
||||||
// other parameters will be initialized when the program is loaded
|
// other parameters will be initialized when the program is loaded
|
||||||
|
@ -136,30 +134,42 @@ Process::openOutputFile(const string &filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
int
|
||||||
Process::registerExecContext(ExecContext *ec)
|
Process::registerExecContext(ExecContext *xc)
|
||||||
{
|
{
|
||||||
if (execContexts.empty()) {
|
// add to list
|
||||||
|
int myIndex = execContexts.size();
|
||||||
|
execContexts.push_back(xc);
|
||||||
|
|
||||||
|
if (myIndex == 0) {
|
||||||
// first exec context for this process... initialize & enable
|
// first exec context for this process... initialize & enable
|
||||||
|
|
||||||
// copy process's initial regs struct
|
// copy process's initial regs struct
|
||||||
ec->regs = *init_regs;
|
xc->regs = *init_regs;
|
||||||
|
|
||||||
// mark this context as active
|
// mark this context as active
|
||||||
ec->setStatus(ExecContext::Active);
|
xc->initStatus(ExecContext::Active);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ec->setStatus(ExecContext::Unallocated);
|
xc->initStatus(ExecContext::Unallocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to list
|
// return CPU number to caller and increment available CPU count
|
||||||
execContexts.push_back(ec);
|
return myIndex;
|
||||||
|
|
||||||
// increment available CPU count
|
|
||||||
++numCpus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Process::replaceExecContext(int xcIndex, ExecContext *xc)
|
||||||
|
{
|
||||||
|
if (xcIndex >= execContexts.size()) {
|
||||||
|
panic("replaceExecContext: bad xcIndex, %d >= %d\n",
|
||||||
|
xcIndex, execContexts.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
execContexts[xcIndex] = xc;
|
||||||
|
}
|
||||||
|
|
||||||
// map simulator fd sim_fd to target fd tgt_fd
|
// map simulator fd sim_fd to target fd tgt_fd
|
||||||
void
|
void
|
||||||
Process::dup_fd(int sim_fd, int tgt_fd)
|
Process::dup_fd(int sim_fd, int tgt_fd)
|
||||||
|
|
18
sim/prog.hh
18
sim/prog.hh
|
@ -36,7 +36,7 @@
|
||||||
//
|
//
|
||||||
#ifndef FULL_SYSTEM
|
#ifndef FULL_SYSTEM
|
||||||
|
|
||||||
#include <list>
|
#include <vector>
|
||||||
|
|
||||||
#include "targetarch/isa_traits.hh"
|
#include "targetarch/isa_traits.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
|
@ -55,10 +55,10 @@ class Process : public SimObject
|
||||||
bool initialContextLoaded;
|
bool initialContextLoaded;
|
||||||
|
|
||||||
// execution contexts associated with this process
|
// execution contexts associated with this process
|
||||||
std::list<ExecContext *> execContexts;
|
std::vector<ExecContext *> execContexts;
|
||||||
// number of CPUs assigned to this process: should match number of
|
|
||||||
// contexts in execContexts list
|
// number of CPUs (esxec contexts, really) assigned to this process.
|
||||||
unsigned numCpus;
|
unsigned int numCpus() { return execContexts.size(); }
|
||||||
|
|
||||||
// record of blocked context
|
// record of blocked context
|
||||||
struct WaitRec
|
struct WaitRec
|
||||||
|
@ -123,8 +123,12 @@ class Process : public SimObject
|
||||||
// override of virtual SimObject method: register statistics
|
// override of virtual SimObject method: register statistics
|
||||||
virtual void regStats();
|
virtual void regStats();
|
||||||
|
|
||||||
// register an execution context for this process
|
// register an execution context for this process.
|
||||||
void registerExecContext(ExecContext *);
|
// returns xc's cpu number (index into execContexts[])
|
||||||
|
int registerExecContext(ExecContext *xc);
|
||||||
|
|
||||||
|
|
||||||
|
void replaceExecContext(int xcIndex, ExecContext *xc);
|
||||||
|
|
||||||
// map simulator fd sim_fd to target fd tgt_fd
|
// map simulator fd sim_fd to target fd tgt_fd
|
||||||
void dup_fd(int sim_fd, int tgt_fd);
|
void dup_fd(int sim_fd, int tgt_fd);
|
||||||
|
|
|
@ -56,16 +56,24 @@ System::~System()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
int
|
||||||
System::registerExecContext(ExecContext *xc)
|
System::registerExecContext(ExecContext *xc)
|
||||||
{
|
{
|
||||||
if (xc->cpu_id >= 12/*MAX_CPUS*/)
|
int myIndex = execContexts.size();
|
||||||
panic("Too many CPU's\n");
|
execContexts.push_back(xc);
|
||||||
|
return myIndex;
|
||||||
|
}
|
||||||
|
|
||||||
if (xc->cpu_id >= xcvec.size())
|
|
||||||
xcvec.resize(xc->cpu_id + 1);
|
|
||||||
|
|
||||||
xcvec[xc->cpu_id] = xc;
|
void
|
||||||
|
System::replaceExecContext(int xcIndex, ExecContext *xc)
|
||||||
|
{
|
||||||
|
if (xcIndex >= execContexts.size()) {
|
||||||
|
panic("replaceExecContext: bad xcIndex, %d >= %d\n",
|
||||||
|
xcIndex, execContexts.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
execContexts[xcIndex] = xc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,16 +52,16 @@ class System : public SimObject
|
||||||
|
|
||||||
PCEventQueue pcEventQueue;
|
PCEventQueue pcEventQueue;
|
||||||
|
|
||||||
std::vector<ExecContext *> xcvec;
|
std::vector<ExecContext *> execContexts;
|
||||||
void registerExecContext(ExecContext *xc);
|
|
||||||
|
virtual int registerExecContext(ExecContext *xc);
|
||||||
|
virtual void replaceExecContext(int xcIndex, ExecContext *xc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
System(const std::string _name, const uint64_t _init_param,
|
System(const std::string _name, const uint64_t _init_param,
|
||||||
MemoryController *, PhysicalMemory *);
|
MemoryController *, PhysicalMemory *);
|
||||||
~System();
|
~System();
|
||||||
|
|
||||||
virtual void init(ExecContext *xc) = 0;
|
|
||||||
|
|
||||||
virtual Addr getKernelStart() const = 0;
|
virtual Addr getKernelStart() const = 0;
|
||||||
virtual Addr getKernelEnd() const = 0;
|
virtual Addr getKernelEnd() const = 0;
|
||||||
virtual Addr getKernelEntry() const = 0;
|
virtual Addr getKernelEntry() const = 0;
|
||||||
|
|
Loading…
Reference in a new issue