generate working ISS from CoreDSL 2.0

This commit is contained in:
Eyck Jentzsch 2021-02-06 14:47:06 +00:00
parent da7e29fbb7
commit 34bb8e62ae
9 changed files with 2778 additions and 2398 deletions

@ -1 +1 @@
Subproject commit ab8ac7045927ca1d12e0142c476cd2e146083169 Subproject commit 998444fba8e9273fda6a4d9c89303b62129500f2

View File

@ -29,7 +29,14 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
*******************************************************************************/ *******************************************************************************/
<%
def getRegisterSizes(){
def regs = registers.collect{it.size}
regs[-1]=64 // correct for NEXT_PC
regs+=[32, 32, 32, 32, 64] // append TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, ICOUNT
return regs
}
%>
#include "util/ities.h" #include "util/ities.h"
#include <util/logging.h> #include <util/logging.h>
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
@ -41,8 +48,8 @@ using namespace iss::arch;
constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names; constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names;
constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases; constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases;
constexpr std::array<const uint32_t, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths; constexpr std::array<const uint32_t, ${getRegisterSizes().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths;
constexpr std::array<const uint32_t, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets; constexpr std::array<const uint32_t, ${getRegisterSizes().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets;
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { ${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() {
reg.icount = 0; reg.icount = 0;

View File

@ -29,7 +29,24 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
*******************************************************************************/ *******************************************************************************/
<%
def getRegisterSizes(){
def regs = registers.collect{it.size}
regs[-1]=pc.size // correct for NEXT_PC
regs+=[32, 32, 32, 32, 64] // append TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, ICOUNT
return regs
}
def getRegisterOffsets(){
def regs = registers.collect{it.offset}
def offs= regs[-1]
// append TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, ICOUNT offsets starting with NEXT_PC size
[pc.size/8, 4, 4, 4, 4].each{ sz ->
regs+=offs+sz
offs+=sz
}
return regs
}
%>
#ifndef _${coreDef.name.toUpperCase()}_H_ #ifndef _${coreDef.name.toUpperCase()}_H_
#define _${coreDef.name.toUpperCase()}_H_ #define _${coreDef.name.toUpperCase()}_H_
@ -61,7 +78,6 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
registers.each { reg -> %> registers.each { reg -> %>
${reg.name},<% ${reg.name},<%
}%> }%>
NUM_REGS,
NEXT_${pc.name}=NUM_REGS, NEXT_${pc.name}=NUM_REGS,
TRAP_STATE, TRAP_STATE,
PENDING_TRAP, PENDING_TRAP,
@ -80,11 +96,11 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, ${registers.size}> reg_bit_widths{ static constexpr std::array<const uint32_t, ${getRegisterSizes().size}> reg_bit_widths{
{${registers.collect{it.size}.join(',')}}}; {${getRegisterSizes().join(',')}}};
static constexpr std::array<const uint32_t, ${registers.size}> reg_byte_offsets{ static constexpr std::array<const uint32_t, ${getRegisterOffsets().size}> reg_byte_offsets{
{${registers.collect{it.offset}.join(',')}}}; {${getRegisterOffsets().join(',')}}};
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
@ -137,9 +153,9 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
protected: protected:
struct ${coreDef.name}_regs {<% struct ${coreDef.name}_regs {<%
registers.each { reg ->%> registers.each { reg -> if(reg.size>0) {%>
uint${reg.size}_t ${reg.name} = 0;<% uint${reg.size}_t ${reg.name} = 0;<%
}%> }}%>
uint${pc.size}_t NEXT_${pc.name} = 0; uint${pc.size}_t NEXT_${pc.name} = 0;
uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0;
uint64_t icount = 0; uint64_t icount = 0;

View File

@ -185,27 +185,32 @@ private:
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
/* instruction ${idx}: ${instr.name} */ /* instruction ${idx}: ${instr.name} */
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){ compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){
this->do_sync(PRE_SYNC, ${idx}); // pre execution stuff
<%instr.fields.eachLine{%>${it} this->do_sync(PRE_SYNC, ${idx});
<%}%>if(this->disass_enabled){ <%instr.fields.eachLine{%>${it}
/* generate console output when executing the command */ <%}%>if(this->disass_enabled){
<%instr.disass.eachLine{%>${it} /* generate console output when executing the command */
<%}%>} <%instr.disass.eachLine{%>${it}
auto cur_pc_val = pc.val; <%}%>
super::template get_reg<reg_t>(arch::traits<ARCH>::NEXT_PC) = cur_pc_val + ${instr.length/8}; }
uint${addrDataWidth}_t* X = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::X0); // prepare execution
uint${addrDataWidth}_t* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::PC); uint${addrDataWidth}_t* X = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
<%instr.behavior.eachLine{%>${it} uint${addrDataWidth}_t* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
<%}%>this->do_sync(POST_SYNC, ${idx}); // execute instruction
auto& trap_state = super::template get_reg<uint32_t>(arch::traits<ARCH>::TRAP_STATE); <%instr.behavior.eachLine{%>${it}
// trap check <%}%>// post execution stuff<% if(instr.modifiesPC) { %>
if(trap_state!=0){ super::template get_reg<reg_t>(arch::traits<ARCH>::NEXT_PC) = super::template get_reg<reg_t>(arch::traits<ARCH>::PC);<% } else { %>
auto& last_br = super::template get_reg<uint32_t>(arch::traits<ARCH>::LAST_BRANCH); super::template get_reg<reg_t>(arch::traits<ARCH>::NEXT_PC) = pc.val + ${instr.length/8};<% } %>
last_br = std::numeric_limits<uint32_t>::max(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx});
super::core.enter_trap(trap_state, cur_pc_val); auto& trap_state = super::template get_reg<uint32_t>(arch::traits<ARCH>::TRAP_STATE);
} // trap check
pc.val=super::template get_reg<reg_t>(arch::traits<ARCH>::NEXT_PC); if(trap_state!=0){
return pc; auto& last_br = super::template get_reg<uint32_t>(arch::traits<ARCH>::LAST_BRANCH);
last_br = std::numeric_limits<uint32_t>::max();
super::core.enter_trap(trap_state, pc.val);
}
pc.val=super::template get_reg<reg_t>(arch::traits<ARCH>::NEXT_PC);
return pc;
} }
<%}%> <%}%>
/**************************************************************************** /****************************************************************************

View File

@ -47,11 +47,11 @@ template <> struct traits<tgf_c> {
constexpr static char const* const core_type = "TGF_C"; constexpr static char const* const core_type = "TGF_C";
static constexpr std::array<const char*, 33> reg_names{ static constexpr std::array<const char*, 34> reg_names{
{"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC"}}; {"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NUM_REGS"}};
static constexpr std::array<const char*, 33> reg_aliases{ static constexpr std::array<const char*, 34> reg_aliases{
{"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC"}}; {"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NUM_REGS"}};
enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0xfff, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0xfff, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64};
@ -110,11 +110,11 @@ template <> struct traits<tgf_c> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 33> reg_bit_widths{ static constexpr std::array<const uint32_t, 39> reg_bit_widths{
{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32}}; {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}};
static constexpr std::array<const uint32_t, 33> reg_byte_offsets{ static constexpr std::array<const uint32_t, 39> reg_byte_offsets{
{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128}}; {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152}};
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);

View File

@ -39,10 +39,10 @@
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::tgf_c>::reg_names; constexpr std::array<const char*, 34> iss::arch::traits<iss::arch::tgf_c>::reg_names;
constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::tgf_c>::reg_aliases; constexpr std::array<const char*, 34> iss::arch::traits<iss::arch::tgf_c>::reg_aliases;
constexpr std::array<const uint32_t, 33> iss::arch::traits<iss::arch::tgf_c>::reg_bit_widths; constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::tgf_c>::reg_bit_widths;
constexpr std::array<const uint32_t, 33> iss::arch::traits<iss::arch::tgf_c>::reg_byte_offsets; constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::tgf_c>::reg_byte_offsets;
tgf_c::tgf_c() { tgf_c::tgf_c() {
reg.icount = 0; reg.icount = 0;

View File

@ -83,7 +83,7 @@ int main(int argc, char *argv[]) {
("elf", po::value<std::vector<std::string>>(), "ELF file(s) to load") ("elf", po::value<std::vector<std::string>>(), "ELF file(s) to load")
("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("tcc"), "the memory input file") ("backend", po::value<std::string>()->default_value("interp"), "the memory input file")
("isa", po::value<std::string>()->default_value("tgf_c"), "isa to use for simulation"); ("isa", po::value<std::string>()->default_value("tgf_c"), "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();

File diff suppressed because it is too large Load Diff