Skip to content

Commit

Permalink
Split register info class into multiple classes; one per register file (
Browse files Browse the repository at this point in the history
#320)

* Split register info class into multiple classes; one per register file

* Rename MIPS_RegInfo to MIPS_GPRInfo

* Replace RegInfoSet with a normal std::vector

NOTE: This does not compile yet.

* Specify register file types everywhere that registers are indexed

* Create virtual function to return an ISA's register info map

This makes it harder to forget to implement this map for each ISA.

* Fix tests

* Replace RegisterFileType enum with a std::string_view

* Fix added QVariant

* Fix --reginit register file name comparison

* Fix clang-format

* Remove radix parameter from `decodeRadixValue`

* Add interleaveComma function from LLVM

Taken from https://github.com/llvm/llvm-project/blob/6b87d84ff45d03c244e7511fba9359776ce27977/llvm/include/llvm/ADT/STLExtras.h#L2134C18-L2134C18

* Remove unecessary const return type

* Fix PR errors

* Remove returns in else statements

* Fix const auto pointers

* Add syscall register assertion in tst_cosimulate
  • Loading branch information
raccog authored Nov 26, 2023
1 parent f673e59 commit 357f796
Show file tree
Hide file tree
Showing 51 changed files with 634 additions and 361 deletions.
63 changes: 63 additions & 0 deletions src/STLExtras.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename ForwardIterator, typename UnaryFunctor,
typename NullaryFunctor,
typename = std::enable_if_t<
!std::is_constructible<std::string_view, UnaryFunctor>::value &&
!std::is_constructible<std::string_view, NullaryFunctor>::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 <typename Container, typename UnaryFunctor, typename NullaryFunctor,
typename = std::enable_if_t<
!std::is_constructible<std::string_view, UnaryFunctor>::value &&
!std::is_constructible<std::string_view, NullaryFunctor>::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 <typename Container, typename UnaryFunctor, typename StreamT,
typename T = detail::ValueOfRange<Container>>
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 <typename Container, typename StreamT,
typename T = detail::ValueOfRange<Container>>
inline void interleave(const Container &c, StreamT &os,
const std::string_view &separator) {
interleave(
c, os, [&](const T &a) { os << a; }, separator);
}

template <typename Container, typename UnaryFunctor, typename StreamT,
typename T = detail::ValueOfRange<Container>>
inline void interleaveComma(const Container &c, StreamT &os,
UnaryFunctor each_fn) {
interleave(c, os, each_fn, ", ");
}
template <typename Container, typename StreamT,
typename T = detail::ValueOfRange<Container>>
inline void interleaveComma(const Container &c, StreamT &os) {
interleaveComma(c, os, [&](const T &a) { os << a; });
}

} // namespace llvm

#endif // LLVM_ADT_STLEXTRAS_H
2 changes: 1 addition & 1 deletion src/addressdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <QDialog>

#include "ripes_types.h"
#include "isa/isa_types.h"

namespace Ripes {

Expand Down
2 changes: 1 addition & 1 deletion src/assembler/assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <cstdint>
#include <numeric>
Expand Down
2 changes: 1 addition & 1 deletion src/assembler/program.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <vector>

#include "isa/isa_defines.h"
#include "ripes_types.h"
#include "isa/isa_types.h"

namespace Ripes {

Expand Down
2 changes: 1 addition & 1 deletion src/binutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#include <vector>

#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

Expand Down
2 changes: 1 addition & 1 deletion src/cachesim/cacheview.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <QGraphicsView>

#include "ripes_types.h"
#include "isa/isa_types.h"

namespace Ripes {

Expand Down
2 changes: 1 addition & 1 deletion src/cachesim/l1cacheshim.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "cachesim.h"

#include "VSRTL/core/vsrtl_memory.h"
#include "ripes_types.h"
#include "isa/isa_types.h"

namespace Ripes {

Expand Down
2 changes: 1 addition & 1 deletion src/cachetab.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "ripestab.h"
#include <QWidget>

#include "ripes_types.h"
#include "isa/isa_types.h"

namespace Ripes {

Expand Down
115 changes: 77 additions & 38 deletions src/cli/clioptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
#include <QFile>
#include <QMetaEnum>

#include <sstream>
#include <string>

#include "STLExtras.h"

namespace Ripes {

void addCLIOptions(QCommandLineParser &parser, Ripes::CLIModeOptions &options) {
Expand All @@ -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"
"<register idx>=<value>,<register idx>=<value>",
"[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"
"<register file>:<register idx>=<value>,<register idx>=<value>",
"regfile:[rid=v]"));
parser.addOption(QCommandLineOption(
"timeout",
"Simulation timeout in milliseconds. If simulation does not finish "
Expand Down Expand Up @@ -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 &regInit : 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 &regFileInit : 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 &regInit : 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 &regFileName : 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;
}
}

Expand Down
22 changes: 13 additions & 9 deletions src/cli/telemetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 &regFile : 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 &regFile : 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;
}
Expand Down
23 changes: 15 additions & 8 deletions src/gotocombobox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ void GoToComboBox::showPopup() {
void GoToComboBox::signalFilter(int index) {
const auto &value = itemData(index);

const auto f = qvariant_cast<GoToUserData>(value);
switch (f.func) {
GoToUserData data;
if (value.metaType() == QMetaType::fromType<GoToRegisterValue>()) {
data = qvariant_cast<GoToRegisterValue>(value);
} else {
data = qvariant_cast<GoToUserData>(value);
}
switch (data.func) {
case GoToFunction::Select:
break;
case GoToFunction::Address: {
Expand Down Expand Up @@ -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<GoToUserData>({GoToFunction::Custom, i}));
for (const auto &regInfo : isa->regInfos()) {
for (unsigned i = 0; i < regInfo->regCnt(); ++i) {
addItem(regInfo->regName(i) + " (" + regInfo->regAlias(i) + ")",
QVariant::fromValue<GoToRegisterValue>(
{{GoToFunction::Custom, i}, regInfo->regFileName()}));
}
}
}

AInt GoToRegisterComboBox::addrForIndex(int i) {
const auto &regIdx = qvariant_cast<GoToUserData>(itemData(i));
return ProcessorHandler::getRegisterValue(RegisterFileType::GPR, regIdx.arg);
const auto &regIdx = qvariant_cast<GoToRegisterValue>(itemData(i));
return ProcessorHandler::getRegisterValue(regIdx.regFileName, regIdx.arg);
}

} // namespace Ripes
7 changes: 6 additions & 1 deletion src/gotocombobox.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <QComboBox>
#include <QMetaType>

#include "ripes_types.h"
#include "isa/isa_types.h"

namespace Ripes {

Expand All @@ -13,6 +13,10 @@ struct GoToUserData {
unsigned arg;
};

struct GoToRegisterValue : public GoToUserData {
std::string_view regFileName;
};

class GoToComboBox : public QComboBox {
Q_OBJECT
public:
Expand Down Expand Up @@ -50,3 +54,4 @@ class GoToRegisterComboBox : public GoToComboBox {
} // namespace Ripes

Q_DECLARE_METATYPE(Ripes::GoToUserData);
Q_DECLARE_METATYPE(Ripes::GoToRegisterValue);
3 changes: 1 addition & 2 deletions src/isa/isa_defines.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include <cstdint>
#include <iostream>
#include <map>
#include <set>
Expand All @@ -10,7 +9,7 @@
#include <QString>
#include <QTextStream>

#include "ripes_types.h"
#include "isa_types.h"

namespace Ripes {

Expand Down
File renamed without changes.
Loading

0 comments on commit 357f796

Please sign in to comment.