Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
40 changes: 22 additions & 18 deletions src/cpu_state/cpu_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <fmt/core.h>
#include <fmt/ostream.h>
#include <fmt/ranges.h>

namespace prot {

Expand All @@ -12,27 +13,30 @@ enum class NumSysCall : isa::Word {
};

void CPUState::dump(std::ostream &ost) const {
fmt::println(ost, "---CPU STATE DUMP---");
fmt::println(ost, "Icount = {}", icount);
fmt::println(ost, "PC = {:#x}", pc);
static constexpr auto kAbiRegs = std::to_array<std::string_view>(
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0",
"a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5",
"s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"});

static constexpr std::size_t kRegPerRow = 5;
static constexpr std::size_t kNumRows =
(kNumRegs + kRegPerRow - 1) / kRegPerRow;
static_assert(kNumRows * kRegPerRow >= kNumRegs);
static constexpr std::size_t kRegNameSpace =
std::ranges::max(kAbiRegs | std::views::transform(std::ranges::size)) +
5; // 4 for xXX/ + 1 for space

for (auto i : std::views::iota(0U, kNumRows)) {
for (auto j : std::views::iota(0U, kRegPerRow)) {
const auto effIdx = (i * kRegPerRow) + j;
if (effIdx >= regs.size()) {
break;
}
fmt::print(ost, "X[{:02}] = {:#010x} ", effIdx, regs[effIdx]);
}
ost << "\n";
}
fmt::println(ost, " {:<{}}{:08x}", "pc", kRegNameSpace, pc);
static constexpr std::size_t kRegsByRow = 4;
static_assert(kNumRegs % kRegsByRow == 0);

for (std::size_t i = 0; i < regs.size(); i += 4) {
auto regDumps =
std::views::iota(0U, kRegsByRow) |
std::views::transform([i](auto j) { return i + j; }) |
std::views::transform([&](auto idx) {
auto name = fmt::format("x{}/{}", idx, kAbiRegs[idx]);
return fmt::format("{:<{}}{:08x}", name, kRegNameSpace, regs.at(idx));
});

fmt::println(ost, "---CPU STATE DUMP END---");
fmt::println(ost, " {}", fmt::join(regDumps, " "));
}
}

void CPUState::doExit(isa::Word code) {
Expand Down
11 changes: 8 additions & 3 deletions src/jit/base/base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ extern "C" {
namespace prot::engine {
void JitEngine::step(CPUState &cpu) {
while (!cpu.finished) [[likely]] {
if (m_config.enableDump) {
cpu.dump(std::cout);
}

// colllect bb
const auto pc = cpu.getPC();
auto found = m_tbCache.lookup(pc);
Expand All @@ -35,13 +39,14 @@ void JitEngine::step(CPUState &cpu) {
}

bb.insns.push_back(*inst);
if (isa::isTerminator(inst->opcode())) {

if (m_config.singleStep || isa::isTerminator(inst->opcode())) {
break;
}
curAddr += isa::kWordSize;
}
}
if (bbIt->second.num_exec >= m_execThreshold) [[likely]] {
if (bbIt->second.num_exec >= m_config.execThreshold) [[likely]] {
auto code = translate(bbIt->second);
m_tbCache.insert(pc, code);
if (code != nullptr) [[likely]] {
Expand All @@ -63,7 +68,7 @@ void JitEngine::interpret(CPUState &cpu, BBInfo &info) {

auto JitEngine::getBBInfo(isa::Addr pc) const -> const BBInfo * {
if (const auto found = m_cacheBB.find(pc); found != m_cacheBB.end()) {
if (found->second.num_exec >= m_execThreshold) {
if (found->second.num_exec >= m_config.execThreshold) {
return &found->second;
}
}
Expand Down
14 changes: 10 additions & 4 deletions src/jit/base/include/prot/jit/base.hh
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@

#include "prot/interpreter.hh"

#include <functional>
#include <map>
#include <unordered_map>
#include <vector>

namespace prot::engine {
using JitFunction = void (*)(CPUState &);

class JitEngine : public Interpreter {
public:
struct Config final {
std::size_t execThreshold{};
bool singleStep{false};
bool enableDump{false};
};

void step(CPUState &cpu) override;
void setExecThres(std::size_t thres) { m_execThreshold = thres; }

void setConfig(const Config &config) { m_config = config; }

protected:
struct TbCache {
Expand Down Expand Up @@ -62,7 +68,7 @@ private:
private:
[[nodiscard]] virtual JitFunction translate(const BBInfo &info) = 0;

std::size_t m_execThreshold{};
Config m_config{};
TbCache m_tbCache;
std::unordered_map<isa::Addr, BBInfo> m_cacheBB;
};
Expand Down
3 changes: 1 addition & 2 deletions src/jit/factory/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ add_library(prot_jit_factory STATIC factory.cc)

target_link_libraries(
prot_jit_factory
PUBLIC PROT::exec_engine
PUBLIC PROT::exec_engine PROT::JIT::base
PRIVATE PROT::defaults
PROT::JIT::xbyak
PROT::JIT::asmjit
PROT::JIT::base
PROT::JIT::llvmbased
PROT::JIT::lightning
PROT::JIT::mir
Expand Down
7 changes: 4 additions & 3 deletions src/jit/factory/factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ std::vector<std::string_view> JitFactory::backends() {
return res;
}

std::unique_ptr<ExecEngine> JitFactory::createEngine(const std::string &backend,
std::size_t execThres) {
std::unique_ptr<ExecEngine>
JitFactory::createEngine(const std::string &backend,
const JitEngine::Config &config) {
auto it = kFactories.find(backend);
if (it != kFactories.end()) {
auto engine = it->second();
Expand All @@ -40,7 +41,7 @@ std::unique_ptr<ExecEngine> JitFactory::createEngine(const std::string &backend,
throw std::invalid_argument{"Not a JIT engine"};
}

jitBase->setExecThres(execThres);
jitBase->setConfig(config);

return engine;
}
Expand Down
5 changes: 3 additions & 2 deletions src/jit/factory/include/prot/jit/factory.hh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define INCLUDE_PROT_JIT_FACTORY_HH_INCLUDED

#include "prot/exec_engine.hh"
#include "prot/jit/base.hh"

#include <functional>
#include <string>
Expand All @@ -14,8 +15,8 @@ namespace prot::engine {
class JitFactory {
public:
[[nodiscard]] static std::vector<std::string_view> backends();
static std::unique_ptr<ExecEngine> createEngine(const std::string &backend,
std::size_t execThres);
static std::unique_ptr<ExecEngine>
createEngine(const std::string &backend, const JitEngine::Config &config);
static bool exist(const std::string &backend);

private:
Expand Down
21 changes: 14 additions & 7 deletions tools/sim/sim_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int main(int argc, const char *argv[]) try {
constexpr prot::isa::Addr kDefaultStack = 0x7fffffff;
prot::isa::Addr stackTop{};
std::string jitBackend{};
std::size_t execThres{};
prot::engine::JitEngine::Config jitConfig{};

{
CLI::App app{"App for JIT research from ProteusLab team"};
Expand All @@ -34,13 +34,19 @@ int main(int argc, const char *argv[]) try {
auto *jit =
app.add_option("--jit", jitBackend, "Use JIT & set backend")
->check(CLI::IsMember(prot::engine::JitFactory::backends()));
auto *jitOpts = app.add_option_group("JIT options")->needs(jit);

app.add_option("--exec-threshold", execThres,
"Specify amount of BB execs before translation starts")
jitOpts->add_flag("--single-step", jitConfig.singleStep,
"Set single step (by instruction) JIT-simulation mode");
jitOpts
->add_option("--exec-threshold", jitConfig.execThreshold,
"Specify amount of BB execs before translation starts")
->default_val(10)
->needs(jit)
->capture_default_str();

jitOpts->add_flag("--dump-cpu", jitConfig.enableDump,
"Enable dump of CPU state before each TB");

CLI11_PARSE(app, argc, argv);
}
const bool jitEnabled = !jitBackend.empty();
Expand All @@ -50,11 +56,12 @@ int main(int argc, const char *argv[]) try {

auto engine = [&]() -> std::unique_ptr<prot::ExecEngine> {
if (jitEnabled) {
return prot::engine::JitFactory::createEngine(jitBackend, execThres);
return prot::engine::JitFactory::createEngine(jitBackend, jitConfig);
}
return std::make_unique<prot::engine::Interpreter>();
}();
prot::Hart hart{prot::memory::makePlain(4ULL << 30U), std::move(engine)};
auto mem = prot::memory::makePlain(4ULL << 30U);
prot::Hart hart{std::move(mem), std::move(engine)};
hart.load(loader);
hart.setSP(stackTop);

Expand All @@ -69,7 +76,7 @@ int main(int argc, const char *argv[]) try {
fmt::println("icount: {}", hart.getIcount());
fmt::println("time: {}s", duration.count());
if (jitEnabled) {
fmt::println("threshold: {}", execThres);
fmt::println("threshold: {}", jitConfig.execThreshold);
}
fmt::println("mips: {}", hart.getIcount() / (duration.count() * 1000000));
return hart.getExitCode();
Expand Down
Loading