diff --git a/util/systemc/main.cc b/util/systemc/main.cc index c9fbd48a0..cbbdd7229 100644 --- a/util/systemc/main.cc +++ b/util/systemc/main.cc @@ -96,6 +96,9 @@ usage(const std::string &prog_name) " -c -- 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"); - BaseCPU &old_cpu = config_manager->getObject(from_cpu); - BaseCPU &new_cpu = config_manager->getObject(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"); + BaseCPU &old_cpu = config_manager->getObject(from_cpu_name.str()); + BaseCPU &new_cpu = config_manager->getObject(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"<