fixes compile issues from merge

This commit is contained in:
Eyck Jentzsch 2023-08-30 15:49:28 +02:00
parent 813b40409d
commit b5d915f389
5 changed files with 109 additions and 64 deletions

View File

@ -63,7 +63,7 @@ uint8_t *tgc5c::get_regs_base_ptr() {
return reinterpret_cast<uint8_t*>(&reg); return reinterpret_cast<uint8_t*>(&reg);
} }
tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &pc) { tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &addr) {
return phys_addr_t(pc); // change logical address to physical address return phys_addr_t(addr.access, addr.space, addr.val&traits<tgc5c>::addr_mask);
} }

View File

@ -195,14 +195,6 @@ struct tgc5c: public arch_if {
inline uint64_t stop_code() { return interrupt_sim; } inline uint64_t stop_code() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){
if (addr.space != traits<tgc5c>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<tgc5c>::addr_mask);
} else
return virt2phys(addr);
}
virtual phys_addr_t virt2phys(const iss::addr_t& addr); virtual phys_addr_t virt2phys(const iss::addr_t& addr);
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }

View File

@ -42,15 +42,15 @@ namespace iss {
namespace interp { namespace interp {
using namespace sysc; using namespace sysc;
volatile std::array<bool, 2> tgc_init = { volatile std::array<bool, 2> tgc_init = {
core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple<cpu_ptr, vm_ptr>{ iss_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
arch::tgc5c* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
}), }),
core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple<cpu_ptr, vm_ptr>{ iss_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
arch::tgc5c* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
}) })
}; };
} }
@ -58,15 +58,15 @@ volatile std::array<bool, 2> tgc_init = {
namespace tcc { namespace tcc {
using namespace sysc; using namespace sysc;
volatile std::array<bool, 2> tgc_init = { volatile std::array<bool, 2> tgc_init = {
core_factory::instance().register_creator("tgc5c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple<cpu_ptr, vm_ptr>{ iss_factory::instance().register_creator("tgc5c|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
arch::tgc5c* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
}), }),
core_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple<cpu_ptr, vm_ptr>{ iss_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data); auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
arch::tgc5c* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc); auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
}) })
}; };
} }

View File

