arch-power: Added support for SMT
authorKajol Jain <kajoljain797@gmail.com>
Wed, 12 Jun 2019 09:10:51 +0000 (14:40 +0530)
committerSandipan Das <sandipan@linux.ibm.com>
Tue, 20 Aug 2019 06:24:29 +0000 (11:54 +0530)
This adds support for SMT (simultaneous multi-threading).
  * Enable multithreading for power architecture.
  * Make number of threads 2.
  * Added support for post and clear interrupt.
  * Added interrupt array support for external interrupts so
    that it will check any pending interrupt request in every
    tick.
  * Initialize PIR for second thread.
  * Initialize PC state for second thread so that it
    will loop until first thread try to wake up secondary
    threads.
  * Initialize register r3 for second thread.

Change-Id: I5825e62a94b50aaa213eb64335973129addf2e4c
Signed-off-by: Kajol Jain <kajoljain797@gmail.com>
configs/common/FSConfig.py
src/arch/power/interrupts.hh
src/arch/power/system.cc
src/cpu/BaseCPU.py
src/cpu/base.cc
src/sim/system.cc

index e725d31010eda13beffde15f2e8974357e7257e2..47c79184cecf6a2b1a8c10cbfd57930b857bfd38 100644 (file)
@@ -705,6 +705,8 @@ def makeLinuxPowerSystem(mem_mode, numCPUs=1, mdesc=None, cmdline=None):
     self.boot_osflags = fillInCmdline(mdesc, cmdline)
     self.kernel = binary('vmlinux')
     self.dtb_filename = binary('gem5-power9-fs.dtb')
+    self.multi_thread = True;
+    self._num_cpus = 2;
     return self
 
 
index d4bfd876e301a3b1407f848f0798bcfb09570149..81045d294b08d2d898791d5fe73c919020daa4dc 100644 (file)
 #include "params/PowerInterrupts.hh"
 #include "sim/sim_object.hh"
 
+#define NumInterruptLevels 8
+
+#define SystemReset 0 //System Reset Interrupt(Highest Priority)
+#define MachineCheck 1 //Machine Check Interrupt
+#define DirectExt 2 //Direct External Interrupt
+#define MediatedExt 3 //Mediated External Interrupt
+#define Decrementer 4 //Decrementer Interrupt
+#define PerfMoniter 5 //Performance Monitor Interrupt
+#define DirPriDoorbell 6 //Directed Privileged Doorbell Interrupt
+#define DirHypDoorbell 7 //Directed Hypervisor Doorbell Interrupt
+
 class BaseCPU;
 class ThreadContext;
 
@@ -46,7 +57,9 @@ class Interrupts : public SimObject
 {
   private:
     BaseCPU * cpu;
-    bool si = false;
+
+  protected:
+    bool interrupts[NumInterruptLevels];
 
   public:
     typedef PowerInterruptsParams Params;
@@ -58,7 +71,9 @@ class Interrupts : public SimObject
     }
 
     Interrupts(Params * p) : SimObject(p), cpu(NULL)
-    {}
+    {
+        memset(interrupts, 0, sizeof(interrupts));
+    }
 
     void
     setCPU(BaseCPU * _cpu)
