diff --git a/src/cpu_state/cpu_state.cc b/src/cpu_state/cpu_state.cc index 3be1868..eda19eb 100644 --- a/src/cpu_state/cpu_state.cc +++ b/src/cpu_state/cpu_state.cc @@ -4,6 +4,7 @@ #include #include +#include namespace prot { @@ -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( + {"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) { diff --git a/src/jit/base/base.cc b/src/jit/base/base.cc index 74ee5fd..af61d8a 100644 --- a/src/jit/base/base.cc +++ b/src/jit/base/base.cc @@ -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); @@ -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]] { @@ -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; } } diff --git a/src/jit/base/include/prot/jit/base.hh b/src/jit/base/include/prot/jit/base.hh index 0486709..fb02a68 100644 --- a/src/jit/base/include/prot/jit/base.hh +++ b/src/jit/base/include/prot/jit/base.hh @@ -3,17 +3,23 @@ #include "prot/interpreter.hh" -#include -#include #include #include 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 { @@ -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 m_cacheBB; }; diff --git a/src/jit/factory/CMakeLists.txt b/src/jit/factory/CMakeLists.txt index 8f4a4a4..dbbc99a 100644 --- a/src/jit/factory/CMakeLists.txt +++ b/src/jit/factory/CMakeLists.txt @@ -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 diff --git a/src/jit/factory/factory.cc b/src/jit/factory/factory.cc index 269dc77..f703d4e 100644 --- a/src/jit/factory/factory.cc +++ b/src/jit/factory/factory.cc @@ -30,8 +30,9 @@ std::vector JitFactory::backends() { return res; } -std::unique_ptr JitFactory::createEngine(const std::string &backend, - std::size_t execThres) { +std::unique_ptr +JitFactory::createEngine(const std::string &backend, + const JitEngine::Config &config) { auto it = kFactories.find(backend); if (it != kFactories.end()) { auto engine = it->second(); @@ -40,7 +41,7 @@ std::unique_ptr JitFactory::createEngine(const std::string &backend, throw std::invalid_argument{"Not a JIT engine"}; } - jitBase->setExecThres(execThres); + jitBase->setConfig(config); return engine; } diff --git a/src/jit/factory/include/prot/jit/factory.hh b/src/jit/factory/include/prot/jit/factory.hh index 2020597..3ce4da1 100644 --- a/src/jit/factory/include/prot/jit/factory.hh +++ b/src/jit/factory/include/prot/jit/factory.hh @@ -2,6 +2,7 @@ #define INCLUDE_PROT_JIT_FACTORY_HH_INCLUDED #include "prot/exec_engine.hh" +#include "prot/jit/base.hh" #include #include @@ -14,8 +15,8 @@ namespace prot::engine { class JitFactory { public: [[nodiscard]] static std::vector backends(); - static std::unique_ptr createEngine(const std::string &backend, - std::size_t execThres); + static std::unique_ptr + createEngine(const std::string &backend, const JitEngine::Config &config); static bool exist(const std::string &backend); private: diff --git a/tools/sim/sim_app.cpp b/tools/sim/sim_app.cpp index 3603bcb..f67bfdf 100644 --- a/tools/sim/sim_app.cpp +++ b/tools/sim/sim_app.cpp @@ -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"}; @@ -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(); @@ -50,11 +56,12 @@ int main(int argc, const char *argv[]) try { auto engine = [&]() -> std::unique_ptr { if (jitEnabled) { - return prot::engine::JitFactory::createEngine(jitBackend, execThres); + return prot::engine::JitFactory::createEngine(jitBackend, jitConfig); } return std::make_unique(); }(); - 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); @@ -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();