@ -152,14 +152,22 @@ private:
/**************************************************************************** /****************************************************************************
* start opcode definitions * start opcode definitions
****************************************************************************/ ****************************************************************************/
struct InstructionDesriptor { struct instruction_descriptor {
size_t length; size_t length;
uint32_t value; uint32_t value;
uint32_t mask; uint32_t mask;
typename arch::traits<ARCH>::opcode_e op; typename arch::traits<ARCH>::opcode_e op;
}; };
struct decoding_tree_node{
std::vector<instruction_descriptor> instrs;
std::vector<decoding_tree_node*> children;
uint32_t submask = std::numeric_limits<uint32_t>::max();
uint32_t value;
decoding_tree_node(uint32_t value) : value(value){}
};
const std::array<InstructionDesriptor, 87> instr_descr = {{ decoding_tree_node* root {nullptr};
const std::array<instruction_descriptor, 87> instr_descr = {{
/* entries are: size, valid value, valid mask, function ptr */ /* entries are: size, valid value, valid mask, function ptr */
{32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits<ARCH>::opcode_e::LUI}, {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits<ARCH>::opcode_e::LUI},
{32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits<ARCH>::opcode_e::AUIPC}, {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits<ARCH>::opcode_e::AUIPC},
@ -250,18 +258,76 @@ private:
{16, 0b0000000000000000, 0b1111111111111111, arch::traits<ARCH>::opcode_e::DII}, {16, 0b0000000000000000, 0b1111111111111111, arch::traits<ARCH>::opcode_e::DII},
}}; }};
//static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK;
iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ iss::status fetch_ins(virt_addr_t pc, uint8_t * data){
auto phys_pc = this->core.v2p(pc); if(this->core.has_mmu()) {
auto phys_pc = this->core.virt2phys(pc);
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
// if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err;
// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction
// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; // if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok)
// return iss::Err;
// } else { // } else {
if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; if (this->core.read(phys_pc, 4, data) != iss::Ok)
return iss::Err;
// } // }
} else {
if (this->core.read(phys_addr_t(pc.access, pc.space, pc.val), 4, data) != iss::Ok)
return iss::Err;
}
return iss::Ok; return iss::Ok;
} }
void populate_decoding_tree(decoding_tree_node* root){
//create submask
for(auto instr: root->instrs){
root->submask &= instr.mask;
}
//put each instr according to submask&encoding into children
for(auto instr: root->instrs){
bool foundMatch = false;
for(auto child: root->children){
//use value as identifying trait
if(child->value == (instr.value&root->submask)){
child->instrs.push_back(instr);
foundMatch = true;
}
}
if(!foundMatch){
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
child->instrs.push_back(instr);
root->children.push_back(child);
}
}
root->instrs.clear();
//call populate_decoding_tree for all children
if(root->children.size() >1)
for(auto child: root->children){
populate_decoding_tree(child);
}
else{
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
return instr1.mask > instr2.mask;
});
}
}
typename arch::traits<ARCH>::opcode_e decode_instr(decoding_tree_node* node, code_word_t word){
if(!node->children.size()){
if(node->instrs.size() == 1) return node->instrs[0].op;
for(auto instr : node->instrs){
if((instr.mask&word) == instr.value) return instr.op;
}
}
else{
for(auto child : node->children){
if (child->value == (node->submask&word)){
return decode_instr(child, word);
}
}
}
return arch::traits<ARCH>::opcode_e::MAX_OPCODE;
}
}; };
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) { template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
@ -288,16 +354,11 @@ constexpr size_t bit_count(uint32_t u) {
template <typename ARCH> template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id) { : vm_base<ARCH>(core, core_id, cluster_id) {
unsigned id=0; root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
for(auto instr:instr_descr){ for(auto instr:instr_descr){
auto quadrant = instr.value & 0x3; root->instrs.push_back(instr);
qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op});
}
for(auto& lut: qlut){
std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){
return bit_count(a.mask) > bit_count(b.mask);
});
} }
populate_decoding_tree(root);
} }
inline bool is_count_limit_enabled(finish_cond_e cond){ inline bool is_count_limit_enabled(finish_cond_e cond){
@ -308,14 +369,6 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){
return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF;
} }
template <typename ARCH>
typename arch::traits<ARCH>::opcode_e vm_impl<ARCH>::decode_inst_id(code_word_t instr){
for(auto& e: qlut[instr&0x3]){
if(!((instr&e.mask) ^ e.value )) return e.id;
}
return arch::traits<ARCH>::opcode_e::MAX_OPCODE;
}
template <typename ARCH> template <typename ARCH>
typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){
auto pc=start; auto pc=start;
@ -337,7 +390,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} else { } else {
if (is_jump_to_self_enabled(cond) && if (is_jump_to_self_enabled(cond) &&
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
auto inst_id = decode_inst_id(instr); auto inst_id = decode_instr(root, instr);
// pre execution stuff // pre execution stuff
this->core.reg.last_branch = 0; this->core.reg.last_branch = 0;
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id)); if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));

View File

@ -3138,9 +3138,9 @@ private:
} }
}; };
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) { template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
volatile CODE_WORD x = insn; volatile CODE_WORD x = instr;
insn = 2 * x; instr = 2 * x;
} }
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); } template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
@ -3163,30 +3163,30 @@ std::tuple<continuation_e>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { 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 // we fetch at max 4 byte, alignment is 2
enum {TRAP_ID=1<<16}; enum {TRAP_ID=1<<16};
code_word_t insn = 0; code_word_t instr = 0;
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
auto *const data = (uint8_t *)&insn; if(this->core.has_mmu())
paddr = this->core.v2p(pc); paddr = this->core.virt2phys(pc);
//TODO: re-add page handling
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
// auto res = this->core.read(paddr, 2, data); // auto res = this->core.read(paddr, 2, data);
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction // if ((instr & 0x3) == 0x3) { // this is a 32bit instruction
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
// } // }
// } else { // } else {
auto res = this->core.read(paddr, 4, data); auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
// } // }
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack // curr pc on stack
++inst_cnt; ++inst_cnt;
auto lut_val = extract_fields(insn); auto lut_val = extract_fields(instr);
auto f = qlut[insn & 0x3][lut_val]; auto f = qlut[instr & 0x3][lut_val];
if (f == nullptr) { if (f == nullptr) {
f = &this_class::illegal_intruction; f = &this_class::illegal_intruction;
} }
return (this->*f)(pc, insn, tu); return (this->*f)(pc, instr, tu);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {