Compare commits
4 Commits
feature/ev
...
75e81ce236
Author | SHA1 | Date | |
---|---|---|---|
75e81ce236 | |||
82a70efdb8 | |||
978c3db06e | |||
0e88664ff7 |
@ -109,14 +109,15 @@ if(TARGET yaml-cpp::yaml-cpp)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
|
||||
endif()
|
||||
|
||||
# if(WITH_LLVM)
|
||||
# target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS})
|
||||
# target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS})
|
||||
if(WITH_LLVM)
|
||||
find_package(LLVM)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS})
|
||||
|
||||
# if(BUILD_SHARED_LIBS)
|
||||
# target_link_libraries(${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES})
|
||||
# endif()
|
||||
# endif()
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
|
@ -131,6 +131,8 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
||||
|
||||
uint8_t* get_regs_base_ptr() override;
|
||||
|
||||
inline uint64_t get_icount() { return reg.icount; }
|
||||
|
||||
inline bool should_stop() { return interrupt_sim; }
|
||||
|
||||
inline uint64_t stop_code() { return interrupt_sim; }
|
||||
@ -139,6 +141,8 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
||||
|
||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||
|
||||
inline uint32_t get_last_branch() { return reg.last_branch; }
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ${coreDef.name}_regs {<%
|
||||
|
@ -45,17 +45,17 @@ namespace interp {
|
||||
using namespace sysc;
|
||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
})<%}%>
|
||||
@ -66,17 +66,17 @@ namespace llvm {
|
||||
using namespace sysc;
|
||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
})<%}%>
|
||||
@ -88,17 +88,17 @@ namespace tcc {
|
||||
using namespace sysc;
|
||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
})<%}%>
|
||||
@ -110,17 +110,17 @@ namespace asmjit {
|
||||
using namespace sysc;
|
||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||
})<%}%>
|
||||
|
@ -263,7 +263,6 @@ void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
|
||||
cmp(cc, current_trap_state, 0);
|
||||
cc.jne(jh.trap_entry);
|
||||
cc.inc(get_ptr_for(jh, traits::ICOUNT));
|
||||
cc.inc(get_ptr_for(jh, traits::CYCLE));
|
||||
}
|
||||
template <typename ARCH>
|
||||
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
|
||||
|
@ -83,21 +83,21 @@ protected:
|
||||
using vm_base<ARCH>::get_reg_ptr;
|
||||
|
||||
using this_class = vm_impl<ARCH>;
|
||||
using compile_ret_t = continuation_e;
|
||||
using compile_ret_t = std::tuple<continuation_e>;
|
||||
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&);
|
||||
|
||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||
<%
|
||||
if(fcsr != null) {%>
|
||||
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
|
||||
<%}%>
|
||||
void add_prologue(tu_builder& tu) override;
|
||||
|
||||
void add_prologue(tu_builder& tu) override;
|
||||
<%}%>
|
||||
void setup_module(std::string m) override {
|
||||
super::setup_module(m);
|
||||
}
|
||||
|
||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &, tu_builder&) override;
|
||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override;
|
||||
|
||||
void gen_trap_behavior(tu_builder& tu) override;
|
||||
|
||||
@ -225,8 +225,8 @@ vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||
}()) {}
|
||||
|
||||
template <typename ARCH>
|
||||
continuation_e
|
||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
|
||||
std::tuple<continuation_e>
|
||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) {
|
||||
// we fetch at max 4 byte, alignment is 2
|
||||
enum {TRAP_ID=1<<16};
|
||||
code_word_t instr = 0;
|
||||
@ -238,6 +238,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
|
||||
return ILLEGAL_FETCH;
|
||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||
return JUMP_TO_SELF;
|
||||
++inst_cnt;
|
||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||
compile_func f = nullptr;
|
||||
if(inst_index < instr_descr.size())
|
||||
@ -273,12 +274,9 @@ template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(tu_builder& tu) {
|
||||
tu("return *next_pc;");
|
||||
}
|
||||
<%
|
||||
|
||||
if(fcsr != null) {%>
|
||||
template <typename ARCH> void vm_impl<ARCH>::add_prologue(tu_builder& tu){
|
||||
std::ostringstream os;
|
||||
os << add_reg_ptr("trap_state", arch::traits<ARCH>::TRAP_STATE);
|
||||
os << add_reg_ptr("pending_trap", arch::traits<ARCH>::PENDING_TRAP);
|
||||
if(fcsr != null) {%>
|
||||
os << "uint32_t (*fget_flags)()=" << (uintptr_t)&fget_flags << ";\\n";
|
||||
os << "uint32_t (*fadd_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fadd_s << ";\\n";
|
||||
os << "uint32_t (*fsub_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fsub_s << ";\\n";
|
||||
@ -305,10 +303,9 @@ if(fcsr != null) {%>
|
||||
os << "uint64_t (*fcvt_32_64)(uint32_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_32_64 << ";\\n";
|
||||
os << "uint32_t (*fcvt_64_32)(uint64_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_64_32 << ";\\n";
|
||||
os << "uint32_t (*unbox_s)(uint64_t v)=" << (uintptr_t)&unbox_s << ";\\n";
|
||||
<%}%>
|
||||
tu.add_prologue(os.str());
|
||||
}
|
||||
|
||||
<%}%>
|
||||
|
||||
} // namespace ${coreDef.name.toLowerCase()}
|
||||
|
||||
|
@ -3,33 +3,34 @@
|
||||
#define ELFIO_NO_INTTYPES
|
||||
#endif
|
||||
|
||||
#include <elfio/elfio_dump.hpp>
|
||||
#include <iostream>
|
||||
#include <elfio/elfio_dump.hpp>
|
||||
|
||||
using namespace ELFIO;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if(argc != 2) {
|
||||
printf("Usage: elfdump <file_name>\n");
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
if ( argc != 2 ) {
|
||||
printf( "Usage: elfdump <file_name>\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
elfio reader;
|
||||
|
||||
if(!reader.load(argv[1])) {
|
||||
printf("File %s is not found or it is not an ELF file\n", argv[1]);
|
||||
if ( !reader.load( argv[1] ) ) {
|
||||
printf( "File %s is not found or it is not an ELF file\n", argv[1] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
dump::header(std::cout, reader);
|
||||
dump::section_headers(std::cout, reader);
|
||||
dump::segment_headers(std::cout, reader);
|
||||
dump::symbol_tables(std::cout, reader);
|
||||
dump::notes(std::cout, reader);
|
||||
dump::modinfo(std::cout, reader);
|
||||
dump::dynamic_tags(std::cout, reader);
|
||||
dump::section_datas(std::cout, reader);
|
||||
dump::segment_datas(std::cout, reader);
|
||||
dump::header( std::cout, reader );
|
||||
dump::section_headers( std::cout, reader );
|
||||
dump::segment_headers( std::cout, reader );
|
||||
dump::symbol_tables( std::cout, reader );
|
||||
dump::notes( std::cout, reader );
|
||||
dump::modinfo( std::cout, reader );
|
||||
dump::dynamic_tags( std::cout, reader );
|
||||
dump::section_datas( std::cout, reader );
|
||||
dump::segment_datas( std::cout, reader );
|
||||
|
||||
return 0;
|
||||
}
|
@ -354,7 +354,7 @@ protected:
|
||||
using csr_page_type = typename csr_type::page_type;
|
||||
mem_type mem;
|
||||
csr_type csr;
|
||||
std::stringstream uart_buf;
|
||||
std::stringstream io_buf;
|
||||
std::unordered_map<reg_t, uint64_t> ptw;
|
||||
std::unordered_map<uint64_t, uint8_t> atomic_reservation;
|
||||
std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
|
||||
@ -446,7 +446,7 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
|
||||
csr[marchid] = traits<BASE>::MARCHID_VAL;
|
||||
csr[mimpid] = 1;
|
||||
|
||||
uart_buf.str("");
|
||||
io_buf.str("");
|
||||
if(traits<BASE>::FLEN > 0) {
|
||||
csr_rd_cb[fcsr] = &this_class::read_fcsr;
|
||||
csr_wr_cb[fcsr] = &this_class::write_fcsr;
|
||||
@ -720,7 +720,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
|
||||
return iss::Err;
|
||||
}
|
||||
try {
|
||||
if(length > 1 && (addr & (length - 1)) && (access & access_type::DEBUG) != access_type::DEBUG) {
|
||||
if(length > 1 && (addr & (length - 1)) && !is_debug(access)) {
|
||||
this->reg.trap_state = (1UL << 31) | 6 << 16;
|
||||
fault_data = addr;
|
||||
return iss::Err;
|
||||
@ -740,7 +740,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
|
||||
} else {
|
||||
res = write_mem(phys_addr, length, data);
|
||||
}
|
||||
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||
if(unlikely(res != iss::Ok && !is_debug(access))) {
|
||||
this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
|
||||
fault_data = addr;
|
||||
}
|
||||
@ -756,10 +756,10 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
|
||||
switch(addr) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
case 0x10023000: // UART1 base, TXFIFO reg
|
||||
uart_buf << (char)data[0];
|
||||
io_buf << (char)data[0];
|
||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||
std::cout << uart_buf.str();
|
||||
uart_buf.str("");
|
||||
std::cout << io_buf.str();
|
||||
io_buf.str("");
|
||||
}
|
||||
return iss::Ok;
|
||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
||||
@ -1094,59 +1094,79 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_mem(phys_addr_t paddr, unsi
|
||||
|
||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||
switch(paddr.val) {
|
||||
// TODO remove UART, Peripherals should not be part of the ISS
|
||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||
CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
|
||||
uart_buf.str("");
|
||||
} else if(((char)data[0]) != '\r')
|
||||
uart_buf << (char)data[0];
|
||||
break;
|
||||
default: {
|
||||
mem_type::page_type& p = mem(paddr.val / mem.page_size);
|
||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||
// tohost handling in case of riscv-test
|
||||
if(paddr.access && iss::access_type::FUNC) {
|
||||
auto tohost_upper =
|
||||
(traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
if(tohost_lower || tohost_upper) {
|
||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||
// in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
|
||||
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
|
||||
switch(hostvar >> 48) {
|
||||
case 0:
|
||||
if(hostvar != 0x1) {
|
||||
CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||
<< "), stopping simulation";
|
||||
} else {
|
||||
CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||
<< "), stopping simulation";
|
||||
}
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = hostvar;
|
||||
break;
|
||||
case 0x0101: {
|
||||
char c = static_cast<char>(hostvar & 0xff);
|
||||
if(c == '\n' || c == 0) {
|
||||
CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
|
||||
uart_buf.str("");
|
||||
mem_type::page_type& p = mem(paddr.val / mem.page_size);
|
||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||
// tohost handling in case of riscv-test
|
||||
// according to https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754:
|
||||
if(paddr.access && iss::access_type::FUNC) {
|
||||
if(paddr.val == tohost) {
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
tohost &= 0x00000000ffffffff;
|
||||
// Extract Device (bits 63:56)
|
||||
uint8_t device = (tohost >> 56) & 0xFF;
|
||||
// Extract Command (bits 55:48)
|
||||
uint8_t command = (tohost >> 48) & 0xFF;
|
||||
// Extract payload (bits 47:0)
|
||||
uint64_t payload = tohost & 0xFFFFFFFFFFFFULL;
|
||||
if(payload & 1) {
|
||||
CPPLOG(FATAL) << "tohost value is 0x" << std::hex << payload << std::dec << " (" << payload << "), stopping simulation";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
} else if(device == 0 && command == 0) {
|
||||
reg_t payload_addr;
|
||||
// payload contains the addr of the struct containing information about the syscall
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, payload, sizeof(reg_t),
|
||||
reinterpret_cast<uint8_t*>(&payload_addr));
|
||||
// If the payload_addr is missaligned end simulation
|
||||
if(payload_addr & 1) {
|
||||
CPPLOG(FATAL) << "tohost payload value is 0x" << std::hex << payload_addr << std::dec << " (" << payload_addr
|
||||
<< "), stopping simulation";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
// read the entire struct into an array
|
||||
reg_t loaded_payload[8];
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, payload_addr, sizeof(loaded_payload),
|
||||
reinterpret_cast<uint8_t*>(loaded_payload));
|
||||
reg_t syscall_num = loaded_payload[0];
|
||||
if(syscall_num == 64) { // SYS_WRITE
|
||||
reg_t fd = loaded_payload[1];
|
||||
reg_t buf_ptr = loaded_payload[2];
|
||||
reg_t len = loaded_payload[3];
|
||||
std::vector<char> buf(len);
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, buf_ptr, len,
|
||||
reinterpret_cast<uint8_t*>(buf.data()));
|
||||
// we disregard the fd and just log to stdout
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
if(buf[i] == '\n') {
|
||||
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
|
||||
io_buf.str("");
|
||||
} else
|
||||
uart_buf << c;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
io_buf << buf[i];
|
||||
}
|
||||
tohost_lower_written = false;
|
||||
} else if(tohost_lower)
|
||||
tohost_lower_written = true;
|
||||
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||
// Not sure what the correct return value should be
|
||||
uint8_t ret_val = 1;
|
||||
write(address_type::PHYSICAL, access_type::WRITE, traits<BASE>::MEM, fromhost, 1, &ret_val);
|
||||
} else {
|
||||
CPPLOG(ERR) << "tohost syscall with number " << std::hex << syscall_num << std::dec << " (" << syscall_num
|
||||
<< ") not implemented";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
} else {
|
||||
CPPLOG(ERR) << "tohost functionality not implemented for device " << device << " and command " << command;
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||
}
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ protected:
|
||||
mem_type mem;
|
||||
csr_type csr;
|
||||
void update_vm_info();
|
||||
std::stringstream uart_buf;
|
||||
std::stringstream io_buf;
|
||||
std::unordered_map<reg_t, uint64_t> ptw;
|
||||
std::unordered_map<uint64_t, uint8_t> atomic_reservation;
|
||||
std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
|
||||
@ -459,7 +459,7 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
|
||||
csr[marchid] = traits<BASE>::MARCHID_VAL;
|
||||
csr[mimpid] = 1;
|
||||
|
||||
uart_buf.str("");
|
||||
io_buf.str("");
|
||||
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
|
||||
csr_rd_cb[addr] = &this_class::read_null;
|
||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||
@ -727,12 +727,12 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
||||
switch(paddr.val) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
case 0x10023000: // UART1 base, TXFIFO reg
|
||||
uart_buf << (char)data[0];
|
||||
io_buf << (char)data[0];
|
||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||
// CPPLOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
|
||||
// '"<<uart_buf.str()<<"'";
|
||||
std::cout << uart_buf.str();
|
||||
uart_buf.str("");
|
||||
// '"<<io_buf.str()<<"'";
|
||||
std::cout << io_buf.str();
|
||||
io_buf.str("");
|
||||
}
|
||||
return iss::Ok;
|
||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
||||
@ -1024,61 +1024,79 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||
switch(paddr.val) {
|
||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||
CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
|
||||
uart_buf.str("");
|
||||
} else if(((char)data[0]) != '\r')
|
||||
uart_buf << (char)data[0];
|
||||
break;
|
||||
default: {
|
||||
mem_type::page_type& p = mem(paddr.val / mem.page_size);
|
||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||
// tohost handling in case of riscv-test
|
||||
if(paddr.access && iss::access_type::FUNC) {
|
||||
auto tohost_upper =
|
||||
(traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
if(tohost_lower || tohost_upper) {
|
||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||
// in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
|
||||
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
|
||||
switch(hostvar >> 48) {
|
||||
case 0:
|
||||
if(hostvar != 0x1) {
|
||||
CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||
<< "), stopping simulation";
|
||||
} else {
|
||||
CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||
<< "), stopping simulation";
|
||||
}
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = hostvar;
|
||||
#ifndef WITH_TCC
|
||||
throw(iss::simulation_stopped(hostvar));
|
||||
#endif
|
||||
break;
|
||||
case 0x0101: {
|
||||
char c = static_cast<char>(hostvar & 0xff);
|
||||
if(c == '\n' || c == 0) {
|
||||
CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
|
||||
uart_buf.str("");
|
||||
mem_type::page_type& p = mem(paddr.val / mem.page_size);
|
||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||
// tohost handling in case of riscv-test
|
||||
// according to https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754:
|
||||
if(paddr.access && iss::access_type::FUNC) {
|
||||
if(paddr.val == tohost) {
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
tohost &= 0x00000000ffffffff;
|
||||
// Extract Device (bits 63:56)
|
||||
uint8_t device = (tohost >> 56) & 0xFF;
|
||||
// Extract Command (bits 55:48)
|
||||
uint8_t command = (tohost >> 48) & 0xFF;
|
||||
// Extract payload (bits 47:0)
|
||||
uint64_t payload = tohost & 0xFFFFFFFFFFFFULL;
|
||||
if(payload & 1) {
|
||||
CPPLOG(FATAL) << "tohost value is 0x" << std::hex << payload << std::dec << " (" << payload << "), stopping simulation";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
} else if(device == 0 && command == 0) {
|
||||
reg_t payload_addr;
|
||||
// payload contains the addr of the struct containing information about the syscall
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, payload, sizeof(reg_t),
|
||||
reinterpret_cast<uint8_t*>(&payload_addr));
|
||||
// If the payload_addr is missaligned end simulation
|
||||
if(payload_addr & 1) {
|
||||
CPPLOG(FATAL) << "tohost payload value is 0x" << std::hex << payload_addr << std::dec << " (" << payload_addr
|
||||
<< "), stopping simulation";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
// read the entire struct into an array
|
||||
reg_t loaded_payload[8];
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, payload_addr, sizeof(loaded_payload),
|
||||
reinterpret_cast<uint8_t*>(loaded_payload));
|
||||
reg_t syscall_num = loaded_payload[0];
|
||||
if(syscall_num == 64) { // SYS_WRITE
|
||||
reg_t fd = loaded_payload[1];
|
||||
reg_t buf_ptr = loaded_payload[2];
|
||||
reg_t len = loaded_payload[3];
|
||||
std::vector<char> buf(len);
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, buf_ptr, len,
|
||||
reinterpret_cast<uint8_t*>(buf.data()));
|
||||
// we disregard the fd and just log to stdout
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
if(buf[i] == '\n') {
|
||||
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
|
||||
io_buf.str("");
|
||||
} else
|
||||
uart_buf << c;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
io_buf << buf[i];
|
||||
}
|
||||
tohost_lower_written = false;
|
||||
} else if(tohost_lower)
|
||||
tohost_lower_written = true;
|
||||
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||
// Not sure what the correct return value should be
|
||||
uint8_t ret_val = 1;
|
||||
write(address_type::PHYSICAL, access_type::WRITE, traits<BASE>::MEM, fromhost, 1, &ret_val);
|
||||
} else {
|
||||
CPPLOG(ERR) << "tohost syscall with number " << std::hex << syscall_num << std::dec << " (" << syscall_num
|
||||
<< ") not implemented";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
} else {
|
||||
CPPLOG(ERR) << "tohost functionality not implemented for device " << device << " and command " << command;
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||
}
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ protected:
|
||||
using csr_page_type = typename csr_type::page_type;
|
||||
mem_type mem;
|
||||
csr_type csr;
|
||||
std::stringstream uart_buf;
|
||||
std::stringstream io_buf;
|
||||
std::unordered_map<reg_t, uint64_t> ptw;
|
||||
std::unordered_map<uint64_t, uint8_t> atomic_reservation;
|
||||
std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
|
||||
@ -475,7 +475,7 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
||||
csr[marchid] = traits<BASE>::MARCHID_VAL;
|
||||
csr[mimpid] = 1;
|
||||
|
||||
uart_buf.str("");
|
||||
io_buf.str("");
|
||||
if(traits<BASE>::FLEN > 0) {
|
||||
csr_rd_cb[fcsr] = &this_class::read_fcsr;
|
||||
csr_wr_cb[fcsr] = &this_class::write_fcsr;
|
||||
@ -938,10 +938,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write(const address_type type,
|
||||
switch(addr) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
case 0x10023000: // UART1 base, TXFIFO reg
|
||||
uart_buf << (char)data[0];
|
||||
io_buf << (char)data[0];
|
||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||
std::cout << uart_buf.str();
|
||||
uart_buf.str("");
|
||||
std::cout << io_buf.str();
|
||||
io_buf.str("");
|
||||
}
|
||||
return iss::Ok;
|
||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
||||
@ -1312,65 +1312,81 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_mem(phys_addr_t paddr, uns
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||
switch(paddr.val) {
|
||||
// TODO remove UART, Peripherals should not be part of the ISS
|
||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||
CPPLOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
|
||||
uart_buf.str("");
|
||||
} else if(((char)data[0]) != '\r')
|
||||
uart_buf << (char)data[0];
|
||||
break;
|
||||
default: {
|
||||
mem_type::page_type& p = mem(paddr.val / mem.page_size);
|
||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||
// tohost handling in case of riscv-test
|
||||
if(paddr.access && iss::access_type::FUNC) {
|
||||
auto tohost_upper =
|
||||
(traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||
if(tohost_lower || tohost_upper) {
|
||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||
// in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
|
||||
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
|
||||
switch(hostvar >> 48) {
|
||||
case 0:
|
||||
if(hostvar != 0x1) {
|
||||
CPPLOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||
<< "), stopping simulation";
|
||||
} else {
|
||||
CPPLOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||
<< "), stopping simulation";
|
||||
}
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = hostvar;
|
||||
#ifndef WITH_TCC
|
||||
throw(iss::simulation_stopped(hostvar));
|
||||
#endif
|
||||
break;
|
||||
case 0x0101: {
|
||||
char c = static_cast<char>(hostvar & 0xff);
|
||||
if(c == '\n' || c == 0) {
|
||||
CPPLOG(INFO) << "tohost send '" << uart_buf.str() << "'";
|
||||
uart_buf.str("");
|
||||
mem_type::page_type& p = mem(paddr.val / mem.page_size);
|
||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||
// tohost handling in case of riscv-test
|
||||
// according to https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754:
|
||||
if(paddr.access && iss::access_type::FUNC) {
|
||||
if(paddr.val == tohost) {
|
||||
if(traits<BASE>::XLEN == 32)
|
||||
tohost &= 0x00000000ffffffff;
|
||||
// Extract Device (bits 63:56)
|
||||
uint8_t device = (tohost >> 56) & 0xFF;
|
||||
// Extract Command (bits 55:48)
|
||||
uint8_t command = (tohost >> 48) & 0xFF;
|
||||
// Extract payload (bits 47:0)
|
||||
uint64_t payload = tohost & 0xFFFFFFFFFFFFULL;
|
||||
if(payload & 1) {
|
||||
CPPLOG(FATAL) << "tohost value is 0x" << std::hex << payload << std::dec << " (" << payload << "), stopping simulation";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
} else if(device == 0 && command == 0) {
|
||||
reg_t payload_addr;
|
||||
// payload contains the addr of the struct containing information about the syscall
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, payload, sizeof(reg_t),
|
||||
reinterpret_cast<uint8_t*>(&payload_addr));
|
||||
// If the payload_addr is missaligned end simulation
|
||||
if(payload_addr & 1) {
|
||||
CPPLOG(FATAL) << "tohost payload value is 0x" << std::hex << payload_addr << std::dec << " (" << payload_addr
|
||||
<< "), stopping simulation";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
// read the entire struct into an array
|
||||
reg_t loaded_payload[8];
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, payload_addr, sizeof(loaded_payload),
|
||||
reinterpret_cast<uint8_t*>(loaded_payload));
|
||||
reg_t syscall_num = loaded_payload[0];
|
||||
if(syscall_num == 64) { // SYS_WRITE
|
||||
reg_t fd = loaded_payload[1];
|
||||
reg_t buf_ptr = loaded_payload[2];
|
||||
reg_t len = loaded_payload[3];
|
||||
std::vector<char> buf(len);
|
||||
read(address_type::PHYSICAL, access_type::READ, traits<BASE>::MEM, buf_ptr, len,
|
||||
reinterpret_cast<uint8_t*>(buf.data()));
|
||||
// we disregard the fd and just log to stdout
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
if(buf[i] == '\n') {
|
||||
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
|
||||
io_buf.str("");
|
||||
} else
|
||||
uart_buf << c;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
io_buf << buf[i];
|
||||
}
|
||||
tohost_lower_written = false;
|
||||
} else if(tohost_lower)
|
||||
tohost_lower_written = true;
|
||||
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||
// Not sure what the correct return value should be
|
||||
uint8_t ret_val = 1;
|
||||
write(address_type::PHYSICAL, access_type::WRITE, traits<BASE>::MEM, fromhost, 1, &ret_val);
|
||||
} else {
|
||||
CPPLOG(ERR) << "tohost syscall with number " << std::hex << syscall_num << std::dec << " (" << syscall_num
|
||||
<< ") not implemented";
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
} else {
|
||||
CPPLOG(ERR) << "tohost functionality not implemented for device " << device << " and command " << command;
|
||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||
this->interrupt_sim = payload;
|
||||
return iss::Ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||
}
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ struct tgc5c: public arch_if {
|
||||
|
||||
uint8_t* get_regs_base_ptr() override;
|
||||
|
||||
inline uint64_t get_icount() { return reg.icount; } //This should not be accessible, only through the instrumentation_if
|
||||
inline uint64_t get_icount() { return reg.icount; }
|
||||
|
||||
inline bool should_stop() { return interrupt_sim; }
|
||||
|
||||
@ -199,7 +199,7 @@ struct tgc5c: public arch_if {
|
||||
|
||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||
|
||||
inline uint32_t get_last_branch() { return reg.last_branch; } //This should also only be accessible through the instrumentation_if
|
||||
inline uint32_t get_last_branch() { return reg.last_branch; }
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
12
src/main.cpp
12
src/main.cpp
@ -206,21 +206,13 @@ int main(int argc, char* argv[]) {
|
||||
if(clim.count("elf"))
|
||||
for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
|
||||
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;
|
||||
else {
|
||||
LOG(ERR) << "Error occured while loading file " << input << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
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 <sth, true>
|
||||
start_address = start_addr.first;
|
||||
else {
|
||||
LOG(ERR) << "Error occured while loading file " << input << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(clim.count("reset")) {
|
||||
auto str = clim["reset"].as<std::string>();
|
||||
|
@ -62,12 +62,12 @@ using namespace sysc;
|
||||
volatile std::array<bool, 2> tgc_init = {
|
||||
iss_factory::instance().register_creator("tgc5c|m_p|llvm",
|
||||
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
}),
|
||||
iss_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||
})};
|
||||
|
@ -4822,7 +4822,6 @@ void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
|
||||
cmp(cc, current_trap_state, 0);
|
||||
cc.jne(jh.trap_entry);
|
||||
cc.inc(get_ptr_for(jh, traits::ICOUNT));
|
||||
cc.inc(get_ptr_for(jh, traits::CYCLE));
|
||||
}
|
||||
template <typename ARCH>
|
||||
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
|
||||
|
@ -275,6 +275,9 @@ template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
|
||||
volatile CODE_WORD x = insn;
|
||||
insn = 2 * x;
|
||||
}
|
||||
|
||||
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
||||
|
||||
// according to
|
||||
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
|
||||
#ifdef __GCC__
|
||||
|
@ -81,18 +81,16 @@ protected:
|
||||
using vm_base<ARCH>::get_reg_ptr;
|
||||
|
||||
using this_class = vm_impl<ARCH>;
|
||||
using compile_ret_t = continuation_e;
|
||||
using compile_ret_t = std::tuple<continuation_e>;
|
||||
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&);
|
||||
|
||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||
|
||||
void add_prologue(tu_builder& tu) override;
|
||||
|
||||
void setup_module(std::string m) override {
|
||||
super::setup_module(m);
|
||||
}
|
||||
|
||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &,tu_builder&) override;
|
||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override;
|
||||
|
||||
void gen_trap_behavior(tu_builder& tu) override;
|
||||
|
||||
@ -354,7 +352,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.constant((uint32_t)((int32_t)imm),32));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,0);
|
||||
@ -389,7 +387,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.constant((uint32_t)(PC+(int32_t)imm),32));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,1);
|
||||
@ -434,7 +432,7 @@ private:
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(KNOWN_JUMP), 2));
|
||||
}
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,2);
|
||||
@ -491,7 +489,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,3);
|
||||
@ -540,7 +538,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,4);
|
||||
@ -589,7 +587,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,5);
|
||||
@ -638,7 +636,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,6);
|
||||
@ -687,7 +685,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,7);
|
||||
@ -736,7 +734,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,8);
|
||||
@ -785,7 +783,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,9);
|
||||
@ -825,7 +823,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.ext(res,32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,10);
|
||||
@ -865,7 +863,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.ext(res,32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,11);
|
||||
@ -905,7 +903,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.ext(res,32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,12);
|
||||
@ -945,7 +943,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.ext(res,32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,13);
|
||||
@ -985,7 +983,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.ext(res,32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,14);
|
||||
@ -1022,7 +1020,7 @@ private:
|
||||
tu.constant((int16_t)sext<12>(imm),16))),32,false),32);
|
||||
tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2 + traits::X0, 0),8,false));
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,15);
|
||||
@ -1059,7 +1057,7 @@ private:
|
||||
tu.constant((int16_t)sext<12>(imm),16))),32,false),32);
|
||||
tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2 + traits::X0, 0),16,false));
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,16);
|
||||
@ -1096,7 +1094,7 @@ private:
|
||||
tu.constant((int16_t)sext<12>(imm),16))),32,false),32);
|
||||
tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2 + traits::X0, 0),32,false));
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,17);
|
||||
@ -1134,7 +1132,7 @@ private:
|
||||
tu.constant((int16_t)sext<12>(imm),16))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,18);
|
||||
@ -1172,7 +1170,7 @@ private:
|
||||
tu.constant((int16_t)sext<12>(imm),16))), tu.constant(1,8),tu.constant(0,8)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,19);
|
||||
@ -1210,7 +1208,7 @@ private:
|
||||
tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))), tu.constant(1,8),tu.constant(0,8)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,20);
|
||||
@ -1248,7 +1246,7 @@ private:
|
||||
tu.constant((uint32_t)((int16_t)sext<12>(imm)),32)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,21);
|
||||
@ -1286,7 +1284,7 @@ private:
|
||||
tu.constant((uint32_t)((int16_t)sext<12>(imm)),32)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,22);
|
||||
@ -1324,7 +1322,7 @@ private:
|
||||
tu.constant((uint32_t)((int16_t)sext<12>(imm)),32)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,23);
|
||||
@ -1362,7 +1360,7 @@ private:
|
||||
tu.constant(shamt,8)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,24);
|
||||
@ -1400,7 +1398,7 @@ private:
|
||||
tu.constant(shamt,8)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,25);
|
||||
@ -1438,7 +1436,7 @@ private:
|
||||
tu.constant(shamt,8))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,26);
|
||||
@ -1476,7 +1474,7 @@ private:
|
||||
tu.load(rs2 + traits::X0, 0))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,27);
|
||||
@ -1514,7 +1512,7 @@ private:
|
||||
tu.load(rs2 + traits::X0, 0))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,28);
|
||||
@ -1554,7 +1552,7 @@ private:
|
||||
tu.constant((static_cast<uint32_t>(traits:: XLEN)-1),64)))));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,29);
|
||||
@ -1592,7 +1590,7 @@ private:
|
||||
tu.ext(tu.load(rs2 + traits::X0, 0),32,true)), tu.constant(1,8),tu.constant(0,8)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,30);
|
||||
@ -1630,7 +1628,7 @@ private:
|
||||
tu.load(rs2 + traits::X0, 0)), tu.constant(1,8),tu.constant(0,8)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,31);
|
||||
@ -1668,7 +1666,7 @@ private:
|
||||
tu.load(rs2 + traits::X0, 0)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,32);
|
||||
@ -1708,7 +1706,7 @@ private:
|
||||
tu.constant((static_cast<uint32_t>(traits:: XLEN)-1),64)))));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,33);
|
||||
@ -1748,7 +1746,7 @@ private:
|
||||
tu.constant((static_cast<uint32_t>(traits:: XLEN)-1),64))))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,34);
|
||||
@ -1786,7 +1784,7 @@ private:
|
||||
tu.load(rs2 + traits::X0, 0)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,35);
|
||||
@ -1824,7 +1822,7 @@ private:
|
||||
tu.load(rs2 + traits::X0, 0)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,36);
|
||||
@ -1855,7 +1853,7 @@ private:
|
||||
tu.open_scope();
|
||||
this->gen_set_tval(tu, instr);
|
||||
tu.write_mem(traits::FENCE, static_cast<uint32_t>(traits:: fence), tu.constant((uint8_t)pred<<4|succ,8));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,37);
|
||||
@ -1881,7 +1879,7 @@ private:
|
||||
this->gen_set_tval(tu, instr);
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
|
||||
this->gen_raise_trap(tu, 0, 11);
|
||||
auto returnValue = TRAP;
|
||||
auto returnValue = std::make_tuple(TRAP);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,38);
|
||||
@ -1907,7 +1905,7 @@ private:
|
||||
this->gen_set_tval(tu, instr);
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
|
||||
this->gen_raise_trap(tu, 0, 3);
|
||||
auto returnValue = TRAP;
|
||||
auto returnValue = std::make_tuple(TRAP);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,39);
|
||||
@ -1933,7 +1931,7 @@ private:
|
||||
this->gen_set_tval(tu, instr);
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(NO_JUMP),32));
|
||||
this->gen_leave_trap(tu, 3);
|
||||
auto returnValue = TRAP;
|
||||
auto returnValue = std::make_tuple(TRAP);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,40);
|
||||
@ -1958,7 +1956,7 @@ private:
|
||||
tu.open_scope();
|
||||
this->gen_set_tval(tu, instr);
|
||||
tu.callf("wait", tu.constant(1,8));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,41);
|
||||
@ -1999,7 +1997,7 @@ private:
|
||||
tu.write_mem(traits::CSR, csr, xrs1);
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,42);
|
||||
@ -2042,7 +2040,7 @@ private:
|
||||
tu.store(rd + traits::X0, xrd);
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,43);
|
||||
@ -2085,7 +2083,7 @@ private:
|
||||
tu.store(rd + traits::X0, xrd);
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,44);
|
||||
@ -2123,7 +2121,7 @@ private:
|
||||
tu.store(rd + traits::X0, xrd);
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,45);
|
||||
@ -2165,7 +2163,7 @@ private:
|
||||
tu.store(rd + traits::X0, xrd);
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,46);
|
||||
@ -2207,7 +2205,7 @@ private:
|
||||
tu.store(rd + traits::X0, xrd);
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,47);
|
||||
@ -2236,7 +2234,7 @@ private:
|
||||
tu.open_scope();
|
||||
this->gen_set_tval(tu, instr);
|
||||
tu.write_mem(traits::FENCE, static_cast<uint32_t>(traits:: fencei), tu.constant(imm,16));
|
||||
auto returnValue = FLUSH;
|
||||
auto returnValue = std::make_tuple(FLUSH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,48);
|
||||
@ -2275,7 +2273,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.ext(res,32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,49);
|
||||
@ -2316,7 +2314,7 @@ private:
|
||||
tu.constant(static_cast<uint32_t>(traits:: XLEN),32))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,50);
|
||||
@ -2357,7 +2355,7 @@ private:
|
||||
tu.constant(static_cast<uint32_t>(traits:: XLEN),32))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,51);
|
||||
@ -2398,7 +2396,7 @@ private:
|
||||
tu.constant(static_cast<uint32_t>(traits:: XLEN),32))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,52);
|
||||
@ -2462,7 +2460,7 @@ private:
|
||||
tu.close_scope();
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,53);
|
||||
@ -2512,7 +2510,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,54);
|
||||
@ -2579,7 +2577,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,55);
|
||||
@ -2629,7 +2627,7 @@ private:
|
||||
}
|
||||
tu.close_scope();
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,56);
|
||||
@ -2664,7 +2662,7 @@ private:
|
||||
else{
|
||||
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,57);
|
||||
@ -2696,7 +2694,7 @@ private:
|
||||
tu.load(rs1+8 + traits::X0, 0),
|
||||
tu.constant(uimm,8))),32,false),32);
|
||||
tu.store(rd+8 + traits::X0, tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,true),32,false));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,58);
|
||||
@ -2728,7 +2726,7 @@ private:
|
||||
tu.load(rs1+8 + traits::X0, 0),
|
||||
tu.constant(uimm,8))),32,false),32);
|
||||
tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+8 + traits::X0, 0),32,false));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,59);
|
||||
@ -2765,7 +2763,7 @@ private:
|
||||
tu.constant((int8_t)sext<6>(imm),8))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,60);
|
||||
@ -2790,7 +2788,7 @@ private:
|
||||
gen_set_pc(tu, pc, traits::NEXT_PC);
|
||||
tu.open_scope();
|
||||
this->gen_set_tval(tu, instr);
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,61);
|
||||
@ -2821,7 +2819,7 @@ private:
|
||||
auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<12>(imm)),32);
|
||||
tu.store(traits::NEXT_PC, PC_val_v);
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(KNOWN_JUMP), 2));
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,62);
|
||||
@ -2856,7 +2854,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.constant((uint32_t)((int8_t)sext<6>(imm)),32));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,63);
|
||||
@ -2889,7 +2887,7 @@ private:
|
||||
if(rd!=0) {
|
||||
tu.store(rd + traits::X0, tu.constant((uint32_t)((int32_t)sext<18>(imm)),32));
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,64);
|
||||
@ -2923,7 +2921,7 @@ private:
|
||||
else{
|
||||
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,65);
|
||||
@ -2949,7 +2947,7 @@ private:
|
||||
tu.open_scope();
|
||||
this->gen_set_tval(tu, instr);
|
||||
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,66);
|
||||
@ -2979,7 +2977,7 @@ private:
|
||||
tu.store(rs1+8 + traits::X0, tu.lshr(
|
||||
tu.load(rs1+8 + traits::X0, 0),
|
||||
tu.constant(shamt,8)));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,67);
|
||||
@ -3016,7 +3014,7 @@ private:
|
||||
tu.constant(64,8))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,68);
|
||||
@ -3046,7 +3044,7 @@ private:
|
||||
tu.store(rs1+8 + traits::X0, tu.ext((tu.bitwise_and(
|
||||
tu.load(rs1+8 + traits::X0, 0),
|
||||
tu.constant((int8_t)sext<6>(imm),8))),32,false));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,69);
|
||||
@ -3076,7 +3074,7 @@ private:
|
||||
tu.store(rd+8 + traits::X0, tu.ext((tu.sub(
|
||||
tu.load(rd+8 + traits::X0, 0),
|
||||
tu.load(rs2+8 + traits::X0, 0))),32,false));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,70);
|
||||
@ -3106,7 +3104,7 @@ private:
|
||||
tu.store(rd+8 + traits::X0, tu.bitwise_xor(
|
||||
tu.load(rd+8 + traits::X0, 0),
|
||||
tu.load(rs2+8 + traits::X0, 0)));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,71);
|
||||
@ -3136,7 +3134,7 @@ private:
|
||||
tu.store(rd+8 + traits::X0, tu.bitwise_or(
|
||||
tu.load(rd+8 + traits::X0, 0),
|
||||
tu.load(rs2+8 + traits::X0, 0)));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,72);
|
||||
@ -3166,7 +3164,7 @@ private:
|
||||
tu.store(rd+8 + traits::X0, tu.bitwise_and(
|
||||
tu.load(rd+8 + traits::X0, 0),
|
||||
tu.load(rs2+8 + traits::X0, 0)));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,73);
|
||||
@ -3196,7 +3194,7 @@ private:
|
||||
auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<12>(imm)),32);
|
||||
tu.store(traits::NEXT_PC, PC_val_v);
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(KNOWN_JUMP), 2));
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,74);
|
||||
@ -3233,7 +3231,7 @@ private:
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(KNOWN_JUMP), 2));
|
||||
}
|
||||
tu.close_scope();
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,75);
|
||||
@ -3270,7 +3268,7 @@ private:
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(KNOWN_JUMP), 2));
|
||||
}
|
||||
tu.close_scope();
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,76);
|
||||
@ -3307,7 +3305,7 @@ private:
|
||||
tu.constant(nzuimm,8)));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,77);
|
||||
@ -3343,7 +3341,7 @@ private:
|
||||
tu.constant(uimm,8))),32,false),32);
|
||||
tu.store(rd + traits::X0, tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,true),32,false));
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,78);
|
||||
@ -3378,7 +3376,7 @@ private:
|
||||
tu.store(rd + traits::X0, tu.load(rs2 + traits::X0, 0));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,79);
|
||||
@ -3415,7 +3413,7 @@ private:
|
||||
else{
|
||||
this->gen_raise_trap(tu, 0, 2);
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,80);
|
||||
@ -3440,7 +3438,7 @@ private:
|
||||
tu.open_scope();
|
||||
this->gen_set_tval(tu, instr);
|
||||
this->gen_raise_trap(tu, 0, 2);
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,81);
|
||||
@ -3477,7 +3475,7 @@ private:
|
||||
tu.load(rs2 + traits::X0, 0))),32,false));
|
||||
}
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,82);
|
||||
@ -3517,7 +3515,7 @@ private:
|
||||
tu.store(traits::NEXT_PC, PC_val_v);
|
||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP), 2));
|
||||
}
|
||||
auto returnValue = BRANCH;
|
||||
auto returnValue = std::make_tuple(BRANCH);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,83);
|
||||
@ -3542,7 +3540,7 @@ private:
|
||||
tu.open_scope();
|
||||
this->gen_set_tval(tu, instr);
|
||||
this->gen_raise_trap(tu, 0, 3);
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,84);
|
||||
@ -3578,7 +3576,7 @@ private:
|
||||
tu.constant(uimm,8))),32,false),32);
|
||||
tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2 + traits::X0, 0),32,false));
|
||||
}
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,85);
|
||||
@ -3603,7 +3601,7 @@ private:
|
||||
tu.open_scope();
|
||||
this->gen_set_tval(tu, instr);
|
||||
this->gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||
auto returnValue = CONT;
|
||||
auto returnValue = std::make_tuple(CONT);
|
||||
|
||||
tu.close_scope();
|
||||
vm_base<ARCH>::gen_sync(tu, POST_SYNC,86);
|
||||
@ -3650,8 +3648,8 @@ vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||
}()) {}
|
||||
|
||||
template <typename ARCH>
|
||||
continuation_e
|
||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
|
||||
std::tuple<continuation_e>
|
||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) {
|
||||
// we fetch at max 4 byte, alignment is 2
|
||||
enum {TRAP_ID=1<<16};
|
||||
code_word_t instr = 0;
|
||||
@ -3663,6 +3661,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
|
||||
return ILLEGAL_FETCH;
|
||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||
return JUMP_TO_SELF;
|
||||
++inst_cnt;
|
||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||
compile_func f = nullptr;
|
||||
if(inst_index < instr_descr.size())
|
||||
@ -3698,12 +3697,7 @@ template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(tu_builder& tu) {
|
||||
tu("return *next_pc;");
|
||||
}
|
||||
|
||||
template <typename ARCH> void vm_impl<ARCH>::add_prologue(tu_builder& tu){
|
||||
std::ostringstream os;
|
||||
os << tu.add_reg_ptr("trap_state", arch::traits<ARCH>::TRAP_STATE, this->regs_base_ptr);
|
||||
os << tu.add_reg_ptr("pending_trap", arch::traits<ARCH>::PENDING_TRAP, this->regs_base_ptr);
|
||||
tu.add_prologue(os.str());
|
||||
}
|
||||
|
||||
} // namespace tgc5c
|
||||
|
||||
template <>
|
||||
|
Reference in New Issue
Block a user