Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sliderules: A dynamic ISA reference table #329

Draft
wants to merge 64 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
4743185
Prevent release-based Github Actions from running on forks
raccog Jan 6, 2024
132765f
Remove unnecessary conditionals
raccog Jan 6, 2024
8996044
Add initial Qt Designer layout for sliderules tab
raccog Nov 13, 2023
e19938b
Create template table model for instruction decoding
raccog Nov 13, 2023
1dbf773
Add encoding table
raccog Nov 13, 2023
4a92d75
Fill table with instruction names and extension origin
raccog Nov 13, 2023
6c45fbb
Try to generate initial parts of the encoding table
raccog Nov 13, 2023
80e336b
Fix column resizing and disable filter input
raccog Nov 13, 2023
9da20b9
Fix column sizes and add some spans
raccog Nov 13, 2023
448a97f
Generate field names for sliderules encoding table
raccog Nov 13, 2023
ee70d09
Set opcode bits in the table and mark them with the color red
raccog Nov 13, 2023
c6c5eac
Reorganize sliderule table by using a certain structure for each column
raccog Nov 14, 2023
7669aa8
Add fields to bitfields
raccog Nov 14, 2023
69f9f6c
Fix immediates intersecting with zeroes
raccog Nov 14, 2023
a4dcc86
Fix BitRangeSet fold expression
raccog Nov 14, 2023
a72655b
Give fields shortened names if only using one column
raccog Nov 14, 2023
c2e304a
Blank out instruction bits that are not used (for compressed instrs)
raccog Nov 14, 2023
f3fbaa4
Add splitter between encodings and decodings
raccog Nov 14, 2023
baf4ecb
Fix spanning issues
raccog Nov 14, 2023
019e96b
Move instruction instances from Assembler into ISAInfoBase
raccog Nov 14, 2023
c451ea6
Quick refactor
raccog Nov 14, 2023
eae42ec
Further reduce ISAInfo instantiations by caching all accesses
raccog Nov 14, 2023
0b99885
Show instructions from all supported extensions in sliderules
raccog Nov 14, 2023
52a5f2d
Add descriptions to RISC-V instructions and sliderules table
raccog Dec 5, 2023
4a798b6
Add long description for tooltip when hovering over description
raccog Dec 5, 2023
e8fc451
Fix rebase
raccog Dec 6, 2023
693f01e
Refactor (simplify) encoding table
raccog Dec 13, 2023
9b3a389
Stretch description column
raccog Dec 13, 2023
e74af17
Add rows for encoding constructed immediates
raccog Dec 13, 2023
d161984
Add some TODO comments
raccog Dec 13, 2023
e82c1bd
Add UI selectors for ISA and register width
raccog Dec 13, 2023
657f6b9
Add ISA options to combo boxes
raccog Dec 13, 2023
e900764
Change grouping of ISA selectors
raccog Dec 13, 2023
2ab6139
Got ISA filtering working properly
raccog Dec 18, 2023
461e774
Add main ISA extension selector
raccog Dec 18, 2023
e4db60b
Get main extensions selector working
raccog Dec 18, 2023
dfbd2a5
Fix encoding table column stretching when changing ISA options
raccog Dec 28, 2023
8cdfcc0
Quick refactor
raccog Dec 28, 2023
6f7d385
Add UI element for selecting multiple extensions
raccog Dec 28, 2023
554e8fb
Fix rows being hidden when they shouldn't be
raccog Dec 28, 2023
778daff
Remove "Explanation" column
raccog Jan 6, 2024
d3b5dfb
Rewrite parts of the EncodingModel
raccog Jan 6, 2024
d173b8a
Create EncodingView manually to be more independent from SliderulesTab
raccog Jan 6, 2024
cf4b070
Get encoding table filters working again (mostly)
raccog Jan 6, 2024
a69f3ea
Get main extension selector working (mostly)
raccog Jan 7, 2024
649a1d1
Remove some unused code
raccog Jan 7, 2024
4ad140d
Get all current filters working properly
raccog Jan 7, 2024
237ed95
Add checkboxes for selecting additional extensions
raccog Jan 7, 2024
fe28e14
Remove blank extension from MIPS ISAInfo
raccog Jan 7, 2024
4cdddbf
Show in UI how many instructions are shown/filtered
raccog Jan 7, 2024
e1435ad
Only reset the register width selector when changing ISA families
raccog Jan 7, 2024
d82f4c8
Fix clang-format
raccog Jan 7, 2024
1d0f205
Separate encoding model (data) from encoding view (UI)
raccog Jan 15, 2024
5164176
Start reworking UI after learning more about Qt
raccog Jan 19, 2024
baf1b7e
Add back ISA register width selector
raccog Jan 19, 2024
f3951ee
Working on flow of data between Qt widgets and models
raccog Feb 3, 2024
f225d79
Redo again
raccog Feb 26, 2024
631bd93
Get sliderules filters working
raccog Feb 26, 2024
3851d01
Start Qt model from scratch
raccog Feb 26, 2024
95815d6
Remove complex code to start with a simple example
raccog Feb 26, 2024
acb054b
Get a working model for a QTreeView
raccog Feb 27, 2024
342722e
Add first signal and slot for ISAInstructionsModel
raccog Feb 27, 2024
fb22184
Connect signals/slots so that ISA filters work properly
raccog Feb 27, 2024
453a2e9
Update extension filters when model changes
raccog Feb 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/docker-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:

