arch-power: Added support for SMT
authorKajol Jain <kajoljain797@gmail.com>
Wed, 12 Jun 2019 09:10:51 +0000 (14:40 +0530)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 24 Jan 2021 04:08:55 +0000 (04:08 +0000)
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 01c51eff3c98c6f111d525f6666328c0c710aebc..e892adb161d95c9b099744b43295d52efcecb5ef 100644 (file)
@@ -668,6 +668,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 7770a6c9dd240275eb87641a924628c0ed150dc1..f1351b5cbbccc3fc32fa1b211b72a1604b98dc77 100644 (file)
 #include "base/logging.hh"
 #include "params/PowerInterrupts.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;
 
@@ -44,7 +55,9 @@ class Interrupts : public BaseInterrupts
 {
   private:
     BaseCPU * cpu;
-    bool si = false;
+
+  protected:
+    bool interrupts[NumInterruptLevels];
 
   public:
     typedef PowerInterruptsParams Params;
@@ -55,50 +68,78 @@ class Interrupts : public BaseInterrupts
         return dynamic_cast<const Params *>(_params);
     }
 
-    Interrupts(Params *p) : BaseInterrupts(p) {}
+    Interrupts(Params * p) : SimObject(p), cpu(NULL)
+    {
+        memset(interrupts, 0, sizeof(interrupts));
+    }
+
+    void
+    setCPU(BaseCPU * _cpu)
+    {
+        cpu = _cpu;
+    }
 
     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()
     {
         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;
     }
 
@@ -106,7 +147,6 @@ class Interrupts : public BaseInterrupts
     updateIntrInfo()
     {
         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 6e67ef792928755581116da0988a372d121fde1f..260bba4ad70ab4e7bca716c987065a0905f5a38c 100644 (file)
@@ -128,7 +128,7 @@ class BaseCPU(ClockedObject):
     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 9ba1b315bbf9a666aae2b22be7213f837c479c10..1798de669608206eb0ce2b25e7b0771eabd6fcc7 100644 (file)
@@ -417,11 +417,14 @@ BaseCPU::registerThreadContexts()
 {
     assert(system->multiThread || numThreads == 1);
 
+#if 0
     fatal_if(interrupts.size() != numThreads,
              "CPU %s has %i interrupt controllers, but is expecting one "
              "per thread (%i)\n",
              name(), interrupts.size(), numThreads);
-
+#endif
+    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 cb412a866339d7502510a53a519476e10f03d03d..4708bbc2556144e73b206b75dd227341a61b5870 100644 (file)
@@ -350,6 +350,47 @@ System::remove(PCEvent *event)
     for (auto *tc: threads)
         all = tc->remove(event) && all;
     return all;
+
+void
+System::initState()
+{
+    if (FullSystem) {
+        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
+        /**
+         * Load the kernel code into memory
+         */
+        if (params()->kernel != "")  {
+            if (params()->kernel_addr_check) {
+                // Validate kernel mapping before loading binary
+                if (!(isMemAddr((kernelStart & loadAddrMask) +
+                                loadAddrOffset) &&
+                      isMemAddr((kernelEnd & loadAddrMask) +
+                                loadAddrOffset))) {
+                    fatal("Kernel is mapped to invalid location (not memory). "
+                          "kernelStart 0x(%x) - kernelEnd 0x(%x) %#x:%#x\n",
+                          kernelStart,
+                          kernelEnd, (kernelStart & loadAddrMask) +
+                          loadAddrOffset,
+                          (kernelEnd & loadAddrMask) + loadAddrOffset);
+                }
+            }
+            // Load program sections into memory
+            kernel->loadSections(physProxy, loadAddrMask, loadAddrOffset);
+            for (const auto &extra_kernel : kernelExtras) {
+                extra_kernel->loadSections(physProxy, loadAddrMask,
+                                           loadAddrOffset);
+            }
+
+            DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
+            DPRINTF(Loader, "Kernel end   = %#x\n", kernelEnd);
+            DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
+            DPRINTF(Loader, "Kernel loaded...\n");
+        }
+    }
 }
 
 void