From 68a4a2de66430e4d435726182f930acbd9a91b8b Mon Sep 17 00:00:00 2001 From: Giacomo Gabrielli Date: Mon, 30 Sep 2019 14:30:48 +0100 Subject: [PATCH] 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 Reviewed-by: Giacomo Gabrielli Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21560 Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini Tested-by: kokoro --- src/arch/arm/tracers/tarmac_base.cc | 7 +- src/arch/arm/tracers/tarmac_base.hh | 14 +- src/arch/arm/tracers/tarmac_parser.cc | 243 +++++++++++++++++------ src/arch/arm/tracers/tarmac_parser.hh | 5 +- src/arch/arm/tracers/tarmac_record.cc | 14 +- src/arch/arm/tracers/tarmac_record_v8.cc | 4 +- 6 files changed, 213 insertions(+), 74 deletions(-) diff --git a/src/arch/arm/tracers/tarmac_base.cc b/src/arch/arm/tracers/tarmac_base.cc index 3b6201def..c32784886 100644 --- a/src/arch/arm/tracers/tarmac_base.cc +++ b/src/arch/arm/tracers/tarmac_base.cc @@ -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 ( diff --git a/src/arch/arm/tracers/tarmac_base.hh b/src/arch/arm/tracers/tarmac_base.hh index 4e6cbe0f3..4cd18487f 100644 --- a/src/arch/arm/tracers/tarmac_base.hh +++ b/src/arch/arm/tracers/tarmac_base.hh @@ -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 values; }; /** TARMAC memory access trace record (stores only). */ diff --git a/src/arch/arm/tracers/tarmac_parser.cc b/src/arch/arm/tracers/tarmac_parser.cc index 04a2a051e..9089e3f6d 100644 --- a/src/arch/arm/tracers/tarmac_parser.cc +++ b/src/arch/arm/tracers/tarmac_parser.cc @@ -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::iterator it = destRegRecords.begin(), end = destRegRecords.end(); - uint64_t value_hi, value_lo; - bool check_value_hi = false; + std::vector 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + if (maxVectorLength == 0) { + maxVectorLength = ArmStaticInst::getCurSveVecLen(_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; diff --git a/src/arch/arm/tracers/tarmac_parser.hh b/src/arch/arm/tracers/tarmac_parser.hh index afba50fef..ab0c49b9b 100644 --- a/src/arch/arm/tracers/tarmac_parser.hh +++ b/src/arch/arm/tracers/tarmac_parser.hh @@ -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; }; diff --git a/src/arch/arm/tracers/tarmac_record.cc b/src/arch/arm/tracers/tarmac_record.cc index 51fbf2c0a..d3df6895c 100644 --- a/src/arch/arm/tracers/tarmac_record.cc +++ b/src/arch/arm/tracers/tarmac_record.cc @@ -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 diff --git a/src/arch/arm/tracers/tarmac_record_v8.cc b/src/arch/arm/tracers/tarmac_record_v8.cc index 90f1a6fc3..f17016124 100644 --- a/src/arch/arm/tracers/tarmac_record_v8.cc +++ b/src/arch/arm/tracers/tarmac_record_v8.cc @@ -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 */ } } -- 2.30.2