diff options
author | Steve Reinhardt <stever@eecs.umich.edu> | 2003-10-23 19:07:52 -0700 |
---|---|---|
committer | Steve Reinhardt <stever@eecs.umich.edu> | 2003-10-23 19:07:52 -0700 |
commit | f5da73b6881991a28844ed59e8dcc1d154ddae7e (patch) | |
tree | bc89728af5db24ef0bf1580045c3bcd26a206e85 /cpu/simple_cpu | |
parent | 73b050a541b1778596f9ebffa8a9f780446365c3 (diff) | |
download | gem5-f5da73b6881991a28844ed59e8dcc1d154ddae7e.tar.xz |
Initial support for CPU switching. New SamplingCPU object encompasses a set
of CPUs that get switched round-robin (though currently we're only shooting for
two CPUs and one switch event, and even that doesn't quite work yet). Registration
of ExecContexts with System/Process object factored out so we can create two CPUs
but only register one of them at a time. Also worked at making behavior and naming
in System and Process objects more consistent.
arch/alpha/ev5.cc:
Rename ipr_init to initIPRs and get rid of unused mem arg.
arch/alpha/fake_syscall.cc:
Process:numCpus is now a function (not a data member).
base/remote_gdb.hh:
Support for ExecContext switching.
cpu/base_cpu.cc:
cpu/base_cpu.hh:
cpu/exec_context.cc:
cpu/exec_context.hh:
cpu/simple_cpu/simple_cpu.hh:
Support for ExecContext switching.
Renamed contexts array to execContexts to be consistent with Process.
CPU ID now auto-assigned by system object.
cpu/simple_cpu/simple_cpu.cc:
Support for ExecContext switching.
Renamed contexts array to execContexts to be consistent with Process.
CPU ID now auto-assigned by system object.
Cleaned up MP full-system initialization a bit.
dev/alpha_console.cc:
Renamed xcvec array to execContexts to be consistent with Process.
kern/tru64/tru64_system.cc:
kern/tru64/tru64_system.hh:
Support for ExecContext switching.
CPU ID now auto-assigned by system object.
sim/prog.cc:
sim/prog.hh:
Support for ExecContext switching.
Process:numCpus is now a function (not a data member).
sim/system.cc:
sim/system.hh:
Support for ExecContext switching.
Renamed xcvec array to execContexts to be consistent with Process.
--HG--
extra : convert_revision : 79649cffad5bf3e83de8df44236941907926d791
Diffstat (limited to 'cpu/simple_cpu')
-rw-r--r-- | cpu/simple_cpu/simple_cpu.cc | 152 | ||||
-rw-r--r-- | cpu/simple_cpu/simple_cpu.hh | 15 |
2 files changed, 101 insertions, 66 deletions
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 3c9be172f..c96e31cb0 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -103,11 +103,11 @@ SimpleCPU::SimpleCPU(const string &_name, FunctionalMemory *mem, MemInterface *icache_interface, MemInterface *dcache_interface, - int cpu_id, Tick freq) + Tick freq) : BaseCPU(_name, /* number_of_threads */ 1, max_insts_any_thread, max_insts_all_threads, max_loads_any_thread, max_loads_all_threads, - _system, cpu_id, freq), + _system, freq), #else SimpleCPU::SimpleCPU(const string &_name, Process *_process, Counter max_insts_any_thread, @@ -122,61 +122,23 @@ SimpleCPU::SimpleCPU(const string &_name, Process *_process, #endif tickEvent(this), xc(NULL), cacheCompletionEvent(this) { + _status = Idle; #ifdef FULL_SYSTEM - xc = new ExecContext(this, 0, system, itb, dtb, mem, cpu_id); + xc = new ExecContext(this, 0, system, itb, dtb, mem); - _status = Running; - if (cpu_id != 0) { + TheISA::initCPU(&xc->regs); - xc->setStatus(ExecContext::Unallocated); + IntReg *ipr = xc->regs.ipr; + ipr[TheISA::IPR_MCSR] = 0x6; - //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; - } - else { - system->init(xc); - - // Reset the system - // - 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 = Running; - tickEvent.schedule(0); - } + AlphaISA::swap_palshadow(&xc->regs, true); + fault = Reset_Fault; + xc->regs.pc = ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault]; + xc->regs.npc = xc->regs.pc + sizeof(MachInst); #else xc = new ExecContext(this, /* thread_num */ 0, _process, /* asid */ 0); fault = No_Fault; - if (xc->status() == ExecContext::Active) { - _status = Running; - tickEvent.schedule(0); - } else - _status = Idle; #endif // !FULL_SYSTEM icacheInterface = icache_interface; @@ -193,13 +155,61 @@ SimpleCPU::SimpleCPU(const string &_name, Process *_process, lastIcacheStall = 0; lastDcacheStall = 0; - contexts.push_back(xc); + execContexts.push_back(xc); } 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 SimpleCPU::regStats() { @@ -488,6 +498,11 @@ SimpleCPU::processCacheCompletion() dcacheStallCycles += curTick - lastDcacheStall; setStatus(Running); 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: panic("SimpleCPU::processCacheCompletion: bad state"); break; @@ -693,7 +708,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) SimObjectParam<AlphaDtb *> dtb; SimObjectParam<FunctionalMemory *> mem; SimObjectParam<System *> system; - Param<int> cpu_id; Param<int> mult; #else SimObjectParam<Process *> workload; @@ -702,6 +716,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) SimObjectParam<BaseMem *> icache; SimObjectParam<BaseMem *> dcache; + Param<bool> defer_registration; + END_DECLARE_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(mem, "memory"), INIT_PARAM(system, "system object"), - INIT_PARAM_DFLT(cpu_id, "CPU identification number", 0), INIT_PARAM_DFLT(mult, "system clock multiplier", 1), #else INIT_PARAM(workload, "processes to run"), #endif // FULL_SYSTEM 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) CREATE_SIM_OBJECT(SimpleCPU) { + SimpleCPU *cpu; #ifdef FULL_SYSTEM if (mult != 1) panic("processor clock multiplier must be 1\n"); - return new SimpleCPU(getInstanceName(), system, - max_insts_any_thread, max_insts_all_threads, - max_loads_any_thread, max_loads_all_threads, - itb, dtb, mem, - (icache) ? icache->getInterface() : NULL, - (dcache) ? dcache->getInterface() : NULL, - cpu_id, ticksPerSecond * mult); + cpu = new SimpleCPU(getInstanceName(), system, + max_insts_any_thread, max_insts_all_threads, + max_loads_any_thread, max_loads_all_threads, + itb, dtb, mem, + (icache) ? icache->getInterface() : NULL, + (dcache) ? dcache->getInterface() : NULL, + ticksPerSecond * mult); #else - return new SimpleCPU(getInstanceName(), workload, - max_insts_any_thread, max_insts_all_threads, - max_loads_any_thread, max_loads_all_threads, - icache->getInterface(), dcache->getInterface()); + cpu = new SimpleCPU(getInstanceName(), workload, + max_insts_any_thread, max_insts_all_threads, + max_loads_any_thread, max_loads_all_threads, + icache->getInterface(), dcache->getInterface()); #endif // FULL_SYSTEM + + if (!defer_registration) { + cpu->registerExecContexts(); + } + + return cpu; } REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU) diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index fd50acfe1..e1b351cab 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -92,7 +92,8 @@ class SimpleCPU : public BaseCPU Idle, IcacheMissStall, IcacheMissComplete, - DcacheMissStall + DcacheMissStall, + SwitchedOut }; private: @@ -117,7 +118,7 @@ class SimpleCPU : public BaseCPU Counter max_loads_any_thread, Counter max_loads_all_threads, AlphaItb *itb, AlphaDtb *dtb, FunctionalMemory *mem, MemInterface *icache_interface, MemInterface *dcache_interface, - int cpu_id, Tick freq); + Tick freq); #else @@ -135,6 +136,11 @@ class SimpleCPU : public BaseCPU // execution context ExecContext *xc; + void registerExecContexts(); + + void switchOut(); + void takeOverFrom(BaseCPU *oldCPU); + #ifdef FULL_SYSTEM Addr dbg_vtophys(Addr addr); @@ -171,6 +177,7 @@ class SimpleCPU : public BaseCPU CacheCompletionEvent cacheCompletionEvent; Status status() const { return _status; } + virtual void execCtxStatusChg() { if (xc) { if (xc->status() == ExecContext::Active) @@ -182,6 +189,10 @@ class SimpleCPU : public BaseCPU void setStatus(Status new_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; switch (status()) { |