adapts name changes

This commit is contained in:
Eyck Jentzsch 2023-09-04 12:37:30 +02:00
parent d5763d2f36
commit 8ee3ac90f7
4 changed files with 95 additions and 77 deletions

View File

@ -53,7 +53,7 @@ if(WITH_TCC)
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
endif() endif()
if(TARGET RapidJSON) if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON)
list(APPEND LIB_SOURCES list(APPEND LIB_SOURCES
src/iss/plugin/cycle_estimate.cpp src/iss/plugin/cycle_estimate.cpp
src/iss/plugin/pctrace.cpp src/iss/plugin/pctrace.cpp
@ -94,6 +94,14 @@ if(TARGET RapidJSON)
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
endif() endif()
if(WITH_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()
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE FRAMEWORK FALSE

View File

@ -74,7 +74,7 @@ int main(int argc, char *argv[]) {
("mem,m", po::value<std::string>(), "the memory input file") ("mem,m", po::value<std::string>(), "the memory input file")
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate") ("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, tcc") ("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, tcc")
("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation"); ("isa", po::value<std::string>()->default_value("tgc5c"), "isa to use for simulation");
// clang-format on // clang-format on
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
try { try {

View File

@ -124,7 +124,7 @@ protected:
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 };
enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 };
enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; enum { LUT_SIZE = 1 << util::bit_count((uint32_t)EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count((uint32_t)EXTR_MASK16) };
using this_class = vm_impl<ARCH>; using this_class = vm_impl<ARCH>;
using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc, using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc,
@ -4082,20 +4082,22 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
// 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 insn = 0;
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK; // const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
auto *const data = (uint8_t *)&insn; auto *const data = (uint8_t *)&insn;
paddr = this->core.v2p(pc); if(this->core.has_mmu())
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary paddr = this->core.virt2phys(pc);
auto res = this->core.read(paddr, 2, data); //TODO: re-add page handling
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction // auto res = this->core.read(paddr, 2, data);
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
} // if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
} else { // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
// }
// } else {
auto res = this->core.read(paddr, 4, data); auto res = this->core.read(paddr, 4, 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 == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack // curr pc on stack
++inst_cnt; ++inst_cnt;

View File

@ -120,57 +120,7 @@ protected:
} }
} }
// some compile time constants
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 };
enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 };
enum { LUT_SIZE = 1 << util::bit_count(static_cast<uint32_t>(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast<uint32_t>(EXTR_MASK16)) };
std::array<compile_func, LUT_SIZE> lut;
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
std::array<compile_func, LUT_SIZE> lut_11;
std::array<compile_func *, 4> qlut;
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
compile_func f) {
if (pos < 0) {
lut[idx] = f;
} else {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f);
} else {
if ((valid & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f);
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f);
} else {
auto new_val = idx << 1;
if ((value & bitmask) != 0) new_val++;
expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f);
}
}
}
}
inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); }
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) {
if (pos >= 0) {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
lut_val = extract_fields(pos - 1, val, mask, lut_val);
} else {
auto new_val = lut_val << 1;
if ((val & bitmask) != 0) new_val++;
lut_val = extract_fields(pos - 1, val, mask, new_val);
}
}
return lut_val;
}
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type> template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) { inline S sext(U from) {
auto mask = (1ULL<<W) - 1; auto mask = (1ULL<<W) - 1;
@ -182,14 +132,23 @@ 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;
compile_func op; compile_func 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 */
/* instruction LUI, encoding '0b00000000000000000000000000110111' */ /* instruction LUI, encoding '0b00000000000000000000000000110111' */
{32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui},
@ -3136,6 +3095,59 @@ private:
vm_impl::gen_trap_check(tu); vm_impl::gen_trap_check(tu);
return BRANCH; return BRANCH;
} }
//decoding functionality
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;
});
}
}
compile_func 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 nullptr;
}
}; };
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) { template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
@ -3148,14 +3160,11 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
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) {
qlut[0] = lut_00.data(); root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
qlut[1] = lut_01.data(); for(auto instr:instr_descr){
qlut[2] = lut_10.data(); root->instrs.push_back(instr);
qlut[3] = lut_11.data();
for (auto instr : instr_descr) {
auto quantrant = instr.value & 0x3;
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
} }
populate_decoding_tree(root);
} }
template <typename ARCH> template <typename ARCH>
@ -3171,7 +3180,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
// 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 ((instr & 0x3) == 0x3) { // this is a 32bit instruction // if ((insn & 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 {
@ -3181,8 +3190,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
if (instr == 0x0000006f || (instr&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(instr); auto f = decode_instr(root, instr);
auto f = qlut[instr & 0x3][lut_val];
if (f == nullptr) { if (f == nullptr) {
f = &this_class::illegal_intruction; f = &this_class::illegal_intruction;
} }
@ -3218,7 +3226,7 @@ std::unique_ptr<vm_if> create<arch::tgc5c>(arch::tgc5c *core, unsigned short por
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port); if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
return std::unique_ptr<vm_if>(ret); return std::unique_ptr<vm_if>(ret);
} }
} // namespace tcc } // namesapce tcc
} // namespace iss } // namespace iss
#include <iss/factory.h> #include <iss/factory.h>