From c6b99cd155877d630102edebeb8def5178913762 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Wed, 24 Jul 2024 12:28:35 +0200 Subject: [PATCH] introduces new decoder to interp backend --- gen_input/templates/interp/CORENAME.cpp.gtl | 93 +++++---------------- src/vm/interp/vm_tgc5c.cpp | 3 + 2 files changed, 26 insertions(+), 70 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index c9624f9..43968bf 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -35,6 +35,7 @@ def nativeTypeSize(int size){ } %> // clang-format off +#include #include #include #include @@ -47,6 +48,8 @@ def nativeTypeSize(int size){ #include #include #include +#include + #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -152,25 +155,20 @@ private: * start opcode definitions ****************************************************************************/ struct instruction_descriptor { - size_t length; + uint32_t length; uint32_t value; uint32_t mask; typename arch::traits::opcode_e op; }; - struct decoding_tree_node{ - std::vector instrs; - std::vector children; - uint32_t submask = std::numeric_limits::max(); - uint32_t value; - decoding_tree_node(uint32_t value) : value(value){} - }; - decoding_tree_node* root {nullptr}; const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> {${instr.length}, ${instr.encoding}, ${instr.mask}, arch::traits::opcode_e::${instr.instruction.name}},<%}%> }}; + //needs to be declared after instr_descr + decoder instr_decoder; + iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ if(this->core.has_mmu()) { auto phys_pc = this->core.virt2phys(pc); @@ -190,58 +188,6 @@ private: } 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::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::opcode_e::MAX_OPCODE; - } }; template void debug_fn(CODE_WORD insn) { @@ -267,13 +213,16 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm_base(core, core_id, cluster_id) { - root = new decoding_tree_node(std::numeric_limits::max()); - for(auto instr:instr_descr){ - root->instrs.push_back(instr); - } - populate_decoding_tree(root); -} +: vm_base(core, core_id, cluster_id) +, instr_decoder([this]() { + std::vector g_instr_descr; + g_instr_descr.reserve(instr_descr.size()); + for (uint32_t i = 0; i < instr_descr.size(); ++i) { + generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i}; + g_instr_descr.push_back(new_instr_descr); + } + return std::move(g_instr_descr); + }()) {} inline bool is_icount_limit_enabled(finish_cond_e cond){ return (cond & finish_cond_e::ICOUNT_LIMIT) == finish_cond_e::ICOUNT_LIMIT; @@ -310,9 +259,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_instr(root, instr); + uint32_t inst_index = instr_decoder.decode_instr(instr); + opcode_e inst_id = arch::traits::opcode_e::MAX_OPCODE;; + if(inst_index core.reg.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); try{ switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 64b716e..aa930ff 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -46,6 +46,7 @@ #include #include + #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif @@ -153,6 +154,7 @@ private: uint32_t mask; typename arch::traits::opcode_e op; }; + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, @@ -243,6 +245,7 @@ private: {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::C__SWSP}, {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, }}; + //needs to be declared after instr_descr decoder instr_decoder;