From: Kajol Jain Date: Wed, 12 Jun 2019 09:10:51 +0000 (+0530) Subject: arch-power: Added support for SMT X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a1d5d18dfe812a263cc0a2e4fd5bd0f4bb7649e7;p=gem5.git arch-power: Added support for SMT 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 --- diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py index 01c51eff3..e892adb16 100644 --- a/configs/common/FSConfig.py +++ b/configs/common/FSConfig.py @@ -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 diff --git a/src/arch/power/interrupts.hh b/src/arch/power/interrupts.hh index 7770a6c9d..f1351b5cb 100644 --- a/src/arch/power/interrupts.hh +++ b/src/arch/power/interrupts.hh @@ -35,6 +35,17 @@ #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(_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(); + if (interrupts[Decrementer]) { + clear(Decrementer,0); + return std::make_shared(); + } + else if (interrupts[DirPriDoorbell]) { + clear(DirPriDoorbell,0); + return std::make_shared(); + } + else if (interrupts[DirHypDoorbell]) { + clear(DirHypDoorbell,0); + return std::make_shared(); + } else return NoFault; } @@ -106,7 +147,6 @@ class Interrupts : public BaseInterrupts updateIntrInfo() { tc->setIntReg(INTREG_DEC , 0xffffffffffffffff); - si = false; } }; diff --git a/src/arch/power/system.cc b/src/arch/power/system.cc index 1df07a506..b54d3c4ec 100644 --- a/src/arch/power/system.cc +++ b/src/arch/power/system.cc @@ -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); } diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 6e67ef792..260bba4ad 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -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") diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 9ba1b315b..1798de669 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -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]; diff --git a/src/sim/system.cc b/src/sim/system.cc index cb412a866..4708bbc25 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -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