Cleanup of templates

This commit is contained in:
Eyck Jentzsch 2018-11-19 10:45:50 +01:00
parent dd7b0f380a
commit a576fdf8e5
6 changed files with 173 additions and 165 deletions

View File

@ -1,8 +1,6 @@
InsructionSet RV32IBase { InsructionSet RV32IBase {
constants { constants {
XLEN, XLEN,
PCLEN,
XLEN_BIT_MASK:=0x1f,
fence:=0, fence:=0,
fencei:=1, fencei:=1,
fencevmal:=2, fencevmal:=2,
@ -16,7 +14,7 @@ InsructionSet RV32IBase {
registers { registers {
[31:0] X[XLEN], [31:0] X[XLEN],
PC[XLEN](is_pc), PC[XLEN](is_pc),
alias ZERO[XLEN] is X[0] alias ZERO[XLEN] is X[0]
} }
instructions { instructions {
@ -197,7 +195,7 @@ InsructionSet RV32IBase {
SLL { SLL {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&XLEN_BIT_MASK); if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&(XLEN-1));
} }
SLT { SLT {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011;
@ -217,12 +215,12 @@ InsructionSet RV32IBase {
SRL { SRL {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&XLEN_BIT_MASK); if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&(XLEN-1));
} }
SRA { SRA {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&XLEN_BIT_MASK); if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&(XLEN-1));
} }
OR { OR {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011;
@ -279,8 +277,8 @@ InsructionSet RV32IBase {
val csr_val[XLEN] <= CSR[csr]; val csr_val[XLEN] <= CSR[csr];
CSR[csr] <= rs_val; CSR[csr] <= rs_val;
// make sure Xrd is updated once CSR write succeeds // make sure Xrd is updated once CSR write succeeds
X[rd] <= csr_val; X[rd] <= csr_val;
} else { } else {
CSR[csr] <= rs_val; CSR[csr] <= rs_val;
} }
} }

View File

@ -9,7 +9,6 @@ import "RV64IBase.core_desc"
import "RV64A.core_desc" import "RV64A.core_desc"
Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC { Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC {
template:"vm_riscv.in.cpp";
constants { constants {
XLEN:=32; XLEN:=32;
PCLEN:=32; PCLEN:=32;
@ -36,7 +35,6 @@ Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D, RV32
Core RV64IA provides RV64IBase, RV64A, RV32A { Core RV64IA provides RV64IBase, RV64A, RV32A {
template:"vm_riscv.in.cpp";
constants { constants {
XLEN:=64; XLEN:=64;
PCLEN:=64; PCLEN:=64;

View File

@ -1,34 +1,35 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017, MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 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 * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
//////////////////////////////////////////////////////////////////////////////// *******************************************************************************/
<% <%
import com.minres.coredsl.coreDsl.Register import com.minres.coredsl.coreDsl.Register
import com.minres.coredsl.coreDsl.RegisterFile import com.minres.coredsl.coreDsl.RegisterFile
@ -39,18 +40,17 @@ def getTypeSize(size){
#ifndef _${coreDef.name.toUpperCase()}_H_ #ifndef _${coreDef.name.toUpperCase()}_H_
#define _${coreDef.name.toUpperCase()}_H_ #define _${coreDef.name.toUpperCase()}_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/vm_if.h> #include <iss/vm_if.h>
#include <iss/arch/traits.h>
#include <array>
namespace iss { namespace iss {
namespace arch { namespace arch {
struct ${coreDef.name.toLowerCase()}; struct ${coreDef.name.toLowerCase()};
template<> template <> struct traits<${coreDef.name.toLowerCase()}> {
struct traits<${coreDef.name.toLowerCase()}> {
constexpr static char const* const core_type = "${coreDef.name}"; constexpr static char const* const core_type = "${coreDef.name}";
@ -87,21 +87,21 @@ 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>;
constexpr static unsigned reg_bit_width(unsigned r) { static constexpr std::array<const uint32_t, ${regSizes.size}> ${coreDef.name}_reg_size{
constexpr std::array<const uint32_t, ${regSizes.size}> ${coreDef.name}_reg_size{{${regSizes.join(",")}}}; {${regSizes.join(",")}}};
return ${coreDef.name}_reg_size[r];
}
constexpr static unsigned reg_byte_offset(unsigned r) { static constexpr unsigned reg_bit_width(unsigned r) { return ${coreDef.name}_reg_size[r]; }
constexpr std::array<const uint32_t, ${regOffsets.size}> ${coreDef.name}_reg_byte_offset{{${regOffsets.join(",")}}};
return ${coreDef.name}_reg_byte_offset[r]; static constexpr std::array<const uint32_t, ${regOffsets.size}> ${coreDef.name}_reg_byte_offset{
} {${regOffsets.join(",")}}};
constexpr static unsigned reg_byte_offset(unsigned r) { return ${coreDef.name}_reg_byte_offset[r]; }
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);
enum sreg_flag_e {FLAGS}; enum sreg_flag_e { FLAGS };
enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}}; enum mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} };
}; };
struct ${coreDef.name.toLowerCase()}: public arch_if { struct ${coreDef.name.toLowerCase()}: public arch_if {
@ -126,12 +126,13 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
/// deprecated /// 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 {};
uint64_t get_icount() { return reg.icount;} inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){ inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || if (addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr.type == iss::address_type::PHYSICAL || addr_mode[static_cast<uint16_t>(addr.access)&0x3]==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<${coreDef.name.toLowerCase()}>::addr_mask); return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask);
} else } else
return virt2phys(addr); return virt2phys(addr);
@ -141,8 +142,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline inline uint32_t get_last_branch() { return reg.last_branch; }
uint32_t get_last_branch(){return reg.last_branch;}
protected: protected:
struct ${coreDef.name}_regs {<% struct ${coreDef.name}_regs {<%

View File

@ -1,34 +1,34 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017,2018 MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 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 * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
//////////////////////////////////////////////////////////////////////////////// *******************************************************************************/
#include "util/ities.h" #include "util/ities.h"
#include <util/logging.h> #include <util/logging.h>
@ -43,30 +43,33 @@ extern "C" {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#include <fstream>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <fstream>
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::${coreDef.name}_reg_size;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::${coreDef.name}_reg_byte_offset;
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { ${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() {
reg.icount=0; reg.icount = 0;
reg.machine_state = 0x3;
} }
${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}(){ ${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default;
} }
void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { void ${coreDef.name.toLowerCase()}::reset(uint64_t address) {
for(size_t i=0; i<traits<${coreDef.name.toLowerCase()}>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); for(size_t i=0; i<traits<${coreDef.name.toLowerCase()}>::NUM_REGS; ++i)
set_reg(i, std::vector<uint8_t>(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0));
reg.PC=address; reg.PC=address;
reg.NEXT_PC=reg.PC; reg.NEXT_PC=reg.PC;
reg.trap_state=0; reg.trap_state=0;
reg.machine_state=0x0; reg.machine_state=0x3;
} }
uint8_t* ${coreDef.name.toLowerCase()}::get_regs_base_ptr(){ uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { return reinterpret_cast<uint8_t*>(&reg); }
return reinterpret_cast<uint8_t*>(&reg);
}
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) { ${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address return phys_addr_t(pc); // change logical address to physical address

View File

@ -1,38 +1,34 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017, MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 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 * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
// Contributors: *******************************************************************************/
// eyck@minres.com - initial API and implementation
//
//
////////////////////////////////////////////////////////////////////////////////
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/arch/riscv_hart_msu_vp.h> #include <iss/arch/riscv_hart_msu_vp.h>
@ -44,12 +40,12 @@
#include <boost/format.hpp> #include <boost/format.hpp>
#include <iss/debugger/riscv_target_adapter.h>
#include <array> #include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss { namespace iss {
namespace vm { namespace vm {
namespace fp_impl{ namespace fp_impl {
void add_fp_functions_2_module(llvm::Module *, unsigned); void add_fp_functions_2_module(llvm::Module *, unsigned);
} }
} }
@ -73,7 +69,7 @@ public:
void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; }
target_adapter_if *accquire_target_adapter(server_if *srv) { target_adapter_if *accquire_target_adapter(server_if *srv) override {
debugger_if::dbg_enabled = true; debugger_if::dbg_enabled = true;
if (vm::vm_base<ARCH>::tgt_adapter == nullptr) if (vm::vm_base<ARCH>::tgt_adapter == nullptr)
vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch()); vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
@ -87,7 +83,7 @@ protected:
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
} }
void setup_module(llvm::Module* m) override { void setup_module(llvm::Module *m) override {
super::setup_module(m); super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE); vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE);
} }
@ -117,7 +113,7 @@ protected:
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { 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), 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); this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
} }
@ -136,9 +132,9 @@ protected:
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10; 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, 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[], void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
compile_func f) { compile_func f) {
@ -248,7 +244,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK; const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
try { try {
uint8_t *const data = (uint8_t *)&insn; auto *const data = (uint8_t *)&insn;
paddr = this->core.v2p(pc); paddr = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
auto res = this->core.read(paddr, 2, data); auto res = this->core.read(paddr, 2, data);
@ -282,7 +278,8 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) { template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true); this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) { template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
@ -292,7 +289,8 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8); auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false); this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) { template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
@ -305,11 +303,10 @@ template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) { template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) {
this->builder.SetInsertPoint(trap_blk); this->builder.SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true); auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
std::vector<llvm::Value *> args{ get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
this->core_ptr, std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->adj_to64(trap_state_val), this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false); auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateRet(trap_addr_val); this->builder.CreateRet(trap_addr_val);
@ -327,10 +324,9 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBl
template <> template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
std::unique_ptr<${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>> ret = auto ret = new ${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*core, dump);
std::make_unique<${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>>(*core, dump); if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret.get(), port); return std::unique_ptr<vm_if>(ret);
return ret;
} }
} // namespace iss } // namespace iss

View File

@ -44,6 +44,12 @@
#include <iss/debugger/riscv_target_adapter.h> #include <iss/debugger/riscv_target_adapter.h>
namespace iss { namespace iss {
namespace vm {
namespace fp_impl {
void add_fp_functions_2_module(llvm::Module *, unsigned);
}
}
namespace CORE_DEF_NAME { namespace CORE_DEF_NAME {
using namespace iss::arch; using namespace iss::arch;
using namespace llvm; using namespace llvm;
@ -63,7 +69,7 @@ public:
void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; }
target_adapter_if *accquire_target_adapter(server_if *srv) { target_adapter_if *accquire_target_adapter(server_if *srv) override {
debugger_if::dbg_enabled = true; debugger_if::dbg_enabled = true;
if (vm::vm_base<ARCH>::tgt_adapter == nullptr) if (vm::vm_base<ARCH>::tgt_adapter == nullptr)
vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch()); vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
@ -77,8 +83,12 @@ protected:
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
} }
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, void setup_module(llvm::Module *m) override {
unsigned size) const { super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE);
}
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) {
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
} }
@ -225,7 +235,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK; const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
try { try {
uint8_t *const data = (uint8_t *)&insn; auto *const data = (uint8_t *)&insn;
paddr = this->core.v2p(pc); paddr = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
auto res = this->core.read(paddr, 2, data); auto res = this->core.read(paddr, 2, data);
@ -242,7 +252,6 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
} }
if (insn == 0x0000006f || (insn & 0xffff) == 0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' if (insn == 0x0000006f || (insn & 0xffff) == 0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack // curr pc on stack
typename vm_impl<ARCH>::processing_pc_entry addr(*this, pc, paddr);
++inst_cnt; ++inst_cnt;
auto lut_val = extract_fields(insn); auto lut_val = extract_fields(insn);
auto f = qlut[insn & 0x3][lut_val]; auto f = qlut[insn & 0x3][lut_val];
@ -260,6 +269,8 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) { template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true); this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) { template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
@ -269,6 +280,8 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8); auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false); this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) { template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
@ -281,6 +294,8 @@ template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) { template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) {
this->builder.SetInsertPoint(trap_blk); this->builder.SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true); auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val), std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))}; this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
@ -298,12 +313,10 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBl
} // namespace CORE_DEF_NAME } // namespace CORE_DEF_NAME
template <> template <> std::unique_ptr<vm_if> create<arch::CORE_DEF_NAME>(arch::CORE_DEF_NAME *core, unsigned short port, bool dump) {
std::unique_ptr<vm_if> create<arch::CORE_DEF_NAME>(arch::CORE_DEF_NAME *core, unsigned short port, bool dump) { auto ret = new CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>(*core, dump);
std::unique_ptr<CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>> ret = if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
std::make_unique<CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>>(*core, dump); return std::unique_ptr<vm_if>(ret);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret.get(), port);
return ret;
} }
} // namespace iss } // namespace iss