@@ -69,45 +84,64 @@ class Interrupts : public SimObject
     void
     post(int int_num, int index)
     {
-        panic("Interrupts::post not implemented.\n");
+       DPRINTF(Interrupt, "Interrupt %d: posted\n", int_num);
+       if (int_num < 0 || int_num >= NumInterruptLevels)
+         panic("int_num out of bounds for fun POST%d\n",int_num);
+       interrupts[int_num] = 1;
     }
 
     void
     clear(int int_num, int index)
     {
-        panic("Interrupts::clear not implemented.\n");
+       DPRINTF(Interrupt, "Interrupt %d:\n", int_num);
+       if (int_num < 0 || int_num >= NumInterruptLevels)
+         panic("int_num out of bounds for fun CLEAR%d\n",int_num);
+       interrupts[int_num] = 0;
     }
 
     void
     clearAll()
     {
-        panic("Interrupts::clearAll not implemented.\n");
+       memset(interrupts, 0, sizeof(interrupts));
     }
 
     bool
     checkInterrupts(ThreadContext *tc)
     {
-        //panic("Interrupts::checkInterrupts not implemented.\n");
-      Msr msr = tc->readIntReg(INTREG_MSR);
-      tc->setIntReg(INTREG_TB , tc->readIntReg(INTREG_TB)+1);
-      if ( tc->readIntReg(INTREG_DEC) == 0 && msr.ee) {
-           si = true;
-           return true;
-        }
-      else if (tc->readIntReg(INTREG_DEC) == 0 && !msr.ee) {
+       Msr msr = tc->readIntReg(INTREG_MSR);
+       tc->setIntReg(INTREG_TB , tc->readIntReg(INTREG_TB)+1);
+       if (tc->readIntReg(INTREG_DEC) != 0)
+         tc->setIntReg(INTREG_DEC , tc->readIntReg(INTREG_DEC)-1);
+       else
+         interrupts[Decrementer] = 1;
+       if (msr.ee)
+       {
+         for (int i = 0; i < NumInterruptLevels; i++) {
+             if (interrupts[i] == 1)
+               return true;
+         }
+       }
+       if (interrupts[DirHypDoorbell] && (!msr.hv || msr.pr))
+         return true;
        return false;
-      } else {
-           tc->setIntReg(INTREG_DEC , tc->readIntReg(INTREG_DEC)-1);
-           return false;
-        }
     }
 
     Fault
     getInterrupt(ThreadContext *tc)
     {
         assert(checkInterrupts(tc));
-        if (si)
-        return std::make_shared<DecrementerInterrupt>();
+        if (interrupts[Decrementer]) {
+            clear(Decrementer,0);
+            return std::make_shared<DecrementerInterrupt>();
+        }
+        else if (interrupts[DirPriDoorbell]) {
+            clear(DirPriDoorbell,0);
+            return std::make_shared<PriDoorbellInterrupt>();
+        }
+        else if (interrupts[DirHypDoorbell]) {
+            clear(DirHypDoorbell,0);
+            return std::make_shared<HypDoorbellInterrupt>();
+        }
         else return NoFault;
     }
 
@@ -115,7 +149,6 @@ class Interrupts : public SimObject
     updateIntrInfo(ThreadContext *tc)
     {
         tc->setIntReg(INTREG_DEC , 0xffffffffffffffff);
-        si = false;
     }
 };
 
index 1df07a5060d153593d1999cec9d20007fdf72e65..b54d3c4ec866f517a978dc607ef103b293fdd2b9 100644 (file)
@@ -80,4 +80,9 @@ PowerSystem::initState()
     //ArgumentReg0 is initialized with 0xc00000 because in linux/system.cc
     //dtb is loaded at 0xc00000
     tc->setIntReg(ArgumentReg0, 0x1800000);
+    ThreadID tid = 1;
+    ThreadContext *tc1 = threadContexts[tid];
+    tc1->pcState(0xc00000000000a840);
+    tc1->setIntReg(ArgumentReg0, 0x1);
+    tc1->setIntReg(INTREG_PIR,0x1);
 }
index 9a25067784044b79bd5e7ba807d0a04c320d675f..3c7f233f18c8cb827110bc7f664f7fe7c7fd6932 100644 (file)
@@ -141,7 +141,7 @@ class BaseCPU(MemObject):
     system = Param.System(Parent.any, "system object")
     cpu_id = Param.Int(-1, "CPU identifier")
     socket_id = Param.Unsigned(0, "Physical Socket identifier")
-    numThreads = Param.Unsigned(1, "number of HW thread contexts")
+    numThreads = Param.Unsigned(2, "number of HW thread contexts")
     pwr_gating_latency = Param.Cycles(300,
         "Latency to enter power gating state when all contexts are suspended")
 
index c576f1defd3bffffcf7c81ae4d84e9eba35e3e39..2d6e4765fad59dfa010861dd56e291afd8a7b0be 100644 (file)
@@ -467,7 +467,8 @@ void
 BaseCPU::registerThreadContexts()
 {
     assert(system->multiThread || numThreads == 1);
-
+    printf("System in multithread: %d\n",system->multiThread );
+     printf("NumThreads:: %d\n",numThreads );
     ThreadID size = threadContexts.size();
     for (ThreadID tid = 0; tid < size; ++tid) {
         ThreadContext *tc = threadContexts[tid];
index 74bc94ee848b78f49bd10c54b722c60c1779bd9c..dc4d3f7c348280300a2fdb050256bec378ffc67c 100644 (file)
@@ -300,8 +300,9 @@ void
 System::initState()
 {
     if (FullSystem) {
-        for (int i = 0; i < threadContexts.size(); i++)
-            TheISA::startupCPU(threadContexts[i], i);
+        for (int i = 0; i < threadContexts.size(); i++){
+            printf("[LOG]: Starting CPU with id %d\n",i);
+            TheISA::startupCPU(threadContexts[i], i);}
         // Moved from the constructor to here since it relies on the
         // address map being resolved in the interconnect
         /**