Skip to content

Commit

Permalink
Added prefetcher to decoder (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
levBagryansky authored Oct 28, 2023
1 parent c478557 commit 19bf2e5
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 11 deletions.
13 changes: 11 additions & 2 deletions include/besm-666/decoder/decoder.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#pragma once
#include "besm-666/autogen/operations-matrix.hpp"
#include "besm-666/instruction.hpp"

#include <cassert>
#include <cstdlib>
#include <stdexcept>

#include "besm-666/autogen/operations-matrix.hpp"
#include "besm-666/decoder/prefetcher.hpp"
#include "besm-666/instruction.hpp"

namespace besm::dec {

class Decoder {
Expand All @@ -21,14 +24,20 @@ class Decoder {
static constexpr RV64UWord RS2_MASK = 0b11111 << RS2_SHIFT;

public:
explicit Decoder(mem::MMU::SPtr mmu) : prefetcher_(std::move(mmu)) {}

/**
* Give the {@link Instruction} by the bytecode word.
* @param bytecode word.
* @return {@link Instruction} struct.
*/
[[nodiscard]] besm::Instruction parse(RV64UWord bytecode) const;

RV64UWord fetch(RV64Ptr address) { return prefetcher_.loadWord(address); }

private:
Prefetcher prefetcher_;

static inline Instruction parse_R(RV64UWord bytecode, Opcode opcode,
uint8_t func3);

Expand Down
42 changes: 42 additions & 0 deletions include/besm-666/decoder/prefetcher.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "besm-666/memory/mmu.hpp"

namespace besm::dec {

/**
* This class provides fetching of raw instructions, keeping
* the host memory address for the case if several of them
* are sequentially arranged in host memory.
*/
class Prefetcher {
public:
explicit Prefetcher(mem::MMU::SPtr mmu);

/**
* Loads word using mmu.
* @param vaddress Virtual address.
* @return word.
*/
RV64UWord loadWord(RV64Ptr vaddress);

private:
mem::MMU::SPtr mmu_;

/**
* Hosted address of continuous bytes.
*/
const RV64UWord *saved_;

/**
* Virtual address that corresponds to {@link Prefetcher::saved_}.
*/
RV64Ptr start_;

/**
* Number of continuous bytes starting from {@link Prefetcher::start_}
*/
RV64Size len_;
};

} // namespace besm::dec
6 changes: 4 additions & 2 deletions include/besm-666/memory/mmu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ class MMU : public INonCopyable {
void storeWord(RV64Ptr address, RV64Word value);
void storeDWord(RV64Ptr address, RV64DWord value);

std::pair<void *, size_t> getHostAddress(RV64Ptr address);
std::pair<void const *, size_t> getHostAddress(RV64Ptr address) const;
std::pair<void *, RV64Size> touchHostAddress(RV64Ptr vaddress);
std::pair<void const *, RV64Size> getHostAddress(RV64Ptr vaddress) const {
return pMem_->getHostAddress(translateAddress(vaddress));
}

private:
explicit MMU(std::shared_ptr<PhysMem> const &pMem)
Expand Down
4 changes: 2 additions & 2 deletions include/besm-666/sim/hart.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ class Hart : public INonCopyable {

private:
explicit Hart(std::shared_ptr<mem::PhysMem> const &pMem,
std::shared_ptr<HookManager> const &hookManager);
std::shared_ptr<HookManager> hookManager);

dec::Decoder dec_;
mem::MMU::SPtr mmu_;
dec::Decoder dec_;
exec::Executor exec_;
std::shared_ptr<sim::HookManager> hookManager_;

Expand Down
4 changes: 3 additions & 1 deletion src/decoder/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
add_library(besm666_decoder STATIC)
target_sources(besm666_decoder PRIVATE
decoder.cpp
prefetcher.cpp
)
target_link_libraries(besm666_decoder PRIVATE
besm666_include
besm666_include
besm666_memory
)
27 changes: 27 additions & 0 deletions src/decoder/prefetcher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "besm-666/decoder/prefetcher.hpp"
#include <cassert>

namespace besm::dec {

Prefetcher::Prefetcher(mem::MMU::SPtr mmu)
: mmu_(std::move(mmu)), saved_(nullptr), start_(-1), len_(0) {}

RV64UWord Prefetcher::loadWord(RV64Ptr vaddress) {
if (vaddress > start_ && vaddress < start_ + len_) {
// this address was already load
assert((vaddress - start_) % sizeof(RV64UWord) == 0);
return *(saved_ + (vaddress - start_) / sizeof(RV64UWord));
} else {
// load address
auto pair = mmu_->getHostAddress(vaddress);
if (pair.second > 0) {
start_ = vaddress;
len_ = pair.second;
saved_ = static_cast<const RV64UWord *>(pair.first);
return *saved_;
}
return mmu_->loadWord(vaddress);
}
}

} // namespace besm::dec
8 changes: 5 additions & 3 deletions src/sim/hart.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <cassert>
#include <iostream>
#include <utility>

#include "besm-666/exec/gprf.hpp"
#include "besm-666/memory/phys-mem.hpp"
Expand All @@ -14,8 +15,9 @@ Hart::SPtr Hart::Create(std::shared_ptr<mem::PhysMem> const &pMem,
}

Hart::Hart(std::shared_ptr<mem::PhysMem> const &pMem,
std::shared_ptr<HookManager> const &hookManager)
: mmu_(mem::MMU::Create(pMem)), exec_(mmu_), hookManager_(hookManager),
std::shared_ptr<HookManager> hookManager)
: mmu_(mem::MMU::Create(pMem)), dec_(mmu_), exec_(mmu_),
hookManager_(std::move(hookManager)),
prevPC_(std::numeric_limits<RV64UDWord>::max()), instrsExecuted_(0) {}

void Hart::runCycle() {
Expand All @@ -26,7 +28,7 @@ void Hart::runCycle() {
prevPC_ = pc;

// fetch
RV64UWord instrBytecode = mmu_->loadWord(pc);
RV64UWord instrBytecode = dec_.fetch(pc);
hookManager_->triggerHooks(HookManager::INSTRUCTION_FETCH, *this,
&instrBytecode);

Expand Down
1 change: 1 addition & 0 deletions unit_test/decoder/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
besm666_test(decoder_test.cpp)
besm666_test(prefetcher_test.cpp)
2 changes: 1 addition & 1 deletion unit_test/decoder/decoder_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ using namespace besm;

class DecoderCommon : public ::testing::Test {
protected:
const besm::dec::Decoder decoder{};
const besm::dec::Decoder decoder{nullptr};

[[nodiscard]] virtual bool equal(Instruction lhs, Instruction rhs) = 0;
void SetUp() override {}
Expand Down
25 changes: 25 additions & 0 deletions unit_test/decoder/prefetcher_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "./besm-666/decoder/prefetcher.hpp"
#include "besm-666/autogen/encoding.out.h"
#include <gtest/gtest.h>

using namespace besm;

TEST(Prefecher, fetch_not_fails) {
constexpr size_t RAM_SIZE = 1024 * 1024 * 1024;
std::shared_ptr<mem::PhysMem> pMem =
mem::PhysMemBuilder()
.mapRAM(0, RAM_SIZE, 4096, 2 * 1024 * 1024)
.build();
mem::MMU::SPtr mmu = mem::MMU::Create(pMem);
dec::Prefetcher prefetcher{mmu};
constexpr RV64Ptr const ADDR = 1000;

constexpr int to_store = 4096;
for (int i = 0; i < to_store; ++i) {
mmu->storeWord(ADDR + i * sizeof(RV64UWord), i);
}
for (int i = 0; i < to_store; ++i) {
RV64UWord word = prefetcher.loadWord(ADDR + i * sizeof(RV64UWord));
EXPECT_EQ(word, i);
}
}

0 comments on commit 19bf2e5

Please sign in to comment.