cpu: Result refactoring
The Result union used to collect the result of an instruction is now a class of its own, with its constructor, and explicit casting methods for cleanliness. This is also a stepping stone to have vector registers, and instructions that produce a vector register as output. Change-Id: I6f40c11cb5e835d8b11f7804a4e967aff18025b9 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/2703 Reviewed-by: Anthony Gutierrez <anthony.gutierrez@amd.com> Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
committed by
Andreas Sandberg
parent
a473b5a6eb
commit
2da7656a9a
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 ARM Limited
|
||||
* Copyright (c) 2011, 2016 ARM Limited
|
||||
* Copyright (c) 2013 Advanced Micro Devices, Inc.
|
||||
* All rights reserved
|
||||
*
|
||||
@@ -481,27 +481,29 @@ template <class Impl>
|
||||
void
|
||||
Checker<Impl>::validateExecution(DynInstPtr &inst)
|
||||
{
|
||||
uint64_t checker_val;
|
||||
uint64_t inst_val;
|
||||
InstResult checker_val;
|
||||
InstResult inst_val;
|
||||
int idx = -1;
|
||||
bool result_mismatch = false;
|
||||
bool scalar_mismatch = false;
|
||||
|
||||
if (inst->isUnverifiable()) {
|
||||
// Unverifiable instructions assume they were executed
|
||||
// properly by the CPU. Grab the result from the
|
||||
// instruction and write it to the register.
|
||||
copyResult(inst, 0, idx);
|
||||
copyResult(inst, InstResult(0ul, InstResult::ResultType::Scalar), idx);
|
||||
} else if (inst->numDestRegs() > 0 && !result.empty()) {
|
||||
DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n",
|
||||
inst->numDestRegs(), result.size());
|
||||
for (int i = 0; i < inst->numDestRegs() && !result.empty(); i++) {
|
||||
result.front().get(checker_val);
|
||||
checker_val = result.front();
|
||||
result.pop();
|
||||
inst_val = 0;
|
||||
inst->template popResult<uint64_t>(inst_val);
|
||||
inst_val = inst->popResult(
|
||||
InstResult(0ul, InstResult::ResultType::Scalar));
|
||||
if (checker_val != inst_val) {
|
||||
result_mismatch = true;
|
||||
idx = i;
|
||||
scalar_mismatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -512,9 +514,12 @@ Checker<Impl>::validateExecution(DynInstPtr &inst)
|
||||
// this is ok and not a bug. May be worthwhile to try and correct this.
|
||||
|
||||
if (result_mismatch) {
|
||||
warn("%lli: Instruction results do not match! (Values may not "
|
||||
"actually be integers) Inst: %#x, checker: %#x",
|
||||
curTick(), inst_val, checker_val);
|
||||
if (scalar_mismatch) {
|
||||
warn("%lli: Instruction results (%i) do not match! (Values may"
|
||||
" not actually be integers) Inst: %#x, checker: %#x",
|
||||
curTick(), idx, inst_val.asIntegerNoAssert(),
|
||||
checker_val.asInteger());
|
||||
}
|
||||
|
||||
// It's useful to verify load values from memory, but in MP
|
||||
// systems the value obtained at execute may be different than
|
||||
@@ -589,7 +594,7 @@ Checker<Impl>::validateState()
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val,
|
||||
Checker<Impl>::copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
|
||||
int start_idx)
|
||||
{
|
||||
// We've already popped one dest off the queue,
|
||||
@@ -598,37 +603,45 @@ Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val,
|
||||
const RegId& idx = inst->destRegIdx(start_idx);
|
||||
switch (idx.classValue()) {
|
||||
case IntRegClass:
|
||||
thread->setIntReg(idx.index(), mismatch_val);
|
||||
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
|
||||
thread->setIntReg(idx.index(), mismatch_val.asInteger());
|
||||
break;
|
||||
case FloatRegClass:
|
||||
thread->setFloatRegBits(idx.index(), mismatch_val);
|
||||
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
|
||||
thread->setFloatRegBits(idx.index(), mismatch_val.asInteger());
|
||||
break;
|
||||
case CCRegClass:
|
||||
thread->setCCReg(idx.index(), mismatch_val);
|
||||
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
|
||||
thread->setCCReg(idx.index(), mismatch_val.asInteger());
|
||||
break;
|
||||
case MiscRegClass:
|
||||
thread->setMiscReg(idx.index(), mismatch_val);
|
||||
panic_if(!mismatch_val.isScalar(), "Unexpected type of result");
|
||||
thread->setMiscReg(idx.index(), mismatch_val.asInteger());
|
||||
break;
|
||||
}
|
||||
}
|
||||
start_idx++;
|
||||
uint64_t res = 0;
|
||||
InstResult res;
|
||||
for (int i = start_idx; i < inst->numDestRegs(); i++) {
|
||||
const RegId& idx = inst->destRegIdx(i);
|
||||
inst->template popResult<uint64_t>(res);
|
||||
res = inst->popResult();
|
||||
switch (idx.classValue()) {
|
||||
case IntRegClass:
|
||||
thread->setIntReg(idx.index(), res);
|
||||
panic_if(!res.isScalar(), "Unexpected type of result");
|
||||
thread->setIntReg(idx.index(), res.asInteger());
|
||||
break;
|
||||
case FloatRegClass:
|
||||
thread->setFloatRegBits(idx.index(), res);
|
||||
panic_if(!res.isScalar(), "Unexpected type of result");
|
||||
thread->setFloatRegBits(idx.index(), res.asInteger());
|
||||
break;
|
||||
case CCRegClass:
|
||||
thread->setCCReg(idx.index(), res);
|
||||
panic_if(!res.isScalar(), "Unexpected type of result");
|
||||
thread->setCCReg(idx.index(), res.asInteger());
|
||||
break;
|
||||
case MiscRegClass:
|
||||
panic_if(res.isValid(), "MiscReg expecting invalid result");
|
||||
// Try to get the proper misc register index for ARM here...
|
||||
thread->setMiscReg(idx.index(), res);
|
||||
thread->setMiscReg(idx.index(), 0);
|
||||
break;
|
||||
// else Register is out of range...
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user