/*
- * Copyright (c) 2013-2014 ARM Limited
+ * Copyright (c) 2013-2014,2018-2020 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Andrew Bardsley
*/
#include "cpu/minor/execute.hh"
#include "debug/Activity.hh"
#include "debug/Branch.hh"
#include "debug/Drain.hh"
+#include "debug/ExecFaulting.hh"
#include "debug/MinorExecute.hh"
#include "debug/MinorInterrupt.hh"
#include "debug/MinorMem.hh"
pc_before, target);
}
- if (thread->status() == ThreadContext::Suspended) {
- /* Thread got suspended */
- DPRINTF(Branch, "Thread got suspended: branch from 0x%x to 0x%x "
- "inst: %s\n",
- inst->pc.instAddr(), target.instAddr(), *inst);
-
- reason = BranchData::SuspendThread;
- } else if (inst->predictedTaken && !force_branch) {
+ if (inst->predictedTaken && !force_branch) {
/* Predicted to branch */
if (!must_branch) {
/* No branch was taken, change stream to get us back to the
bool is_load = inst->staticInst->isLoad();
bool is_store = inst->staticInst->isStore();
+ bool is_atomic = inst->staticInst->isAtomic();
bool is_prefetch = inst->staticInst->isDataPrefetch();
/* If true, the trace's predicate value will be taken from the exec
* context predicate, otherwise, it will be set to false */
bool use_context_predicate = true;
- if (response->fault != NoFault) {
+ if (inst->translationFault != NoFault) {
/* Invoke memory faults. */
DPRINTF(MinorMem, "Completing fault from DTLB access: %s\n",
- response->fault->name());
+ inst->translationFault->name());
if (inst->staticInst->isPrefetch()) {
DPRINTF(MinorMem, "Not taking fault on prefetch: %s\n",
- response->fault->name());
+ inst->translationFault->name());
/* Don't assign to fault */
} else {
/* Take the fault raised during the TLB/memory access */
- fault = response->fault;
+ fault = inst->translationFault;
fault->invoke(thread, inst->staticInst);
}
DPRINTF(MinorMem, "Completing failed request inst: %s\n",
*inst);
use_context_predicate = false;
+ if (!context.readMemAccPredicate())
+ inst->staticInst->completeAcc(nullptr, &context, inst->traceData);
} else if (packet->isError()) {
DPRINTF(MinorMem, "Trying to commit error response: %s\n",
*inst);
fatal("Received error response packet for inst: %s\n", *inst);
- } else if (is_store || is_load || is_prefetch) {
+ } else if (is_store || is_load || is_prefetch || is_atomic) {
assert(packet);
DPRINTF(MinorMem, "Memory response inst: %s addr: 0x%x size: %d\n",
bool
Execute::isInterrupted(ThreadID thread_id) const
{
- return cpu.checkInterrupts(cpu.getContext(thread_id));
+ return cpu.checkInterrupts(thread_id);
}
bool
DPRINTF(MinorInterrupt, "Considering interrupt status from PC: %s\n",
cpu.getContext(thread_id)->pcState());
- Fault interrupt = cpu.getInterruptController(thread_id)->getInterrupt
- (cpu.getContext(thread_id));
+ Fault interrupt = cpu.getInterruptController(thread_id)->getInterrupt();
if (interrupt != NoFault) {
/* The interrupt *must* set pcState */
- cpu.getInterruptController(thread_id)->updateIntrInfo
- (cpu.getContext(thread_id));
+ cpu.getInterruptController(thread_id)->updateIntrInfo();
interrupt->invoke(cpu.getContext(thread_id));
assert(!lsq.accessesInFlight());
Fault init_fault = inst->staticInst->initiateAcc(&context,
inst->traceData);
+ if (inst->inLSQ) {
+ if (init_fault != NoFault) {
+ assert(inst->translationFault != NoFault);
+ // Translation faults are dealt with in handleMemResponse()
+ init_fault = NoFault;
+ } else {
+ // If we have a translation fault then it got suppressed by
+ // initateAcc()
+ inst->translationFault = NoFault;
+ }
+ }
+
if (init_fault != NoFault) {
DPRINTF(MinorExecute, "Fault on memory inst: %s"
" initiateAcc: %s\n", *inst, init_fault->name());
} else {
/* Only set this if the instruction passed its
* predicate */
+ if (!context.readMemAccPredicate()) {
+ DPRINTF(MinorMem, "No memory access for inst: %s\n", *inst);
+ assert(context.readPredicate());
+ }
passed_predicate = context.readPredicate();
/* Set predicate in tracing */
if (inst->traceData)
inst->traceData->setPredicate(passed_predicate);
- /* If the instruction didn't pass its predicate (and so will not
- * progress from here) Try to branch to correct and branch
- * mis-prediction. */
- if (!passed_predicate) {
+ /* If the instruction didn't pass its predicate
+ * or it is a predicated vector instruction and the
+ * associated predicate register is all-false (and so will not
+ * progress from here) Try to branch to correct and branch
+ * mis-prediction. */
+ if (!inst->inLSQ) {
/* Leave it up to commit to handle the fault */
lsq.pushFailedRequest(inst);
+ inst->inLSQ = true;
}
}
Addr oldPC;
do {
oldPC = thread->instAddr();
- cpu.system->pcEventQueue.service(thread);
+ cpu.threads[thread_id]->pcEventQueue.service(oldPC, thread);
num_pc_event_checks++;
} while (oldPC != thread->instAddr());
if (!inst->staticInst->isMicroop() || inst->staticInst->isLastMicroop())
{
thread->numInst++;
- thread->numInsts++;
+ thread->threadStats.numInsts++;
cpu.stats.numInsts++;
cpu.system->totalNumInsts++;
/* Act on events related to instruction counts */
- cpu.comInstEventQueue[inst->id.threadId]->serviceEvents(thread->numInst);
- cpu.system->instEventQueue.serviceEvents(cpu.system->totalNumInsts);
+ thread->comInstEventQueue.serviceEvents(thread->numInst);
}
thread->numOp++;
- thread->numOps++;
+ thread->threadStats.numOps++;
cpu.stats.numOps++;
cpu.stats.committedInstType[inst->id.threadId]
[inst->staticInst->opClass()]++;
if (inst->traceData)
inst->traceData->setCPSeq(thread->numOp);
- cpu.probeInstCommit(inst->staticInst);
+ cpu.probeInstCommit(inst->staticInst, inst->pc.instAddr());
}
bool
* until it gets to the head of inFlightInsts */
inst->canEarlyIssue = false;
/* Not completed as we'll come here again to pick up
- * the fault when we get to the end of the FU */
+ * the fault when we get to the end of the FU */
completed_inst = false;
} else {
DPRINTF(MinorExecute, "Fault in execute: %s\n",
committed = true;
if (fault != NoFault) {
+ if (inst->traceData) {
+ if (DTRACE(ExecFaulting)) {
+ inst->traceData->setFaulting(true);
+ } else {
+ delete inst->traceData;
+ inst->traceData = NULL;
+ }
+ }
+
DPRINTF(MinorExecute, "Fault in execute of inst: %s fault: %s\n",
*inst, fault->name());
fault->invoke(thread, inst->staticInst);
for (auto tid : priority_list) {
ExecuteThreadInfo &ex_info = executeInfo[tid];
-
- bool is_thread_active =
- cpu.getContext(tid)->status() == ThreadContext::Active;
- bool can_commit_insts = !ex_info.inFlightInsts->empty() &&
- is_thread_active;
-
+ bool can_commit_insts = !ex_info.inFlightInsts->empty();
if (can_commit_insts) {
QueuedInst *head_inflight_inst = &(ex_info.inFlightInsts->front());
MinorDynInstPtr inst = head_inflight_inst->inst;
}
for (auto tid : priority_list) {
- if (cpu.getContext(tid)->status() == ThreadContext::Active &&
- getInput(tid)) {
+ if (getInput(tid)) {
issuePriority = tid;
return tid;
}