misc: Add support for switching multiple cores in SystemC

This patch adds a '-n' flag to the gem5 SystemC driver which allows
multiple CPUs to be switched out to a new CPU. Primarily this involves
appending CPU numbers to the objects searched for in the config
manager if there are multiple CPUs in the system.

Note that an equivalent change should be made to the util/cxx_config driver,
but I wanted to get input on this first before making the same change over
there

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
Paul Rosenfeld 2017-01-27 15:03:17 -06:00
parent e9889c46ed
commit c5df9308c9

View file

@ -96,6 +96,9 @@ usage(const std::string &prog_name)
" -c <from> <to> <ticks> -- switch from cpu 'from' to cpu"
" 'to' after\n"
" the given number of ticks\n"
" -n <#cpus> the number of cpus to switch\n"
" (appended to 'to' and 'from'"
" cpus above)\n"
"\n"
);
@ -118,6 +121,7 @@ class SimControl : public Gem5SystemC::Module
std::string to_cpu;
Tick pre_run_time;
Tick pre_switch_time;
unsigned num_switch_cpus;
public:
SC_HAS_PROCESS(SimControl);
@ -125,6 +129,18 @@ class SimControl : public Gem5SystemC::Module
SimControl(sc_core::sc_module_name name, int argc_, char **argv_);
void run();
private:
/**
* Switch a single CPU
*
* If numTotalCpus is greater than 1, the CPU index will be appended to
* the object name when searching config manager for the CPU name
*
* @param The CPU number to switch
* @param The total number of CPUs in the system
*/
void switchCpu(unsigned cpuNum, unsigned numTotalCpus);
};
SimControl::SimControl(sc_core::sc_module_name name,
@ -177,6 +193,7 @@ SimControl::SimControl(sc_core::sc_module_name name,
to_cpu = "";
pre_run_time = 1000000;
pre_switch_time = 1000000;
num_switch_cpus = 1;
const std::string config_file(argv[arg_ptr]);
@ -239,6 +256,11 @@ SimControl::SimControl(sc_core::sc_module_name name,
to_cpu = argv[arg_ptr + 1];
std::istringstream(argv[arg_ptr + 2]) >> pre_switch_time;
arg_ptr += 3;
} else if (option == "-n") {
if (num_args < 1)
usage(prog_name);
std::istringstream(argv[arg_ptr]) >> num_switch_cpus;
arg_ptr++;
} else {
usage(prog_name);
}
@ -342,13 +364,6 @@ void SimControl::run()
if (switch_cpus) {
exit_event = simulate(pre_switch_time);
std::cerr << "Switching CPU\n";
/* Assume the system is called system */
System &system = config_manager->getObject<System>("system");
BaseCPU &old_cpu = config_manager->getObject<BaseCPU>(from_cpu);
BaseCPU &new_cpu = config_manager->getObject<BaseCPU>(to_cpu);
unsigned int drain_count = 1;
do {
drain_count = config_manager->drain();
@ -360,13 +375,12 @@ void SimControl::run()
}
} while (drain_count > 0);
old_cpu.switchOut();
system.setMemoryMode(Enums::timing);
for (unsigned cpu_num = 0; cpu_num < num_switch_cpus; ++cpu_num) {
switchCpu(cpu_num, num_switch_cpus);
}
new_cpu.takeOverFrom(&old_cpu);
config_manager->drainResume();
std::cerr << "Switched CPU\n";
}
exit_event = simulate();
@ -394,3 +408,39 @@ sc_main(int argc, char **argv)
return EXIT_SUCCESS;
}
void
SimControl::switchCpu(unsigned cpuNum, unsigned numTotalCpus) {
assert(cpuNum < numTotalCpus);
std::ostringstream from_cpu_name;
std::ostringstream to_cpu_name;
from_cpu_name << from_cpu;
to_cpu_name << to_cpu;
if (numTotalCpus > 1) {
from_cpu_name << cpuNum;
to_cpu_name << cpuNum;
}
std::cerr << "Switching CPU "<< cpuNum << "(from='" << from_cpu_name.str()
<<"' to '"<< to_cpu_name.str() << "')\n";
/* Assume the system is called system */
System &system = config_manager->getObject<System>("system");
BaseCPU &old_cpu = config_manager->getObject<BaseCPU>(from_cpu_name.str());
BaseCPU &new_cpu = config_manager->getObject<BaseCPU>(to_cpu_name.str());
old_cpu.switchOut();
// I'm not sure if this can be called before old_cpu.switchOut(). If so,
// it is best to just move this call before the switchCpu loop in run()
// where it previously was
if (cpuNum == 0)
system.setMemoryMode(Enums::timing);
new_cpu.takeOverFrom(&old_cpu);
std::cerr << "Switched CPU"<<cpuNum<<"\n";
}