generate working ISS from CoreDSL 2.0
This commit is contained in:
parent
da7e29fbb7
commit
34bb8e62ae
|
@ -1 +1 @@
|
||||||
Subproject commit ab8ac7045927ca1d12e0142c476cd2e146083169
|
Subproject commit 998444fba8e9273fda6a4d9c89303b62129500f2
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
<%}%>
|
<%}%>
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue