Back-ported DVCon turorial changes

This commit is contained in:
2018-11-08 13:31:28 +01:00
parent 124a308ffa
commit 20b3665003
86 changed files with 429488 additions and 4424 deletions

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>riscv</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
</natures>
</projectDescription>

View File

@@ -1 +0,0 @@
/com.minres.coredsl.CoreDsl.prefs

View File

@@ -10,37 +10,10 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
# Set the name of your project here
project("riscv")
# Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0)
set(VERSION_MAJOR "0")
set(VERSION_MINOR "0")
set(VERSION_PATCH "1")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
include(Common)
## Git (and its revision)
find_package(Git QUIET) # if we don't find git or FindGit.cmake is not on the system we ignore it.
## The Git module will trigger a reconfiguration for each pull that will bring a new revision on the local repository
set (VCS_REVISION "-1")
if(GIT_FOUND)
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
message(STATUS "GIT branch ${GIT_REFSPEC}")
message(STATUS "GIT revision ${GIT_SHA1}")
set (VCS_REVISION ${GIT_SHA1})
endif()
conan_basic_setup()
# This line finds the boost lib and headers.
set(Boost_NO_BOOST_CMAKE ON) # Don't do a find_package in config mode before searching for a regular boost install.
find_package(Boost COMPONENTS program_options system thread REQUIRED)
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser)
# This sets the include directory for the reference project. This is the -I flag in gcc.
include_directories(
${PROJECT_SOURCE_DIR}/incl

View File

@@ -143,19 +143,19 @@ InsructionSet RV32IBase {
if (rd != 0) X[rd] <= choose(X[rs1]'u < full_imm'u, 1, 0);
}
XORI {
encoding: imm[11:0] | rs1[4:0] | b100 | rd[4:0] | b0010011;
encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%";
if(rd != 0) X[rd] <= X[rs1] ^ imm;
if(rd != 0) X[rd] <= X[rs1]s ^ imm;
}
ORI {
encoding: imm[11:0] | rs1[4:0] | b110 | rd[4:0] | b0010011;
encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%";
if(rd != 0) X[rd] <= X[rs1] | imm;
if(rd != 0) X[rd] <= X[rs1]s | imm;
}
ANDI {
encoding: imm[11:0] | rs1[4:0] | b111 | rd[4:0] | b0010011;
encoding: imm[11:0]s | rs1[4:0] | b111 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%";
if(rd != 0) X[rd] <= X[rs1] & imm;
if(rd != 0) X[rd] <= X[rs1]s & imm;
}
SLLI {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011;

View File

@@ -1,38 +1,34 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Contributors:
// eyck@minres.com - initial API and implementation
//
//
////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include <iss/arch/CORE_DEF_NAME.h>
#include <iss/arch/riscv_hart_msu_vp.h>
@@ -44,8 +40,8 @@
#include <boost/format.hpp>
#include <iss/debugger/riscv_target_adapter.h>
#include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss {
namespace CORE_DEF_NAME {
@@ -101,14 +97,13 @@ protected:
void gen_trap_check(llvm::BasicBlock *bb);
inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) {
return this->builder.CreateLoad(get_reg_ptr(i), false);
}
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
this->get_type(traits<ARCH>::XLEN));
this->get_type(traits<ARCH>::XLEN));
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
}
@@ -127,9 +122,9 @@ protected:
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<compile_func *, 4> qlut;
std::array<const uint32_t, 4> lutmasks = { { EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32 } };
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) {
@@ -180,23 +175,23 @@ private:
};
/* «start generated code» */
std::array<InstructionDesriptor, 0> instr_descr = { { } };
std::array<InstructionDesriptor, 0> instr_descr = {{}};
/* «end generated code» */
/****************************************************************************
* end opcode definitions
****************************************************************************/
std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr,
llvm::BasicBlock *bb) {
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
get_reg_ptr(traits<ARCH>::PC), true);
get_reg_ptr(traits<ARCH>::PC), true);
this->builder.CreateStore(
this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
this->gen_const(64U, 1)),
this->gen_const(64U, 1)),
get_reg_ptr(traits<ARCH>::ICOUNT), true);
pc = pc + ((instr & 3) == 3 ? 4 : 2);
this->gen_raise_trap(0, 2); // illegal instruction trap
this->gen_sync(iss::POST_SYNC, instr_descr.size());
this->gen_raise_trap(0, 2); // illegal instruction trap
this->gen_sync(iss::POST_SYNC, instr_descr.size());
this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr);
}
@@ -245,7 +240,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
} catch (trap_access &ta) {
throw trap_access(ta.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
typename vm_impl<ARCH>::processing_pc_entry addr(*this, pc, paddr);
++inst_cnt;

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017, MINRES Technologies GmbH
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,21 +37,26 @@
#include "iss/arch/traits.h"
#include "iss/arch_if.h"
#include "iss/instrumentation_if.h"
#include "iss/log_categories.h"
#include "iss/vm_if.h"
#include "iss/instrumentation_if.h"
#include <array>
#include <elfio/elfio.hpp>
#include <iomanip>
#include <sstream>
#include <type_traits>
#include <unordered_map>
#include <util/bit_field.h>
#include <util/ities.h>
#include <util/sparse_array.h>
#include <util/bit_field.h>
#include <array>
#include <type_traits>
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#if defined(__GNUC__)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) x
#define unlikely(x) x
#endif
namespace iss {
namespace arch {
@@ -165,29 +170,29 @@ enum riscv_csr {
namespace {
std::array<const char, 4> lvl = { { 'U', 'S', 'H', 'M' } };
std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
std::array<const char*, 16> trap_str = { { ""
"Instruction address misaligned", //0
"Instruction access fault", //1
"Illegal instruction", //2
"Breakpoint", //3
"Load address misaligned", //4
"Load access fault", //5
"Store/AMO address misaligned", //6
"Store/AMO access fault", //7
"Environment call from U-mode", //8
"Environment call from S-mode", //9
"Reserved", //a
"Environment call from M-mode", //b
"Instruction page fault", //c
"Load page fault", //d
"Reserved", //e
"Store/AMO page fault" } };
std::array<const char*, 12> irq_str = { {
"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt",
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", "User external interrupt",
"Supervisor external interrupt", "Reserved", "Machine external interrupt" } };
std::array<const char *, 16> trap_str = {{""
"Instruction address misaligned", // 0
"Instruction access fault", // 1
"Illegal instruction", // 2
"Breakpoint", // 3
"Load address misaligned", // 4
"Load access fault", // 5
"Store/AMO address misaligned", // 6
"Store/AMO access fault", // 7
"Environment call from U-mode", // 8
"Environment call from S-mode", // 9
"Reserved", // a
"Environment call from M-mode", // b
"Instruction page fault", // c
"Load page fault", // d
"Reserved", // e
"Store/AMO page fault"}};
std::array<const char *, 12> irq_str = {
{"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt",
"User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt",
"User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
enum {
PGSHIFT = 12,
@@ -229,7 +234,7 @@ struct vm_info {
int idxbits;
int ptesize;
uint64_t ptbase;
bool is_active() { return levels;}
bool is_active() { return levels; }
};
class trap_load_access_fault : public trap_access {
@@ -272,10 +277,9 @@ public:
using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t);
// primary template
template<class T, class Enable = void> struct hart_state { };
template <class T, class Enable = void> struct hart_state {};
// specialization 32bit
template <typename T>
class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
public:
BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11)))
@@ -318,10 +322,10 @@ public:
static const reg_t mstatus_reset_val = 0;
void write_mstatus(T val, unsigned priv_lvl){
void write_mstatus(T val, unsigned priv_lvl) {
auto mask = get_mask(priv_lvl);
auto new_val = (mstatus.st.value & ~mask) | (val & mask);
mstatus=new_val;
mstatus = new_val;
}
T satp;
@@ -329,11 +333,15 @@ public:
static constexpr T get_misa() { return (1UL << 30) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; }
static constexpr uint32_t get_mask(unsigned priv_lvl) {
#if __cplusplus < 201402L
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
#else
switch (priv_lvl) {
case PRIV_U: return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
case PRIV_S: return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
default: return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
}
#endif
}
static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
@@ -349,8 +357,7 @@ public:
}
};
// specialization 64bit
template <typename T>
class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
public:
BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11)))
@@ -397,17 +404,17 @@ public:
static const reg_t mstatus_reset_val = 0xa00000000;
void write_mstatus(T val, unsigned priv_lvl){
void write_mstatus(T val, unsigned priv_lvl) {
T old_val = mstatus;
auto mask = get_mask(priv_lvl);
auto new_val = (old_val & ~mask) | (val & mask);
if((new_val&mstatus.SXL.Mask)==0){
new_val |= old_val&mstatus.SXL.Mask;
if ((new_val & mstatus.SXL.Mask) == 0) {
new_val |= old_val & mstatus.SXL.Mask;
}
if((new_val&mstatus.UXL.Mask)==0){
new_val |= old_val&mstatus.UXL.Mask;
if ((new_val & mstatus.UXL.Mask) == 0) {
new_val |= old_val & mstatus.UXL.Mask;
}
mstatus=new_val;
mstatus = new_val;
}
T satp;
@@ -426,9 +433,9 @@ public:
if (state == PRIV_M) return {0, 0, 0, 0};
if (state <= PRIV_S)
switch (bit_sub<60, 4>(sptbr)) {
case 0: return {0, 0, 0, 0}; // off
case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39
case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48
case 0: return {0, 0, 0, 0}; // off
case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39
case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48
case 10: return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV57
case 11: return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV64
default: abort();
@@ -442,12 +449,12 @@ public:
const typename super::reg_t PGMASK = PGSIZE - 1;
constexpr reg_t get_irq_mask(size_t mode) {
std::array<const reg_t,4> m = { {
0b000100010001,// U mode
0b001100110011,// S mode
0,
0b101110111011 // M mode
}};
std::array<const reg_t, 4> m = {{
0b000100010001, // U mode
0b001100110011, // S mode
0,
0b101110111011 // M mode
}};
return m[mode];
}
@@ -456,7 +463,7 @@ public:
void reset(uint64_t address) override;
std::pair<uint64_t,bool> load_file(std::string name, int type = -1) override;
std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
virtual phys_addr_t virt2phys(const iss::addr_t &addr) override;
@@ -468,40 +475,39 @@ public:
virtual uint64_t leave_trap(uint64_t flags) override;
void wait_until(uint64_t flags) override;
void disass_output(uint64_t pc, const std::string instr) override {
std::stringstream s;
s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0')
<< std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]";
CLOG(INFO, disass) << "0x"<<std::setw(16)<<std::setfill('0')<<std::hex<<pc<<"\t\t"<<instr<<"\t"<<s.str();
CLOG(INFO, disass) << "0x" << std::setw(16) << std::setfill('0') << std::hex << pc << "\t\t" << instr << "\t" << s.str();
};
iss::instrumentation_if* get_instrumentation_if() override {return &instr_if;}
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
protected:
struct riscv_instrumentation_if : public iss::instrumentation_if{
struct riscv_instrumentation_if : public iss::instrumentation_if {
riscv_instrumentation_if(riscv_hart_msu_vp<BASE>& arch):arch(arch){}
riscv_instrumentation_if(riscv_hart_msu_vp<BASE> &arch)
: arch(arch) {}
/**
* get the name of this architecture
*
* @return the name of this architecture
*/
const std::string core_type_name() const override {return traits<BASE>::core_type;}
const std::string core_type_name() const override { return traits<BASE>::core_type; }
virtual uint64_t get_pc(){ return arch.get_pc(); };
virtual uint64_t get_pc() { return arch.get_pc(); };
virtual uint64_t get_next_pc(){ return arch.get_next_pc(); };
virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
virtual void set_curr_instr_cycles(unsigned cycles){ arch.cycle_offset+=cycles-1; };
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
riscv_hart_msu_vp<BASE>& arch;
riscv_hart_msu_vp<BASE> &arch;
};
friend struct riscv_instrumentation_if;
addr_t get_pc(){return this->reg.PC;}
addr_t get_next_pc(){return this->reg.NEXT_PC;}
addr_t get_pc() { return this->reg.PC; }
addr_t get_next_pc() { return this->reg.NEXT_PC; }
virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data);
virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data);
@@ -512,7 +518,7 @@ protected:
hart_state<reg_t> state;
uint64_t cycle_offset;
reg_t fault_data;
std::array<vm_info,2> vm;
std::array<vm_info, 2> vm;
uint64_t tohost = tohost_dflt;
uint64_t fromhost = fromhost_dflt;
unsigned to_host_wr_cnt = 0;
@@ -541,15 +547,18 @@ private:
iss::status write_ip(unsigned addr, reg_t val);
iss::status read_satp(unsigned addr, reg_t &val);
iss::status write_satp(unsigned addr, reg_t val);
iss::status read_fcsr(unsigned addr, reg_t& val);
iss::status read_fcsr(unsigned addr, reg_t &val);
iss::status write_fcsr(unsigned addr, reg_t val);
protected:
void check_interrupt();
};
template <typename BASE>
riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
: state(), cycle_offset(0), instr_if(*this) {
: state()
, cycle_offset(0)
, instr_if(*this) {
csr[misa] = hart_state<reg_t>::get_misa();
uart_buf.str("");
// read-only registers
@@ -591,27 +600,26 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
csr_wr_cb[fflags] = &riscv_hart_msu_vp<BASE>::write_fcsr;
csr_rd_cb[frm] = &riscv_hart_msu_vp<BASE>::read_fcsr;
csr_wr_cb[frm] = &riscv_hart_msu_vp<BASE>::write_fcsr;
}
template <typename BASE> std::pair<uint64_t,bool> riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
FILE *fp = fopen(name.c_str(), "r");
if (fp) {
std::array<char, 5> buf;
auto n = fread(buf.data(), 1, 4, fp);
std::array<char, 5> buf;
auto n = fread(buf.data(), 1, 4, fp);
if (n != 4) throw std::runtime_error("input file has insufficient size");
buf[4] = 0;
if (strcmp(buf.data() + 1, "ELF") == 0) {
if (strcmp(buf.data() + 1, "ELF") == 0) {
fclose(fp);
// Create elfio reader
ELFIO::elfio reader;
// Load ELF data
if (!reader.load(name)) throw std::runtime_error("could not process elf file");
// check elf properties
if ( reader.get_class() != ELFCLASS32 )
if(sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
if (reader.get_class() != ELFCLASS32)
if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
if ( reader.get_machine() != EM_RISCV ) throw std::runtime_error("wrong elf machine in file");
if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
for (const auto pseg : reader.segments) {
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
const auto seg_data = pseg->get_data();
@@ -642,9 +650,9 @@ template <typename BASE>
iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned length, uint8_t *const data) {
#ifndef NDEBUG
if (addr.access && iss::access_type::DEBUG) {
LOG(DEBUG) << "debug read of " << length << " bytes @addr " << addr;
LOG(TRACE) << "debug read of " << length << " bytes @addr " << addr;
} else {
LOG(DEBUG) << "read of " << length << " bytes @addr " << addr;
LOG(TRACE) << "read of " << length << " bytes @addr " << addr;
}
#endif
try {
@@ -716,26 +724,26 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned leng
template <typename BASE>
iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) {
#ifndef NDEBUG
const char *prefix = (addr.access && iss::access_type::DEBUG)? "debug " : "";
const char *prefix = (addr.access && iss::access_type::DEBUG) ? "debug " : "";
switch (length) {
case 8:
LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
<< ") @addr " << addr;
break;
case 4:
LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
<< ") @addr " << addr;
break;
case 2:
LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
<< ") @addr " << addr;
break;
case 1:
LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
<< ") @addr " << addr;
break;
default:
LOG(DEBUG) << prefix << "write of " << length << " bytes @addr " << addr;
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
}
#endif
try {
@@ -760,7 +768,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned len
}
}
auto res = write_mem(BASE::v2p(addr), length, data);
if (unlikely(res != iss::Ok)) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 7 (Store/AMO access fault)
if (unlikely(res != iss::Ok))
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 7 (Store/AMO access fault)
return res;
} catch (trap_access &ta) {
this->reg.trap_state = (1 << 31) | ta.id;
@@ -857,7 +866,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned
}
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t &val) {
auto cycle_val= this->reg.icount + cycle_offset;
auto cycle_val = this->reg.icount + cycle_offset;
if (addr == mcycle) {
val = static_cast<reg_t>(cycle_val);
} else if (addr == mcycleh) {
@@ -868,7 +877,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigne
}
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t &val) {
uint64_t time_val=(this->reg.icount + cycle_offset) / (100000000/32768-1); //-> ~3052;
uint64_t time_val = (this->reg.icount + cycle_offset) / (100000000 / 32768 - 1); //-> ~3052;
if (addr == time) {
val = static_cast<reg_t>(time_val);
} else if (addr == timeh) {
@@ -925,7 +934,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ip(unsigned
auto req_priv_lvl = addr >> 8;
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
auto mask = get_irq_mask(req_priv_lvl);
mask &= ~(1<<7); // MTIP is read only
mask &= ~(1 << 7); // MTIP is read only
csr[mip] = (csr[mip] & ~mask) | (val & mask);
check_interrupt();
return iss::Ok;
@@ -953,16 +962,16 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigne
update_vm_info();
return iss::Ok;
}
template<typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_fcsr(unsigned addr, reg_t& val) {
switch(addr){
case 1: //fflags, 4:0
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_fcsr(unsigned addr, reg_t &val) {
switch (addr) {
case 1: // fflags, 4:0
val = bit_sub<0, 5>(this->get_fcsr());
break;
case 2: // frm, 7:5
val = bit_sub<5, 3>(this->get_fcsr());
break;
break;
case 3: // fcsr
val=this->get_fcsr();
val = this->get_fcsr();
break;
default:
return iss::Err;
@@ -970,16 +979,16 @@ template<typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_fcsr(unsigned
return iss::Ok;
}
template<typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigned addr, reg_t val) {
switch(addr){
case 1: //fflags, 4:0
this->set_fcsr( (this->get_fcsr() & 0xffffffe0) | (val&0x1f));
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigned addr, reg_t val) {
switch (addr) {
case 1: // fflags, 4:0
this->set_fcsr((this->get_fcsr() & 0xffffffe0) | (val & 0x1f));
break;
case 2: // frm, 7:5
this->set_fcsr( (this->get_fcsr() & 0xffffff1f) | ((val&0x7)<<5));
break;
this->set_fcsr((this->get_fcsr() & 0xffffff1f) | ((val & 0x7) << 5));
break;
case 3: // fcsr
this->set_fcsr(val&0xff);
this->set_fcsr(val & 0xff);
break;
default:
return iss::Err;
@@ -992,7 +1001,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
if ((paddr.val + length) > mem.size()) return iss::Err;
switch (paddr.val) {
case 0x0200BFF8: { // CLINT base, mtime reg
if(sizeof(reg_t)<length) return iss::Err;
if (sizeof(reg_t) < length) return iss::Err;
reg_t time_val;
this->read_csr(time, time_val);
std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data);
@@ -1054,10 +1063,10 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
switch (hostvar >> 48) {
case 0:
if (hostvar != 0x1){
if (hostvar != 0x1) {
LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation";
}else{
} else {
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation";
}
@@ -1087,22 +1096,20 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
return iss::Ok;
}
template<typename BASE>
inline void riscv_hart_msu_vp<BASE>::reset(uint64_t address) {
template <typename BASE> inline void riscv_hart_msu_vp<BASE>::reset(uint64_t address) {
BASE::reset(address);
state.mstatus = hart_state<reg_t>::mstatus_reset_val;
update_vm_info();
}
template<typename BASE>
inline void riscv_hart_msu_vp<BASE>::update_vm_info() {
template <typename BASE> inline void riscv_hart_msu_vp<BASE>::update_vm_info() {
vm[1] = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
BASE::addr_mode[3]=BASE::addr_mode[2]=vm[1].is_active()?iss::address_type::VIRTUAL:iss::address_type::PHYSICAL;
if(state.mstatus.MPRV)
BASE::addr_mode[3]=BASE::addr_mode[2] = vm[1].is_active()? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL;
if (state.mstatus.MPRV)
vm[0] = hart_state<reg_t>::decode_vm_info(state.mstatus.MPP, state.satp);
else
vm[0] = vm[1];
BASE::addr_mode[1]=BASE::addr_mode[0]=vm[0].is_active()?iss::address_type::VIRTUAL:iss::address_type::PHYSICAL;
BASE::addr_mode[1] = BASE::addr_mode[0]=vm[0].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL;
ptw.clear();
}
@@ -1117,7 +1124,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
// any synchronous traps.
auto ena_irq = ip & ie;
auto mie = state.mstatus.MIE;
bool mie = state.mstatus.MIE;
auto m_enabled = this->reg.machine_state < PRIV_M || (this->reg.machine_state == PRIV_M && mie);
auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0;
@@ -1153,10 +1160,10 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
#endif
} else {
uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV
state.mstatus.MPP:
state.mstatus.MPP :
this->reg.machine_state;
const vm_info& vm = this->vm[static_cast<uint16_t>(type)/2];
const vm_info &vm = this->vm[static_cast<uint16_t>(type) / 2];
const bool s_mode = mode == PRIV_S;
const bool sum = state.mstatus.SUM;
@@ -1175,8 +1182,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
// check that physical address of PTE is legal
reg_t pte = 0;
const uint8_t res =
this->read(phys_addr_t{addr.access, traits<BASE>::MEM, base + idx * vm.ptesize}, vm.ptesize, (uint8_t *)&pte);
const uint8_t res = this->read(phys_addr_t{addr.access, traits<BASE>::MEM, base + idx * vm.ptesize},
vm.ptesize, (uint8_t *)&pte);
if (res != 0) throw trap_load_access_fault(addr.val);
const reg_t ppn = pte >> PTE_PPN_SHIFT;
@@ -1186,9 +1193,10 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
break;
} else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break;
} else if (type == iss::access_type::FETCH ? !(pte & PTE_X)
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
: !((pte & PTE_R) && (pte & PTE_W))) {
} else if (type == iss::access_type::FETCH
? !(pte & PTE_X)
: type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
: !((pte & PTE_R) && (pte & PTE_W))) {
break;
} else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
break;
@@ -1254,8 +1262,8 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt
this->reg.pending_trap = 0;
}
size_t adr=ucause | (new_priv << 8);
csr[adr] = (trap_id<<31)+cause;
size_t adr = ucause | (new_priv << 8);
csr[adr] = (trap_id << 31) + cause;
// update mstatus
// xPP field of mstatus is written with the active privilege mode at the time
// of the trap; the x PIE field of mstatus
@@ -1265,15 +1273,18 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
// store the actual privilege level in yPP and store interrupt enable flags
switch (new_priv) {
case PRIV_M:
state.mstatus.MPP=cur_priv;
state.mstatus.MPIE=state.mstatus.MIE;
state.mstatus.MPP = cur_priv;
state.mstatus.MPIE = state.mstatus.MIE;
state.mstatus.MIE = false;
break;
case PRIV_S:
state.mstatus.SPP = cur_priv;
state.mstatus.SPIE=state.mstatus.SIE;
state.mstatus.SPIE = state.mstatus.SIE;
state.mstatus.SIE = false;
break;
case PRIV_U:
state.mstatus.UPIE=state.mstatus.UIE;
state.mstatus.UPIE = state.mstatus.UIE;
state.mstatus.UIE = false;
break;
default:
break;
@@ -1288,11 +1299,12 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
// reset trap state
this->reg.machine_state = new_priv;
this->reg.trap_state = 0;
std::array<char, 32> buffer;
sprintf(buffer.data(), "0x%016lx", addr);
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause])<<"' ("<<trap_id<<")"
<< " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[cur_priv]
<< " to " << lvl[new_priv];
std::array<char, 32> buffer;
sprintf(buffer.data(), "0x%016lx", addr);
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << trap_id << ")"
<< " at address " << buffer.data() << " occurred, changing privilege level from "
<< lvl[cur_priv] << " to " << lvl[new_priv];
update_vm_info();
return this->reg.NEXT_PC;
}
@@ -1314,22 +1326,23 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t f
switch (inst_priv) {
case PRIV_M:
this->reg.machine_state = state.mstatus.MPP;
state.mstatus.MPP=0; // clear mpp to U mode
state.mstatus.MIE=state.mstatus.MPIE;
state.mstatus.MPP = 0; // clear mpp to U mode
state.mstatus.MIE = state.mstatus.MPIE;
break;
case PRIV_S:
this->reg.machine_state = state.mstatus.SPP;
state.mstatus.SPP= 0; // clear spp to U mode
state.mstatus.SIE=state.mstatus.SPIE;
state.mstatus.SPP = 0; // clear spp to U mode
state.mstatus.SIE = state.mstatus.SPIE;
break;
case PRIV_U:
this->reg.machine_state = 0;
state.mstatus.UIE=state.mstatus.UPIE;
state.mstatus.UIE = state.mstatus.UPIE;
break;
}
// sets the pc to the value stored in the x epc register.
this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.machine_state];
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to "
<< lvl[this->reg.machine_state];
update_vm_info();
return this->reg.NEXT_PC;
}
@@ -1345,5 +1358,4 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags
}
}
#endif /* _RISCV_CORE_H_ */

View File

@@ -179,7 +179,7 @@ struct rv32gc: public arch_if {
uint64_t get_icount() { return reg.icount;}
bool should_stop(){return false;}
inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv32gc>::MEM ||
@@ -272,6 +272,7 @@ protected:
std::array<address_type, 4> addr_mode;
bool interrupt_sim=false;
uint32_t get_fcsr(){return reg.FCSR;}
void set_fcsr(uint32_t val){reg.FCSR = val;}

View File

@@ -1,54 +1,59 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#ifndef _RV32IMAC_H_
#define _RV32IMAC_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h>
#include <iss/vm_if.h>
#include <iss/arch/traits.h>
#include <array>
namespace iss {
namespace arch {
struct rv32imac;
template<>
struct traits<rv32imac> {
template <> struct traits<rv32imac> {
constexpr static char const* const core_type = "RV32IMAC";
enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000101000001000100000101, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static char const *const core_type = "RV32IMAC";
enum constants {
XLEN = 32,
PCLEN = 32,
MISA_VAL = 0b1000000000101000001000100000101,
PGSIZE = 0x1000,
PGMASK = 0xfff
};
constexpr static unsigned FP_REGS_SIZE = 0;
@@ -87,7 +92,7 @@ struct traits<rv32imac> {
X31,
PC,
NUM_REGS,
NEXT_PC=NUM_REGS,
NEXT_PC = NUM_REGS,
TRAP_STATE,
PENDING_TRAP,
MACHINE_STATE,
@@ -99,72 +104,70 @@ struct traits<rv32imac> {
using addr_t = uint32_t;
using code_word_t = uint32_t; //TODO: check removal
using code_word_t = uint32_t; // TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) {
constexpr std::array<const uint32_t, 39> RV32IMAC_reg_size{{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}};
return RV32IMAC_reg_size[r];
}
static constexpr std::array<const uint32_t, 39> RV32IMAC_reg_size{
{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}};
constexpr static unsigned reg_byte_offset(unsigned r) {
constexpr std::array<const uint32_t, 40> RV32IMAC_reg_byte_offset{{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,160}};
return RV32IMAC_reg_byte_offset[r];
}
constexpr static unsigned reg_bit_width(unsigned r) { return RV32IMAC_reg_size[r]; }
static constexpr std::array<const uint32_t, 40> RV32IMAC_reg_byte_offset{
{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, 160}};
constexpr static unsigned reg_byte_offset(unsigned r) { return RV32IMAC_reg_byte_offset[r]; }
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e {FLAGS};
enum sreg_flag_e { FLAGS };
enum mem_type_e {MEM, CSR, FENCE, RES};
enum mem_type_e { MEM, CSR, FENCE, RES };
};
struct rv32imac: public arch_if {
struct rv32imac : public arch_if {
using virt_addr_t = typename traits<rv32imac>::virt_addr_t;
using phys_addr_t = typename traits<rv32imac>::phys_addr_t;
using reg_t = typename traits<rv32imac>::reg_t;
using reg_t = typename traits<rv32imac>::reg_t;
using addr_t = typename traits<rv32imac>::addr_t;
rv32imac();
~rv32imac();
void reset(uint64_t address=0) override;
void reset(uint64_t address = 0) override;
uint8_t* get_regs_base_ptr() override;
uint8_t *get_regs_base_ptr() override;
/// deprecated
void get_reg(short idx, std::vector<uint8_t>& value) override {}
void set_reg(short idx, const std::vector<uint8_t>& value) override {}
void get_reg(short idx, std::vector<uint8_t> &value) override {}
void set_reg(short idx, const std::vector<uint8_t> &value) override {}
/// deprecated
bool get_flag(int flag) override {return false;}
void set_flag(int, bool value) override {};
bool get_flag(int flag) override { return false; }
void set_flag(int, bool value) override{};
/// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{};
inline
uint64_t get_icount() { return reg.icount;}
inline uint64_t get_icount() { return reg.icount; }
inline
bool should_stop() { return interrupt_sim;}
inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv32imac>::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<rv32imac>::addr_mask);
inline phys_addr_t v2p(const iss::addr_t &addr) {
if (addr.space != traits<rv32imac>::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<rv32imac>::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; }
inline
uint32_t get_last_branch(){return reg.last_branch;}
inline uint32_t get_last_branch() { return reg.last_branch; }
protected:
struct RV32IMAC_regs {
@@ -207,14 +210,12 @@ protected:
} reg;
std::array<address_type, 4> addr_mode;
bool interrupt_sim=false;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
bool interrupt_sim = false;
uint32_t get_fcsr() { return 0; }
void set_fcsr(uint32_t val) {}
};
}
}
}
#endif /* _RV32IMAC_H_ */

View File

@@ -144,9 +144,9 @@ struct rv64ia: public arch_if {
/// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
uint64_t get_icount() { return reg.icount;}
inline uint64_t get_icount() { return reg.icount; }
bool should_stop(){return false;}
inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv64ia>::MEM ||
@@ -206,6 +206,7 @@ protected:
std::array<address_type, 4> addr_mode;
bool interrupt_sim=false;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}

View File

@@ -1,9 +1,34 @@
/*
* riscv_target_adapter.h
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Created on: 26.09.2017
* Author: eyck
*/
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#ifndef _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_
#define _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_
@@ -13,9 +38,9 @@
#include <iss/debugger/target_adapter_base.h>
#include <iss/iss.h>
#include <array>
#include <memory>
#include <util/logging.h>
#include <array>
namespace iss {
namespace debugger {
@@ -95,9 +120,10 @@ public:
status remove_break(int type, uint64_t addr, unsigned int length) override;
status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, std::function<void(unsigned)> stop_callback) override;
status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
std::function<void(unsigned)> stop_callback) override;
status target_xml_query(std::string& out_buf) override;
status target_xml_query(std::string &out_buf) override;
protected:
static inline constexpr addr_t map_addr(const addr_t &i) { return i; }
@@ -160,11 +186,11 @@ status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, st
data.push_back(*(reg_base + offset + j));
avail.push_back(0xff);
}
// if(arch::traits<ARCH>::XLEN < 64)
// for(unsigned j=0; j<4; ++j){
// data.push_back(0);
// avail.push_back(0xff);
// }
// if(arch::traits<ARCH>::XLEN < 64)
// for(unsigned j=0; j<4; ++j){
// data.push_back(0);
// avail.push_back(0xff);
// }
}
// work around fill with F type registers
if (arch::traits<ARCH>::NUM_REGS < 65) {
@@ -174,11 +200,11 @@ status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, st
data.push_back(0x0);
avail.push_back(0x00);
}
// if(arch::traits<ARCH>::XLEN < 64)
// for(unsigned j=0; j<4; ++j){
// data.push_back(0x0);
// avail.push_back(0x00);
// }
// if(arch::traits<ARCH>::XLEN < 64)
// for(unsigned j=0; j<4; ++j){
// data.push_back(0x0);
// avail.push_back(0x00);
// }
}
}
return Ok;
@@ -280,10 +306,10 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int
template <typename ARCH>
status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) {
std::array<char, 20> buf;
memset(buf.data(), 0, 20);
sprintf(buf.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
out_buf = buf.data();
std::array<char, 20> buf;
memset(buf.data(), 0, 20);
sprintf(buf.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
out_buf = buf.data();
return Ok;
}
@@ -317,56 +343,56 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(int typ
return Err;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
std::function<void(unsigned)> stop_callback) {
auto* reg_base = core->get_regs_base_ptr();
template <typename ARCH>
status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
std::function<void(unsigned)> stop_callback) {
auto *reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_width(arch::traits<ARCH>::PC) / 8;
auto offset = traits<ARCH>::reg_byte_offset(arch::traits<ARCH>::PC);
const uint8_t* iter = reinterpret_cast<const uint8_t*>(&addr);
const uint8_t *iter = reinterpret_cast<const uint8_t *>(&addr);
std::copy(iter, iter + reg_width, reg_base);
return resume_from_current(step, sig, thread, stop_callback);
}
template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std::string& out_buf) {
const std::string res{
"<?xml version=\"1.0\"?><!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
"<target><architecture>riscv:rv32</architecture>"
//" <feature name=\"org.gnu.gdb.riscv.rv32i\">\n"
//" <reg name=\"x0\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x1\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x2\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x3\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x4\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x5\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x6\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x7\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x8\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x9\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x10\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x11\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x12\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x13\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x14\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x15\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x16\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x17\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x18\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x19\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x20\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x21\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x22\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x23\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x24\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x25\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x26\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x27\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x28\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x29\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x30\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x31\" bitsize=\"32\" group=\"general\"/>\n"
//" </feature>\n"
"</target>"};
out_buf=res;
template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std::string &out_buf) {
const std::string res{"<?xml version=\"1.0\"?><!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
"<target><architecture>riscv:rv32</architecture>"
//" <feature name=\"org.gnu.gdb.riscv.rv32i\">\n"
//" <reg name=\"x0\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x1\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x2\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x3\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x4\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x5\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x6\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x7\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x8\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x9\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x10\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x11\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x12\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x13\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x14\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x15\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x16\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x17\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x18\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x19\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x20\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x21\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x22\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x23\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x24\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x25\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x26\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x27\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x28\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x29\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x30\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x31\" bitsize=\"32\" group=\"general\"/>\n"
//" </feature>\n"
"</target>"};
out_buf = res;
return Ok;
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017, MINRES Technologies GmbH
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,8 +35,8 @@
#ifndef _ISS_PLUGIN_CYCLE_ESTIMATE_H_
#define _ISS_PLUGIN_CYCLE_ESTIMATE_H_
#include "iss/vm_plugin.h"
#include "iss/instrumentation_if.h"
#include "iss/vm_plugin.h"
#include <json/json.h>
#include <string>
#include <unordered_map>
@@ -58,38 +58,38 @@ class cycle_estimate: public iss::vm_plugin {
END_BF_DECL();
public:
cycle_estimate() = delete;
cycle_estimate() = delete;
cycle_estimate(const cycle_estimate& ) = delete;
cycle_estimate(const cycle_estimate &) = delete;
cycle_estimate(const cycle_estimate&&) = delete;
cycle_estimate(const cycle_estimate &&) = delete;
cycle_estimate(std::string config_file_name);
cycle_estimate(std::string config_file_name);
virtual ~cycle_estimate();
virtual ~cycle_estimate();
cycle_estimate& operator=(const cycle_estimate& ) = delete;
cycle_estimate &operator=(const cycle_estimate &) = delete;
cycle_estimate& operator=(const cycle_estimate&& ) = delete;
cycle_estimate &operator=(const cycle_estimate &&) = delete;
bool registration(const char* const version, vm_if& arch) override;
bool registration(const char *const version, vm_if &arch) override;
sync_type get_sync() override {return POST_SYNC;};
sync_type get_sync() override { return POST_SYNC; };
void callback(instr_info_t instr_info) override;
void callback(instr_info_t instr_info) override;
private:
iss::instrumentation_if* arch_instr;
iss::instrumentation_if *arch_instr;
std::vector<instr_desc> delays;
struct pair_hash {
size_t operator()(const std::pair<uint64_t, uint64_t>& p) const{
std::hash<uint64_t> hash;
return hash(p.first)+hash(p.second);
}
size_t operator()(const std::pair<uint64_t, uint64_t> &p) const {
std::hash<uint64_t> hash;
return hash(p.first) + hash(p.second);
}
};
std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t, pair_hash> blocks;
Json::Value root;
};
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017, MINRES Technologies GmbH
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,39 +42,40 @@
namespace iss {
namespace plugin {
class instruction_count: public iss::vm_plugin {
struct instr_delay {
std::string instr_name;
size_t size;
size_t not_taken_delay;
size_t taken_delay;
};
class instruction_count : public iss::vm_plugin {
struct instr_delay {
std::string instr_name;
size_t size;
size_t not_taken_delay;
size_t taken_delay;
};
public:
instruction_count() = delete;
instruction_count() = delete;
instruction_count(const instruction_count& ) = delete;
instruction_count(const instruction_count &) = delete;
instruction_count(const instruction_count&&) = delete;
instruction_count(const instruction_count &&) = delete;
instruction_count(std::string config_file_name);
instruction_count(std::string config_file_name);
virtual ~instruction_count();
virtual ~instruction_count();
instruction_count& operator=(const instruction_count& ) = delete;
instruction_count &operator=(const instruction_count &) = delete;
instruction_count& operator=(const instruction_count&& ) = delete;
instruction_count &operator=(const instruction_count &&) = delete;
bool registration(const char* const version, vm_if& arch) override;
bool registration(const char *const version, vm_if &arch) override;
sync_type get_sync() override {return POST_SYNC;};
sync_type get_sync() override { return POST_SYNC; };
void callback(instr_info_t instr_info) override;
void callback(instr_info_t instr_info) override;
private:
Json::Value root;
std::vector<instr_delay> delays;
std::vector<uint64_t> rep_counts;
};
}
}

View File

@@ -1,14 +1,16 @@
# library files
FILE(GLOB RiscVHeaders *.h)
FILE(GLOB IssSources iss/*.cpp internal/*.cpp)
set(LIB_HEADERS ${RiscVHeaders} )
set(LIB_SOURCES
${IssSources}
FILE(GLOB RiscVSCHeaders ${PROJECT_SOURCE_DIR}/incl/sysc/*.h ${PROJECT_SOURCE_DIR}/incl/sysc/*/*.h)
set(LIB_HEADERS ${RiscVSCHeaders} )
set(LIB_SOURCES
iss/rv32gc.cpp
iss/rv32imac.cpp
iss/rv64ia.cpp
internal/fp_functions.cpp
internal/vm_rv32gc.cpp
internal/vm_rv32imac.cpp
internal/vm_rv64ia.cpp
plugin/instruction_count.cpp
plugin/cycle_estimate.cpp
)
plugin/cycle_estimate.cpp)
set(APP_HEADERS )
@@ -18,7 +20,6 @@ set(APP_SOURCES main.cpp)
set(LIBRARY_NAME riscv)
# Define the library
#add_library(${LIBRARY_NAME} SHARED ${LIB_SOURCES})
add_library(${LIBRARY_NAME} ${LIB_SOURCES})
SET(${LIBRARY_NAME} -Wl,-whole-archive -l${LIBRARY_NAME} -Wl,-no-whole-archive)
set_target_properties(${LIBRARY_NAME} PROPERTIES

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,34 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Created on: Tue Aug 29 16:45:20 CEST 2017
// * rv32imac.cpp Author: <CoreDSL Generator>
//
////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include "util/ities.h"
#include <util/logging.h>
@@ -52,9 +49,15 @@ extern "C" {
using namespace iss::arch;
rv32imac::rv32imac() { reg.icount = 0; reg.machine_state = 0x3;}
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::rv32imac>::RV32IMAC_reg_size;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::rv32imac>::RV32IMAC_reg_byte_offset;
rv32imac::~rv32imac(){}
rv32imac::rv32imac() {
reg.icount = 0;
reg.machine_state = 0x3;
}
rv32imac::~rv32imac() = default;
void rv32imac::reset(uint64_t address) {
for (size_t i = 0; i < traits<rv32imac>::NUM_REGS; ++i)

View File

@@ -1,36 +1,34 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Contributors:
// eyck@minres.com - initial implementation
////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include <iostream>
#include <iss/iss.h>
@@ -43,8 +41,8 @@
#include <iss/arch/rv64ia.h>
#include <iss/jit/jit_helper.h>
#include <iss/log_categories.h>
#include <iss/plugin/instruction_count.h>
#include <iss/plugin/cycle_estimate.h>
#include <iss/plugin/instruction_count.h>
namespace po = boost::program_options;
@@ -98,8 +96,8 @@ int main(int argc, char *argv[]) {
LOG_OUTPUT(connection)::stream() = f;
}
std::vector<iss::vm_plugin*> plugin_list;
auto res=0;
std::vector<iss::vm_plugin *> plugin_list;
auto res = 0;
try {
// application code comes here //
iss::init_jit(argc, argv);
@@ -125,24 +123,24 @@ int main(int argc, char *argv[]) {
return 127;
}
if (clim.count("plugin")) {
for (std::string opt_val : clim["plugin"].as<std::vector<std::string>>()){
auto plugin_name{opt_val};
std::string filename{"cycles.txt"};
std::size_t found = opt_val.find('=');
if (found!=std::string::npos){
plugin_name=opt_val.substr(0, found);
filename=opt_val.substr(found+1, opt_val.size());
}
if(plugin_name=="ic"){
auto* ic_plugin= new iss::plugin::instruction_count(filename);
for (std::string opt_val : clim["plugin"].as<std::vector<std::string>>()) {
std::string plugin_name{opt_val};
std::string filename{"cycles.txt"};
std::size_t found = opt_val.find('=');
if (found != std::string::npos) {
plugin_name = opt_val.substr(0, found);
filename = opt_val.substr(found + 1, opt_val.size());
}
if (plugin_name == "ic") {
auto *ic_plugin = new iss::plugin::instruction_count(filename);
vm->register_plugin(*ic_plugin);
plugin_list.push_back(ic_plugin);
} else if(plugin_name=="ce"){
auto* ce_plugin= new iss::plugin::cycle_estimate(filename);
} else if (plugin_name == "ce") {
auto *ce_plugin = new iss::plugin::cycle_estimate(filename);
vm->register_plugin(*ce_plugin);
plugin_list.push_back(ce_plugin);
} else {
LOG(ERROR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'"<<std::endl;
LOG(ERROR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl;
return 127;
}
}
@@ -157,33 +155,32 @@ int main(int argc, char *argv[]) {
LOGGER(disass)::print_severity() = false;
}
}
uint64_t start_address=0;
uint64_t start_address = 0;
if (clim.count("mem"))
vm->get_arch()->load_file(clim["mem"].as<std::string>(), iss::arch::traits<iss::arch::rv32imac>::MEM);
vm->get_arch()->load_file(clim["mem"].as<std::string>(), iss::arch::traits<iss::arch::rv32imac>::MEM);
if (clim.count("elf"))
for (std::string input : clim["elf"].as<std::vector<std::string>>()){
auto start_addr = vm->get_arch()->load_file(input);
if(start_addr.second)
start_address=start_addr.first;
for (std::string input : clim["elf"].as<std::vector<std::string>>()) {
auto start_addr = vm->get_arch()->load_file(input);
if (start_addr.second) start_address = start_addr.first;
}
for (std::string input : args){
auto start_addr = vm->get_arch()->load_file(input);// treat remaining arguments as elf files
if(start_addr.second)
start_address=start_addr.first;
for (std::string input : args) {
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
if (start_addr.second) start_address = start_addr.first;
}
if (clim.count("reset")) {
auto str = clim["reset"].as<std::string>();
start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), 0, 16) : std::stoull(str, 0, 10);
start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10);
}
vm->reset(start_address);
vm->reset(start_address);
auto cycles = clim["instructions"].as<uint64_t>();
res = vm->start(cycles, dump);
} catch (std::exception &e) {
LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl;
res=2;
LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit"
<< std::endl;
res = 2;
}
// cleanup to let plugins report of needed
for(auto* p:plugin_list){
for (auto *p : plugin_list) {
delete p;
}
return res;