Compare commits
2 Commits
8aed551813
...
6c986d38d8
Author | SHA1 | Date | |
---|---|---|---|
6c986d38d8 | |||
a1ebd83d2a |
@ -36,7 +36,12 @@
|
|||||||
#define _RISCV_HART_COMMON
|
#define _RISCV_HART_COMMON
|
||||||
|
|
||||||
#include "iss/arch_if.h"
|
#include "iss/arch_if.h"
|
||||||
|
#include "iss/log_categories.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <elfio/elfio.hpp>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
namespace arch {
|
||||||
@ -296,6 +301,61 @@ inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t* const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct riscv_hart_common {
|
||||||
|
riscv_hart_common(){};
|
||||||
|
~riscv_hart_common(){};
|
||||||
|
std::unordered_map<std::string, uint64_t> symbol_table;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, uint64_t> get_sym_table(std::string name) {
|
||||||
|
if(!symbol_table.empty())
|
||||||
|
return symbol_table;
|
||||||
|
FILE* fp = fopen(name.c_str(), "r");
|
||||||
|
if(fp) {
|
||||||
|
std::array<char, 5> 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 arch
|
||||||
} // namespace iss
|
} // namespace iss
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "iss/log_categories.h"
|
#include "iss/log_categories.h"
|
||||||
#include "iss/vm_if.h"
|
#include "iss/vm_if.h"
|
||||||
#include "riscv_hart_common.h"
|
#include "riscv_hart_common.h"
|
||||||
|
#include <stdexcept>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -68,7 +69,7 @@
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
namespace arch {
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_m_p : public BASE {
|
template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_m_p : public BASE, public riscv_hart_common {
|
||||||
protected:
|
protected:
|
||||||
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||||
const std::array<const char*, 16> trap_str = {{""
|
const std::array<const char*, 16> trap_str = {{""
|
||||||
@ -326,6 +327,8 @@ protected:
|
|||||||
|
|
||||||
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
||||||
|
|
||||||
|
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
||||||
|
|
||||||
riscv_hart_m_p<BASE, FEAT>& arch;
|
riscv_hart_m_p<BASE, FEAT>& arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -570,6 +573,12 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) {
|
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::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");
|
FILE* fp = fopen(name.c_str(), "r");
|
||||||
if(fp) {
|
if(fp) {
|
||||||
std::array<char, 5> buf;
|
std::array<char, 5> buf;
|
||||||
@ -604,27 +613,7 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(const auto sec : reader.sections) {
|
for(const auto sec : reader.sections) {
|
||||||
if(sec->get_name() == ".symtab") {
|
if(sec->get_name() == ".tohost") {
|
||||||
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") {
|
|
||||||
tohost = sec->get_address();
|
tohost = sec->get_address();
|
||||||
fromhost = tohost + 0x40;
|
fromhost = tohost + 0x40;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
namespace arch {
|
||||||
|
|
||||||
template <typename BASE> class riscv_hart_msu_vp : public BASE {
|
template <typename BASE> class riscv_hart_msu_vp : public BASE, public riscv_hart_common {
|
||||||
protected:
|
protected:
|
||||||
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||||
const std::array<const char*, 16> trap_str = {{""
|
const std::array<const char*, 16> trap_str = {{""
|
||||||
@ -377,6 +377,8 @@ protected:
|
|||||||
|
|
||||||
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
||||||
|
|
||||||
|
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
||||||
|
|
||||||
riscv_hart_msu_vp<BASE>& arch;
|
riscv_hart_msu_vp<BASE>& arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
namespace arch {
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : public BASE {
|
template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : public BASE, public riscv_hart_common {
|
||||||
protected:
|
protected:
|
||||||
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||||
const std::array<const char*, 16> trap_str = {{""
|
const std::array<const char*, 16> trap_str = {{""
|
||||||
@ -353,6 +353,8 @@ protected:
|
|||||||
|
|
||||||
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
||||||
|
|
||||||
|
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
||||||
|
|
||||||
riscv_hart_mu_p<BASE, FEAT>& arch;
|
riscv_hart_mu_p<BASE, FEAT>& arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
39
src/main.cpp
39
src/main.cpp
@ -35,6 +35,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iss/factory.h>
|
#include <iss/factory.h>
|
||||||
#include <iss/semihosting/semihosting.h>
|
#include <iss/semihosting/semihosting.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "iss/arch/tgc_mapper.h"
|
#include "iss/arch/tgc_mapper.h"
|
||||||
@ -199,12 +201,12 @@ int main(int argc, char* argv[]) {
|
|||||||
if(clim.count("elf"))
|
if(clim.count("elf"))
|
||||||
for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
|
for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
|
||||||
auto start_addr = vm->get_arch()->load_file(input);
|
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 <sth, true>
|
||||||
start_address = start_addr.first;
|
start_address = start_addr.first;
|
||||||
}
|
}
|
||||||
for(std::string input : args) {
|
for(std::string input : args) {
|
||||||
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
|
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 <sth, true>
|
||||||
start_address = start_addr.first;
|
start_address = start_addr.first;
|
||||||
}
|
}
|
||||||
if(clim.count("reset")) {
|
if(clim.count("reset")) {
|
||||||
@ -214,11 +216,42 @@ int main(int argc, char* argv[]) {
|
|||||||
vm->reset(start_address);
|
vm->reset(start_address);
|
||||||
auto cycles = clim["instructions"].as<uint64_t>();
|
auto cycles = clim["instructions"].as<uint64_t>();
|
||||||
res = vm->start(cycles, dump);
|
res = vm->start(cycles, dump);
|
||||||
|
|
||||||
|
auto instr_if = vm->get_arch()->get_instrumentation_if();
|
||||||
|
// this assumes a single input file
|
||||||
|
std::unordered_map<std::string, uint64_t> sym_table;
|
||||||
|
if(args.empty())
|
||||||
|
sym_table = instr_if->get_symbol_table(clim["elf"].as<std::vector<std::string>>()[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<uint8_t, 4> 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<ARCH>::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) {
|
} catch(std::exception& e) {
|
||||||
CPPLOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl;
|
CPPLOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl;
|
||||||
res = 2;
|
res = 2;
|
||||||
}
|
}
|
||||||
// cleanup to let plugins report of needed
|
// cleanup to let plugins report if needed
|
||||||
for(auto* p : plugin_list) {
|
for(auto* p : plugin_list) {
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user