3 Commits

8 changed files with 172 additions and 86 deletions

View File

@ -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

View File

@ -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;
@ -600,31 +609,11 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data)); pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
} }
} }
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;
} }
@ -654,11 +643,11 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
const unsigned length, uint8_t* const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
} else if(access && iss::access_type::FETCH) { } else if(access && iss::access_type::FETCH) {
LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr;
} else { } else {
LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr;
} }
#endif #endif
try { try {
@ -740,23 +729,23 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; CPPLOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
} }
#endif #endif
try { try {
@ -808,7 +797,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send // CPPLOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'"; // '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
@ -1108,7 +1097,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
// TODO remove UART, Peripherals should not be part of the ISS // TODO remove UART, Peripherals should not be part of the ISS
case 0xFFFF0000: // UART0 base, TXFIFO reg case 0xFFFF0000: // UART0 base, TXFIFO reg
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else if(((char)data[0]) != '\r') } else if(((char)data[0]) != '\r')
uart_buf << (char)data[0]; uart_buf << (char)data[0];
@ -1128,10 +1117,10 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
switch(hostvar >> 48) { switch(hostvar >> 48) {
case 0: case 0:
if(hostvar != 0x1) { if(hostvar != 0x1) {
LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} else { } else {
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} }
this->reg.trap_state = std::numeric_limits<uint32_t>::max(); this->reg.trap_state = std::numeric_limits<uint32_t>::max();
@ -1143,7 +1132,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
case 0x0101: { case 0x0101: {
char c = static_cast<char>(hostvar & 0xff); char c = static_cast<char>(hostvar & 0xff);
if(c == '\n' || c == 0) { if(c == '\n' || c == 0) {
LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else } else
uart_buf << c; uart_buf << c;

View File

@ -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;
}; };
@ -591,7 +593,7 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data)); pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
} }
} }
for(const auto sec : reader.sections) { for(const auto sec : reader.sections) {
@ -632,11 +634,11 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
const unsigned length, uint8_t* const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
} else if(access && iss::access_type::FETCH) { } else if(access && iss::access_type::FETCH) {
LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr;
} else { } else {
LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr;
} }
#endif #endif
try { try {
@ -726,23 +728,23 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; CPPLOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
} }
#endif #endif
try { try {
@ -787,7 +789,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send // CPPLOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'"; // '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
@ -1083,7 +1085,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_add
switch(paddr.val) { switch(paddr.val) {
case 0xFFFF0000: // UART0 base, TXFIFO reg case 0xFFFF0000: // UART0 base, TXFIFO reg
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else if(((char)data[0]) != '\r') } else if(((char)data[0]) != '\r')
uart_buf << (char)data[0]; uart_buf << (char)data[0];
@ -1103,10 +1105,10 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_add
switch(hostvar >> 48) { switch(hostvar >> 48) {
case 0: case 0:
if(hostvar != 0x1) { if(hostvar != 0x1) {
LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} else { } else {
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} }
this->reg.trap_state = std::numeric_limits<uint32_t>::max(); this->reg.trap_state = std::numeric_limits<uint32_t>::max();
@ -1118,7 +1120,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_add
case 0x0101: { case 0x0101: {
char c = static_cast<char>(hostvar & 0xff); char c = static_cast<char>(hostvar & 0xff);
if(c == '\n' || c == 0) { if(c == '\n' || c == 0) {
LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else } else
uart_buf << c; uart_buf << c;

View File

@ -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;
}; };
@ -678,7 +680,7 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data)); pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
if(res != iss::Ok) if(res != iss::Ok)
LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
} }
} }
for(const auto sec : reader.sections) { for(const auto sec : reader.sections) {
@ -818,11 +820,11 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
const unsigned length, uint8_t* const data) { const unsigned length, uint8_t* const data) {
#ifndef NDEBUG #ifndef NDEBUG
if(access && iss::access_type::DEBUG) { if(access && iss::access_type::DEBUG) {
LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
} else if(is_fetch(access)) { } else if(is_fetch(access)) {
LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr;
} else { } else {
LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; CPPLOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr;
} }
#endif #endif
try { try {
@ -913,23 +915,23 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
switch(length) { switch(length) {
case 8: case 8:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 4: case 4:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 2: case 2:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
case 1: case 1:
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" CPPLOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x"
<< std::hex << addr; << std::hex << addr;
break; break;
default: default:
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; CPPLOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
} }
#endif #endif
try { try {
@ -990,7 +992,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send // CPPLOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'"; // '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
@ -1326,7 +1328,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
// TODO remove UART, Peripherals should not be part of the ISS // TODO remove UART, Peripherals should not be part of the ISS
case 0xFFFF0000: // UART0 base, TXFIFO reg case 0xFFFF0000: // UART0 base, TXFIFO reg
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else if(((char)data[0]) != '\r') } else if(((char)data[0]) != '\r')
uart_buf << (char)data[0]; uart_buf << (char)data[0];
@ -1346,10 +1348,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
switch(hostvar >> 48) { switch(hostvar >> 48) {
case 0: case 0:
if(hostvar != 0x1) { if(hostvar != 0x1) {
LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} else { } else {
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation"; << "), stopping simulation";
} }
this->reg.trap_state = std::numeric_limits<uint32_t>::max(); this->reg.trap_state = std::numeric_limits<uint32_t>::max();
@ -1361,7 +1363,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
case 0x0101: { case 0x0101: {
char c = static_cast<char>(hostvar & 0xff); char c = static_cast<char>(hostvar & 0xff);
if(c == '\n' || c == 0) { if(c == '\n' || c == 0) {
LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
uart_buf.str(""); uart_buf.str("");
} else } else
uart_buf << c; uart_buf << c;

View File

@ -174,7 +174,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query
} }
template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) { template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
LOG(TRACE) << "reading target registers"; CPPLOG(TRACE) << "reading target registers";
// return idx<0?:; // return idx<0?:;
data.clear(); data.clear();
avail.clear(); avail.clear();
@ -328,9 +328,9 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(break_type
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length}); auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length});
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val);
LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << saddr.val CPPLOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << saddr.val
<< std::dec; << std::dec;
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Ok; return Ok;
} }
} }
@ -345,13 +345,13 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(break_t
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val);
if(handle) { if(handle) {
LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec; CPPLOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec;
// TODO: check length of addr range // TODO: check length of addr range
target_adapter_base::bp_lut.removeEntry(handle); target_adapter_base::bp_lut.removeEntry(handle);
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Ok; return Ok;
} }
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Err; return Err;
} }
} }

