Merge stever@zizzer:/bk/m5 into isabel.reinhardt.house:/z/stever/bk/m5

--HG--
extra : convert_revision : b0f93bd35d767fd3a520a9fed70a71d40b0056db
This commit is contained in:
Steve Reinhardt 2003-10-23 19:09:18 -07:00
commit cc9a838f4c
18 changed files with 339 additions and 171 deletions

View file

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

View file

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

View file

@ -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] == '+');

View file

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

View file

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

View file

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

View file

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

View file

@ -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(&regs, 0, sizeof(RegFile)); memset(&regs, 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)
{ {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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