pwr: Adds logic to enter power gating for the cpu model
[gem5.git] / src / cpu / simple / timing.cc
index c99f9c475941ed71db1bb2d610a856cede16440f..f57354d56d73812b9636c1f647e5c62acb119a72 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright 2014 Google, Inc.
- * Copyright (c) 2010-2013,2015 ARM Limited
+ * Copyright (c) 2010-2013,2015,2017 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
  * Authors: Steve Reinhardt
  */
 
+#include "cpu/simple/timing.hh"
+
 #include "arch/locked_mem.hh"
 #include "arch/mmapped_ipr.hh"
 #include "arch/utility.hh"
 #include "base/bigint.hh"
 #include "config/the_isa.hh"
-#include "cpu/simple/timing.hh"
 #include "cpu/exetrace.hh"
 #include "debug/Config.hh"
 #include "debug/Drain.hh"
 #include "debug/ExecFaulting.hh"
+#include "debug/Mwait.hh"
 #include "debug/SimpleCPU.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
@@ -59,8 +61,6 @@
 #include "sim/full_system.hh"
 #include "sim/system.hh"
 
-#include "debug/Mwait.hh"
-
 using namespace std;
 using namespace TheISA;
 
@@ -80,7 +80,7 @@ TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
 TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
     : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this),
       dcachePort(this), ifetch_pkt(NULL), dcache_pkt(NULL), previousCycle(0),
-      fetchEvent(this)
+      fetchEvent([this]{ fetch(); }, name())
 {
     _status = Idle;
 }
@@ -94,6 +94,9 @@ TimingSimpleCPU::~TimingSimpleCPU()
 DrainState
 TimingSimpleCPU::drain()
 {
+    // Deschedule any power gating event (if any)
+    deschedulePowerGatingEvent();
+
     if (switchedOut())
         return DrainState::Drained;
 
@@ -146,6 +149,9 @@ TimingSimpleCPU::drainResume()
         }
     }
 
+    // Reschedule any power gating event (if any)
+    schedulePowerGatingEvent();
+
     system->totalNumInsts = 0;
 }
 
@@ -409,21 +415,21 @@ TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2,
 
 Fault
 TimingSimpleCPU::readMem(Addr addr, uint8_t *data,
-                         unsigned size, unsigned flags)
+                         unsigned size, Request::Flags flags)
 {
     panic("readMem() is for atomic accesses, and should "
           "never be called on TimingSimpleCPU.\n");
 }
 
 Fault
-TimingSimpleCPU::initiateMemRead(Addr addr, unsigned size, unsigned flags)
+TimingSimpleCPU::initiateMemRead(Addr addr, unsigned size,
+                                 Request::Flags flags)
 {
     SimpleExecContext &t_info = *threadInfo[curThread];
     SimpleThread* thread = t_info.thread;
 
     Fault fault;
     const int asid = 0;
-    const ThreadID tid = curThread;
     const Addr pc = thread->instAddr();
     unsigned block_size = cacheLineSize();
     BaseTLB::Mode mode = BaseTLB::Read;
@@ -431,9 +437,8 @@ TimingSimpleCPU::initiateMemRead(Addr addr, unsigned size, unsigned flags)
     if (traceData)
         traceData->setMem(addr, size, flags);
 
-    RequestPtr req  = new Request(asid, addr, size,
-                                  flags, dataMasterId(), pc,
-                                  thread->contextId(), tid);
+    RequestPtr req = new Request(asid, addr, size, flags, dataMasterId(), pc,
+                                 thread->contextId());
 
     req->taskId(taskId());
 
@@ -491,14 +496,13 @@ TimingSimpleCPU::handleWritePacket()
 
 Fault
 TimingSimpleCPU::writeMem(uint8_t *data, unsigned size,
-                          Addr addr, unsigned flags, uint64_t *res)
+                          Addr addr, Request::Flags flags, uint64_t *res)
 {
     SimpleExecContext &t_info = *threadInfo[curThread];
     SimpleThread* thread = t_info.thread;
 
     uint8_t *newData = new uint8_t[size];
     const int asid = 0;
-    const ThreadID tid = curThread;
     const Addr pc = thread->instAddr();
     unsigned block_size = cacheLineSize();
     BaseTLB::Mode mode = BaseTLB::Write;
@@ -514,9 +518,8 @@ TimingSimpleCPU::writeMem(uint8_t *data, unsigned size,
     if (traceData)
         traceData->setMem(addr, size, flags);
 
-    RequestPtr req = new Request(asid, addr, size,
-                                 flags, dataMasterId(), pc,
-                                 thread->contextId(), tid);
+    RequestPtr req = new Request(asid, addr, size, flags, dataMasterId(), pc,
+                                 thread->contextId());
 
     req->taskId(taskId());
 
@@ -618,7 +621,7 @@ TimingSimpleCPU::fetch()
         _status = BaseSimpleCPU::Running;
         Request *ifetch_req = new Request();
         ifetch_req->taskId(taskId());
-        ifetch_req->setThreadContext(thread->contextId(), curThread);
+        ifetch_req->setContext(thread->contextId());
         setupFetchRequest(ifetch_req);
         DPRINTF(SimpleCPU, "Translating address %#x\n", ifetch_req->getVaddr());
         thread->itb->translateTiming(ifetch_req, thread->getTC(),
@@ -673,9 +676,15 @@ TimingSimpleCPU::advanceInst(const Fault &fault)
         return;
 
     if (fault != NoFault) {
-        advancePC(fault);
         DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n");
-        reschedule(fetchEvent, clockEdge(), true);
+
+        advancePC(fault);
+
+        Tick stall = dynamic_pointer_cast<SyscallRetryFault>(fault) ?
+                     clockEdge(syscallRetryLatency) : clockEdge();
+
+        reschedule(fetchEvent, stall, true);
+
         _status = Faulting;
         return;
     }