From a1ebd83d2a1b401c03b62668f96719c660ba641d Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Tue, 19 Mar 2024 11:02:03 +0100 Subject: [PATCH] adds riscv_hart_common and signature output --- src/iss/arch/riscv_hart_common.h | 60 ++++++++++++++++++++++++++++++++ src/iss/arch/riscv_hart_m_p.h | 33 ++++++------------ src/iss/arch/riscv_hart_msu_vp.h | 4 ++- src/iss/arch/riscv_hart_mu_p.h | 4 ++- src/main.cpp | 39 +++++++++++++++++++-- 5 files changed, 113 insertions(+), 27 deletions(-) diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 4ac086d..037b801 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -36,7 +36,12 @@ #define _RISCV_HART_COMMON #include "iss/arch_if.h" +#include "iss/log_categories.h" #include +#include +#include +#include +#include namespace iss { namespace arch { @@ -296,6 +301,61 @@ inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t* const break; } } +struct riscv_hart_common { + riscv_hart_common(){}; + ~riscv_hart_common(){}; + std::unordered_map symbol_table; + + std::unordered_map get_sym_table(std::string name) { + if(!symbol_table.empty()) + return symbol_table; + FILE* fp = fopen(name.c_str(), "r"); + if(fp) { + std::array buf; + auto n = fread(buf.data(), 1, 4, fp); + fclose(fp); + if(n != 4) + throw std::runtime_error("input file has insufficient size"); + buf[4] = 0; + if(strcmp(buf.data() + 1, "ELF") == 0) { + // Create elfio reader + ELFIO::elfio reader; + // Load ELF data + if(!reader.load(name)) + throw std::runtime_error("could not process elf file"); + // check elf properties + if(reader.get_type() != ET_EXEC) + throw std::runtime_error("wrong elf type in file"); + if(reader.get_machine() != EM_RISCV) + throw std::runtime_error("wrong elf machine in file"); + const auto sym_sec = reader.sections[".symtab"]; + if(SHT_SYMTAB == sym_sec->get_type() || SHT_DYNSYM == sym_sec->get_type()) { + ELFIO::symbol_section_accessor symbols(reader, sym_sec); + auto sym_no = symbols.get_symbols_num(); + std::string name; + ELFIO::Elf64_Addr value = 0; + ELFIO::Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + ELFIO::Elf_Half section = 0; + unsigned char other = 0; + for(auto i = 0U; i < sym_no; ++i) { + symbols.get_symbol(i, name, value, size, bind, type, section, other); + if(name != "") { + this->symbol_table[name] = value; +#ifndef NDEBUG + LOG(DEBUG) << "Found Symbol " << name; +#endif + } + } + } + return symbol_table; + } + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); + } else + throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); + }; +}; } // namespace arch } // namespace iss diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 99a7f06..0f480a3 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -40,6 +40,7 @@ #include "iss/log_categories.h" #include "iss/vm_if.h" #include "riscv_hart_common.h" +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif @@ -68,7 +69,7 @@ namespace iss { namespace arch { -template class riscv_hart_m_p : public BASE { +template class riscv_hart_m_p : public BASE, public riscv_hart_common { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; const std::array trap_str = {{"" @@ -326,6 +327,8 @@ protected: unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } + std::unordered_map get_symbol_table(std::string name) override { return arch.get_sym_table(name); } + riscv_hart_m_p& arch; }; @@ -570,6 +573,12 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) } template std::pair riscv_hart_m_p::load_file(std::string name, int type) { + get_sym_table(name); + try { + tohost = symbol_table.at("tohost"); + fromhost = symbol_table.at("fromhost"); + } catch(std::out_of_range& e) { + } FILE* fp = fopen(name.c_str(), "r"); if(fp) { std::array buf; @@ -604,27 +613,7 @@ template std::pair riscv_hart_m } } for(const auto sec : reader.sections) { - if(sec->get_name() == ".symtab") { - if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { - ELFIO::symbol_section_accessor symbols(reader, sec); - auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for(auto i = 0U; i < sym_no; ++i) { - symbols.get_symbol(i, name, value, size, bind, type, section, other); - if(name == "tohost") { - tohost = value; - } else if(name == "fromhost") { - fromhost = value; - } - } - } - } else if(sec->get_name() == ".tohost") { + if(sec->get_name() == ".tohost") { tohost = sec->get_address(); fromhost = tohost + 0x40; } diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index 4329160..58e5bb3 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -68,7 +68,7 @@ namespace iss { namespace arch { -template class riscv_hart_msu_vp : public BASE { +template class riscv_hart_msu_vp : public BASE, public riscv_hart_common { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; const std::array trap_str = {{"" @@ -377,6 +377,8 @@ protected: unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } + std::unordered_map get_symbol_table(std::string name) override { return arch.get_sym_table(name); } + riscv_hart_msu_vp& arch; }; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 362fece..6f4bbd4 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -68,7 +68,7 @@ namespace iss { namespace arch { -template class riscv_hart_mu_p : public BASE { +template class riscv_hart_mu_p : public BASE, public riscv_hart_common { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; const std::array trap_str = {{"" @@ -353,6 +353,8 @@ protected: unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } + std::unordered_map get_symbol_table(std::string name) override { return arch.get_sym_table(name); } + riscv_hart_mu_p& arch; }; diff --git a/src/main.cpp b/src/main.cpp index aad92da..c5d3d3b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include "iss/arch/tgc_mapper.h" @@ -199,12 +201,12 @@ int main(int argc, char* argv[]) { if(clim.count("elf")) for(std::string input : clim["elf"].as>()) { auto start_addr = vm->get_arch()->load_file(input); - if(start_addr.second) + if(start_addr.second) // FIXME: this always evaluates to true as load file always returns start_address = start_addr.first; } for(std::string input : args) { auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files - if(start_addr.second) + if(start_addr.second) // FIXME: this always evaluates to true as load file always returns start_address = start_addr.first; } if(clim.count("reset")) { @@ -214,11 +216,42 @@ int main(int argc, char* argv[]) { vm->reset(start_address); auto cycles = clim["instructions"].as(); res = vm->start(cycles, dump); + + auto instr_if = vm->get_arch()->get_instrumentation_if(); + // this assumes a single input file + std::unordered_map sym_table; + if(args.empty()) + sym_table = instr_if->get_symbol_table(clim["elf"].as>()[0]); + else + sym_table = instr_if->get_symbol_table(args[0]); + if(sym_table.find("begin_signature") != std::end(sym_table) && sym_table.find("end_signature") != std::end(sym_table)) { + auto start_addr = sym_table["begin_signature"]; + auto end_addr = sym_table["end_signature"]; + std::array data; + std::ofstream file; + std::string filename = fmt::format("{}.signature", isa_opt); + std::replace(std::begin(filename), std::end(filename), '|', '_'); + // default riscof requires this filename + filename = "DUT-tgc.signature"; + file.open(filename, std::ios::out); + if(!file.is_open()) { + LOG(ERR) << "Error opening file " << filename << std::endl; + return 1; + } + for(auto addr = start_addr; addr < end_addr; addr += data.size()) { + vm->get_arch()->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0 /*MEM*/, addr, data.size(), + data.data()); // FIXME: get space from iss::arch::traits::mem_type_e::MEM + + // TODO : obey Target endianess + uint32_t to_print = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; + file << std::hex << fmt::format("{:08x}", to_print) << std::dec << std::endl; + } + } } catch(std::exception& e) { LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl; res = 2; } - // cleanup to let plugins report of needed + // cleanup to let plugins report if needed for(auto* p : plugin_list) { delete p; }