arch-arm: Provide SVE support to the TarmacParser

This patch is providing SVE support to the tarmac parser, so that
it is recognizing Vector & Predicate entries.

Change-Id: I268e621cffa05644d3f1d80170b067aacaa2d5ea
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21560
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Giacomo Gabrielli
2019-09-30 14:30:48 +01:00
committed by Giacomo Travaglini
parent 27c262735c
commit 68a4a2de66
6 changed files with 213 additions and 74 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 ARM Limited
* Copyright (c) 2017-2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -83,8 +83,11 @@ TarmacBaseRecord::InstEntry::InstEntry(
}
TarmacBaseRecord::RegEntry::RegEntry(PCState pc)
: isetstate(pcToISetState(pc))
: isetstate(pcToISetState(pc)),
values(2, 0)
{
// values vector is constructed with size = 2, for
// holding Lo and Hi values.
}
TarmacBaseRecord::MemEntry::MemEntry (

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011,2017-2018 ARM Limited
* Copyright (c) 2011,2017-2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -78,7 +78,7 @@ class TarmacBaseRecord : public InstRecord
ISET_UNSUPPORTED };
/** ARM register type. */
enum RegType { REG_R, REG_X, REG_S, REG_D, REG_Q, REG_MISC };
enum RegType { REG_R, REG_X, REG_S, REG_D, REG_P, REG_Q, REG_Z, REG_MISC };
/** TARMAC instruction trace record. */
struct InstEntry
@@ -100,14 +100,20 @@ class TarmacBaseRecord : public InstRecord
/** TARMAC register trace record. */
struct RegEntry
{
enum RegElement {
Lo = 0,
Hi = 1,
// Max = (max SVE vector length) 2048b / 64 = 32
Max = 32
};
RegEntry() = default;
RegEntry(ArmISA::PCState pc);
RegType type;
RegIndex index;
ISetState isetstate;
uint64_t valueHi;
uint64_t valueLo;
std::vector<uint64_t> values;
};
/** TARMAC memory access trace record (stores only). */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011,2017-2018 ARM Limited
* Copyright (c) 2011,2017-2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -63,6 +63,7 @@ namespace Trace {
// TARMAC Parser static variables
const int TarmacParserRecord::MaxLineLength;
int8_t TarmacParserRecord::maxVectorLength = 0;
TarmacParserRecord::ParserInstEntry TarmacParserRecord::instRecord;
TarmacParserRecord::ParserRegEntry TarmacParserRecord::regRecord;
@@ -636,47 +637,98 @@ TarmacParserRecord::TarmacParserRecordEvent::process()
list<ParserRegEntry>::iterator it = destRegRecords.begin(),
end = destRegRecords.end();
uint64_t value_hi, value_lo;
bool check_value_hi = false;
std::vector<uint64_t> values;
for (; it != end; ++it) {
values.clear();
switch (it->type) {
case REG_R:
case REG_X:
value_lo = thread->readIntReg(it->index);
values.push_back(thread->readIntReg(it->index));
break;
case REG_S:
if (instRecord.isetstate == ISET_A64)
value_lo = thread->readFloatReg(it->index * 4);
else
value_lo = thread->readFloatReg(it->index);
if (instRecord.isetstate == ISET_A64) {
const ArmISA::VecRegContainer& vc = thread->readVecReg(
RegId(VecRegClass, it->index));
auto vv = vc.as<uint32_t>();
values.push_back(vv[0]);
} else {
const VecElem elem = thread->readVecElem(
RegId(VecElemClass,
it->index / NumVecElemPerNeonVecReg,
it->index % NumVecElemPerNeonVecReg));
values.push_back(elem);
}
break;
case REG_D:
if (instRecord.isetstate == ISET_A64)
value_lo = thread->readFloatReg(it->index * 4) |
(uint64_t) thread->readFloatReg(it->index * 4 + 1) <<
32;
else
value_lo = thread->readFloatReg(it->index * 2) |
(uint64_t) thread->readFloatReg(it->index * 2 + 1) <<
32;
if (instRecord.isetstate == ISET_A64) {
const ArmISA::VecRegContainer& vc = thread->readVecReg(
RegId(VecRegClass, it->index));
auto vv = vc.as<uint64_t>();
values.push_back(vv[0]);
} else {
const VecElem w0 = thread->readVecElem(
RegId(VecElemClass,
it->index / NumVecElemPerNeonVecReg,
it->index % NumVecElemPerNeonVecReg));
const VecElem w1 = thread->readVecElem(
RegId(VecElemClass,
(it->index + 1) / NumVecElemPerNeonVecReg,
(it->index + 1) % NumVecElemPerNeonVecReg));
values.push_back((uint64_t)(w1) << 32 | w0);
}
break;
case REG_P:
{
const ArmISA::VecPredRegContainer& pc =
thread->readVecPredReg(RegId(VecPredRegClass, it->index));
auto pv = pc.as<uint8_t>();
uint64_t p = 0;
for (int i = maxVectorLength * 8; i > 0; ) {
p = (p << 1) | pv[--i];
}
values.push_back(p);
}
break;
case REG_Q:
check_value_hi = true;
if (instRecord.isetstate == ISET_A64) {
value_lo = thread->readFloatReg(it->index * 4) |
(uint64_t) thread->readFloatReg(it->index * 4 + 1) <<
32;
value_hi = thread->readFloatReg(it->index * 4 + 2) |
(uint64_t) thread->readFloatReg(it->index * 4 + 3) <<
32;
const ArmISA::VecRegContainer& vc = thread->readVecReg(
RegId(VecRegClass, it->index));
auto vv = vc.as<uint64_t>();
values.push_back(vv[0]);
values.push_back(vv[1]);
} else {
value_lo = thread->readFloatReg(it->index * 2) |
(uint64_t) thread->readFloatReg(it->index * 2 + 1) <<
32;
value_hi = thread->readFloatReg(it->index * 2 + 2) |
(uint64_t) thread->readFloatReg(it->index * 2 + 3) <<
32;
const VecElem w0 = thread->readVecElem(
RegId(VecElemClass,
it->index / NumVecElemPerNeonVecReg,
it->index % NumVecElemPerNeonVecReg));
const VecElem w1 = thread->readVecElem(
RegId(VecElemClass,
(it->index + 1) / NumVecElemPerNeonVecReg,
(it->index + 1) % NumVecElemPerNeonVecReg));
const VecElem w2 = thread->readVecElem(
RegId(VecElemClass,
(it->index + 2) / NumVecElemPerNeonVecReg,
(it->index + 2) % NumVecElemPerNeonVecReg));
const VecElem w3 = thread->readVecElem(
RegId(VecElemClass,
(it->index + 3) / NumVecElemPerNeonVecReg,
(it->index + 3) % NumVecElemPerNeonVecReg));
values.push_back((uint64_t)(w1) << 32 | w0);
values.push_back((uint64_t)(w3) << 32 | w2);
}
break;
case REG_Z:
{
int8_t i = maxVectorLength;
const TheISA::VecRegContainer& vc = thread->readVecReg(
RegId(VecRegClass, it->index));
auto vv = vc.as<uint64_t>();
while (i > 0) {
values.push_back(vv[--i]);
}
}
break;
case REG_MISC:
@@ -687,41 +739,86 @@ TarmacParserRecord::TarmacParserRecordEvent::process()
cpsr.c = thread->readCCReg(CCREG_C);
cpsr.v = thread->readCCReg(CCREG_V);
cpsr.ge = thread->readCCReg(CCREG_GE);
value_lo = cpsr;
values.push_back(cpsr);
} else if (it->index == MISCREG_NZCV) {
CPSR cpsr = 0;
cpsr.nz = thread->readCCReg(CCREG_NZ);
cpsr.c = thread->readCCReg(CCREG_C);
cpsr.v = thread->readCCReg(CCREG_V);
value_lo = cpsr;
values.push_back(cpsr);
} else if (it->index == MISCREG_FPCR) {
// Read FPSCR and extract FPCR value
FPSCR fpscr = thread->readMiscRegNoEffect(MISCREG_FPSCR);
const uint32_t ones = (uint32_t)(-1);
FPSCR fpcrMask = 0;
fpcrMask.ioe = ones;
fpcrMask.dze = ones;
fpcrMask.ofe = ones;
fpcrMask.ufe = ones;
fpcrMask.ixe = ones;
fpcrMask.ide = ones;
fpcrMask.len = ones;
fpcrMask.stride = ones;
fpcrMask.rMode = ones;
fpcrMask.fz = ones;
fpcrMask.dn = ones;
fpcrMask.ahp = ones;
values.push_back(fpscr & fpcrMask);
} else if (it->index == MISCREG_FPSR) {
// Read FPSCR and extract FPSR value
FPSCR fpscr = thread->readMiscRegNoEffect(MISCREG_FPSCR);
const uint32_t ones = (uint32_t)(-1);
FPSCR fpsrMask = 0;
fpsrMask.ioc = ones;
fpsrMask.dzc = ones;
fpsrMask.ofc = ones;
fpsrMask.ufc = ones;
fpsrMask.ixc = ones;
fpsrMask.idc = ones;
fpsrMask.qc = ones;
fpsrMask.v = ones;
fpsrMask.c = ones;
fpsrMask.z = ones;
fpsrMask.n = ones;
values.push_back(fpscr & fpsrMask);
} else {
value_lo = thread->readMiscRegNoEffect(it->index);
values.push_back(thread->readMiscRegNoEffect(it->index));
}
break;
default:
panic("Unknown TARMAC trace record type!");
}
if (value_lo != it->valueLo ||
(check_value_hi && (value_hi != it->valueHi))) {
if (!mismatch)
TarmacParserRecord::printMismatchHeader(inst, pc);
outs << "diff> [" << it->repr << "] gem5: 0x";
if (check_value_hi)
outs << hex << setfill('0') << setw(16) << value_hi
<< setfill('0') << setw(16) << value_lo;
else
outs << hex << value_lo;
outs << ", TARMAC: 0x";
if (check_value_hi)
outs << hex << setfill('0') << setw(16) << it->valueHi
<< setfill('0') << setw(16) << it->valueLo << endl;
else
outs << it->valueLo << endl;
mismatch = true;
bool same = true;
if (values.size() != it->values.size()) same = false;
uint32_t size = values.size();
if (size > it->values.size())
size = it->values.size();
if (same) {
for (int i = 0; i < size; ++i) {
if (values[i] != it->values[i]) {
same = false;
break;
}
}
}
check_value_hi = false;
if (!same) {
if (!mismatch) {
TarmacParserRecord::printMismatchHeader(inst, pc);
mismatch = true;
}
outs << "diff> [" << it->repr << "] gem5: 0x" << hex;
for (auto v : values)
outs << setw(16) << setfill('0') << v;
outs << ", TARMAC: 0x" << hex;
for (auto v : it->values)
outs << setw(16) << setfill('0') << v;
outs << endl;
}
}
destRegRecords.clear();
@@ -766,6 +863,9 @@ TarmacParserRecord::TarmacParserRecord(Tick _when, ThreadContext *_thread,
mismatchOnPcOrOpcode(false), parent(_parent)
{
memReq = std::make_shared<Request>();
if (maxVectorLength == 0) {
maxVectorLength = ArmStaticInst::getCurSveVecLen<uint64_t>(_thread);
}
}
void
@@ -936,6 +1036,7 @@ TarmacParserRecord::advanceTrace()
} else if (buf[0] == 'R') {
// Register trace record
currRecordType = TARMAC_REG;
regRecord.values.clear();
trace >> buf;
strcpy(regRecord.repr, buf);
if (buf[0] == 'r' && isdigit(buf[1])) {
@@ -981,6 +1082,14 @@ TarmacParserRecord::advanceTrace()
// Q register
regRecord.type = REG_Q;
regRecord.index = atoi(&buf[1]);
} else if (buf[0] == 'z' && isdigit(buf[1])) {
// Z (SVE vector) register
regRecord.type = REG_Z;
regRecord.index = atoi(&buf[1]);
} else if (buf[0] == 'p' && isdigit(buf[1])) {
// P (SVE predicate) register
regRecord.type = REG_P;
regRecord.index = atoi(&buf[1]);
} else if (strncmp(buf, "SP_EL", 5) == 0) {
// A64 stack pointer
regRecord.type = REG_X;
@@ -1008,20 +1117,38 @@ TarmacParserRecord::advanceTrace()
if (regRecord.type == REG_Q) {
trace.ignore();
trace.get(buf, 17);
// buf[16] = '\0';
regRecord.valueHi = strtoull(buf, NULL, 16);
uint64_t hi = strtoull(buf, NULL, 16);
trace.get(buf, 17);
// buf[16] = '\0';
regRecord.valueLo = strtoull(buf, NULL, 16);
uint64_t lo = strtoull(buf, NULL, 16);
regRecord.values.push_back(lo);
regRecord.values.push_back(hi);
} else if (regRecord.type == REG_Z) {
regRecord.values.resize(maxVectorLength);
for (uint8_t i = 0; i < maxVectorLength; ++i) {
uint64_t v;
trace >> v;
char c;
trace >> c;
assert(c == '_');
uint64_t lsw = 0;
trace >> lsw;
v = (v << 32) | lsw;
if (i < maxVectorLength - 1) trace >> c;
regRecord.values[i] = v;
}
} else {
trace >> regRecord.valueLo;
// REG_P values are also parsed here
uint64_t v;
trace >> v;
char c = trace.peek();
if (c == ':') {
// 64-bit value with colon in the middle
if ((c == ':') || (c == '_')) {
// 64-bit value with : or _ in the middle
uint64_t lsw = 0;
trace >> c >> lsw;
regRecord.valueLo = (regRecord.valueLo << 32) | lsw;
v = (v << 32) | lsw;
}
regRecord.values.push_back(v);
}
trace.ignore(MaxLineLength, '\n');
buf[0] = 0;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011,2017-2018 ARM Limited
* Copyright (c) 2011,2017-2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -199,6 +199,9 @@ class TarmacParserRecord : public TarmacBaseRecord
/** Request for memory write checks. */
RequestPtr memReq;
/** Max. vector length (SVE). */
static int8_t maxVectorLength;
protected:
TarmacParser& parent;
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 ARM Limited
* Copyright (c) 2017-2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -195,7 +195,7 @@ TarmacTracerRecord::TraceRegEntry::updateMisc(
regValid = true;
regName = miscRegName[regRelIdx];
valueLo = thread->readMiscRegNoEffect(regRelIdx);
values[Lo] = thread->readMiscRegNoEffect(regRelIdx);
// If it is the CPSR:
// update the value of the CPSR register and add
@@ -208,7 +208,7 @@ TarmacTracerRecord::TraceRegEntry::updateMisc(
cpsr.ge = thread->readCCReg(CCREG_GE);
// update the entry value
valueLo = cpsr;
values[Lo] = cpsr;
}
}
@@ -222,7 +222,7 @@ TarmacTracerRecord::TraceRegEntry::updateCC(
regValid = true;
regName = ccRegName[regRelIdx];
valueLo = thread->readCCReg(regRelIdx);
values[Lo] = thread->readCCReg(regRelIdx);
}
void
@@ -235,7 +235,7 @@ TarmacTracerRecord::TraceRegEntry::updateFloat(
regValid = true;
regName = "f" + std::to_string(regRelIdx);
valueLo = bitsToFloat32(thread->readFloatReg(regRelIdx));
values[Lo] = bitsToFloat32(thread->readFloatReg(regRelIdx));
}
void
@@ -275,7 +275,7 @@ TarmacTracerRecord::TraceRegEntry::updateInt(
regName = "r" + std::to_string(regRelIdx);
break;
}
valueLo = thread->readIntReg(regRelIdx);
values[Lo] = thread->readIntReg(regRelIdx);
}
void
@@ -451,7 +451,7 @@ TarmacTracerRecord::TraceRegEntry::print(
ccprintf(outs, "%s clk R %s %08x\n",
curTick(), /* Tick time */
regName, /* Register name */
valueLo); /* Register value */
values[Lo]); /* Register value */
}
} // namespace Trace

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 ARM Limited
* Copyright (c) 2017-2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -241,7 +241,7 @@ TarmacTracerRecordV8::TraceRegEntryV8::print(
cpuName, /* Cpu name */
regName, /* Register name */
regWidth >> 2, /* Register value padding */
valueLo); /* Register value */
values[Lo]); /* Register value */
}
}