/*
* 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"
#include "sim/full_system.hh"
#include "sim/system.hh"
-#include "debug/Mwait.hh"
-
using namespace std;
using namespace TheISA;
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;
}
DrainState
TimingSimpleCPU::drain()
{
+ // Deschedule any power gating event (if any)
+ deschedulePowerGatingEvent();
+
if (switchedOut())
return DrainState::Drained;
}
}
+ // Reschedule any power gating event (if any)
+ schedulePowerGatingEvent();
+
system->totalNumInsts = 0;
}
== activeThreads.end()) {
activeThreads.push_back(thread_num);
}
+
+ BaseCPU::activateContext(thread_num);
}
deschedule(fetchEvent);
}
}
+
+ BaseCPU::suspendContext(thread_num);
}
bool
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;
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());
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;
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());
{
for (ThreadID tid = 0; tid < numThreads; tid++) {
if (tid != sender) {
- if(getCpuAddrMonitor(tid)->doMonitor(pkt)) {
+ if (getCpuAddrMonitor(tid)->doMonitor(pkt)) {
wakeup(tid);
}
TheISA::handleLockedSnoop(threadInfo[tid]->thread, pkt,
_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(),
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;
}
}
}
- for (auto &t_info : cpu->threadInfo) {
- TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
+ // Making it uniform across all CPUs:
+ // The CPUs need to be woken up only on an invalidation packet (when using caches)
+ // or on an incoming write packet (when not using caches)
+ // It is not necessary to wake up the processor on all incoming packets
+ if (pkt->isInvalidate() || pkt->isWrite()) {
+ for (auto &t_info : cpu->threadInfo) {
+ TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
+ }
}
}
TimingSimpleCPU::DcachePort::recvFunctionalSnoop(PacketPtr pkt)
{
for (ThreadID tid = 0; tid < cpu->numThreads; tid++) {
- if(cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
+ if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
cpu->wakeup(tid);
}
}