jobs:
docker:
if: github.repository == 'mortbopet/Ripes'
runs-on: ubuntu-latest
steps:
-
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release_setup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:

jobs:
release-setup:
if: github.repository == 'mortbopet/Ripes'
runs-on: ubuntu-latest
steps:

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Ripes Tests
on:
push:
branches:
- '*'
- '**'
pull_request:

jobs:
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/wasm-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: WASM / Qt 6.6.0
on:
push:
branches:
- '*'
- '**'

jobs:
buildUbuntuXenial:
Expand Down Expand Up @@ -103,5 +103,6 @@ jobs:
# Dispatch the publish.yml workflow over at mortbopet.github.io
- run: |
gh workflow run publish.yml -R mortbopet/mortbopet.github.io --ref master
if: github.repository == 'mortbopet/Ripes'
env:
GH_TOKEN: ${{ secrets.MORTBOPET_GITHUB_IO_TOKEN }}
2 changes: 1 addition & 1 deletion src/assembler/assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ constructAssemblerDynamic(const std::shared_ptr<const ISAInfoBase> &isa) {

throw std::runtime_error(
std::string("Cannot dynamically construct assembler for isa: ") +
isa->name().toStdString());
isa->fullName().toStdString());
}

} // namespace Assembler
Expand Down
117 changes: 114 additions & 3 deletions src/isa/instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ struct BitRangeBase {

const unsigned start, stop, N;

/// Returns true if the index is within the start/stop range
constexpr bool isWithinRange(unsigned idx) const {
return (idx >= start && idx <= stop);
}
constexpr unsigned width() const { return stop - start + 1; }
// TODO(raccog): Decouple from vsrtl library
constexpr Instr_T getMask() const { return vsrtl::generateBitmask(width()); }
Expand Down Expand Up @@ -133,6 +137,9 @@ struct BitRangeSet {
using CombineWith =
typename OtherBitRangeImpl::template CombinedBitRanges<BitRanges...>;

/// Returns all BitRanges in this set as a vector that can be read at runtime
static std::vector<BitRangeBase> getRanges() { return {BitRanges()...}; }

/// Returns the combined width of all BitRanges
constexpr static unsigned width() { return (BitRanges().width() + ... + 0); }

Expand Down Expand Up @@ -182,6 +189,11 @@ struct OpPartBase {
return range < other.range;
}

/// Returns true if the i'th bit is set in this OpPart
constexpr bool bitIsSet(unsigned i) const {
return ((range.apply(value) >> i) & 1) == 1;
}

/// Applies this OpPart's encoding to the instruction.
constexpr void apply(Instr_T &instruction) const {
instruction |= range.apply(value);
Expand Down Expand Up @@ -271,6 +283,9 @@ struct OpcodeSet {
return IndexedOpPart<OpParts...>::getOpPart(partIndex);
}

/// Returns all OpParts in this set as a vector that can be read at runtime
static std::vector<OpPartBase> getParts() { return {OpParts()...}; }

private:
/// Run verifications for all BitRanges
constexpr static BitRanges ranges{};
Expand All @@ -290,16 +305,31 @@ struct InstrRes {

using AssembleRes = Result<InstrRes>;

struct FieldBase {
enum class Type { Reg, Immediate };

FieldBase(Type _type, unsigned _tokenIndex, std::vector<BitRangeBase> _ranges)
: type(_type), tokenIndex(_tokenIndex), ranges(_ranges) {}

const Type type;
const unsigned tokenIndex;
const std::vector<BitRangeBase> ranges;

virtual QString fieldType() const { return "UNKNOWN"; }
};

/** @brief An instruction field defined at compile-time.
* @param _tokenIndex: The index of this field in an assembly instruction
* (starting at 0).
* @param _BitRanges: A set of BitRanges that define which bits contain field in
* the instruction. Must be BitRangesImpl type.
*/
template <unsigned _tokenIndex, typename _BitRanges>
struct Field {
struct Field : public FieldBase {
using BitRanges = _BitRanges;

Field(Type type) : FieldBase(type, _tokenIndex, BitRanges::getRanges()) {}

private:
/// Run verifications for all BitRanges
constexpr static BitRanges ranges{};
Expand All @@ -316,6 +346,7 @@ class FieldSet {
template <unsigned, template <unsigned> typename...>
struct IndexedFieldSet {
using BitRanges = BitRangeSet<>;
static std::vector<std::shared_ptr<FieldBase>> getFields() { return {}; }
};
template <unsigned tokenIndex, template <unsigned> typename FirstField,
template <unsigned> typename... NextFields>
Expand Down Expand Up @@ -354,6 +385,19 @@ class FieldSet {
else
return true;
}

/// Returns all Fields in this set as a vector that can be read at runtime
static std::vector<std::shared_ptr<FieldBase>> getFields() {
auto field = std::make_shared<IndexedField>();
if constexpr (tokenIndex < sizeof...(Fields)) {
std::vector<std::shared_ptr<FieldBase>> vec =
NextIndexedFieldSet::getFields();
vec.insert(vec.begin(), field);
return vec;
} else {
return {field};
}
}
};

using IndexedFields = IndexedFieldSet<0, Fields...>;
Expand Down Expand Up @@ -383,6 +427,14 @@ class FieldSet {
/// Returns the number of Fields in this set.
constexpr static unsigned numFields() { return sizeof...(Fields); }

/// Returns all Fields in this set as a vector that can be read at runtime
static std::vector<std::shared_ptr<FieldBase>> getFields() {
if constexpr (sizeof...(Fields) == 0) {
return {};
}
return IndexedFields::getFields();
}

private:
/// This calls all BitRanges' static assertions
constexpr static BitRanges ranges{};
Expand All @@ -404,7 +456,9 @@ template <typename RegImpl, unsigned tokenIndex, typename BitRange,
struct Reg : public Field<tokenIndex, BitRangeSet<BitRange>> {
static_assert(verifyBitRange<BitRange>(), "Invalid BitRange type");

Reg() : regsd(RegImpl::NAME.data()) {}
Reg()
: Field<tokenIndex, BitRangeSet<BitRange>>(FieldBase::Type::Reg),
regsd(RegImpl::NAME.data()) {}

/// Applies this register's encoding to the instruction.
static Result<> apply(const TokenizedSrcLine &line, Instr_T &instruction,
Expand Down Expand Up @@ -435,6 +489,8 @@ struct Reg : public Field<tokenIndex, BitRangeSet<BitRange>> {
return true;
}

QString fieldType() const override { return regsd; }

const QString regsd = "reg";
};

Expand Down Expand Up @@ -553,6 +609,12 @@ struct ImmBase : public Field<tokenIndex, typename ImmParts::BitRanges> {
using Reg_T_S = typename std::make_signed<Reg_T>::type;
using Reg_T_U = typename std::make_unsigned<Reg_T>::type;

ImmBase()
: Field<tokenIndex, typename ImmParts::BitRanges>(
FieldBase::Type::Immediate) {}

QString fieldType() const override { return "imm"; }

/// Converts a string to its immediate value (if it exists). Success is set to
/// false if this fails.
constexpr static int64_t getImm(const QString &immToken, bool &success,
Expand Down Expand Up @@ -712,8 +774,14 @@ class InstructionBase {
virtual OpPartBase getOpPart(unsigned partIndex) const = 0;
/// Returns the name of this instruction.
virtual const QString &name() const = 0;
/// Returns a description of this instruction.
virtual const QString &description() const = 0;
/// Returns a long description of this instruction.
virtual const QString &longDescription() const = 0;
/// Returns the number of OpParts in this instruction.
virtual unsigned numOpParts() const = 0;
/// Returns the name of the extension that this instruction came from.
virtual QString extensionOrigin() const = 0;

/**
* @brief size
Expand All @@ -730,6 +798,30 @@ class InstructionBase {
[&](const auto &f) { return f(instr); });
}

virtual const std::vector<std::shared_ptr<FieldBase>> &getFields() const = 0;
virtual const std::vector<OpPartBase> &getOpParts() const = 0;

bool opPartBitIsSet(unsigned idx) const {
auto opParts = getOpParts();
// Check each OpPart to see if this bit is set
for (const auto &part : opParts) {
if (part.bitIsSet(idx)) {
return true;
}
}
return false;
}
bool opPartInRange(unsigned idx) const {
auto opParts = getOpParts();
// Check each OpPart to see if this bit is set
for (const auto &part : opParts) {
if (part.range.isWithinRange(idx)) {
return true;
}
}
return false;
}

protected:
/// An optional set of disassembler match conditions, if the default
/// opcode-based matching is insufficient.
Expand Down Expand Up @@ -772,7 +864,13 @@ template <typename InstrImpl>
struct Instruction : public InstructionBase {
Instruction()
: InstructionBase(InstrByteSize<InstrImpl>::byteSize),
m_name(InstrImpl::NAME.data()) {}
m_name(InstrImpl::NAME.data()), m_description(InstrImpl::DESC.data()),
m_longDescription(InstrImpl::LONG_DESC.data()),
m_fields(InstrImpl::Fields::getFields()),
m_opParts(InstrImpl::Opcode::getParts()) {}

constexpr static std::string_view DESC = "TODO: DESCRIPTION";
constexpr static std::string_view LONG_DESC = "TODO: LONG DESCRIPTION";

AssembleRes assemble(const TokenizedSrcLine &tokens) override {
Instr_T instruction = 0;
Expand Down Expand Up @@ -804,10 +902,23 @@ struct Instruction : public InstructionBase {
return InstrImpl::Opcode::getOpPart(partIndex);
}
const QString &name() const override { return m_name; }
const QString &description() const override { return m_description; }
const QString &longDescription() const override { return m_longDescription; }
unsigned numOpParts() const override { return InstrImpl::Opcode::numParts(); }

const std::vector<std::shared_ptr<FieldBase>> &getFields() const override {
return m_fields;
}
const std::vector<OpPartBase> &getOpParts() const override {
return m_opParts;
}

private:
const QString m_name;
const QString m_description;
const QString m_longDescription;
const std::vector<std::shared_ptr<FieldBase>> m_fields;
const std::vector<OpPartBase> m_opParts;
};

using InstrMap = std::map<QString, std::shared_ptr<InstructionBase>>;
Expand Down
34 changes: 34 additions & 0 deletions src/isa/isaconstructor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "isaconstructor.h"

#include "mips32isainfo.h"
#include "rv32isainfo.h"
#include "rv64isainfo.h"

namespace Ripes {

template <ISA... isas>
std::map<ISA,
std::function<std::shared_ptr<const ISAInfoBase>(const QStringList &)>>
_constructConstructors() {
std::map<ISA, std::function<std::shared_ptr<const ISAInfoBase>(
const QStringList &)>>
constructors;
(
[&] {
constructors[isas] = [](const QStringList &extensions) {
return std::make_shared<ISAInfo<isas>>(extensions);
};
}(),
...);
return constructors;
}

std::map<ISA,
std::function<std::shared_ptr<const ISAInfoBase>(const QStringList &)>>
constructConstructors() {
/// NOTE: Ensure that every ISA is used in the `_constructConstructors<...>()`
/// template
return _constructConstructors<ISA::MIPS32I, ISA::RV32I, ISA::RV64I>();
}

} // namespace Ripes
16 changes: 16 additions & 0 deletions src/isa/isaconstructor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <map>

#include <QStringList>

namespace Ripes {

enum class ISA;
class ISAInfoBase;

std::map<ISA,
std::function<std::shared_ptr<const ISAInfoBase>(const QStringList &)>>
constructConstructors();

} // namespace Ripes
Loading
Loading