misc: Add support for switching multiple cores in SystemC
authorPaul Rosenfeld <prosenfeld@micon.com>
Fri, 27 Jan 2017 21:03:17 +0000 (15:03 -0600)
committerPaul Rosenfeld <prosenfeld@micon.com>
Fri, 27 Jan 2017 21:03:17 +0000 (15:03 -0600)
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>
util/systemc/main.cc

index c9fbd48a077cc30934bef0fb69d8cce3e13e33e6..cbbdd722986d3aac80ccd00bede40728dd12cadb 100644 (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";
+}