diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh index 7b041f61b2..a60c887391 100644 --- a/src/arch/arm/isa.hh +++ b/src/arch/arm/isa.hh @@ -435,6 +435,8 @@ namespace ArmISA void globalClearExclusive() override; void globalClearExclusive(ExecContext *xc) override; + + int64_t getVectorLengthInBytes() const override { return sveVL * 16; } }; } // namespace ArmISA diff --git a/src/arch/generic/isa.hh b/src/arch/generic/isa.hh index 07ff5a5226..b324591995 100644 --- a/src/arch/generic/isa.hh +++ b/src/arch/generic/isa.hh @@ -137,6 +137,15 @@ class BaseISA : public SimObject { SERIALIZE_SCALAR(isaName); } + + /** + * This function returns the vector length of the Vector Length Agnostic + * extension of the ISA. + * For ARM ISA, this function returns the SVE/SVE2 vector length. + * For RISC-V ISA, this function returns the RVV vector length. + * For other ISAs, this function returns -1. + */ + virtual int64_t getVectorLengthInBytes() const { return -1; } }; } // namespace gem5 diff --git a/src/arch/generic/vec_reg.hh b/src/arch/generic/vec_reg.hh index 349811f1f0..d643c9db5b 100644 --- a/src/arch/generic/vec_reg.hh +++ b/src/arch/generic/vec_reg.hh @@ -99,7 +99,9 @@ #include #include +#include #include +#include #include #include "base/cprintf.hh" @@ -218,6 +220,24 @@ class VecRegContainer return os; } + std::string + getString(const uint64_t& size) const + { + std::stringstream s; + size_t count = 0; + s << "["; + for (auto& b: container) { + if (count && (count % 4) == 0) + s << "_"; + s << std::hex << std::setfill('0') << std::setw(2) << (uint16_t)b; + count++; + if (count == size) + break; + } + s << "]"; + return s.str(); + } + /** @} */ /** * Used for serialization. diff --git a/src/arch/riscv/insts/vector.cc b/src/arch/riscv/insts/vector.cc index dca0259bd5..d73fb93882 100644 --- a/src/arch/riscv/insts/vector.cc +++ b/src/arch/riscv/insts/vector.cc @@ -464,8 +464,9 @@ VMaskMergeMicroInst::execute(ExecContext* xc, memcpy(Vd + i * byte_offset, s + i * byte_offset, byte_offset); } } - if (traceData) + if (traceData) { traceData->setData(vecRegClass, &tmp_d0); + } return NoFault; } @@ -666,8 +667,9 @@ VlSegDeIntrlvMicroInst::execute(ExecContext* xc, trace::InstRecord* traceData) c elem++; } } - if (traceData) + if (traceData) { traceData->setData(vecRegClass, &tmp_d0); + } return NoFault; } @@ -776,8 +778,9 @@ VsSegIntrlvMicroInst::execute(ExecContext* xc, } } - if (traceData) + if (traceData) { traceData->setData(vecRegClass, &tmp_d0); + } return NoFault; } diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 8622bf2338..9c0fd70f35 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -166,6 +166,8 @@ class ISA : public BaseISA unsigned getVecLenInBytes() { return vlen >> 3; } unsigned getVecElemLenInBits() { return elen; } + int64_t getVectorLengthInBytes() const override { return vlen >> 3; } + PrivilegeModeSet getPrivilegeModeSet() { return _privilegeModeSet; } virtual Addr getFaultHandlerAddr( diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 2be3557d4b..89c9a66e74 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -115,10 +115,15 @@ ExeTracerRecord::traceInst(const StaticInstPtr &inst, bool ran) } if (debug::ExecResult && dataStatus != DataInvalid) { - if (dataStatus == DataReg) - ccprintf(outs, " D=%s", data.asReg.asString()); - else + if (dataStatus == DataReg) { + if (vectorLengthInBytes > 0 && inst->isVector()) { + outs << " D=" << data.asReg.asString(vectorLengthInBytes); + } else { + ccprintf(outs, " D=%s", data.asReg.asString()); + } + } else { ccprintf(outs, " D=%#018x", data.asInt); + } } if (debug::ExecEffAddr && getMemValid()) diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index 3fbeb98bc3..0b77795c5b 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -66,6 +66,7 @@ class ExeTracerRecord : public InstRecord : InstRecord(_when, _thread, _staticInst, _pc, _macroStaticInst), tracer(_tracer) { + vectorLengthInBytes = _thread->getIsaPtr()->getVectorLengthInBytes(); } void traceInst(const StaticInstPtr &inst, bool ran); @@ -74,6 +75,7 @@ class ExeTracerRecord : public InstRecord protected: const ExeTracer &tracer; + int64_t vectorLengthInBytes; }; class ExeTracer : public InstTracer diff --git a/src/cpu/inst_res.hh b/src/cpu/inst_res.hh index 30bb2b262b..bfcf4fd461 100644 --- a/src/cpu/inst_res.hh +++ b/src/cpu/inst_res.hh @@ -176,6 +176,13 @@ class InstResult return _regClass->valString(®); } } + + std::string + asString(const int64_t& num_bytes) const + { + assert(blob()); + return _regClass->valString(getBlob(), num_bytes); + } }; } // namespace gem5 diff --git a/src/cpu/reg_class.cc b/src/cpu/reg_class.cc index 12d1c7f2e0..a72156195c 100644 --- a/src/cpu/reg_class.cc +++ b/src/cpu/reg_class.cc @@ -56,7 +56,7 @@ RegClassOps::regName(const RegId &id) const } std::string -RegClassOps::valString(const void *val, size_t size) const +RegClassOps::valString(const void *val, const size_t& size) const { // If this is just a RegVal, or could be interpreted as one, print it // that way. diff --git a/src/cpu/reg_class.hh b/src/cpu/reg_class.hh index 37618e530a..68a3fb8023 100644 --- a/src/cpu/reg_class.hh +++ b/src/cpu/reg_class.hh @@ -45,6 +45,7 @@ #include #include +#include "arch/generic/vec_reg.hh" #include "base/cprintf.hh" #include "base/debug.hh" #include "base/intmath.hh" @@ -170,7 +171,7 @@ class RegClassOps /** Print the name of the register specified in id. */ virtual std::string regName(const RegId &id) const; /** Print the value of a register pointed to by val of size size. */ - virtual std::string valString(const void *val, size_t size) const; + virtual std::string valString(const void *val, const size_t& size) const; /** Flatten register id id using information in the ISA object isa. */ virtual RegId flatten(const BaseISA &isa, const RegId &id) const @@ -246,6 +247,11 @@ class RegClass { return _ops->valString(val, regBytes()); } + std::string + valString(const void *val, const uint64_t& num_bytes) const + { + return _ops->valString(val, std::min(regBytes(), num_bytes)); + } RegId flatten(const BaseISA &isa, const RegId &id) const { @@ -354,15 +360,30 @@ RegClass::operator[](RegIndex idx) const return RegId(*this, idx); } +// Type matching for gem5::VecRegContainer class +// This is used in TypedRegClassOps. +template +struct is_vec_reg_container : std::false_type {}; +template +struct is_vec_reg_container> : std::true_type {}; + template class TypedRegClassOps : public RegClassOps { public: std::string - valString(const void *val, size_t size) const override + valString(const void *val, const size_t& size) const override { - assert(size == sizeof(ValueType)); - return csprintf("%s", *(const ValueType *)val); + if constexpr (is_vec_reg_container::value) { + if (size == sizeof(ValueType)) { + return csprintf("%s", *(const ValueType *)val); + } else { + return ((const ValueType *)val)->getString(size); + } + } else { + assert(size == sizeof(ValueType)); + return csprintf("%s", *(const ValueType *)val); + } } }; diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh index 37e29756a2..1a4b3119ae 100644 --- a/src/sim/insttracer.hh +++ b/src/sim/insttracer.hh @@ -232,14 +232,38 @@ class InstRecord setData(const RegClass ®_class, RegVal val) { new(&data.asReg) InstResult(reg_class, val); - dataStatus = DataReg; + switch (reg_class.type()) { + case IntRegClass: + case MiscRegClass: + case CCRegClass: + dataStatus = DataInt64; + break; + case FloatRegClass: + dataStatus = DataDouble; + break; + default: + dataStatus = DataReg; + break; + } } void setData(const RegClass ®_class, const void *val) { new(&data.asReg) InstResult(reg_class, val); - dataStatus = DataReg; + switch (reg_class.type()) { + case IntRegClass: + case MiscRegClass: + case CCRegClass: + dataStatus = DataInt64; + break; + case FloatRegClass: + dataStatus = DataDouble; + break; + default: + dataStatus = DataReg; + break; + } } void