diff --git a/src/STLExtras.h b/src/STLExtras.h index f75705066..78a373099 100644 --- a/src/STLExtras.h +++ b/src/STLExtras.h @@ -417,6 +417,69 @@ auto find_if_not(R &&Range, UnaryPredicate P) { return std::find_if_not(adl_begin(Range), adl_end(Range), P); } +/// An STL-style algorithm similar to std::for_each that applies a second +/// functor between every pair of elements. +/// +/// This provides the control flow logic to, for example, print a +/// comma-separated list: +/// \code +/// interleave(names.begin(), names.end(), +/// [&](StringRef name) { os << name; }, +/// [&] { os << ", "; }); +/// \endcode +template ::value && + !std::is_constructible::value>> +inline void interleave(ForwardIterator begin, ForwardIterator end, + UnaryFunctor each_fn, NullaryFunctor between_fn) { + if (begin == end) + return; + each_fn(*begin); + ++begin; + for (; begin != end; ++begin) { + between_fn(); + each_fn(*begin); + } +} + +template ::value && + !std::is_constructible::value>> +inline void interleave(const Container &c, UnaryFunctor each_fn, + NullaryFunctor between_fn) { + interleave(c.begin(), c.end(), each_fn, between_fn); +} + +/// Overload of interleave for the common case of string separator. +template > +inline void interleave(const Container &c, StreamT &os, UnaryFunctor each_fn, + const std::string_view &separator) { + interleave(c.begin(), c.end(), each_fn, [&] { os << separator; }); +} +template > +inline void interleave(const Container &c, StreamT &os, + const std::string_view &separator) { + interleave( + c, os, [&](const T &a) { os << a; }, separator); +} + +template > +inline void interleaveComma(const Container &c, StreamT &os, + UnaryFunctor each_fn) { + interleave(c, os, each_fn, ", "); +} +template > +inline void interleaveComma(const Container &c, StreamT &os) { + interleaveComma(c, os, [&](const T &a) { os << a; }); +} + } // namespace llvm #endif // LLVM_ADT_STLEXTRAS_H diff --git a/src/addressdialog.h b/src/addressdialog.h index 3eaf6cf76..fde48d6e0 100644 --- a/src/addressdialog.h +++ b/src/addressdialog.h @@ -2,7 +2,7 @@ #include -#include "ripes_types.h" +#include "isa/isa_types.h" namespace Ripes { diff --git a/src/assembler/assembler.h b/src/assembler/assembler.h index 9cec73e47..f7c04e9ff 100644 --- a/src/assembler/assembler.h +++ b/src/assembler/assembler.h @@ -5,9 +5,9 @@ #include "assembler_defines.h" #include "isa/instruction.h" #include "isa/isa_defines.h" +#include "isa/isa_types.h" #include "isa/pseudoinstruction.h" #include "matcher.h" -#include "ripes_types.h" #include #include diff --git a/src/assembler/program.h b/src/assembler/program.h index 5923c370c..6d4500d5b 100644 --- a/src/assembler/program.h +++ b/src/assembler/program.h @@ -10,7 +10,7 @@ #include #include "isa/isa_defines.h" -#include "ripes_types.h" +#include "isa/isa_types.h" namespace Ripes { diff --git a/src/binutils.h b/src/binutils.h index 16a86ff89..48039d482 100644 --- a/src/binutils.h +++ b/src/binutils.h @@ -5,8 +5,8 @@ #include #include "VSRTL/interface/vsrtl_binutils.h" +#include "isa/isa_types.h" #include "limits.h" -#include "ripes_types.h" /// Most of the code in this file originates from LLVM MathExtras.h diff --git a/src/cachesim/cacheview.h b/src/cachesim/cacheview.h index e7504e626..c121ebe3a 100644 --- a/src/cachesim/cacheview.h +++ b/src/cachesim/cacheview.h @@ -2,7 +2,7 @@ #include -#include "ripes_types.h" +#include "isa/isa_types.h" namespace Ripes { diff --git a/src/cachesim/l1cacheshim.h b/src/cachesim/l1cacheshim.h index 045128f89..45b16a8bf 100644 --- a/src/cachesim/l1cacheshim.h +++ b/src/cachesim/l1cacheshim.h @@ -5,7 +5,7 @@ #include "cachesim.h" #include "VSRTL/core/vsrtl_memory.h" -#include "ripes_types.h" +#include "isa/isa_types.h" namespace Ripes { diff --git a/src/cachetab.h b/src/cachetab.h index b20b149fd..528196b1c 100644 --- a/src/cachetab.h +++ b/src/cachetab.h @@ -3,7 +3,7 @@ #include "ripestab.h" #include -#include "ripes_types.h" +#include "isa/isa_types.h" namespace Ripes { diff --git a/src/cli/clioptions.cpp b/src/cli/clioptions.cpp index 80f506248..a2c1715d8 100644 --- a/src/cli/clioptions.cpp +++ b/src/cli/clioptions.cpp @@ -5,6 +5,11 @@ #include #include +#include +#include + +#include "STLExtras.h" + namespace Ripes { void addCLIOptions(QCommandLineParser &parser, Ripes::CLIModeOptions &options) { @@ -27,9 +32,10 @@ void addCLIOptions(QCommandLineParser &parser, Ripes::CLIModeOptions &options) { parser.addOption(QCommandLineOption( "reginit", "Comma-separated list of register initialization values. The register " - "value may be specified in signed, hex, or boolean notation. Format:\n" - "=,=", - "[rid:v]")); + "value may be specified in signed, hex, or boolean notation. Can be used " + "multiple times to initialize more than one register file type. Format:\n" + ":=,=", + "regfile:[rid=v]")); parser.addOption(QCommandLineOption( "timeout", "Simulation timeout in milliseconds. If simulation does not finish " @@ -136,44 +142,77 @@ bool parseCLIOptions(QCommandLineParser &parser, QString &errorMessage, // Validate register initializations if (parser.isSet("reginit")) { - QStringList regInitList = parser.value("reginit").split(","); - for (auto ®Init : regInitList) { - QStringList regInitParts = regInit.split("="); - if (regInitParts.size() != 2) { - errorMessage = "Invalid register initialization '" + regInit + - "' specified (--reginit)."; - return false; - } - bool ok; - int regIdx = regInitParts[0].toInt(&ok); - if (!ok) { - errorMessage = "Invalid register index '" + regInitParts[0] + - "' specified (--reginit)."; - return false; - } - - auto &vstr = regInitParts[1]; - VInt regVal; - if (vstr.startsWith("0x")) - regVal = decodeRadixValue(vstr, Radix::Hex, &ok); - else if (vstr.startsWith("0b")) - regVal = decodeRadixValue(vstr, Radix::Binary, &ok); - else - regVal = decodeRadixValue(vstr, Radix::Signed, &ok); - - if (!ok) { - errorMessage = - "Invalid register value '" + vstr + "' specified (--reginit)."; + const auto &procisa = + ProcessorRegistry::getAvailableProcessors().at(options.proc)->isaInfo(); + const auto *isa = procisa.isa.get(); + for (const auto ®FileInit : parser.values("reginit")) { + if (!regFileInit.contains(':')) { + errorMessage = "Cannot find register file type (--reginit)."; return false; } - - if (options.regInit.count(regIdx) > 0) { - errorMessage = "Duplicate register initialization for register " + - QString::number(regIdx) + " specified (--reginit)."; - return false; + auto regFileSplit = regFileInit.indexOf(':'); + QString regFile = regFileInit.mid(0, regFileSplit); + + QStringList regInitList = regFileInit.mid(regFileSplit + 1).split(","); + for (auto ®Init : regInitList) { + QStringList regInitParts = regInit.split("="); + if (regInitParts.size() != 2) { + errorMessage = "Invalid register initialization '" + regInit + + "' specified (--reginit)."; + return false; + } + bool ok; + int regIdx = regInitParts[0].toInt(&ok); + if (!ok) { + errorMessage = "Invalid register index '" + regInitParts[0] + + "' specified (--reginit)."; + return false; + } + + auto &vstr = regInitParts[1]; + VInt regVal = decodeRadixValue(vstr, &ok); + + if (!ok) { + errorMessage = + "Invalid register value '" + vstr + "' specified (--reginit)."; + return false; + } + + std::string_view rfid = ""; + auto fileNames = isa->regFileNames(); + for (const auto ®FileName : fileNames) { + if (regFile == QString(regFileName.data())) { + rfid = regFileName; + break; + } + } + if (rfid.empty()) { + errorMessage = "Invalid register file type '" + regFile + + "' specified (--reginit). Valid types for '" + + parser.value("proc") + "' with extensions ["; + std::stringstream extInfo; + std::string isaExtensions = + options.isaExtensions.join("").toStdString(); + llvm::interleaveComma(isaExtensions, extInfo); + extInfo << "]: ["; + llvm::interleaveComma(fileNames, extInfo); + extInfo << "]"; + errorMessage += extInfo.str(); + return false; + } + + if (options.regInit.count(rfid) == 0) { + options.regInit[rfid] = {{regIdx, regVal}}; + } else { + if (options.regInit.at(rfid).count(regIdx) > 0) { + errorMessage = "Duplicate register initialization for register " + + QString::number(regIdx) + " specified (--reginit)."; + return false; + } + + options.regInit[rfid][regIdx] = regVal; + } } - - options.regInit[regIdx] = regVal; } } diff --git a/src/cli/telemetry.h b/src/cli/telemetry.h index 824d6b74f..67ecbda06 100644 --- a/src/cli/telemetry.h +++ b/src/cli/telemetry.h @@ -117,22 +117,26 @@ class RegisterTelemetry : public Telemetry { QVariant report(bool json) override { QVariantMap registerMap; auto isa = ProcessorHandler::currentISA(); - auto regInfo = isa->regInfo().value(); if (json) { - for (unsigned i = 0; i < regInfo->regCnt(); i++) { - registerMap[regInfo->regName(i)] = QVariant::fromValue( - ProcessorHandler::getRegisterValue(RegisterFileType::GPR, i)); + for (const auto ®File : isa->regInfos()) { + for (unsigned i = 0; i < regFile->regCnt(); i++) { + registerMap[regFile->regName(i)] = QVariant::fromValue( + ProcessorHandler::getRegisterValue(regFile->regFileName(), i)); + } } return registerMap; } else { QString outStr; QTextStream out(&outStr); - for (unsigned i = 0; i < regInfo->regCnt(); i++) { - auto v = ProcessorHandler::getRegisterValue(RegisterFileType::GPR, i); - out << regInfo->regName(i) << ":\t" - << encodeRadixValue(v, Radix::Signed, isa->bytes()) << "\t"; - out << "(" << encodeRadixValue(v, Radix::Hex, isa->bytes()) << ")\n"; + for (const auto ®File : isa->regInfos()) { + for (unsigned i = 0; i < regFile->regCnt(); i++) { + auto v = + ProcessorHandler::getRegisterValue(regFile->regFileName(), i); + out << regFile->regName(i) << ":\t" + << encodeRadixValue(v, Radix::Signed, isa->bytes()) << "\t"; + out << "(" << encodeRadixValue(v, Radix::Hex, isa->bytes()) << ")\n"; + } } return outStr; } diff --git a/src/gotocombobox.cpp b/src/gotocombobox.cpp index bf848efc4..a4b022f87 100644 --- a/src/gotocombobox.cpp +++ b/src/gotocombobox.cpp @@ -31,8 +31,13 @@ void GoToComboBox::showPopup() { void GoToComboBox::signalFilter(int index) { const auto &value = itemData(index); - const auto f = qvariant_cast(value); - switch (f.func) { + GoToUserData data; + if (value.metaType() == QMetaType::fromType()) { + data = qvariant_cast(value); + } else { + data = qvariant_cast(value); + } + switch (data.func) { case GoToFunction::Select: break; case GoToFunction::Address: { @@ -73,16 +78,18 @@ AInt GoToSectionComboBox::addrForIndex(int i) { void GoToRegisterComboBox::addTargets() { const auto &isa = ProcessorHandler::currentISA(); - const auto regInfo = isa->regInfo().value(); - for (unsigned i = 0; i < regInfo->regCnt(); ++i) { - addItem(regInfo->regName(i) + " (" + regInfo->regAlias(i) + ")", - QVariant::fromValue({GoToFunction::Custom, i})); + for (const auto ®Info : isa->regInfos()) { + for (unsigned i = 0; i < regInfo->regCnt(); ++i) { + addItem(regInfo->regName(i) + " (" + regInfo->regAlias(i) + ")", + QVariant::fromValue( + {{GoToFunction::Custom, i}, regInfo->regFileName()})); + } } } AInt GoToRegisterComboBox::addrForIndex(int i) { - const auto ®Idx = qvariant_cast(itemData(i)); - return ProcessorHandler::getRegisterValue(RegisterFileType::GPR, regIdx.arg); + const auto ®Idx = qvariant_cast(itemData(i)); + return ProcessorHandler::getRegisterValue(regIdx.regFileName, regIdx.arg); } } // namespace Ripes diff --git a/src/gotocombobox.h b/src/gotocombobox.h index c318512fd..2a4c004d7 100644 --- a/src/gotocombobox.h +++ b/src/gotocombobox.h @@ -3,7 +3,7 @@ #include #include -#include "ripes_types.h" +#include "isa/isa_types.h" namespace Ripes { @@ -13,6 +13,10 @@ struct GoToUserData { unsigned arg; }; +struct GoToRegisterValue : public GoToUserData { + std::string_view regFileName; +}; + class GoToComboBox : public QComboBox { Q_OBJECT public: @@ -50,3 +54,4 @@ class GoToRegisterComboBox : public GoToComboBox { } // namespace Ripes Q_DECLARE_METATYPE(Ripes::GoToUserData); +Q_DECLARE_METATYPE(Ripes::GoToRegisterValue); diff --git a/src/isa/isa_defines.h b/src/isa/isa_defines.h index 629ab5ae3..90c14a3a4 100644 --- a/src/isa/isa_defines.h +++ b/src/isa/isa_defines.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -10,7 +9,7 @@ #include #include -#include "ripes_types.h" +#include "isa_types.h" namespace Ripes { diff --git a/src/ripes_types.h b/src/isa/isa_types.h similarity index 100% rename from src/ripes_types.h rename to src/isa/isa_types.h diff --git a/src/isa/isainfo.h b/src/isa/isainfo.h index 3f891fcb5..5b72ae155 100644 --- a/src/isa/isainfo.h +++ b/src/isa/isainfo.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "elfio/elf_types.hpp" @@ -15,21 +16,17 @@ namespace Ripes { enum class ISA { RV32I, RV64I, MIPS32I }; const static std::map ISAFamilyNames = { {ISA::RV32I, "RISC-V"}, {ISA::RV64I, "RISC-V"}, {ISA::MIPS32I, "MIPS"}}; -enum class RegisterFileType { GPR, FPR, CSR }; struct RegisterFileName { QString shortName; QString longName; }; -/// Maintain a mapping between register file enum's and their string -/// representation. -const static std::map s_RegsterFileName = { - {RegisterFileType::GPR, {"GPR", "General purpose registers"}}, - {RegisterFileType::FPR, {"FPR", "Floating-point registers"}}, - {RegisterFileType::CSR, {"CSR", "Control and status registers"}}}; - -struct RegInfoBase { - virtual RegisterFileType regFileType() const = 0; +/// An interface into a register file. +struct RegFileInfoInterface { + /// Returns this register file's type. + virtual std::string_view regFileName() const = 0; + /// Returns this register file's description. + virtual std::string_view regFileDesc() const = 0; /// Returns the number of registers in the instruction set. virtual unsigned regCnt() const = 0; /// Returns the canonical name of the i'th register in the ISA. @@ -47,28 +44,45 @@ struct RegInfoBase { virtual bool regIsReadOnly(unsigned i) const = 0; }; +/// An index into a single register. +struct RegIndex { + const std::shared_ptr file; + const unsigned index; +}; + +using RegInfoVec = std::vector>; +using RegInfoMap = + std::map>; + /// The ISAInfoBase class defines an interface for instruction set information. class ISAInfoBase { public: virtual ~ISAInfoBase(){}; virtual QString name() const = 0; virtual ISA isaID() const = 0; + virtual const RegInfoMap ®InfoMap() const = 0; - std::optional - regInfo(RegisterFileType regFileType = RegisterFileType::GPR) const { - if (auto match = m_regInfos.find(regFileType); match != m_regInfos.end()) { - return m_regInfos.at(regFileType).get(); - } else { - return {}; + std::set regFileNames() const { + std::set names; + for (const auto ®Info : regInfoMap()) { + names.insert(regInfo.second->regFileName()); } + return names; } - /// Returns the total number of registers in the instruction set. - unsigned regCnt() const { - unsigned count = 0; - for (const auto &pair : m_regInfos) { - count += pair.second->regCnt(); + RegInfoVec regInfos() const { + RegInfoVec regVec; + for (const auto ®Info : regInfoMap()) { + regVec.emplace_back(regInfo.second); } - return count; + return regVec; + } + std::optional + regInfo(const std::string_view ®FileName) const { + if (auto match = regInfoMap().find(regFileName); + match != regInfoMap().end()) { + return {regInfoMap().at(regFileName).get()}; + } + return {}; } virtual unsigned bits() const = 0; // Register width, in bits @@ -81,13 +95,17 @@ class ISAInfoBase { } // Instruction width, in bytes virtual unsigned instrByteAlignment() const { return 0; - } // Instruction Alignment, in bytes - virtual int spReg() const { return -1; } // Stack pointer - virtual int gpReg() const { return -1; } // Global pointer - virtual int syscallReg() const { return -1; } // Syscall function register + } // Instruction Alignment, in bytes + virtual std::optional spReg() const { return {}; } // Stack pointer + virtual std::optional gpReg() const { return {}; } // Global pointer + virtual std::optional syscallReg() const { + return {}; + } // Syscall function register // Mapping between syscall argument # and the corresponding register # wherein // that argument is passed. - virtual int syscallArgReg(unsigned /*argIdx*/) const { return -1; } + virtual std::optional syscallArgReg(unsigned /*argIdx*/) const { + return {}; + } // GCC Compile command architecture and ABI specification strings virtual QString CCmarch() const = 0; @@ -135,8 +153,6 @@ class ISAInfoBase { protected: ISAInfoBase() {} - - std::map> m_regInfos; }; struct ProcessorISAInfo { diff --git a/src/isa/mipsisainfo_common.h b/src/isa/mipsisainfo_common.h index 5cfe00263..8e0ec8a15 100644 --- a/src/isa/mipsisainfo_common.h +++ b/src/isa/mipsisainfo_common.h @@ -132,10 +132,12 @@ enum Function { SYSCALL = 0b001100 }; -struct MIPS_RegInfo : public RegInfoBase { - RegisterFileType regFileType() const override { - return RegisterFileType::GPR; - } +constexpr std::string_view GPR = "gpr"; +constexpr std::string_view GPR_DESC = "General purpose registers"; + +struct MIPS_GPRInfo : public RegFileInfoInterface { + std::string_view regFileName() const override { return GPR; } + std::string_view regFileDesc() const override { return GPR_DESC; } unsigned int regCnt() const override { return 34; } QString regName(unsigned i) const override { return (MIPSISA::RegNames.size() > static_cast(i) @@ -179,19 +181,27 @@ struct MIPS_RegInfo : public RegInfoBase { class MIPS_ISAInfoBase : public ISAInfoBase { public: MIPS_ISAInfoBase() { - m_regInfos[RegisterFileType::GPR] = - std::make_unique(); + m_regInfos[MIPSISA::GPR] = std::make_unique(); } + const RegInfoMap ®InfoMap() const override { return m_regInfos; } + QString name() const override { return CCmarch().toUpper(); } - int spReg() const override { return 29; } - int gpReg() const override { return 28; } - int syscallReg() const override { return 2; } + std::optional spReg() const override { + return RegIndex{m_regInfos.at(MIPSISA::GPR), 29}; + } + std::optional gpReg() const override { + return RegIndex{m_regInfos.at(MIPSISA::GPR), 28}; + } + std::optional syscallReg() const override { + return RegIndex{m_regInfos.at(MIPSISA::GPR), 2}; + } unsigned instrBits() const override { return 32; } unsigned elfMachineId() const override { return EM_MIPS; } - virtual int syscallArgReg(unsigned argIdx) const override { + virtual std::optional + syscallArgReg(unsigned argIdx) const override { assert(argIdx < 2 && "MIPS only implements argument registers a0-a7"); - return argIdx + 4; + return RegIndex{m_regInfos.at(MIPSISA::GPR), argIdx + 4}; } QString elfSupportsFlags(unsigned flags) const override { @@ -217,6 +227,7 @@ class MIPS_ISAInfoBase : public ISAInfoBase { protected: QStringList m_enabledExtensions; QStringList m_supportedExtensions = {""}; + RegInfoMap m_regInfos; }; } // namespace Ripes diff --git a/src/isa/rv_i_ext.h b/src/isa/rv_i_ext.h index 3a9979bdd..d56394091 100644 --- a/src/isa/rv_i_ext.h +++ b/src/isa/rv_i_ext.h @@ -554,7 +554,7 @@ struct Bgeu : public Instr { namespace TypePseudo { template -struct PseudoReg : public Ripes::PseudoReg {}; +struct PseudoReg : public Ripes::PseudoReg {}; template struct PseudoInstrLoad : public PseudoInstruction { diff --git a/src/isa/rvisainfo_common.h b/src/isa/rvisainfo_common.h index a23b2782b..6bdf8e861 100644 --- a/src/isa/rvisainfo_common.h +++ b/src/isa/rvisainfo_common.h @@ -62,13 +62,18 @@ struct RV_Instruction : public Instruction { constexpr static unsigned instrBits() { return INSTR_BITS; } }; -// TODO(raccog): This will be split into multiple classes; one for each register -// file. Currently, this class describes all registers in RISC-V. +constexpr std::string_view GPR = "gpr"; +constexpr std::string_view FPR = "fpr"; +constexpr std::string_view CSR = "csr"; + +constexpr std::string_view GPR_DESC = "General purpose registers"; +constexpr std::string_view FPR_DESC = "Floating-point registers"; +constexpr std::string_view CSR_DESC = "Control and status registers"; + /// Defines information about the general RISC-V register file. -struct RV_RegInfo : public RegInfoBase { - RegisterFileType regFileType() const override { - return RegisterFileType::GPR; - } +struct RV_GPRInfo : public RegFileInfoInterface { + std::string_view regFileName() const override { return GPR; } + std::string_view regFileDesc() const override { return GPR_DESC; } unsigned int regCnt() const override { return 32; } QString regName(unsigned i) const override { return RVISA::GPRRegNames.size() > static_cast(i) @@ -100,6 +105,22 @@ struct RV_RegInfo : public RegInfoBase { } }; +/// Defines information about the floating-point RISC-V register file. +struct RV_FPRInfo : public RegFileInfoInterface { + std::string_view regFileName() const override { return FPR; } + std::string_view regFileDesc() const override { return FPR_DESC; } + // TODO: Fill out RISC-V floating point register info + unsigned int regCnt() const override { return 0; } + QString regName(unsigned) const override { return QString(); } + QString regAlias(unsigned) const override { return QString(); } + QString regInfo(unsigned) const override { return QString(); } + bool regIsReadOnly(unsigned) const override { return false; } + unsigned int regNumber(const QString &, bool &success) const override { + success = false; + return 0; + } +}; + class RV_ISAInfoBase : public ISAInfoBase { public: RV_ISAInfoBase(const QStringList extensions) { @@ -112,20 +133,29 @@ class RV_ISAInfoBase : public ISAInfoBase { } } - // TODO(raccog): This map will contain more entries when register info is - // split between classes - m_regInfos[RegisterFileType::GPR] = std::make_unique(); + m_regInfos[GPR] = std::make_unique(); + if (supportsExtension("F")) { + m_regInfos[FPR] = std::make_unique(); + } } + const RegInfoMap ®InfoMap() const override { return m_regInfos; } + QString name() const override { return CCmarch().toUpper(); } - int spReg() const override { return 2; } - int gpReg() const override { return 3; } - int syscallReg() const override { return 17; } + std::optional spReg() const override { + return RegIndex{m_regInfos.at(GPR), 2}; + } + std::optional gpReg() const override { + return RegIndex{m_regInfos.at(GPR), 3}; + } + std::optional syscallReg() const override { + return RegIndex{m_regInfos.at(GPR), 17}; + } unsigned instrBits() const override { return INSTR_BITS; } unsigned elfMachineId() const override { return EM_RISCV; } - int syscallArgReg(unsigned argIdx) const override { + std::optional syscallArgReg(unsigned argIdx) const override { assert(argIdx < 8 && "RISC-V only implements argument registers a0-a7"); - return argIdx + 10; + return RegIndex{m_regInfos.at(GPR), argIdx + 10}; } QString elfSupportsFlags(unsigned flags) const override { @@ -173,6 +203,7 @@ class RV_ISAInfoBase : public ISAInfoBase { QStringList m_enabledExtensions; QStringList m_supportedExtensions = getSupportedExtensions(); + RegInfoMap m_regInfos; }; enum OpcodeID { @@ -225,7 +256,7 @@ template struct OpPartFunct7 : public OpPart> {}; template -struct GPR_Reg : public Reg {}; +struct GPR_Reg : public Reg {}; /// The RISC-V Rs1 field contains a source register index. /// It is defined as a 5-bit field in bits 15-19 of the instruction diff --git a/src/memoryviewerwidget.h b/src/memoryviewerwidget.h index 0bfd2afed..656a67084 100644 --- a/src/memoryviewerwidget.h +++ b/src/memoryviewerwidget.h @@ -2,7 +2,7 @@ #include -#include "ripes_types.h" +#include "isa/isa_types.h" namespace Ripes { diff --git a/src/processorhandler.cpp b/src/processorhandler.cpp index 817bc114c..d11a4ffee 100644 --- a/src/processorhandler.cpp +++ b/src/processorhandler.cpp @@ -287,8 +287,10 @@ void ProcessorHandler::_reset() { getProcessorNonConst()->resetProcessor(); // Rewrite register initializations - for (const auto &kv : m_currentRegInits) { - _setRegisterValue(RegisterFileType::GPR, kv.first, kv.second); + for (const auto ®FileInit : m_currentRegInits) { + for (const auto &kv : regFileInit.second) { + _setRegisterValue(regFileInit.first, kv.first, kv.second); + } } // Reset IO devices. @@ -413,9 +415,13 @@ QString ProcessorHandler::_disassembleInstr(const AInt addr) const { void ProcessorHandler::syscallTrap() { auto futureWatcher = QFutureWatcher(); futureWatcher.setFuture(QtConcurrent::run([=] { - const unsigned int function = m_currentProcessor->getRegister( - RegisterFileType::GPR, _currentISA()->syscallReg()); - return m_syscallManager->execute(function); + if (auto reg = _currentISA()->syscallReg(); reg.has_value()) { + const unsigned int function = + m_currentProcessor->getRegister(reg->file->regFileName(), reg->index); + return m_syscallManager->execute(function); + } else { + return false; + } })); futureWatcher.waitForFinished(); @@ -459,12 +465,12 @@ bool ProcessorHandler::_isExecutableAddress(AInt address) const { return false; } -void ProcessorHandler::_setRegisterValue(RegisterFileType rfid, +void ProcessorHandler::_setRegisterValue(const std::string_view &rfid, const unsigned idx, VInt value) { m_currentProcessor->setRegister(rfid, idx, value); } -VInt ProcessorHandler::_getRegisterValue(RegisterFileType rfid, +VInt ProcessorHandler::_getRegisterValue(const std::string_view &rfid, const unsigned idx) const { return m_currentProcessor->getRegister(rfid, idx); } diff --git a/src/processorhandler.h b/src/processorhandler.h index d5f628877..175a0dfce 100644 --- a/src/processorhandler.h +++ b/src/processorhandler.h @@ -133,7 +133,7 @@ class ProcessorHandler : public QObject { * @brief setRegisterValue * Set the value of register @param idx to @param value. */ - static void setRegisterValue(RegisterFileType rfid, const unsigned idx, + static void setRegisterValue(const std::string_view &rfid, const unsigned idx, VInt value) { get()->_setRegisterValue(rfid, idx, value); } @@ -150,7 +150,8 @@ class ProcessorHandler : public QObject { * @brief getRegisterValue * @returns value of register @param idx */ - static VInt getRegisterValue(RegisterFileType rfid, const unsigned idx) { + static VInt getRegisterValue(const std::string_view &rfid, + const unsigned idx) { return get()->_getRegisterValue(rfid, idx); } @@ -295,9 +296,11 @@ private slots: QString _disassembleInstr(const AInt address) const; vsrtl::core::AddressSpaceMM &_getMemory(); const vsrtl::core::AddressSpace &_getRegisters() const; - void _setRegisterValue(RegisterFileType rfid, const unsigned idx, VInt value); + void _setRegisterValue(const std::string_view &rfid, const unsigned idx, + VInt value); void _writeMem(AInt address, VInt value, int size = sizeof(VInt)); - VInt _getRegisterValue(RegisterFileType rfid, const unsigned idx) const; + VInt _getRegisterValue(const std::string_view &rfid, + const unsigned idx) const; bool _checkBreakpoint(); void _setBreakpoint(const AInt address, bool enabled); void _toggleBreakpoint(const AInt address); diff --git a/src/processorregistry.cpp b/src/processorregistry.cpp index 4b82e91df..eb64a4947 100644 --- a/src/processorregistry.cpp +++ b/src/processorregistry.cpp @@ -53,7 +53,7 @@ ProcessorRegistry::ProcessorRegistry() { {"Extended", ":/layouts/RISC-V/rvss/rv_ss_extended_layout.json", {{{0, 0}, QPointF{0.5, 0}}}}}; - defRegVals = {{2, 0x7ffffff0}, {3, 0x10000000}}; + defRegVals = {{RVISA::GPR, {{2, 0x7ffffff0}, {3, 0x10000000}}}}; addProcessor(ProcInfo>( ProcessorID::RV32_SS, "Single-cycle processor", "A single cycle processor", layouts, defRegVals)); @@ -77,7 +77,7 @@ ProcessorRegistry::ProcessorRegistry() { {{0, 2}, QPointF{0.56, 0.0}}, {{0, 3}, QPointF{0.76, 0.0}}, {{0, 4}, QPointF{0.9, 0.0}}}}}; - defRegVals = {{2, 0x7ffffff0}, {3, 0x10000000}}; + defRegVals = {{RVISA::GPR, {{2, 0x7ffffff0}, {3, 0x10000000}}}}; addProcessor(ProcInfo>( ProcessorID::RV32_5S_NO_FW_HZ, "5-stage processor w/o forwarding or hazard detection", @@ -102,7 +102,7 @@ ProcessorRegistry::ProcessorRegistry() { {{0, 2}, QPointF{0.53, 0}}, {{0, 3}, QPointF{0.78, 0}}, {{0, 4}, QPointF{0.9, 0}}}}}; - defRegVals = {{2, 0x7ffffff0}, {3, 0x10000000}}; + defRegVals = {{RVISA::GPR, {{2, 0x7ffffff0}, {3, 0x10000000}}}}; addProcessor(ProcInfo>( ProcessorID::RV32_5S_NO_HZ, "5-stage processor w/o hazard detection", rv5s_no_hz_desc, layouts, defRegVals)); @@ -125,7 +125,7 @@ ProcessorRegistry::ProcessorRegistry() { {{0, 2}, QPointF{0.53, 0}}, {{0, 3}, QPointF{0.78, 0}}, {{0, 4}, QPointF{0.9, 0}}}}}; - defRegVals = {{2, 0x7ffffff0}, {3, 0x10000000}}; + defRegVals = {{RVISA::GPR, {{2, 0x7ffffff0}, {3, 0x10000000}}}}; addProcessor(ProcInfo>( ProcessorID::RV32_5S_NO_FW, "5-Stage processor w/o forwarding unit", rv5s_no_fw_desc, layouts, defRegVals)); @@ -148,7 +148,7 @@ ProcessorRegistry::ProcessorRegistry() { {{0, 2}, QPointF{0.54, 0}}, {{0, 3}, QPointF{0.78, 0}}, {{0, 4}, QPointF{0.9, 0}}}}}; - defRegVals = {{2, 0x7ffffff0}, {3, 0x10000000}}; + defRegVals = {{RVISA::GPR, {{2, 0x7ffffff0}, {3, 0x10000000}}}}; addProcessor(ProcInfo>( ProcessorID::RV32_5S, "5-stage processor", rv5s_desc, layouts, defRegVals)); @@ -171,7 +171,7 @@ ProcessorRegistry::ProcessorRegistry() { {{1, 4}, QPointF{0.80, 1}}, {{0, 5}, QPointF{0.90, 0}}, {{1, 5}, QPointF{0.90, 1}}}}}}; - defRegVals = {{2, 0x7ffffff0}, {3, 0x10000000}}; + defRegVals = {{RVISA::GPR, {{2, 0x7ffffff0}, {3, 0x10000000}}}}; addProcessor(ProcInfo>( ProcessorID::RV32_6S_DUAL, "6-stage dual-issue processor", rv6s_desc, layouts, defRegVals)); diff --git a/src/processorregistry.h b/src/processorregistry.h index c057d20e9..92cafa93e 100644 --- a/src/processorregistry.h +++ b/src/processorregistry.h @@ -38,7 +38,8 @@ enum ProcessorID { Q_ENUM_NS(ProcessorID); // Register with the metaobject system // ============================================================================ -using RegisterInitialization = std::map; +using RegisterInitialization = + std::map>; struct Layout { QString name; QString file; diff --git a/src/processors/RISC-V/rv5s/rv5s.h b/src/processors/RISC-V/rv5s/rv5s.h index f298c5641..e349e4423 100644 --- a/src/processors/RISC-V/rv5s/rv5s.h +++ b/src/processors/RISC-V/rv5s/rv5s.h @@ -438,7 +438,7 @@ class RV5S : public RipesVSRTLProcessor { pc_reg->setInitValue(address); } AddressSpaceMM &getMemory() override { return *m_memory; } - VInt getRegister(RegisterFileType, unsigned i) const override { + VInt getRegister(const std::string_view &, unsigned i) const override { return registerFile->getRegister(i); } void finalize(FinalizeReason fr) override { @@ -476,7 +476,7 @@ class RV5S : public RipesVSRTLProcessor { return allStagesInvalid; } - void setRegister(RegisterFileType, unsigned i, VInt v) override { + void setRegister(const std::string_view &, unsigned i, VInt v) override { setSynchronousValue(registerFile->_wr_mem, i, v); } @@ -521,12 +521,12 @@ class RV5S : public RipesVSRTLProcessor { return m_enabledISA.get(); } - const std::set registerFiles() const override { - std::set rfs; - rfs.insert(RegisterFileType::GPR); + const std::set registerFiles() const override { + std::set rfs; + rfs.insert(RVISA::GPR); if (implementsISA()->extensionEnabled("F")) { - rfs.insert(RegisterFileType::FPR); + rfs.insert(RVISA::FPR); } return rfs; } diff --git a/src/processors/RISC-V/rv5s_no_fw/rv5s_no_fw.h b/src/processors/RISC-V/rv5s_no_fw/rv5s_no_fw.h index 2fcb85870..28bbc7449 100644 --- a/src/processors/RISC-V/rv5s_no_fw/rv5s_no_fw.h +++ b/src/processors/RISC-V/rv5s_no_fw/rv5s_no_fw.h @@ -412,7 +412,7 @@ class RV5S_NO_FW : public RipesVSRTLProcessor { pc_reg->setInitValue(address); } AddressSpaceMM &getMemory() override { return *m_memory; } - VInt getRegister(RegisterFileType, unsigned i) const override { + VInt getRegister(const std::string_view &, unsigned i) const override { return registerFile->getRegister(i); } void finalize(FinalizeReason fr) override { @@ -450,7 +450,7 @@ class RV5S_NO_FW : public RipesVSRTLProcessor { return allStagesInvalid; } - void setRegister(RegisterFileType, unsigned i, VInt v) override { + void setRegister(const std::string_view &, unsigned i, VInt v) override { setSynchronousValue(registerFile->_wr_mem, i, v); } @@ -495,12 +495,12 @@ class RV5S_NO_FW : public RipesVSRTLProcessor { return m_enabledISA.get(); } - const std::set registerFiles() const override { - std::set rfs; - rfs.insert(RegisterFileType::GPR); + const std::set registerFiles() const override { + std::set rfs; + rfs.insert(RVISA::GPR); if (implementsISA()->extensionEnabled("F")) { - rfs.insert(RegisterFileType::FPR); + rfs.insert(RVISA::FPR); } return rfs; } diff --git a/src/processors/RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz.h b/src/processors/RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz.h index b38e6e20a..e27729528 100644 --- a/src/processors/RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz.h +++ b/src/processors/RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz.h @@ -363,7 +363,7 @@ class RV5S_NO_FW_HZ : public RipesVSRTLProcessor { pc_reg->setInitValue(address); } AddressSpaceMM &getMemory() override { return *m_memory; } - VInt getRegister(RegisterFileType, unsigned i) const override { + VInt getRegister(const std::string_view &, unsigned i) const override { return registerFile->getRegister(i); } void finalize(FinalizeReason fr) override { @@ -400,7 +400,7 @@ class RV5S_NO_FW_HZ : public RipesVSRTLProcessor { } return allStagesInvalid; } - void setRegister(RegisterFileType, unsigned i, VInt v) override { + void setRegister(const std::string_view &, unsigned i, VInt v) override { setSynchronousValue(registerFile->_wr_mem, i, v); } @@ -445,12 +445,12 @@ class RV5S_NO_FW_HZ : public RipesVSRTLProcessor { return m_enabledISA.get(); } - const std::set registerFiles() const override { - std::set rfs; - rfs.insert(RegisterFileType::GPR); + const std::set registerFiles() const override { + std::set rfs; + rfs.insert(RVISA::GPR); if (implementsISA()->extensionEnabled("F")) { - rfs.insert(RegisterFileType::FPR); + rfs.insert(RVISA::FPR); } return rfs; } diff --git a/src/processors/RISC-V/rv5s_no_hz/rv5s_no_hz.h b/src/processors/RISC-V/rv5s_no_hz/rv5s_no_hz.h index fe0682dc4..21dd5bd72 100644 --- a/src/processors/RISC-V/rv5s_no_hz/rv5s_no_hz.h +++ b/src/processors/RISC-V/rv5s_no_hz/rv5s_no_hz.h @@ -398,7 +398,7 @@ class RV5S_NO_HZ : public RipesVSRTLProcessor { pc_reg->setInitValue(address); } AddressSpaceMM &getMemory() override { return *m_memory; } - VInt getRegister(RegisterFileType, unsigned i) const override { + VInt getRegister(const std::string_view &, unsigned i) const override { return registerFile->getRegister(i); } void finalize(FinalizeReason fr) override { @@ -435,7 +435,7 @@ class RV5S_NO_HZ : public RipesVSRTLProcessor { } return allStagesInvalid; } - void setRegister(RegisterFileType, unsigned i, VInt v) override { + void setRegister(const std::string_view &, unsigned i, VInt v) override { setSynchronousValue(registerFile->_wr_mem, i, v); } @@ -480,12 +480,12 @@ class RV5S_NO_HZ : public RipesVSRTLProcessor { return m_enabledISA.get(); } - const std::set registerFiles() const override { - std::set rfs; - rfs.insert(RegisterFileType::GPR); + const std::set registerFiles() const override { + std::set rfs; + rfs.insert(RVISA::GPR); if (implementsISA()->extensionEnabled("F")) { - rfs.insert(RegisterFileType::FPR); + rfs.insert(RVISA::FPR); } return rfs; } diff --git a/src/processors/RISC-V/rv6s_dual/rv6s_dual.h b/src/processors/RISC-V/rv6s_dual/rv6s_dual.h index a978cbfec..fcc1e4334 100644 --- a/src/processors/RISC-V/rv6s_dual/rv6s_dual.h +++ b/src/processors/RISC-V/rv6s_dual/rv6s_dual.h @@ -792,7 +792,7 @@ class RV6S_DUAL : public RipesVSRTLProcessor { pc_reg->setInitValue(address); } AddressSpaceMM &getMemory() override { return *m_memory; } - VInt getRegister(RegisterFileType, unsigned i) const override { + VInt getRegister(const std::string_view &, unsigned i) const override { return registerFile->getRegister(i); } void finalize(FinalizeReason fr) override { @@ -833,7 +833,7 @@ class RV6S_DUAL : public RipesVSRTLProcessor { return allStagesInvalid; } - void setRegister(RegisterFileType, unsigned i, VInt v) override { + void setRegister(const std::string_view &, unsigned i, VInt v) override { setSynchronousValue(registerFile->rf_1->_wr_mem, i, v); } @@ -889,12 +889,12 @@ class RV6S_DUAL : public RipesVSRTLProcessor { return m_enabledISA.get(); } - const std::set registerFiles() const override { - std::set rfs; - rfs.insert(RegisterFileType::GPR); + const std::set registerFiles() const override { + std::set rfs; + rfs.insert(RVISA::GPR); if (implementsISA()->extensionEnabled("F")) { - rfs.insert(RegisterFileType::FPR); + rfs.insert(RVISA::FPR); } return rfs; } diff --git a/src/processors/RISC-V/rvss/rvss.h b/src/processors/RISC-V/rvss/rvss.h index f44a33363..dbe9753f1 100644 --- a/src/processors/RISC-V/rvss/rvss.h +++ b/src/processors/RISC-V/rvss/rvss.h @@ -179,7 +179,7 @@ class RVSS : public RipesVSRTLProcessor { pc_reg->setInitValue(address); } AddressSpaceMM &getMemory() override { return *m_memory; } - VInt getRegister(RegisterFileType, unsigned i) const override { + VInt getRegister(const std::string_view &, unsigned i) const override { return registerFile->getRegister(i); } void finalize(FinalizeReason fr) override { @@ -204,7 +204,7 @@ class RVSS : public RipesVSRTLProcessor { return instrAccess; } - void setRegister(RegisterFileType, unsigned i, VInt v) override { + void setRegister(const std::string_view &, unsigned i, VInt v) override { setSynchronousValue(registerFile->_wr_mem, i, v); } @@ -247,14 +247,13 @@ class RVSS : public RipesVSRTLProcessor { return m_enabledISA.get(); } - const std::set registerFiles() const override { - std::set rfs; - rfs.insert(RegisterFileType::GPR); + const std::set registerFiles() const override { + std::set rfs; + rfs.insert(RVISA::GPR); - // @TODO: uncomment when enabling floating-point support - // if (implementsISA()->extensionEnabled("F")) { - // rfs.insert(RegisterFileType::Float); - // } + if (implementsISA()->extensionEnabled("F")) { + rfs.insert(RVISA::FPR); + } return rfs; } diff --git a/src/processors/interface/ripesprocessor.h b/src/processors/interface/ripesprocessor.h index 81a8c032a..fac467f8f 100644 --- a/src/processors/interface/ripesprocessor.h +++ b/src/processors/interface/ripesprocessor.h @@ -6,8 +6,8 @@ #include "VSRTL/core/vsrtl_design.h" #include +#include "../../isa/isa_types.h" #include "../../isa/isainfo.h" -#include "../../ripes_types.h" namespace Ripes { @@ -154,7 +154,7 @@ class RipesProcessor { * @return the set of register file types exposed by this processor, under * inclusion of the ISA which the processor has been instantiated with. */ - virtual const std::set registerFiles() const = 0; + virtual const std::set registerFiles() const = 0; /** * @brief supportsISA @@ -234,7 +234,7 @@ class RipesProcessor { * @param i: register index * @return value currently present in register @p i */ - virtual VInt getRegister(RegisterFileType rfid, unsigned i) const = 0; + virtual VInt getRegister(const std::string_view &rfid, unsigned i) const = 0; /** * @brief setRegister @@ -242,7 +242,8 @@ class RipesProcessor { * @param i: register index * Set the value of register @param i to @param v. */ - virtual void setRegister(RegisterFileType rfid, unsigned i, VInt v) = 0; + virtual void setRegister(const std::string_view &rfid, unsigned i, + VInt v) = 0; /** * @brief setProgramCounter diff --git a/src/processortab.h b/src/processortab.h index 324f922cf..ac41358d2 100644 --- a/src/processortab.h +++ b/src/processortab.h @@ -6,8 +6,8 @@ #include #include +#include "isa/isa_types.h" #include "processors/interface/ripesprocessor.h" -#include "ripes_types.h" #include "ripestab.h" namespace vsrtl { diff --git a/src/radix.cpp b/src/radix.cpp index 7329a53cb..37dd70840 100644 --- a/src/radix.cpp +++ b/src/radix.cpp @@ -60,41 +60,41 @@ QString encodeRadixValue(VInt value, const Radix type, unsigned byteWidth) { Q_UNREACHABLE(); } -VInt decodeRadixValue(QString value, const Radix type, bool *ok) { - switch (type) { - case Radix::Hex: { +VInt decodeRadixValue(QString value, bool *ok) { + if (hexRegex.match(value).hasMatch()) { return value.toUInt(ok, 16); - } - case Radix::Binary: { + } else if (binRegex.match(value).hasMatch()) { // Qt doesn't support 0b[0-1]* conversion, so remove any possible 0b prefix - if (value.startsWith("0b")) { - value.remove(0, 2); - } + value.remove(0, 2); return value.toUInt(ok, 2); - } - case Radix::Unsigned: { + } else if (unsignedRegex.match(value).hasMatch()) { return value.toUInt(ok, 10); - } - case Radix::Signed: { + } else if (signedRegex.match(value).hasMatch()) { return value.toInt(ok, 10); - } - case Radix::Float: { + } else if (floatRegex.match(value).hasMatch()) { return value.toFloat(ok); } - case Radix::ASCII: { - QString valueRev; - for (const auto &c : value) { - valueRev.prepend(c); - } - uint32_t v = 0; - for (int i = 0; i < valueRev.length(); ++i) { - v |= (valueRev[i].toLatin1() & 0xFF) << (i * 8); + + // Decode ASCII + if (static_cast(value.length()) > sizeof(VInt)) { + // ASCII string is too large to be encoded in a VInt + if (ok) { + *ok = false; } - *ok = true; - return v; + return 0; } + QString valueRev; + for (const auto &c : qAsConst(value)) { + valueRev.prepend(c); } - Q_UNREACHABLE(); + VInt v = 0; + for (int i = 0; i < valueRev.length(); ++i) { + v |= (valueRev[i].toLatin1() & 0xFF) << (i * 8); + } + if (ok) { + *ok = true; + } + return v; } } // namespace Ripes diff --git a/src/radix.h b/src/radix.h index 05658a88f..9bf13434f 100644 --- a/src/radix.h +++ b/src/radix.h @@ -9,7 +9,7 @@ #include #include "isa/isa_defines.h" -#include "ripes_types.h" +#include "isa/isa_types.h" namespace Ripes { @@ -25,10 +25,11 @@ static const auto hexRegex64 = QRegularExpression("0[xX][0-9a-fA-F]{0,16}"); static const auto binRegex = QRegularExpression("0[bB][0-1]+"); static const auto unsignedRegex = QRegularExpression("[0-9]+"); static const auto signedRegex = QRegularExpression("[-]*[0-9]+"); +static const auto floatRegex = QRegularExpression("[-]*[0-9]+\\.[0-9]+"); void setISADepRegex(QRegularExpressionValidator *validator); QString encodeRadixValue(VInt value, const Radix type, unsigned byteWidth); -VInt decodeRadixValue(QString value, const Radix type, bool *ok = nullptr); +VInt decodeRadixValue(QString value, bool *ok = nullptr); } // namespace Ripes diff --git a/src/registercontainerwidget.cpp b/src/registercontainerwidget.cpp index f483ef83f..213ad7f5a 100644 --- a/src/registercontainerwidget.cpp +++ b/src/registercontainerwidget.cpp @@ -21,12 +21,14 @@ RegisterContainerWidget::~RegisterContainerWidget() { delete m_ui; } void RegisterContainerWidget::initialize() { m_ui->tabWidget->clear(); - for (const auto &rfid : ProcessorHandler::getProcessor()->registerFiles()) { + for (const auto ®File : + ProcessorHandler::getProcessor()->implementsISA()->regInfoMap()) { + auto rfid = regFile.second->regFileName(); + auto regDesc = regFile.second->regFileDesc(); auto registerWidget = new RegisterWidget(rfid, this); const unsigned tabIdx = m_ui->tabWidget->count(); - m_ui->tabWidget->insertTab(tabIdx, registerWidget, - s_RegsterFileName.at(rfid).shortName); - m_ui->tabWidget->setTabToolTip(tabIdx, s_RegsterFileName.at(rfid).longName); + m_ui->tabWidget->insertTab(tabIdx, registerWidget, QString(rfid.data())); + m_ui->tabWidget->setTabToolTip(tabIdx, QString(regDesc.data())); registerWidget->initialize(); } updateView(); diff --git a/src/registerinitializationwidget.cpp b/src/registerinitializationwidget.cpp index 731f2769a..c645cc784 100644 --- a/src/registerinitializationwidget.cpp +++ b/src/registerinitializationwidget.cpp @@ -27,23 +27,38 @@ void RegisterSelectionComboBox::showPopup() { const auto &procisa = ProcessorRegistry::getAvailableProcessors() .at(m_parent->m_currentID) ->isaInfo(); - const auto regInfo = procisa.isa->regInfo().value(); + const auto *isa = procisa.isa.get(); const auto &initializations = m_parent->m_initializations.at(m_parent->m_currentID); - std::set regOptions; - for (unsigned i = 0; i < regInfo->regCnt(); ++i) { - if (!regInfo->regIsReadOnly(i)) { - regOptions.insert(i); + std::map> regOptions; + for (const auto ®File : isa->regInfos()) { + for (unsigned i = 0; i < regFile->regCnt(); ++i) { + if (!regFile->regIsReadOnly(i)) { + if (regOptions.count(regFile->regFileName()) == 0) { + regOptions[regFile->regFileName()] = {i}; + } else { + regOptions[regFile->regFileName()].insert(i); + } + } } } - for (const auto &init : initializations) { - regOptions.erase(init.first); + for (const auto ®FileInit : initializations) { + if (regOptions.count(regFileInit.first) > 0) { + for (const auto ®Init : regFileInit.second) { + regOptions.at(regFileInit.first).erase(regInit.first); + } + } } - for (const auto &i : regOptions) { - addItem(regInfo->regName(i) + " (" + regInfo->regAlias(i) + ")", i); + for (const auto ®FileInit : regOptions) { + for (const auto &i : regFileInit.second) { + if (auto opt = isa->regInfo(regFileInit.first)) { + auto regInfo = opt.value(); + addItem(regInfo->regName(i) + " (" + regInfo->regAlias(i) + ")", i); + } + } } QComboBox::showPopup(); } @@ -57,8 +72,11 @@ RegisterInitializationWidget::RegisterInitializationWidget(QWidget *parent) const QIcon addIcon = QIcon(":/icons/plus.svg"); m_ui->addInitButton->setIcon(addIcon); - connect(m_ui->addInitButton, &QPushButton::clicked, this, - [=] { this->addRegisterInitialization(getNonInitializedRegIdx()); }); + connect(m_ui->addInitButton, &QPushButton::clicked, this, [=] { + if (auto regIdx = getNonInitializedRegIdx(); regIdx.has_value()) + this->addRegisterInitialization(regIdx->file->regFileName(), + regIdx->index); + }); // Initialize initializations for all available processors for (const auto &desc : ProcessorRegistry::getAvailableProcessors()) { @@ -77,8 +95,10 @@ void RegisterInitializationWidget::processorSelectionChanged(ProcessorID id) { m_currentRegInitWidgets.clear(); m_currentID = id; - for (const auto &init : m_initializations.at(id)) { - addRegisterInitialization(init.first); + for (const auto ®FileInit : m_initializations.at(id)) { + for (const auto ®Init : regFileInit.second) { + addRegisterInitialization(regFileInit.first, regInit.first); + } } updateAddButtonState(); @@ -89,43 +109,62 @@ RegisterInitializationWidget::~RegisterInitializationWidget() { delete m_ui; } void RegisterInitializationWidget::updateAddButtonState() { // Disable add button if we have exhausted the number of registers to // initialize for the given processor - if (getNonInitializedRegIdx() != -1) { + if (getNonInitializedRegIdx().has_value()) { m_ui->addInitButton->setEnabled(true); } else { m_ui->addInitButton->setEnabled(false); } } -int RegisterInitializationWidget::getNonInitializedRegIdx() { +std::optional +RegisterInitializationWidget::getNonInitializedRegIdx() { const auto ¤tISA = ProcessorRegistry::getAvailableProcessors().at(m_currentID)->isaInfo(); - const auto regInfo = currentISA.isa->regInfo().value(); + const auto *isa = currentISA.isa.get(); const auto ¤tInitForProc = m_initializations.at(m_currentID); - unsigned id = 0; - while (currentInitForProc.count(id) || regInfo->regIsReadOnly(id)) { - id++; + for (const auto ®FileInit : currentInitForProc) { + unsigned id = 0; + if (auto opt = isa->regInfo(regFileInit.first)) { + auto regInfo = opt.value(); + while (regFileInit.second.count(id) || regInfo->regIsReadOnly(id)) { + id++; + } + if (id < regInfo->regCnt()) { + return RegIndex{isa->regInfoMap().at(regFileInit.first), id}; + } + } } - return id < regInfo->regCnt() ? id : -1; + return {}; } -RegisterInitializationWidget::RegInitWidgets * -RegisterInitializationWidget::addRegisterInitialization(unsigned regIdx) { +void RegisterInitializationWidget::addRegisterInitialization( + const std::string_view ®FileName, unsigned regIdx) { constexpr unsigned s_defaultval = 0; - if (!m_initializations.at(m_currentID).count(regIdx)) { + const auto &procisa = + ProcessorRegistry::getAvailableProcessors().at(m_currentID)->isaInfo(); + const auto *isa = procisa.isa.get(); + auto maybeRegInfo = isa->regInfo(regFileName); + if (!maybeRegInfo.has_value()) { + return; + } + auto regInfo = *maybeRegInfo; + + if (!m_initializations.at(m_currentID).count(regFileName)) { + m_initializations.at(m_currentID)[regFileName] = {}; + } + if (!m_initializations.at(m_currentID).at(regFileName).count(regIdx)) { // No default value of the register initialization exists. - m_initializations.at(m_currentID)[regIdx] = s_defaultval; + m_initializations.at(m_currentID).at(regFileName)[regIdx] = s_defaultval; } const auto ®Layout = m_ui->regInitLayout; - const auto &procisa = - ProcessorRegistry::getAvailableProcessors().at(m_currentID)->isaInfo(); - const auto regInfo = procisa.isa->regInfo().value(); auto &w = m_currentRegInitWidgets.emplace_back(std::make_unique()); auto *w_ptr = w.get(); + w->regFileName = regFileName; w->name = new RegisterSelectionComboBox(this); w->value = new QLineEdit(this); w->remove = new QPushButton(this); @@ -135,9 +174,9 @@ RegisterInitializationWidget::addRegisterInitialization(unsigned regIdx) { regIdx); connect(w->name, &RegisterSelectionComboBox::regIndexChanged, this, - [this, w_ptr](int oldIdx, int newIdx) { - m_initializations.at(m_currentID).erase(oldIdx); - m_initializations.at(m_currentID)[newIdx]; + [this, w_ptr, regFileName](int oldIdx, int newIdx) { + m_initializations.at(m_currentID).at(regFileName).erase(oldIdx); + m_initializations.at(m_currentID).at(regFileName)[newIdx]; emit w_ptr->value->textChanged(w_ptr->value->text()); }); @@ -146,10 +185,13 @@ RegisterInitializationWidget::addRegisterInitialization(unsigned regIdx) { w->value->setValidator(m_hexValidator); w->value->setText( - "0x" + QString::number(m_initializations.at(m_currentID).at(regIdx), 16)); + "0x" + + QString::number( + m_initializations.at(m_currentID).at(regFileName).at(regIdx), 16)); connect(w->value, &QLineEdit::textChanged, this, - [this, w_ptr](const QString &text) { + [this, w_ptr, regFileName](const QString &text) { this->m_initializations.at(this->m_currentID) + .at(regFileName) .at(w_ptr->name->currentData().toUInt()) = text.toUInt(nullptr, 16); }); @@ -162,7 +204,6 @@ RegisterInitializationWidget::addRegisterInitialization(unsigned regIdx) { [this, w_ptr] { this->removeRegInitWidget(w_ptr); }); updateAddButtonState(); - return w.get(); } void RegisterInitializationWidget::removeRegInitWidget( @@ -174,7 +215,7 @@ void RegisterInitializationWidget::removeRegInitWidget( // Current register index stored in the combobox of the regInitWidgets const unsigned regIdx = w->name->itemData(0).toUInt(); - m_initializations.at(m_currentID).erase(regIdx); + m_initializations.at(m_currentID).at(w->regFileName).erase(regIdx); m_currentRegInitWidgets.erase(iter); updateAddButtonState(); diff --git a/src/registerinitializationwidget.h b/src/registerinitializationwidget.h index cbeb3070f..1936adcb7 100644 --- a/src/registerinitializationwidget.h +++ b/src/registerinitializationwidget.h @@ -25,6 +25,7 @@ class RegisterInitializationWidget : public QWidget { RegisterSelectionComboBox *name = nullptr; QLineEdit *value = nullptr; QPushButton *remove = nullptr; + std::string_view regFileName = ""; ~RegInitWidgets() { clear(); } void clear(); @@ -39,12 +40,12 @@ class RegisterInitializationWidget : public QWidget { void processorSelectionChanged(ProcessorID id); private slots: - RegisterInitializationWidget::RegInitWidgets * - addRegisterInitialization(unsigned regIdx); + void addRegisterInitialization(const std::string_view ®File, + unsigned regIdx); private: void updateAddButtonState(); - int getNonInitializedRegIdx(); + std::optional getNonInitializedRegIdx(); void removeRegInitWidget(RegInitWidgets *w); Ui::RegisterInitializationWidget *m_ui = nullptr; diff --git a/src/registermodel.cpp b/src/registermodel.cpp index 0c0562653..62d2fb0bf 100644 --- a/src/registermodel.cpp +++ b/src/registermodel.cpp @@ -10,7 +10,7 @@ namespace Ripes { using namespace vsrtl; -RegisterModel::RegisterModel(RegisterFileType rft, QObject *parent) +RegisterModel::RegisterModel(const std::string_view &rft, QObject *parent) : QAbstractTableModel(parent), m_rft(rft) { m_regBytes = ProcessorHandler::getProcessor()->implementsISA()->bytes(); } @@ -25,7 +25,11 @@ std::vector RegisterModel::gatherRegisterValues() { int RegisterModel::columnCount(const QModelIndex &) const { return NColumns; } int RegisterModel::rowCount(const QModelIndex &) const { - return ProcessorHandler::currentISA()->regCnt(); + if (auto regInfo = ProcessorHandler::currentISA()->regInfo(m_rft); + regInfo.has_value()) { + return (*regInfo)->regCnt(); + } + return 0; } void RegisterModel::processorWasClocked() { @@ -50,7 +54,7 @@ bool RegisterModel::setData(const QModelIndex &index, const QVariant &value, const int i = index.row(); if (index.column() == Column::Value) { bool ok; - VInt v = decodeRadixValue(value.toString(), m_radix, &ok); + VInt v = decodeRadixValue(value.toString(), &ok); if (ok) { ProcessorHandler::setRegisterValue(m_rft, i, v); emit dataChanged(index, index); @@ -129,15 +133,29 @@ void RegisterModel::setRadix(Ripes::Radix r) { } QVariant RegisterModel::nameData(unsigned idx) const { - return ProcessorHandler::currentISA()->regInfo().value()->regName(idx); + if (auto regInfo = ProcessorHandler::currentISA()->regInfo(m_rft); + regInfo.has_value()) { + return (*regInfo)->regName(idx); + } + return QVariant(); } QVariant RegisterModel::aliasData(unsigned idx) const { - return ProcessorHandler::currentISA()->regInfo().value()->regAlias(idx); + if (auto regInfo = ProcessorHandler::currentISA()->regInfo(m_rft); + regInfo.has_value()) { + return (*regInfo)->regAlias(idx); + } else { + return QVariant(); + } } QVariant RegisterModel::tooltipData(unsigned idx) const { - return ProcessorHandler::currentISA()->regInfo().value()->regInfo(idx); + if (auto regInfo = ProcessorHandler::currentISA()->regInfo(m_rft); + regInfo.has_value()) { + return (*regInfo)->regInfo(idx); + } else { + return QVariant(); + } } VInt RegisterModel::registerData(unsigned idx) const { @@ -149,13 +167,15 @@ QVariant RegisterModel::valueData(unsigned idx) const { } Qt::ItemFlags RegisterModel::flags(const QModelIndex &index) const { - const auto def = - ProcessorHandler::currentISA()->regInfo().value()->regIsReadOnly( - index.row()) - ? Qt::NoItemFlags - : Qt::ItemIsEnabled; - if (index.column() == Column::Value) - return Qt::ItemIsEditable | def; - return def; + if (auto regInfo = ProcessorHandler::currentISA()->regInfo(m_rft); + regInfo.has_value()) { + const auto def = (*regInfo)->regIsReadOnly(index.row()) ? Qt::NoItemFlags + : Qt::ItemIsEnabled; + if (index.column() == Column::Value) + return Qt::ItemIsEditable | def; + return def; + } else { + return Qt::NoItemFlags; + } } } // namespace Ripes diff --git a/src/registermodel.h b/src/registermodel.h index e9acb059e..9fc260b23 100644 --- a/src/registermodel.h +++ b/src/registermodel.h @@ -14,7 +14,7 @@ class RegisterModel : public QAbstractTableModel { Q_OBJECT public: enum Column { Name, Alias, Value, NColumns }; - RegisterModel(RegisterFileType rft, QObject *parent = nullptr); + RegisterModel(const std::string_view &rft, QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; @@ -52,7 +52,7 @@ public slots: Radix m_radix = Radix::Hex; unsigned m_regBytes; - RegisterFileType m_rft; + std::string_view m_rft; int m_mostRecentlyModifiedReg = -1; std::vector m_regValues; diff --git a/src/registerwidget.cpp b/src/registerwidget.cpp index cbb1b4849..6f7f7a299 100644 --- a/src/registerwidget.cpp +++ b/src/registerwidget.cpp @@ -15,9 +15,9 @@ namespace Ripes { -RegisterWidget::RegisterWidget(const RegisterFileType regFileID, +RegisterWidget::RegisterWidget(const std::string_view ®FileID, QWidget *parent) - : QWidget(parent), m_ui(new Ui::RegisterWidget), m_regFileID(regFileID) { + : QWidget(parent), m_ui(new Ui::RegisterWidget), m_regFileName(regFileID) { m_ui->setupUi(this); } @@ -28,7 +28,7 @@ void RegisterWidget::initialize() { m_model->deleteLater(); } - m_model = new RegisterModel(m_regFileID, this); + m_model = new RegisterModel(m_regFileName, this); m_ui->registerView->setModel(m_model); // Add custom right click menu to register view diff --git a/src/registerwidget.h b/src/registerwidget.h index 66f9b9ded..62dd15cac 100644 --- a/src/registerwidget.h +++ b/src/registerwidget.h @@ -15,7 +15,7 @@ class RegisterWidget : public QWidget { Q_OBJECT public: - explicit RegisterWidget(const RegisterFileType regFileID, + explicit RegisterWidget(const std::string_view ®FileID, QWidget *parent = nullptr); ~RegisterWidget(); @@ -29,6 +29,6 @@ public slots: void showContextMenu(const QPoint &pos); Ui::RegisterWidget *m_ui = nullptr; RegisterModel *m_model = nullptr; - const RegisterFileType m_regFileID; + const std::string_view m_regFileName; }; } // namespace Ripes diff --git a/src/syscall/control.h b/src/syscall/control.h index 89da82dd8..179a254a2 100644 --- a/src/syscall/control.h +++ b/src/syscall/control.h @@ -32,7 +32,7 @@ class Exit2Syscall : public BaseSyscall { void execute() { SystemIO::printString( "\nProgram exited with code: " + - QString::number(BaseSyscall::getArg(RegisterFileType::GPR, 0)) + "\n"); + QString::number(BaseSyscall::getArg(BaseSyscall::REG_FILE, 0)) + "\n"); ProcessorHandler::getProcessorNonConst()->finalize( RipesProcessor::FinalizeReason::exitSyscall); } @@ -58,7 +58,7 @@ class BrkSyscall : public BaseSyscall { // Nothing to do - at the moment we allow infinite growth of the heap. // @todo: Add checks to ensure that the heap doesn't grow into the stack // segment...! - BaseSyscall::setRet(RegisterFileType::GPR, 0, 0); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, 0); } }; diff --git a/src/syscall/file.h b/src/syscall/file.h index d480e883f..65be8c856 100644 --- a/src/syscall/file.h +++ b/src/syscall/file.h @@ -19,8 +19,8 @@ class OpenSyscall : public BaseSyscall { {1, "flags"}}, {{0, "the file decriptor or -1 if an error occurred"}}) {} void execute() { - const AInt arg0 = BaseSyscall::getArg(RegisterFileType::GPR, 0); - const AInt arg1 = BaseSyscall::getArg(RegisterFileType::GPR, 1); + const AInt arg0 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); + const AInt arg1 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 1); QByteArray string; char byte; unsigned int address = arg0; @@ -32,7 +32,7 @@ class OpenSyscall : public BaseSyscall { int ret = SystemIO::openFile(QString::fromUtf8(string), arg1); - BaseSyscall::setRet(RegisterFileType::GPR, 0, ret); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, ret); } }; @@ -45,7 +45,7 @@ class CloseSyscall : public BaseSyscall { : BaseSyscall("Close", "Close a file", {{0, "the file descriptor to close"}}) {} void execute() { - const VInt arg0 = BaseSyscall::getArg(RegisterFileType::GPR, 0); + const VInt arg0 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); SystemIO::closeFile(arg0); } }; @@ -64,10 +64,10 @@ class LSeekSyscall : public BaseSyscall { {{0, "the selected position from the beginning of the file " "or -1 if an error occurred"}}) {} void execute() { - int result = SystemIO::seek(BaseSyscall::getArg(RegisterFileType::GPR, 0), - BaseSyscall::getArg(RegisterFileType::GPR, 1), - BaseSyscall::getArg(RegisterFileType::GPR, 2)); - BaseSyscall::setRet(RegisterFileType::GPR, 0, result); + int result = SystemIO::seek(BaseSyscall::getArg(BaseSyscall::REG_FILE, 0), + BaseSyscall::getArg(BaseSyscall::REG_FILE, 1), + BaseSyscall::getArg(BaseSyscall::REG_FILE, 2)); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, result); } }; @@ -83,14 +83,14 @@ class ReadSyscall : public BaseSyscall { {2, "maximum number of bytes to read"}}, {{0, "number of read bytes or -1 if an error occurred"}}) {} void execute() { - const int fd = BaseSyscall::getArg(RegisterFileType::GPR, 0); + const int fd = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); int byteAddress = BaseSyscall::getArg( - RegisterFileType::GPR, 1); // destination of characters read from file - const int length = BaseSyscall::getArg(RegisterFileType::GPR, 2); + BaseSyscall::REG_FILE, 1); // destination of characters read from file + const int length = BaseSyscall::getArg(BaseSyscall::REG_FILE, 2); QByteArray buffer; int retLength = SystemIO::readFromFile(fd, buffer, length); - BaseSyscall::setRet(RegisterFileType::GPR, 0, retLength); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, retLength); if (retLength != -1) { // copy bytes from returned buffer into memory @@ -118,11 +118,11 @@ class WriteSyscall : public BaseSyscall { {{0, "the number of bytes written"}}) {} void execute() { const int byteAddress = BaseSyscall::getArg( - RegisterFileType::GPR, 1); // source of characters to write to file + BaseSyscall::REG_FILE, 1); // source of characters to write to file const int reqLength = - BaseSyscall::getArg(RegisterFileType::GPR, 2); // user-requested length + BaseSyscall::getArg(BaseSyscall::REG_FILE, 2); // user-requested length if (reqLength < 0) { - BaseSyscall::setRet(RegisterFileType::GPR, 0, -1); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, -1); return; } int index = 0; @@ -135,8 +135,8 @@ class WriteSyscall : public BaseSyscall { } while (index < reqLength); const int retValue = SystemIO::writeToFile( - BaseSyscall::getArg(RegisterFileType::GPR, 0), myBuffer, reqLength); - BaseSyscall::setRet(RegisterFileType::GPR, 0, retValue); + BaseSyscall::getArg(BaseSyscall::REG_FILE, 0), myBuffer, reqLength); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, retValue); } }; @@ -154,17 +154,17 @@ class GetCWDSyscall : public BaseSyscall { {{0, "-1 if the path is longer than the buffer"}}) {} void execute() { const int byteAddress = BaseSyscall::getArg( - RegisterFileType::GPR, 0); // destination of characters read from file + BaseSyscall::REG_FILE, 0); // destination of characters read from file int index = 0; - const int bufferSize = BaseSyscall::getArg(RegisterFileType::GPR, 1); + const int bufferSize = BaseSyscall::getArg(BaseSyscall::REG_FILE, 1); const QString pwd = QDir::currentPath(); if (pwd.length() > bufferSize) { - BaseSyscall::setRet(RegisterFileType::GPR, 0, -1); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, -1); return; } else { - BaseSyscall::setRet(RegisterFileType::GPR, 0, pwd.length()); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, pwd.length()); } // copy bytes from returned buffer into memory @@ -192,7 +192,7 @@ class FStatSyscall : public BaseSyscall { /// syscall's seems to execute fine with just null-values in the fstat /// return struct - this is ofcourse not a valid mode of execution, but for /// the current state of development, it'll have to do. - BaseSyscall::setRet(RegisterFileType::GPR, 0, 0); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, 0); } }; } // namespace Ripes diff --git a/src/syscall/print.h b/src/syscall/print.h index ac57ff50b..038fb22bd 100644 --- a/src/syscall/print.h +++ b/src/syscall/print.h @@ -18,7 +18,7 @@ class PrintIntSyscall : public BaseSyscall { {{0, "integer to print"}}) {} void execute() { const VIntS arg0 = vsrtl::signextend( - BaseSyscall::getArg(RegisterFileType::GPR, 0), + BaseSyscall::getArg(BaseSyscall::REG_FILE, 0), ProcessorHandler::currentISA()->bits()); SystemIO::printString(QString::number(arg0)); } @@ -33,7 +33,7 @@ class PrintFloatSyscall : public BaseSyscall { : BaseSyscall("PrintFloat", "Prints a floating point number", {{0, "float to print"}}) {} void execute() { - const VInt arg0 = BaseSyscall::getArg(RegisterFileType::GPR, 0); + const VInt arg0 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); auto *v_f = reinterpret_cast(&arg0); SystemIO::printString(QString::number(static_cast(*v_f))); } @@ -48,7 +48,7 @@ class PrintStrSyscall : public BaseSyscall { : BaseSyscall("PrintString", "Prints a null-terminated string", {{0, "address of the string"}}) {} void execute() { - const VInt arg0 = BaseSyscall::getArg(RegisterFileType::GPR, 0); + const VInt arg0 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); QByteArray string; char byte; AInt address = arg0; @@ -71,7 +71,7 @@ class PrintCharSyscall : public BaseSyscall { "PrintChar", "Prints an ascii character", {{0, "character to print (only lowest byte is considered)"}}) {} void execute() { - const VInt arg0 = BaseSyscall::getArg(RegisterFileType::GPR, 0); + const VInt arg0 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); SystemIO::printString(QChar(static_cast(arg0))); } }; @@ -87,7 +87,7 @@ class PrintHexSyscall : public BaseSyscall { "Prints an integer (in hexdecimal format left-padded with zeroes)", {{0, "integer to print"}}) {} void execute() { - const VInt arg0 = BaseSyscall::getArg(RegisterFileType::GPR, 0); + const VInt arg0 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); SystemIO::printString("0x" + QString::number(arg0, 16).rightJustified( ProcessorHandler::currentISA()->bytes(), '0')); @@ -105,7 +105,7 @@ class PrintBinarySyscall : public BaseSyscall { "Prints an integer (in binary format left-padded with zeroes)", {{0, "integer to print"}}) {} void execute() { - const VInt arg0 = BaseSyscall::getArg(RegisterFileType::GPR, 0); + const VInt arg0 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); SystemIO::printString("0b" + QString::number(arg0, 2).rightJustified( ProcessorHandler::currentISA()->bits(), '0')); @@ -121,7 +121,7 @@ class PrintUnsignedSyscall : public BaseSyscall { : BaseSyscall("PrintIntUnsigned", "Prints an integer (unsigned)", {{0, "integer to print"}}) {} void execute() { - const VInt arg0 = BaseSyscall::getArg(RegisterFileType::GPR, 0); + const VInt arg0 = BaseSyscall::getArg(BaseSyscall::REG_FILE, 0); SystemIO::printString(QString::number(arg0)); } }; diff --git a/src/syscall/ripes_syscall.cpp b/src/syscall/ripes_syscall.cpp index e5f4e7f36..72efda93a 100644 --- a/src/syscall/ripes_syscall.cpp +++ b/src/syscall/ripes_syscall.cpp @@ -7,14 +7,16 @@ namespace Ripes { bool SyscallManager::execute(SyscallID id) { if (m_syscalls.count(id) == 0) { postToGUIThread([=] { - QMessageBox::warning( - nullptr, "Error", - "Unknown system call in register '" + - ProcessorHandler::currentISA()->regInfo().value()->regAlias( - ProcessorHandler::currentISA()->syscallReg()) + - "': " + QString::number(id) + - "\nRefer to \"Help->System calls\" for a list of support system " - "calls."); + if (auto reg = ProcessorHandler::currentISA()->syscallReg(); + reg.has_value()) { + QMessageBox::warning(nullptr, "Error", + "Unknown system call in register '" + + reg->file->regAlias(reg->index) + + "': " + QString::number(id) + + "\nRefer to \"Help->System calls\" for a list " + "of support system " + "calls."); + } }); return false; } else { diff --git a/src/syscall/ripes_syscall.h b/src/syscall/ripes_syscall.h index bda9094ab..c53430355 100644 --- a/src/syscall/ripes_syscall.h +++ b/src/syscall/ripes_syscall.h @@ -11,7 +11,7 @@ #include #include "../isa/isainfo.h" -#include "ripes_types.h" +#include "isa/isa_types.h" #include "statusmanager.h" namespace Ripes { @@ -51,13 +51,14 @@ class Syscall { * @returns value of the specified argument register. */ - virtual VInt getArg(RegisterFileType rfid, ArgIdx i) const = 0; + virtual VInt getArg(const std::string_view &rfid, ArgIdx i) const = 0; /** * @brief setRet * ABI specific specialization of setting an argument register return value. * Argument index @p i is in range [0; max arg. registers] for the given ABI. */ - virtual void setRet(RegisterFileType rfid, ArgIdx i, VInt value) const = 0; + virtual void setRet(const std::string_view &rfid, ArgIdx i, + VInt value) const = 0; protected: const QString m_name; diff --git a/src/syscall/riscv_syscall.h b/src/syscall/riscv_syscall.h index 866d2a876..377b5e621 100644 --- a/src/syscall/riscv_syscall.h +++ b/src/syscall/riscv_syscall.h @@ -1,5 +1,6 @@ #pragma once +#include "isa/rvisainfo_common.h" #include "processorhandler.h" #include "ripes_syscall.h" @@ -13,6 +14,8 @@ namespace Ripes { class RISCVSyscall : public Syscall { public: + constexpr static std::string_view REG_FILE = RVISA::GPR; + RISCVSyscall(const QString &name, const QString &description = QString(), const std::map &argumentDescriptions = std::map(), @@ -21,14 +24,15 @@ class RISCVSyscall : public Syscall { : Syscall(name, description, argumentDescriptions, returnDescriptions) {} ~RISCVSyscall() override {} - VInt getArg(RegisterFileType rfid, ArgIdx i) const override { + VInt getArg(const std::string_view &rfid, ArgIdx i) const override { // RISC-V arguments range from a0-a6 assert(i < 7); const int regIdx = 10 + i; // a0 = x10 return ProcessorHandler::getRegisterValue(rfid, regIdx); } - void setRet(RegisterFileType rfid, ArgIdx i, VInt value) const override { + void setRet(const std::string_view &rfid, ArgIdx i, + VInt value) const override { // RISC-V arguments range from a0-a6 assert(i < 7); const int regIdx = 10 + i; // a0 = x10 diff --git a/src/syscall/syscall_time.h b/src/syscall/syscall_time.h index 19ea8363a..ed0edaeb0 100644 --- a/src/syscall/syscall_time.h +++ b/src/syscall/syscall_time.h @@ -21,8 +21,8 @@ class CyclesSyscall : public BaseSyscall { {1, "high 32 bits of cycles elapsed"}}) {} void execute() { long long cycleCount = ProcessorHandler::getProcessor()->getCycleCount(); - BaseSyscall::setRet(RegisterFileType::GPR, 0, cycleCount & 0xFFFFFFFF); - BaseSyscall::setRet(RegisterFileType::GPR, 1, + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, cycleCount & 0xFFFFFFFF); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 1, (cycleCount >> 32) & 0xFFFFFFFF); } }; @@ -41,8 +41,8 @@ class TimeMsSyscall : public BaseSyscall { {1, "high 32 bits of milliseconds since epoch"}}) {} void execute() { long long ms = QDateTime::currentMSecsSinceEpoch(); - BaseSyscall::setRet(RegisterFileType::GPR, 0, ms & 0xFFFFFFFF); - BaseSyscall::setRet(RegisterFileType::GPR, 1, (ms >> 32) & 0xFFFFFFFF); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 0, ms & 0xFFFFFFFF); + BaseSyscall::setRet(BaseSyscall::REG_FILE, 1, (ms >> 32) & 0xFFFFFFFF); } }; diff --git a/src/syscall/syscallviewer.cpp b/src/syscall/syscallviewer.cpp index 9e2d8068b..e1c5c2ba5 100644 --- a/src/syscall/syscallviewer.cpp +++ b/src/syscall/syscallviewer.cpp @@ -31,12 +31,11 @@ SyscallViewer::SyscallViewer(QWidget *parent) } m_ui->syscallList->setSelectionBehavior(QAbstractItemView::SelectRows); m_ui->syscallList->verticalHeader()->hide(); - m_ui->syscallList->setHorizontalHeaderLabels( - {"Func. (" + - ProcessorHandler::currentISA()->regInfo().value()->regAlias( - ProcessorHandler::currentISA()->syscallReg()) + - ")", - "Name"}); + if (auto reg = ProcessorHandler::currentISA()->syscallReg(); + reg.has_value()) { + m_ui->syscallList->setHorizontalHeaderLabels( + {"Func. (" + reg->file->regAlias(reg->index) + ")", "Name"}); + } m_ui->syscallList->horizontalHeader()->setStretchLastSection(true); connect(m_ui->syscallList, &QTableWidget::currentItemChanged, this, &SyscallViewer::handleItemChanged); @@ -100,10 +99,11 @@ void SyscallViewer::addItemToTable(QTableWidget *table, unsigned int idx, QTableWidgetItem *textItem = new QTableWidgetItem(); auto isa = ProcessorHandler::currentISA(); - auto regInfo = isa->regInfo().value(); idxItem->setData(Qt::EditRole, QString::number(idx)); - regItem->setData(Qt::EditRole, regInfo->regAlias(isa->syscallArgReg(idx))); + if (auto reg = isa->syscallArgReg(idx); reg.has_value()) { + regItem->setData(Qt::EditRole, reg->file->regAlias(reg->index)); + } textItem->setData(Qt::DisplayRole, description); idxItem->setFlags(idxItem->flags() ^ Qt::ItemIsEditable); diff --git a/test/tst_cosimulate.cpp b/test/tst_cosimulate.cpp index df499725b..2076e675b 100644 --- a/test/tst_cosimulate.cpp +++ b/test/tst_cosimulate.cpp @@ -26,6 +26,7 @@ using namespace Ripes; using namespace vsrtl::core; struct RegisterChange { + std::string_view fileName; unsigned index; VInt newValue; }; @@ -97,9 +98,12 @@ private slots: }; void tst_Cosimulate::trapHandler() { + auto reg = + ProcessorHandler::get()->getProcessor()->implementsISA()->syscallReg(); + assert(reg.has_value()); + unsigned status = ProcessorHandler::get()->getProcessor()->getRegister( - RegisterFileType::GPR, - ProcessorHandler::get()->getProcessor()->implementsISA()->syscallReg()); + reg->file->regFileName(), reg->index); /// @todo: Generalize this by having ISA report exit syscall codes if (status == RVABI::SysCall::Exit || status == RVABI::SysCall::Exit2) { @@ -109,11 +113,12 @@ void tst_Cosimulate::trapHandler() { Registers tst_Cosimulate::dumpRegs() { Registers regs; - for (unsigned i = 0; - i < ProcessorHandler::get()->currentISA()->regInfo().value()->regCnt(); - i++) { - regs[i] = ProcessorHandler::get()->getProcessor()->getRegister( - RegisterFileType::GPR, i); + for (const auto ®File : + ProcessorHandler::get()->currentISA()->regInfos()) { + for (unsigned i = 0; i < regFile->regCnt(); i++) { + regs[i] = ProcessorHandler::get()->getProcessor()->getRegister( + regFile->regFileName(), i); + } } return regs; } @@ -137,11 +142,12 @@ std::optional> regNeq(const Registers &lhs, std::vector registerChange(const Registers &before, const Registers &after) { std::vector change; - for (unsigned i = 0; - i < ProcessorHandler::get()->currentISA()->regInfo().value()->regCnt(); - i++) { - if (before.at(i) != after.at(i)) { - change.push_back({i, after.at(i)}); + for (const auto ®File : + ProcessorHandler::get()->currentISA()->regInfos()) { + for (unsigned i = 0; i < regFile->regCnt(); i++) { + if (before.at(i) != after.at(i)) { + change.push_back({regFile->regFileName(), i, after.at(i)}); + } } } return change; @@ -153,8 +159,15 @@ QString tst_Cosimulate::generateErrorReport(const RegisterChange &change, QString err; err += "\nRegister change discrepancy detected while executing test: " + m_currentTest.filepath; - err += "\nUnexpected change was: x" + QString::number(change.index) + - " -> 0x" + QString::number(change.newValue, 16) + "\n"; + err += "\nUnexpected change was: "; + if (auto regInfo = + ProcessorHandler::get()->currentISA()->regInfo(change.fileName); + regInfo.has_value()) { + err += (*regInfo)->regName(change.index); + } else { + err += "x" + QString::number(change.index); + } + err += " -> 0x" + QString::number(change.newValue, 16) + "\n"; err += "\nTest processor state: \t\tPC: 0x" + QString::number(lhs.pc, 16) + "\t Cycle #: " + QString::number(lhs.cycle); err += "\nReference processor state: \tPC: 0x" + QString::number(rhs.pc, 16) + diff --git a/test/tst_reverse.cpp b/test/tst_reverse.cpp index d143a1da6..df4bbda57 100644 --- a/test/tst_reverse.cpp +++ b/test/tst_reverse.cpp @@ -34,10 +34,12 @@ private slots: using Registers = std::map; static Registers dumpRegs() { Registers regs; - for (unsigned i = 0; i < ProcessorHandler::get()->currentISA()->regCnt(); - i++) { - regs[i] = ProcessorHandler::get()->getProcessor()->getRegister( - RegisterFileType::GPR, i); + for (const auto ®File : + ProcessorHandler::get()->currentISA()->regInfos()) { + for (unsigned i = 0; i < regFile->regCnt(); i++) { + regs[i] = ProcessorHandler::get()->getProcessor()->getRegister( + regFile->regFileName(), i); + } } return regs; } @@ -86,8 +88,7 @@ void tst_reverse::tst_reverse_regs() { << "addi x10 x10 1" << "addi x10 x10 1"; run_test(processor, program, 3, 6, 6, true); - unsigned val = - ProcessorHandler::get()->getRegisterValue(RegisterFileType::GPR, 10); + unsigned val = ProcessorHandler::get()->getRegisterValue(RVISA::GPR, 10); QCOMPARE(val, 5); } } @@ -103,8 +104,7 @@ void tst_reverse::tst_reverse_mem() { << "sw a1 0 a0" << "lw x10 0 a0"; run_test(processor, program, 3, 10, 10, true); - unsigned val = - ProcessorHandler::get()->getRegisterValue(RegisterFileType::GPR, 10); + unsigned val = ProcessorHandler::get()->getRegisterValue(RVISA::GPR, 10); QCOMPARE(val, 43); } } diff --git a/test/tst_riscv.cpp b/test/tst_riscv.cpp index 2a7cf36e9..09481fcdf 100644 --- a/test/tst_riscv.cpp +++ b/test/tst_riscv.cpp @@ -114,12 +114,15 @@ QString tst_RISCV::dumpRegs() { QString::number( ProcessorHandler::getProcessor()->getPcForStage({0, 0}), 16) + "\n"; - const auto regInfo = ProcessorHandler::currentISA()->regInfo().value(); - for (unsigned i = 0; i < regInfo->regCnt(); i++) { - const auto value = - ProcessorHandler::getProcessor()->getRegister(RegisterFileType::GPR, i); - str += "\t" + regInfo->regName(i) + ":" + regInfo->regAlias(i) + ":\t" + - QString::number(value) + " (0x" + QString::number(value, 16) + ")\n"; + const auto *isa = ProcessorHandler::currentISA(); + for (const auto ®File : isa->regInfos()) { + for (unsigned i = 0; i < regFile->regCnt(); i++) { + const auto value = ProcessorHandler::getProcessor()->getRegister( + regFile->regFileName(), i); + str += "\t" + regFile->regName(i) + ":" + regFile->regAlias(i) + ":\t" + + QString::number(value) + " (0x" + QString::number(value, 16) + + ")\n"; + } } return str; } @@ -141,13 +144,13 @@ void tst_RISCV::loadBinaryToSimulator(const QString &binFile) { } void tst_RISCV::trapHandler() { - unsigned status = ProcessorHandler::getProcessor()->getRegister( - RegisterFileType::GPR, s_ecallreg); + unsigned status = + ProcessorHandler::getProcessor()->getRegister(RVISA::GPR, s_ecallreg); if (status != s_success) { m_err = "Test: '" + m_currentTest + "' failed: Internal test error.\n\t test number: " + QString::number(ProcessorHandler::getProcessor()->getRegister( - RegisterFileType::GPR, s_statusreg)); + RVISA::GPR, s_statusreg)); m_err += dumpRegs(); } m_stop |= true; @@ -171,7 +174,7 @@ QString tst_RISCV::executeSimulator() { m_err = "Test: '" + m_currentTest + "' failed: Maximum cycle count reached\n\t test number: " + QString::number(ProcessorHandler::getProcessor()->getRegister( - RegisterFileType::GPR, s_statusreg)); + RVISA::GPR, s_statusreg)); m_err += dumpRegs(); }