View File

@ -61,7 +61,7 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
try { try {
auto root = YAML::LoadAll(is); auto root = YAML::LoadAll(is);
if(root.size() != 1) { if(root.size() != 1) {
LOG(ERR) << "Too many root nodes in YAML file " << config_file_name; CPPLOG(ERR) << "Too many root nodes in YAML file " << config_file_name;
} }
for(auto p : root[0]) { for(auto p : root[0]) {
auto isa_subset = p.first; auto isa_subset = p.first;
@ -87,11 +87,11 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
} }
} }
} catch(YAML::ParserException& e) { } catch(YAML::ParserException& e) {
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); CPPLOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
return false; return false;
} }
} else { } else {
LOG(ERR) << "Could not open input file " << config_file_name; CPPLOG(ERR) << "Could not open input file " << config_file_name;
return false; return false;
} }
} }

View File

@ -47,7 +47,7 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name)
try { try {
auto root = YAML::LoadAll(is); auto root = YAML::LoadAll(is);
if(root.size() != 1) { if(root.size() != 1) {
LOG(ERR) << "Too many rro nodes in YAML file " << config_file_name; CPPLOG(ERR) << "Too many rro nodes in YAML file " << config_file_name;
} }
for(auto p : root[0]) { for(auto p : root[0]) {
auto isa_subset = p.first; auto isa_subset = p.first;
@ -69,10 +69,10 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name)
} }
rep_counts.resize(delays.size()); rep_counts.resize(delays.size());
} catch(YAML::ParserException& e) { } catch(YAML::ParserException& e) {
LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); CPPLOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
} }
} else { } else {
LOG(ERR) << "Could not open input file " << config_file_name; CPPLOG(ERR) << "Could not open input file " << config_file_name;
} }
} }
} }
@ -81,7 +81,7 @@ iss::plugin::instruction_count::~instruction_count() {
size_t idx = 0; size_t idx = 0;
for(auto it : delays) { for(auto it : delays) {
if(rep_counts[idx] > 0 && it.instr_name.find("__" != 0)) if(rep_counts[idx] > 0 && it.instr_name.find("__" != 0))
LOG(INFO) << it.instr_name << ";" << rep_counts[idx]; CPPLOG(INFO) << it.instr_name << ";" << rep_counts[idx];
idx++; idx++;
} }
} }

View File

@ -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"
@ -137,11 +139,11 @@ int main(int argc, char* argv[]) {
std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as<unsigned>(), &semihosting_cb); std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as<unsigned>(), &semihosting_cb);
} }
if(!cpu) { if(!cpu) {
LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl; CPPLOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl;
return 127; return 127;
} }
if(!vm) { if(!vm) {
LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl; CPPLOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl;
return 127; return 127;
} }
if(clim.count("plugin")) { if(clim.count("plugin")) {
@ -177,7 +179,7 @@ int main(int argc, char* argv[]) {
} else } else
#endif #endif
{ {
LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl; CPPLOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl;
return 127; return 127;
} }
} }
@ -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) {
LOG(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;
} }