fixes duplicate variable declaration and templates
This commit is contained in:
parent
ee6218279e
commit
a123beb301
|
@ -1,13 +1,13 @@
|
||||||
import "RV32I.core_desc"
|
import "ISA/RV32I.core_desc"
|
||||||
import "RVM.core_desc"
|
import "ISA/RVM.core_desc"
|
||||||
import "RVC.core_desc"
|
import "ISA/RVC.core_desc"
|
||||||
|
|
||||||
Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
|
Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
|
||||||
architectural_state {
|
architectural_state {
|
||||||
XLEN=32;
|
XLEN=32;
|
||||||
// definitions for the architecture wrapper
|
// definitions for the architecture wrapper
|
||||||
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
|
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
|
||||||
unsigned MISA_VAL = 0b01000000000000000001000100000100;
|
unsigned int MISA_VAL = 0b01000000000000000001000100000100;
|
||||||
unsigned MARCHID_VAL = 0x80000003;
|
unsigned int MARCHID_VAL = 0x80000003;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,8 +62,8 @@ void ${coreDef.name.toLowerCase()}::reset(uint64_t address) {
|
||||||
reg.PC=address;
|
reg.PC=address;
|
||||||
reg.NEXT_PC=reg.PC;
|
reg.NEXT_PC=reg.PC;
|
||||||
reg.PRIV=0x3;
|
reg.PRIV=0x3;
|
||||||
trap_state=0;
|
reg.trap_state=0;
|
||||||
icount=0;
|
reg.icount=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
|
uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
|
||||||
|
|
|
@ -136,7 +136,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
||||||
|
|
||||||
uint8_t* get_regs_base_ptr() override;
|
uint8_t* get_regs_base_ptr() override;
|
||||||
|
|
||||||
inline uint64_t get_icount() { return icount; }
|
inline uint64_t get_icount() { return reg.icount; }
|
||||||
|
|
||||||
inline bool should_stop() { return interrupt_sim; }
|
inline bool should_stop() { return interrupt_sim; }
|
||||||
|
|
||||||
|
@ -154,7 +154,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 uint32_t get_last_branch() { return last_branch; }
|
inline uint32_t get_last_branch() { return reg.last_branch; }
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
@ -170,12 +170,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
||||||
uint32_t last_branch = 0;
|
uint32_t last_branch = 0;
|
||||||
} reg;
|
} reg;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
uint32_t trap_state = 0, pending_trap = 0;
|
|
||||||
uint64_t icount = 0;
|
|
||||||
uint64_t cycle = 0;
|
|
||||||
uint64_t instret = 0;
|
|
||||||
uint32_t instruction = 0;
|
|
||||||
uint32_t last_branch = 0;
|
|
||||||
std::array<address_type, 4> addr_mode;
|
std::array<address_type, 4> addr_mode;
|
||||||
|
|
||||||
uint64_t interrupt_sim=0;
|
uint64_t interrupt_sim=0;
|
||||||
|
|
|
@ -13,5 +13,8 @@ ${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %>
|
||||||
- ${it.instruction.name}:
|
- ${it.instruction.name}:
|
||||||
encoding: ${it.encoding}
|
encoding: ${it.encoding}
|
||||||
mask: ${it.mask}<%if(it.attributes.size) {%>
|
mask: ${it.mask}<%if(it.attributes.size) {%>
|
||||||
attributes: ${it.attributes}<%}}}%>
|
attributes: ${it.attributes}<%}%>
|
||||||
|
size: ${it.length}
|
||||||
|
branch: ${it.modifiesPC}
|
||||||
|
delay: ${it.isConditional?"[1,1]":"1"}<%}}%>
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ protected:
|
||||||
|
|
||||||
inline void raise(uint16_t trap_id, uint16_t cause){
|
inline void raise(uint16_t trap_id, uint16_t cause){
|
||||||
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
||||||
this->core.trap_state = trap_val;
|
this->core.reg.trap_state = trap_val;
|
||||||
this->template get_reg<uint${addrDataWidth}_t>(traits::NEXT_PC) = std::numeric_limits<uint${addrDataWidth}_t>::max();
|
this->template get_reg<uint${addrDataWidth}_t>(traits::NEXT_PC) = std::numeric_limits<uint${addrDataWidth}_t>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,16 +244,16 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
auto pc=start;
|
auto pc=start;
|
||||||
auto* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
|
auto* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
|
||||||
auto* NEXT_PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]);
|
auto* NEXT_PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]);
|
||||||
auto& trap_state = this->core.trap_state;
|
auto& trap_state = this->core.reg.trap_state;
|
||||||
auto& icount = this->core.icount;
|
auto& icount = this->core.reg.icount;
|
||||||
auto& cycle = this->core.cycle;
|
auto& cycle = this->core.reg.cycle;
|
||||||
auto& instret = this->core.instret;
|
auto& instret = this->core.reg.instret;
|
||||||
auto& instr = this->core.instruction;
|
auto& instr = this->core.reg.instruction;
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
auto *const data = reinterpret_cast<uint8_t*>(&instr);
|
auto *const data = reinterpret_cast<uint8_t*>(&instr);
|
||||||
|
|
||||||
while(!this->core.should_stop() &&
|
while(!this->core.should_stop() &&
|
||||||
!(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){
|
!(is_count_limit_enabled(cond) && icount >= icount_limit)){
|
||||||
if(fetch_ins(pc, data)!=iss::Ok){
|
if(fetch_ins(pc, data)!=iss::Ok){
|
||||||
this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
|
this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
|
||||||
pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0);
|
pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0);
|
||||||
|
@ -262,7 +262,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
auto inst_id = decode_inst_id(instr);
|
auto inst_id = decode_inst_id(instr);
|
||||||
// pre execution stuff
|
// pre execution stuff
|
||||||
this->core.last_branch = 0;
|
this->core.reg.last_branch = 0;
|
||||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
||||||
switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %>
|
switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
case arch::traits<ARCH>::opcode_e::${instr.name}: {
|
case arch::traits<ARCH>::opcode_e::${instr.name}: {
|
||||||
|
@ -289,8 +289,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
// post execution stuff
|
// post execution stuff
|
||||||
process_spawn_blocks();
|
process_spawn_blocks();
|
||||||
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id));
|
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id));
|
||||||
// if(!this->core.trap_state) // update trap state if there is a pending interrupt
|
// if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt
|
||||||
// this->core.trap_state = this->core.pending_trap;
|
// this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||||
// trap check
|
// trap check
|
||||||
if(trap_state!=0){
|
if(trap_state!=0){
|
||||||
super::core.enter_trap(trap_state, pc.val, instr);
|
super::core.enter_trap(trap_state, pc.val, instr);
|
||||||
|
@ -301,7 +301,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
cycle++;
|
cycle++;
|
||||||
pc.val=*NEXT_PC;
|
pc.val=*NEXT_PC;
|
||||||
this->core.reg.PC = this->core.reg.NEXT_PC;
|
this->core.reg.PC = this->core.reg.NEXT_PC;
|
||||||
this->core.trap_state = this->core.pending_trap;
|
this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pc;
|
return pc;
|
||||||
|
|
|
@ -256,20 +256,20 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t insn = 0;
|
code_word_t insn = 0;
|
||||||
const typename traits::addr_t upper_bits = ~traits::PGMASK;
|
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
|
||||||
phys_addr_t paddr(pc);
|
phys_addr_t paddr(pc);
|
||||||
auto *const data = (uint8_t *)&insn;
|
auto *const data = (uint8_t *)&insn;
|
||||||
paddr = this->core.v2p(pc);
|
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);
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||||
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
||||||
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto res = this->core.read(paddr, 4, data);
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||||
}
|
// }
|
||||||
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
// curr pc on stack
|
// curr pc on stack
|
||||||
++inst_cnt;
|
++inst_cnt;
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","}
|
|
||||||
{
|
|
||||||
"name" : "${instr.name}",
|
|
||||||
"size" : ${instr.length},
|
|
||||||
"delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1}
|
|
||||||
}<%}%>
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,223 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
<%
|
|
||||||
import com.minres.coredsl.coreDsl.Register
|
|
||||||
import com.minres.coredsl.coreDsl.RegisterFile
|
|
||||||
import com.minres.coredsl.coreDsl.RegisterAlias
|
|
||||||
def getTypeSize(size){
|
|
||||||
if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8
|
|
||||||
}
|
|
||||||
def getOriginalName(reg){
|
|
||||||
if( reg.original instanceof RegisterFile) {
|
|
||||||
if( reg.index != null ) {
|
|
||||||
return reg.original.name+generator.generateHostCode(reg.index)
|
|
||||||
} else {
|
|
||||||
return reg.original.name
|
|
||||||
}
|
|
||||||
} else if(reg.original instanceof Register){
|
|
||||||
return reg.original.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def getRegisterNames(){
|
|
||||||
def regNames = []
|
|
||||||
allRegs.each { reg ->
|
|
||||||
if( reg instanceof RegisterFile) {
|
|
||||||
(reg.range.right..reg.range.left).each{
|
|
||||||
regNames+=reg.name.toLowerCase()+it
|
|
||||||
}
|
|
||||||
} else if(reg instanceof Register){
|
|
||||||
regNames+=reg.name.toLowerCase()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return regNames
|
|
||||||
}
|
|
||||||
def getRegisterAliasNames(){
|
|
||||||
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
|
|
||||||
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
|
|
||||||
if( reg instanceof RegisterFile) {
|
|
||||||
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
|
|
||||||
} else if(reg instanceof Register){
|
|
||||||
regMap[reg.name]?:reg.name.toLowerCase()
|
|
||||||
}
|
|
||||||
}.flatten()
|
|
||||||
}
|
|
||||||
%>
|
|
||||||
#ifndef _${coreDef.name.toUpperCase()}_H_
|
|
||||||
#define _${coreDef.name.toUpperCase()}_H_
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <iss/arch/traits.h>
|
|
||||||
#include <iss/arch_if.h>
|
|
||||||
#include <iss/vm_if.h>
|
|
||||||
|
|
||||||
namespace iss {
|
|
||||||
namespace arch {
|
|
||||||
|
|
||||||
struct ${coreDef.name.toLowerCase()};
|
|
||||||
|
|
||||||
template <> struct traits<${coreDef.name.toLowerCase()}> {
|
|
||||||
|
|
||||||
constexpr static char const* const core_type = "${coreDef.name}";
|
|
||||||
|
|
||||||
static constexpr std::array<const char*, ${getRegisterNames().size}> reg_names{
|
|
||||||
{"${getRegisterNames().join("\", \"")}"}};
|
|
||||||
|
|
||||||
static constexpr std::array<const char*, ${getRegisterAliasNames().size}> reg_aliases{
|
|
||||||
{"${getRegisterAliasNames().join("\", \"")}"}};
|
|
||||||
|
|
||||||
enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}};
|
|
||||||
|
|
||||||
constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0};
|
|
||||||
|
|
||||||
enum reg_e {<%
|
|
||||||
allRegs.each { reg ->
|
|
||||||
if( reg instanceof RegisterFile) {
|
|
||||||
(reg.range.right..reg.range.left).each{%>
|
|
||||||
${reg.name}${it},<%
|
|
||||||
}
|
|
||||||
} else if(reg instanceof Register){ %>
|
|
||||||
${reg.name},<%
|
|
||||||
}
|
|
||||||
}%>
|
|
||||||
NUM_REGS,
|
|
||||||
NEXT_${pc.name}=NUM_REGS,
|
|
||||||
TRAP_STATE,
|
|
||||||
PENDING_TRAP,
|
|
||||||
MACHINE_STATE,
|
|
||||||
LAST_BRANCH,
|
|
||||||
ICOUNT<%
|
|
||||||
allRegs.each { reg ->
|
|
||||||
if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>,
|
|
||||||
${reg.name} = ${aliasname}<%
|
|
||||||
}
|
|
||||||
}%>
|
|
||||||
};
|
|
||||||
|
|
||||||
using reg_t = uint${regDataWidth}_t;
|
|
||||||
|
|
||||||
using addr_t = uint${addrDataWidth}_t;
|
|
||||||
|
|
||||||
using code_word_t = uint${addrDataWidth}_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>;
|
|
||||||
|
|
||||||
static constexpr std::array<const uint32_t, ${regSizes.size}> reg_bit_widths{
|
|
||||||
{${regSizes.join(",")}}};
|
|
||||||
|
|
||||||
static constexpr std::array<const uint32_t, ${regOffsets.size}> reg_byte_offsets{
|
|
||||||
{${regOffsets.join(",")}}};
|
|
||||||
|
|
||||||
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
|
|
||||||
|
|
||||||
enum sreg_flag_e { FLAGS };
|
|
||||||
|
|
||||||
enum mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|
||||||
|
|
||||||
using virt_addr_t = typename traits<${coreDef.name.toLowerCase()}>::virt_addr_t;
|
|
||||||
using phys_addr_t = typename traits<${coreDef.name.toLowerCase()}>::phys_addr_t;
|
|
||||||
using reg_t = typename traits<${coreDef.name.toLowerCase()}>::reg_t;
|
|
||||||
using addr_t = typename traits<${coreDef.name.toLowerCase()}>::addr_t;
|
|
||||||
|
|
||||||
${coreDef.name.toLowerCase()}();
|
|
||||||
~${coreDef.name.toLowerCase()}();
|
|
||||||
|
|
||||||
void reset(uint64_t address=0) 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 {}
|
|
||||||
/// deprecated
|
|
||||||
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 {};
|
|
||||||
|
|
||||||
inline uint64_t get_icount() { return reg.icount; }
|
|
||||||
|
|
||||||
inline bool should_stop() { return interrupt_sim; }
|
|
||||||
|
|
||||||
inline uint64_t stop_code() { return interrupt_sim; }
|
|
||||||
|
|
||||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
|
||||||
if (addr.space != traits<${coreDef.name.toLowerCase()}>::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<${coreDef.name.toLowerCase()}>::addr_mask);
|
|
||||||
} else
|
|
||||||
return virt2phys(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; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
struct ${coreDef.name}_regs {<%
|
|
||||||
allRegs.each { reg ->
|
|
||||||
if( reg instanceof RegisterFile) {
|
|
||||||
(reg.range.right..reg.range.left).each{%>
|
|
||||||
uint${generator.getSize(reg)}_t ${reg.name}${it} = 0;<%
|
|
||||||
}
|
|
||||||
} else if(reg instanceof Register){ %>
|
|
||||||
uint${generator.getSize(reg)}_t ${reg.name} = 0;<%
|
|
||||||
}
|
|
||||||
}%>
|
|
||||||
uint${generator.getSize(pc)}_t NEXT_${pc.name} = 0;
|
|
||||||
uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0;
|
|
||||||
uint64_t icount = 0;
|
|
||||||
} reg;
|
|
||||||
|
|
||||||
std::array<address_type, 4> addr_mode;
|
|
||||||
|
|
||||||
uint64_t interrupt_sim=0;
|
|
||||||
<%
|
|
||||||
def fcsr = allRegs.find {it.name=='FCSR'}
|
|
||||||
if(fcsr != null) {%>
|
|
||||||
uint${generator.getSize(fcsr)}_t get_fcsr(){return reg.FCSR;}
|
|
||||||
void set_fcsr(uint${generator.getSize(fcsr)}_t val){reg.FCSR = val;}
|
|
||||||
<%} else { %>
|
|
||||||
uint32_t get_fcsr(){return 0;}
|
|
||||||
void set_fcsr(uint32_t val){}
|
|
||||||
<%}%>
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* _${coreDef.name.toUpperCase()}_H_ */
|
|
|
@ -1,107 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*******************************************************************************/
|
|
||||||
<%
|
|
||||||
import com.minres.coredsl.coreDsl.Register
|
|
||||||
import com.minres.coredsl.coreDsl.RegisterFile
|
|
||||||
import com.minres.coredsl.coreDsl.RegisterAlias
|
|
||||||
def getOriginalName(reg){
|
|
||||||
if( reg.original instanceof RegisterFile) {
|
|
||||||
if( reg.index != null ) {
|
|
||||||
return reg.original.name+generator.generateHostCode(reg.index)
|
|
||||||
} else {
|
|
||||||
return reg.original.name
|
|
||||||
}
|
|
||||||
} else if(reg.original instanceof Register){
|
|
||||||
return reg.original.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def getRegisterNames(){
|
|
||||||
def regNames = []
|
|
||||||
allRegs.each { reg ->
|
|
||||||
if( reg instanceof RegisterFile) {
|
|
||||||
(reg.range.right..reg.range.left).each{
|
|
||||||
regNames+=reg.name.toLowerCase()+it
|
|
||||||
}
|
|
||||||
} else if(reg instanceof Register){
|
|
||||||
regNames+=reg.name.toLowerCase()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return regNames
|
|
||||||
}
|
|
||||||
def getRegisterAliasNames(){
|
|
||||||
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
|
|
||||||
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
|
|
||||||
if( reg instanceof RegisterFile) {
|
|
||||||
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
|
|
||||||
} else if(reg instanceof Register){
|
|
||||||
regMap[reg.name]?:reg.name.toLowerCase()
|
|
||||||
}
|
|
||||||
}.flatten()
|
|
||||||
}
|
|
||||||
%>
|
|
||||||
#include "util/ities.h"
|
|
||||||
#include <util/logging.h>
|
|
||||||
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
using namespace iss::arch;
|
|
||||||
|
|
||||||
constexpr std::array<const char*, ${getRegisterNames().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names;
|
|
||||||
constexpr std::array<const char*, ${getRegisterAliasNames().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases;
|
|
||||||
constexpr std::array<const uint32_t, ${regSizes.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths;
|
|
||||||
constexpr std::array<const uint32_t, ${regOffsets.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets;
|
|
||||||
|
|
||||||
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() {
|
|
||||||
reg.icount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default;
|
|
||||||
|
|
||||||
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));
|
|
||||||
reg.PC=address;
|
|
||||||
reg.NEXT_PC=reg.PC;
|
|
||||||
reg.trap_state=0;
|
|
||||||
reg.machine_state=0x3;
|
|
||||||
reg.icount=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
|
|
||||||
return reinterpret_cast<uint8_t*>(®);
|
|
||||||
}
|
|
||||||
|
|
||||||
${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
|
|
||||||
}
|
|
||||||
|
|
|
@ -280,7 +280,7 @@ public:
|
||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) override {
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]",
|
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]",
|
||||||
pc, instr, (reg_t)state.mstatus, this->icount + cycle_offset);
|
pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||||
|
@ -308,17 +308,17 @@ protected:
|
||||||
|
|
||||||
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; };
|
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; };
|
||||||
|
|
||||||
uint64_t get_instr_word() override { return arch.instruction; }
|
uint64_t get_instr_word() override { return arch.reg.instruction; }
|
||||||
|
|
||||||
uint64_t get_instr_count() override { return arch.icount; }
|
uint64_t get_instr_count() override { return arch.reg.icount; }
|
||||||
|
|
||||||
uint64_t get_pendig_traps() override { return arch.trap_state; }
|
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||||
|
|
||||||
bool is_branch_taken() override { return arch.last_branch; };
|
bool is_branch_taken() override { return arch.reg.last_branch; };
|
||||||
|
|
||||||
riscv_hart_m_p<BASE, FEAT> &arch;
|
riscv_hart_m_p<BASE, FEAT> &arch;
|
||||||
};
|
};
|
||||||
|
@ -657,12 +657,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
||||||
if (unlikely(is_fetch(access) && (addr&(alignment-1)))) {
|
if (unlikely(is_fetch(access) && (addr&(alignment-1)))) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (is_debug(access)) throw trap_access(0, addr);
|
if (is_debug(access)) throw trap_access(0, addr);
|
||||||
this->trap_state = (1UL << 31); // issue trap 0
|
this->reg.trap_state = (1UL << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(!is_debug(access) && (addr&(alignment-1))){
|
if(!is_debug(access) && (addr&(alignment-1))){
|
||||||
this->trap_state = (1UL << 31) | 4<<16;
|
this->reg.trap_state = (1UL << 31) | 4<<16;
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -681,12 +681,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
||||||
res = hart_mem_rd_delegate( phys_addr, length, data);
|
res = hart_mem_rd_delegate( phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if (unlikely(res != iss::Ok)){
|
if (unlikely(res != iss::Ok)){
|
||||||
this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +712,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -750,12 +750,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
||||||
if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->trap_state = (1UL << 31); // issue trap 0
|
this->reg.trap_state = (1UL << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){
|
if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){
|
||||||
this->trap_state = (1UL << 31) | 6<<16;
|
this->reg.trap_state = (1UL << 31) | 6<<16;
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -774,12 +774,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
||||||
res = write_mem( phys_addr, length, data);
|
res = write_mem( phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if (unlikely(res != iss::Ok)) {
|
if (unlikely(res != iss::Ok)) {
|
||||||
this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -839,7 +839,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -885,7 +885,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_cycle(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_cycle(unsigned addr, reg_t &val) {
|
||||||
auto cycle_val = this->icount + cycle_offset;
|
auto cycle_val = this->reg.icount + cycle_offset;
|
||||||
if (addr == mcycle) {
|
if (addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
} else if (addr == mcycleh) {
|
} else if (addr == mcycleh) {
|
||||||
|
@ -904,35 +904,35 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff);
|
mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around
|
cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_instret(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_instret(unsigned addr, reg_t &val) {
|
||||||
if ((addr&0xff) == (minstret&0xff)) {
|
if ((addr&0xff) == (minstret&0xff)) {
|
||||||
val = static_cast<reg_t>(this->instret);
|
val = static_cast<reg_t>(this->reg.instret);
|
||||||
} else if ((addr&0xff) == (minstreth&0xff)) {
|
} else if ((addr&0xff) == (minstreth&0xff)) {
|
||||||
val = static_cast<reg_t>(this->instret >> 32);
|
val = static_cast<reg_t>(this->reg.instret >> 32);
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) {
|
||||||
if (sizeof(typename traits<BASE>::reg_t) != 4) {
|
if (sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||||
this->instret = static_cast<uint64_t>(val);
|
this->reg.instret = static_cast<uint64_t>(val);
|
||||||
} else {
|
} else {
|
||||||
if ((addr&0xff) == (minstret&0xff)) {
|
if ((addr&0xff) == (minstret&0xff)) {
|
||||||
this->instret = (this->instret & 0xffffffff00000000) + val;
|
this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val;
|
||||||
} else {
|
} else {
|
||||||
this->instret = (static_cast<uint64_t>(val)<<32) + (this->instret & 0xffffffff);
|
this->reg.instret = (static_cast<uint64_t>(val)<<32) + (this->reg.instret & 0xffffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->instret--;
|
this->reg.instret--;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) {
|
||||||
uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052;
|
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
if (addr == time) {
|
if (addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if (addr == timeh) {
|
} else if (addr == timeh) {
|
||||||
|
@ -1074,18 +1074,6 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
|
||||||
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);
|
|
||||||
} break;
|
|
||||||
case 0x10008000: {
|
|
||||||
const mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
uint64_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(p.data() + offs, p.data() + offs + length, data);
|
|
||||||
if (this->icount > 30000) data[3] |= 0x80;
|
|
||||||
} break;
|
|
||||||
default: {
|
default: {
|
||||||
for(auto offs=0U; offs<length; ++offs) {
|
for(auto offs=0U; offs<length; ++offs) {
|
||||||
*(data + offs)=mem[(paddr.val+offs)%mem.size()];
|
*(data + offs)=mem[(paddr.val+offs)%mem.size()];
|
||||||
|
@ -1098,29 +1086,13 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned len
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
|
||||||
uart_buf << (char)data[0];
|
|
||||||
if (((char)data[0]) == '\n' || data[0] == 0) {
|
if (((char)data[0]) == '\n' || data[0] == 0) {
|
||||||
LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'";
|
LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'";
|
||||||
std::cout << uart_buf.str();
|
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
}
|
} else if(((char)data[0]) != '\r')
|
||||||
|
uart_buf << (char)data[0];
|
||||||
break;
|
break;
|
||||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
size_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(data, data + length, p.data() + offs);
|
|
||||||
uint8_t &x = *(p.data() + offs + 3);
|
|
||||||
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
|
|
||||||
} break;
|
|
||||||
case 0x10008008: { // HFROSC base, pllcfg reg
|
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
size_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(data, data + length, p.data() + offs);
|
|
||||||
uint8_t &x = *(p.data() + offs + 3);
|
|
||||||
x |= 0x80; // set pll lock upon writing
|
|
||||||
} break;
|
|
||||||
default: {
|
default: {
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
||||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||||
|
@ -1142,7 +1114,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
||||||
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||||
<< "), stopping simulation";
|
<< "), stopping simulation";
|
||||||
}
|
}
|
||||||
this->trap_state=std::numeric_limits<uint32_t>::max();
|
this->reg.trap_state=std::numeric_limits<uint32_t>::max();
|
||||||
this->interrupt_sim=hostvar;
|
this->interrupt_sim=hostvar;
|
||||||
break;
|
break;
|
||||||
//throw(iss::simulation_stopped(hostvar));
|
//throw(iss::simulation_stopped(hostvar));
|
||||||
|
@ -1227,7 +1199,7 @@ template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check
|
||||||
enabled_interrupts >>= 1;
|
enabled_interrupts >>= 1;
|
||||||
res++;
|
res++;
|
||||||
}
|
}
|
||||||
this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
|
this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,7 +1247,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
||||||
fault_data = 0;
|
fault_data = 0;
|
||||||
} else {
|
} else {
|
||||||
csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt
|
csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt
|
||||||
this->pending_trap = 0;
|
this->reg.pending_trap = 0;
|
||||||
}
|
}
|
||||||
csr[mcause] = (trap_id << (traits<BASE>::XLEN-1)) + cause;
|
csr[mcause] = (trap_id << (traits<BASE>::XLEN-1)) + cause;
|
||||||
// update mstatus
|
// update mstatus
|
||||||
|
@ -1305,7 +1277,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
||||||
}
|
}
|
||||||
// reset trap state
|
// reset trap state
|
||||||
this->reg.PRIV = new_priv;
|
this->reg.PRIV = new_priv;
|
||||||
this->trap_state = 0;
|
this->reg.trap_state = 0;
|
||||||
std::array<char, 32> buffer;
|
std::array<char, 32> buffer;
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
sprintf(buffer.data(), "0x%016llx", addr);
|
sprintf(buffer.data(), "0x%016llx", addr);
|
||||||
|
@ -1326,7 +1298,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::l
|
||||||
this->reg.NEXT_PC = csr[mepc] & get_pc_mask();
|
this->reg.NEXT_PC = csr[mepc] & get_pc_mask();
|
||||||
CLOG(INFO, disass) << "Executing xRET";
|
CLOG(INFO, disass) << "Executing xRET";
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
this->trap_state = this->pending_trap;
|
this->reg.trap_state = this->reg.pending_trap;
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -307,7 +307,7 @@ public:
|
||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) override {
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]",
|
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]",
|
||||||
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->icount + cycle_offset);
|
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||||
|
@ -607,12 +607,12 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
||||||
if (unlikely(is_fetch(access) && (addr&(alignment-1)))) {
|
if (unlikely(is_fetch(access) && (addr&(alignment-1)))) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->trap_state = (1 << 31); // issue trap 0
|
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(!is_debug(access) && (addr&(alignment-1))){
|
if(!is_debug(access) && (addr&(alignment-1))){
|
||||||
this->trap_state = 1<<31 | 4<<16;
|
this->reg.trap_state = 1<<31 | 4<<16;
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -631,12 +631,12 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
||||||
read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data):
|
read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data):
|
||||||
read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||||
if (unlikely(res != iss::Ok)){
|
if (unlikely(res != iss::Ok)){
|
||||||
this->trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1 << 31) | ta.id;
|
this->reg.trap_state = (1 << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -652,7 +652,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
||||||
case 3: { // SFENCE:VMA upper
|
case 3: { // SFENCE:VMA upper
|
||||||
auto tvm = state.mstatus.TVM;
|
auto tvm = state.mstatus.TVM;
|
||||||
if (this->reg.PRIV == PRIV_S & tvm != 0) {
|
if (this->reg.PRIV == PRIV_S & tvm != 0) {
|
||||||
this->trap_state = (1 << 31) | (2 << 16);
|
this->reg.trap_state = (1 << 31) | (2 << 16);
|
||||||
this->fault_data = this->reg.PC;
|
this->fault_data = this->reg.PC;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -673,7 +673,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1 << 31) | ta.id;
|
this->reg.trap_state = (1 << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -711,7 +711,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
||||||
if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->trap_state = (1 << 31); // issue trap 0
|
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -730,12 +730,12 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
||||||
write_mem(phys_addr_t{access, space, addr}, length, data):
|
write_mem(phys_addr_t{access, space, addr}, length, data):
|
||||||
write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||||
if (unlikely(res != iss::Ok)) {
|
if (unlikely(res != iss::Ok)) {
|
||||||
this->trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1 << 31) | ta.id;
|
this->reg.trap_state = (1 << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -784,7 +784,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
||||||
ptw.clear();
|
ptw.clear();
|
||||||
auto tvm = state.mstatus.TVM;
|
auto tvm = state.mstatus.TVM;
|
||||||
if (this->reg.PRIV == PRIV_S & tvm != 0) {
|
if (this->reg.PRIV == PRIV_S & tvm != 0) {
|
||||||
this->trap_state = (1 << 31) | (2 << 16);
|
this->reg.trap_state = (1 << 31) | (2 << 16);
|
||||||
this->fault_data = this->reg.PC;
|
this->fault_data = this->reg.PC;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -800,7 +800,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1 << 31) | ta.id;
|
this->reg.trap_state = (1 << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -846,7 +846,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_reg(unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t &val) {
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t &val) {
|
||||||
auto cycle_val = this->icount + cycle_offset;
|
auto cycle_val = this->reg.icount + cycle_offset;
|
||||||
if (addr == mcycle) {
|
if (addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
} else if (addr == mcycleh) {
|
} else if (addr == mcycleh) {
|
||||||
|
@ -868,7 +868,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_cycle(unsign
|
||||||
mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff);
|
mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around
|
cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,7 +899,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_instret(unsi
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t &val) {
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t &val) {
|
||||||
uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052;
|
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
if (addr == time) {
|
if (addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if (addr == timeh) {
|
} else if (addr == timeh) {
|
||||||
|
@ -968,7 +968,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_epc(unsigned
|
||||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t &val) {
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t &val) {
|
||||||
reg_t tvm = state.mstatus.TVM;
|
reg_t tvm = state.mstatus.TVM;
|
||||||
if (this->reg.PRIV == PRIV_S & tvm != 0) {
|
if (this->reg.PRIV == PRIV_S & tvm != 0) {
|
||||||
this->trap_state = (1 << 31) | (2 << 16);
|
this->reg.trap_state = (1 << 31) | (2 << 16);
|
||||||
this->fault_data = this->reg.PC;
|
this->fault_data = this->reg.PC;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -979,7 +979,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned
|
||||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigned addr, reg_t val) {
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigned addr, reg_t val) {
|
||||||
reg_t tvm = state.mstatus.TVM;
|
reg_t tvm = state.mstatus.TVM;
|
||||||
if (this->reg.PRIV == PRIV_S & tvm != 0) {
|
if (this->reg.PRIV == PRIV_S & tvm != 0) {
|
||||||
this->trap_state = (1 << 31) | (2 << 16);
|
this->reg.trap_state = (1 << 31) | (2 << 16);
|
||||||
this->fault_data = this->reg.PC;
|
this->fault_data = this->reg.PC;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -1024,18 +1024,6 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
|
||||||
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);
|
|
||||||
} break;
|
|
||||||
case 0x10008000: {
|
|
||||||
const mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
uint64_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(p.data() + offs, p.data() + offs + length, data);
|
|
||||||
if (this->icount > 30000) data[3] |= 0x80;
|
|
||||||
} break;
|
|
||||||
default: {
|
default: {
|
||||||
for(auto offs=0U; offs<length; ++offs) {
|
for(auto offs=0U; offs<length; ++offs) {
|
||||||
*(data + offs)=mem[(paddr.val+offs)%mem.size()];
|
*(data + offs)=mem[(paddr.val+offs)%mem.size()];
|
||||||
|
@ -1048,30 +1036,13 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
|
||||||
uart_buf << (char)data[0];
|
|
||||||
if (((char)data[0]) == '\n' || data[0] == 0) {
|
if (((char)data[0]) == '\n' || data[0] == 0) {
|
||||||
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
|
LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'";
|
||||||
// '"<<uart_buf.str()<<"'";
|
|
||||||
std::cout << uart_buf.str();
|
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
}
|
} else if(((char)data[0]) != '\r')
|
||||||
|
uart_buf << (char)data[0];
|
||||||
break;
|
break;
|
||||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
size_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(data, data + length, p.data() + offs);
|
|
||||||
uint8_t &x = *(p.data() + offs + 3);
|
|
||||||
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
|
|
||||||
} break;
|
|
||||||
case 0x10008008: { // HFROSC base, pllcfg reg
|
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
size_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(data, data + length, p.data() + offs);
|
|
||||||
uint8_t &x = *(p.data() + offs + 3);
|
|
||||||
x |= 0x80; // set pll lock upon writing
|
|
||||||
} break;
|
|
||||||
default: {
|
default: {
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
||||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||||
|
@ -1093,7 +1064,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
|
||||||
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||||
<< "), stopping simulation";
|
<< "), stopping simulation";
|
||||||
}
|
}
|
||||||
this->trap_state=std::numeric_limits<uint32_t>::max();
|
this->reg.trap_state=std::numeric_limits<uint32_t>::max();
|
||||||
this->interrupt_sim=hostvar;
|
this->interrupt_sim=hostvar;
|
||||||
break;
|
break;
|
||||||
//throw(iss::simulation_stopped(hostvar));
|
//throw(iss::simulation_stopped(hostvar));
|
||||||
|
@ -1162,7 +1133,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
|
||||||
if (enabled_interrupts != 0) {
|
if (enabled_interrupts != 0) {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++;
|
while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++;
|
||||||
this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
|
this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1306,7 +1277,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
||||||
if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0)
|
if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0)
|
||||||
new_priv = (csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S;
|
new_priv = (csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S;
|
||||||
csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt
|
csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt
|
||||||
this->pending_trap = 0;
|
this->reg.pending_trap = 0;
|
||||||
}
|
}
|
||||||
size_t adr = ucause | (new_priv << 8);
|
size_t adr = ucause | (new_priv << 8);
|
||||||
csr[adr] = (trap_id << 31) + cause;
|
csr[adr] = (trap_id << 31) + cause;
|
||||||
|
@ -1351,7 +1322,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
||||||
<< lvl[cur_priv] << " to " << lvl[new_priv];
|
<< lvl[cur_priv] << " to " << lvl[new_priv];
|
||||||
// reset trap state
|
// reset trap state
|
||||||
this->reg.PRIV = new_priv;
|
this->reg.PRIV = new_priv;
|
||||||
this->trap_state = 0;
|
this->reg.trap_state = 0;
|
||||||
update_vm_info();
|
update_vm_info();
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
@ -1363,7 +1334,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t f
|
||||||
|
|
||||||
auto tsr = state.mstatus.TSR;
|
auto tsr = state.mstatus.TSR;
|
||||||
if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) {
|
if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) {
|
||||||
this->trap_state = (1 << 31) | (2 << 16);
|
this->reg.trap_state = (1 << 31) | (2 << 16);
|
||||||
this->fault_data = this->reg.PC;
|
this->fault_data = this->reg.PC;
|
||||||
return this->reg.PC;
|
return this->reg.PC;
|
||||||
}
|
}
|
||||||
|
@ -1402,7 +1373,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags
|
||||||
auto status = state.mstatus;
|
auto status = state.mstatus;
|
||||||
auto tw = status.TW;
|
auto tw = status.TW;
|
||||||
if (this->reg.PRIV == PRIV_S && tw != 0) {
|
if (this->reg.PRIV == PRIV_S && tw != 0) {
|
||||||
this->trap_state = (1 << 31) | (2 << 16);
|
this->reg.trap_state = (1 << 31) | (2 << 16);
|
||||||
this->fault_data = this->reg.PC;
|
this->fault_data = this->reg.PC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,7 +304,7 @@ public:
|
||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) override {
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]",
|
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]",
|
||||||
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->icount + cycle_offset);
|
pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||||
|
@ -816,7 +816,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
||||||
if(!pmp_check(access, addr, length) && !is_debug(access)) {
|
if(!pmp_check(access, addr, length) && !is_debug(access)) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (is_debug(access)) throw trap_access(0, addr);
|
if (is_debug(access)) throw trap_access(0, addr);
|
||||||
this->trap_state = (1UL << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1
|
this->reg.trap_state = (1UL << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -824,12 +824,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
||||||
if (unlikely(is_fetch(access) && (addr&(alignment-1)))) {
|
if (unlikely(is_fetch(access) && (addr&(alignment-1)))) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (is_debug(access)) throw trap_access(0, addr);
|
if (is_debug(access)) throw trap_access(0, addr);
|
||||||
this->trap_state = (1UL << 31); // issue trap 0
|
this->reg.trap_state = (1UL << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(!is_debug(access) && (addr&(alignment-1))){
|
if(!is_debug(access) && (addr&(alignment-1))){
|
||||||
this->trap_state = (1UL << 31) | 4<<16;
|
this->reg.trap_state = (1UL << 31) | 4<<16;
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -848,12 +848,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
||||||
res = hart_mem_rd_delegate( phys_addr, length, data);
|
res = hart_mem_rd_delegate( phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if (unlikely(res != iss::Ok)){
|
if (unlikely(res != iss::Ok)){
|
||||||
this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -879,7 +879,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -918,19 +918,19 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
||||||
if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) {
|
if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->trap_state = (1UL << 31) | (7 << 16); // issue trap 1
|
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unlikely(is_fetch(access) && (addr & 0x1) == 1)) {
|
if (unlikely(is_fetch(access) && (addr & 0x1) == 1)) {
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->trap_state = (1UL << 31); // issue trap 0
|
this->reg.trap_state = (1UL << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){
|
if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){
|
||||||
this->trap_state = (1UL << 31) | 6<<16;
|
this->reg.trap_state = (1UL << 31) | 6<<16;
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -949,12 +949,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
||||||
res = hart_mem_wr_delegate( phys_addr, length, data);
|
res = hart_mem_wr_delegate( phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if (unlikely(res != iss::Ok)) {
|
if (unlikely(res != iss::Ok)) {
|
||||||
this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
||||||
fault_data=addr;
|
fault_data=addr;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -1014,7 +1014,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch (trap_access &ta) {
|
} catch (trap_access &ta) {
|
||||||
this->trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data=ta.addr;
|
fault_data=ta.addr;
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
|
@ -1060,7 +1060,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_cycle(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_cycle(unsigned addr, reg_t &val) {
|
||||||
auto cycle_val = this->icount + cycle_offset;
|
auto cycle_val = this->reg.icount + cycle_offset;
|
||||||
if (addr == mcycle) {
|
if (addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
} else if (addr == mcycleh) {
|
} else if (addr == mcycleh) {
|
||||||
|
@ -1079,35 +1079,35 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff);
|
mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around
|
cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_instret(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_instret(unsigned addr, reg_t &val) {
|
||||||
if ((addr&0xff) == (minstret&0xff)) {
|
if ((addr&0xff) == (minstret&0xff)) {
|
||||||
val = static_cast<reg_t>(this->instret);
|
val = static_cast<reg_t>(this->reg.instret);
|
||||||
} else if ((addr&0xff) == (minstreth&0xff)) {
|
} else if ((addr&0xff) == (minstreth&0xff)) {
|
||||||
val = static_cast<reg_t>(this->instret >> 32);
|
val = static_cast<reg_t>(this->reg.instret >> 32);
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) {
|
||||||
if (sizeof(typename traits<BASE>::reg_t) != 4) {
|
if (sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||||
this->instret = static_cast<uint64_t>(val);
|
this->reg.instret = static_cast<uint64_t>(val);
|
||||||
} else {
|
} else {
|
||||||
if ((addr&0xff) == (minstret&0xff)) {
|
if ((addr&0xff) == (minstret&0xff)) {
|
||||||
this->instret = (this->instret & 0xffffffff00000000) + val;
|
this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val;
|
||||||
} else {
|
} else {
|
||||||
this->instret = (static_cast<uint64_t>(val)<<32) + (this->instret & 0xffffffff);
|
this->reg.instret = (static_cast<uint64_t>(val)<<32) + (this->reg.instret & 0xffffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->instret--;
|
this->reg.instret--;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) {
|
||||||
uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052;
|
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
if (addr == time) {
|
if (addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if (addr == timeh) {
|
} else if (addr == timeh) {
|
||||||
|
@ -1283,18 +1283,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
|
||||||
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);
|
|
||||||
} break;
|
|
||||||
case 0x10008000: {
|
|
||||||
const mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
uint64_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(p.data() + offs, p.data() + offs + length, data);
|
|
||||||
if (this->icount > 30000) data[3] |= 0x80;
|
|
||||||
} break;
|
|
||||||
default: {
|
default: {
|
||||||
for(auto offs=0U; offs<length; ++offs) {
|
for(auto offs=0U; offs<length; ++offs) {
|
||||||
*(data + offs)=mem[(paddr.val+offs)%mem.size()];
|
*(data + offs)=mem[(paddr.val+offs)%mem.size()];
|
||||||
|
@ -1307,29 +1295,13 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned le
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
|
||||||
uart_buf << (char)data[0];
|
|
||||||
if (((char)data[0]) == '\n' || data[0] == 0) {
|
if (((char)data[0]) == '\n' || data[0] == 0) {
|
||||||
LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'";
|
LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'";
|
||||||
std::cout << uart_buf.str();
|
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
}
|
} else if(((char)data[0]) != '\r')
|
||||||
|
uart_buf << (char)data[0];
|
||||||
break;
|
break;
|
||||||
case 0x10008000: { // HFROSC base, hfrosccfg reg
|
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
size_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(data, data + length, p.data() + offs);
|
|
||||||
uint8_t &x = *(p.data() + offs + 3);
|
|
||||||
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
|
|
||||||
} break;
|
|
||||||
case 0x10008008: { // HFROSC base, pllcfg reg
|
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
|
||||||
size_t offs = paddr.val & mem.page_addr_mask;
|
|
||||||
std::copy(data, data + length, p.data() + offs);
|
|
||||||
uint8_t &x = *(p.data() + offs + 3);
|
|
||||||
x |= 0x80; // set pll lock upon writing
|
|
||||||
} break;
|
|
||||||
default: {
|
default: {
|
||||||
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
mem_type::page_type &p = mem(paddr.val / mem.page_size);
|
||||||
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
|
||||||
|
@ -1351,7 +1323,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
|
||||||
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
|
||||||
<< "), stopping simulation";
|
<< "), stopping simulation";
|
||||||
}
|
}
|
||||||
this->trap_state=std::numeric_limits<uint32_t>::max();
|
this->reg.trap_state=std::numeric_limits<uint32_t>::max();
|
||||||
this->interrupt_sim=hostvar;
|
this->interrupt_sim=hostvar;
|
||||||
break;
|
break;
|
||||||
//throw(iss::simulation_stopped(hostvar));
|
//throw(iss::simulation_stopped(hostvar));
|
||||||
|
@ -1436,14 +1408,14 @@ template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::chec
|
||||||
enabled_interrupts >>= 1;
|
enabled_interrupts >>= 1;
|
||||||
res++;
|
res++;
|
||||||
}
|
}
|
||||||
this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
|
this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
|
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
|
||||||
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
||||||
// calculate and write mcause val
|
// calculate and write mcause val
|
||||||
if(flags==std::numeric_limits<uint64_t>::max()) flags=this->trap_state;
|
if(flags==std::numeric_limits<uint64_t>::max()) flags=this->reg.trap_state;
|
||||||
auto trap_id = bit_sub<0, 16>(flags);
|
auto trap_id = bit_sub<0, 16>(flags);
|
||||||
auto cause = bit_sub<16, 15>(flags);
|
auto cause = bit_sub<16, 15>(flags);
|
||||||
if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause
|
if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause
|
||||||
|
@ -1490,7 +1462,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
||||||
if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0)
|
if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0)
|
||||||
new_priv = PRIV_U;
|
new_priv = PRIV_U;
|
||||||
csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt
|
csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt
|
||||||
this->pending_trap = 0;
|
this->reg.pending_trap = 0;
|
||||||
}
|
}
|
||||||
size_t adr = ucause | (new_priv << 8);
|
size_t adr = ucause | (new_priv << 8);
|
||||||
csr[adr] = (trap_id << (traits<BASE>::XLEN-1)) + cause;
|
csr[adr] = (trap_id << (traits<BASE>::XLEN-1)) + cause;
|
||||||
|
@ -1543,7 +1515,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
||||||
<< lvl[this->reg.PRIV] << " to " << lvl[new_priv];
|
<< lvl[this->reg.PRIV] << " to " << lvl[new_priv];
|
||||||
// reset trap state
|
// reset trap state
|
||||||
this->reg.PRIV = new_priv;
|
this->reg.PRIV = new_priv;
|
||||||
this->trap_state = 0;
|
this->reg.trap_state = 0;
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1552,7 +1524,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
||||||
auto inst_priv = (flags & 0x3)? 3:0;
|
auto inst_priv = (flags & 0x3)? 3:0;
|
||||||
if(inst_priv>cur_priv){
|
if(inst_priv>cur_priv){
|
||||||
auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction
|
auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction
|
||||||
this->trap_state = trap_val;
|
this->reg.trap_state = trap_val;
|
||||||
this->reg.NEXT_PC = std::numeric_limits<uint32_t>::max();
|
this->reg.NEXT_PC = std::numeric_limits<uint32_t>::max();
|
||||||
} else {
|
} else {
|
||||||
auto status = state.mstatus;
|
auto status = state.mstatus;
|
||||||
|
|
|
@ -55,8 +55,8 @@ void tgc_c::reset(uint64_t address) {
|
||||||
reg.PC=address;
|
reg.PC=address;
|
||||||
reg.NEXT_PC=reg.PC;
|
reg.NEXT_PC=reg.PC;
|
||||||
reg.PRIV=0x3;
|
reg.PRIV=0x3;
|
||||||
trap_state=0;
|
reg.trap_state=0;
|
||||||
icount=0;
|
reg.icount=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *tgc_c::get_regs_base_ptr() {
|
uint8_t *tgc_c::get_regs_base_ptr() {
|
||||||
|
|
|
@ -189,7 +189,7 @@ struct tgc_c: public arch_if {
|
||||||
|
|
||||||
uint8_t* get_regs_base_ptr() override;
|
uint8_t* get_regs_base_ptr() override;
|
||||||
|
|
||||||
inline uint64_t get_icount() { return icount; }
|
inline uint64_t get_icount() { return reg.icount; }
|
||||||
|
|
||||||
inline bool should_stop() { return interrupt_sim; }
|
inline bool should_stop() { return interrupt_sim; }
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ struct tgc_c: 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 uint32_t get_last_branch() { return last_branch; }
|
inline uint32_t get_last_branch() { return reg.last_branch; }
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
@ -256,12 +256,6 @@ struct tgc_c: public arch_if {
|
||||||
uint32_t last_branch = 0;
|
uint32_t last_branch = 0;
|
||||||
} reg;
|
} reg;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
uint32_t trap_state = 0, pending_trap = 0;
|
|
||||||
uint64_t icount = 0;
|
|
||||||
uint64_t cycle = 0;
|
|
||||||
uint64_t instret = 0;
|
|
||||||
uint32_t instruction = 0;
|
|
||||||
uint32_t last_branch = 0;
|
|
||||||
std::array<address_type, 4> addr_mode;
|
std::array<address_type, 4> addr_mode;
|
||||||
|
|
||||||
uint64_t interrupt_sim=0;
|
uint64_t interrupt_sim=0;
|
||||||
|
|
|
@ -71,7 +71,7 @@ int main(int argc, char *argv[]) {
|
||||||
("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load")
|
("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load")
|
||||||
("mem,m", po::value<std::string>(), "the memory input file")
|
("mem,m", po::value<std::string>(), "the memory input file")
|
||||||
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
|
||||||
("backend", po::value<std::string>()->default_value("interp"), "the memory input file")
|
("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, tcc")
|
||||||
("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation");
|
("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||||
|
|
|
@ -115,7 +115,7 @@ protected:
|
||||||
|
|
||||||
inline void raise(uint16_t trap_id, uint16_t cause){
|
inline void raise(uint16_t trap_id, uint16_t cause){
|
||||||
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
||||||
this->core.trap_state = trap_val;
|
this->core.reg.trap_state = trap_val;
|
||||||
this->template get_reg<uint32_t>(traits::NEXT_PC) = std::numeric_limits<uint32_t>::max();
|
this->template get_reg<uint32_t>(traits::NEXT_PC) = std::numeric_limits<uint32_t>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,16 +322,16 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
auto pc=start;
|
auto pc=start;
|
||||||
auto* PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
|
auto* PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
|
||||||
auto* NEXT_PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]);
|
auto* NEXT_PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]);
|
||||||
auto& trap_state = this->core.trap_state;
|
auto& trap_state = this->core.reg.trap_state;
|
||||||
auto& icount = this->core.icount;
|
auto& icount = this->core.reg.icount;
|
||||||
auto& cycle = this->core.cycle;
|
auto& cycle = this->core.reg.cycle;
|
||||||
auto& instret = this->core.instret;
|
auto& instret = this->core.reg.instret;
|
||||||
auto& instr = this->core.instruction;
|
auto& instr = this->core.reg.instruction;
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
auto *const data = reinterpret_cast<uint8_t*>(&instr);
|
auto *const data = reinterpret_cast<uint8_t*>(&instr);
|
||||||
|
|
||||||
while(!this->core.should_stop() &&
|
while(!this->core.should_stop() &&
|
||||||
!(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){
|
!(is_count_limit_enabled(cond) && icount >= icount_limit)){
|
||||||
if(fetch_ins(pc, data)!=iss::Ok){
|
if(fetch_ins(pc, data)!=iss::Ok){
|
||||||
this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
|
this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
|
||||||
pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0);
|
pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0);
|
||||||
|
@ -340,7 +340,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
auto inst_id = decode_inst_id(instr);
|
auto inst_id = decode_inst_id(instr);
|
||||||
// pre execution stuff
|
// pre execution stuff
|
||||||
this->core.last_branch = 0;
|
this->core.reg.last_branch = 0;
|
||||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
||||||
switch(inst_id){
|
switch(inst_id){
|
||||||
case arch::traits<ARCH>::opcode_e::LUI: {
|
case arch::traits<ARCH>::opcode_e::LUI: {
|
||||||
|
@ -422,7 +422,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
*(X+rd) = *PC + 4;
|
*(X+rd) = *PC + 4;
|
||||||
}
|
}
|
||||||
*NEXT_PC = *PC + (int32_t)sext<21>(imm);
|
*NEXT_PC = *PC + (int32_t)sext<21>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,7 +457,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
*(X+rd) = *PC + 4;
|
*(X+rd) = *PC + 4;
|
||||||
}
|
}
|
||||||
*NEXT_PC = new_pc & ~ 0x1;
|
*NEXT_PC = new_pc & ~ 0x1;
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,7 +489,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,7 +522,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,7 +555,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -588,7 +588,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -621,7 +621,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,7 +654,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -683,7 +683,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||||
int8_t read_res = super::template read_mem<int8_t>(traits::MEM, load_address);
|
int8_t read_res = super::template read_mem<int8_t>(traits::MEM, load_address);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_LB;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LB;
|
||||||
int8_t res = (int8_t)read_res;
|
int8_t res = (int8_t)read_res;
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = (uint32_t)res;
|
*(X+rd) = (uint32_t)res;
|
||||||
|
@ -714,7 +714,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||||
int16_t read_res = super::template read_mem<int16_t>(traits::MEM, load_address);
|
int16_t read_res = super::template read_mem<int16_t>(traits::MEM, load_address);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_LH;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LH;
|
||||||
int16_t res = (int16_t)read_res;
|
int16_t res = (int16_t)read_res;
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = (uint32_t)res;
|
*(X+rd) = (uint32_t)res;
|
||||||
|
@ -745,7 +745,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||||
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address);
|
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_LW;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LW;
|
||||||
int32_t res = (int32_t)read_res;
|
int32_t res = (int32_t)read_res;
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = (uint32_t)res;
|
*(X+rd) = (uint32_t)res;
|
||||||
|
@ -776,7 +776,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||||
uint8_t read_res = super::template read_mem<uint8_t>(traits::MEM, load_address);
|
uint8_t read_res = super::template read_mem<uint8_t>(traits::MEM, load_address);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_LBU;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LBU;
|
||||||
uint8_t res = (uint8_t)read_res;
|
uint8_t res = (uint8_t)read_res;
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = (uint32_t)res;
|
*(X+rd) = (uint32_t)res;
|
||||||
|
@ -807,7 +807,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||||
uint16_t read_res = super::template read_mem<uint16_t>(traits::MEM, load_address);
|
uint16_t read_res = super::template read_mem<uint16_t>(traits::MEM, load_address);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_LHU;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LHU;
|
||||||
uint16_t res = (uint16_t)read_res;
|
uint16_t res = (uint16_t)read_res;
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = (uint32_t)res;
|
*(X+rd) = (uint32_t)res;
|
||||||
|
@ -838,7 +838,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||||
super::template write_mem<uint8_t>(traits::MEM, store_address, (int8_t)*(X+rs2));
|
super::template write_mem<uint8_t>(traits::MEM, store_address, (int8_t)*(X+rs2));
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_SB;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRAP_SB:break;
|
TRAP_SB:break;
|
||||||
|
@ -865,7 +865,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||||
super::template write_mem<uint16_t>(traits::MEM, store_address, (int16_t)*(X+rs2));
|
super::template write_mem<uint16_t>(traits::MEM, store_address, (int16_t)*(X+rs2));
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_SH;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRAP_SH:break;
|
TRAP_SH:break;
|
||||||
|
@ -892,7 +892,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||||
super::template write_mem<uint32_t>(traits::MEM, store_address, (int32_t)*(X+rs2));
|
super::template write_mem<uint32_t>(traits::MEM, store_address, (int32_t)*(X+rs2));
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_SW;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRAP_SW:break;
|
TRAP_SW:break;
|
||||||
|
@ -1428,7 +1428,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
// execute instruction
|
// execute instruction
|
||||||
{
|
{
|
||||||
super::template write_mem<uint8_t>(traits::FENCE, traits::fence, pred << 4 | succ);
|
super::template write_mem<uint8_t>(traits::FENCE, traits::fence, pred << 4 | succ);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE;
|
||||||
}
|
}
|
||||||
TRAP_FENCE:break;
|
TRAP_FENCE:break;
|
||||||
}// @suppress("No break at end of case")
|
}// @suppress("No break at end of case")
|
||||||
|
@ -1507,15 +1507,15 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
uint32_t xrs1 = *(X+rs1);
|
uint32_t xrs1 = *(X+rs1);
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW;
|
||||||
uint32_t xrd = read_res;
|
uint32_t xrd = read_res;
|
||||||
super::template write_mem<uint32_t>(traits::CSR, csr, xrs1);
|
super::template write_mem<uint32_t>(traits::CSR, csr, xrs1);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW;
|
||||||
*(X+rd) = xrd;
|
*(X+rd) = xrd;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
super::template write_mem<uint32_t>(traits::CSR, csr, xrs1);
|
super::template write_mem<uint32_t>(traits::CSR, csr, xrs1);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1542,12 +1542,12 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS;
|
||||||
uint32_t xrd = read_res;
|
uint32_t xrd = read_res;
|
||||||
uint32_t xrs1 = *(X+rs1);
|
uint32_t xrs1 = *(X+rs1);
|
||||||
if(rs1 != 0) {
|
if(rs1 != 0) {
|
||||||
super::template write_mem<uint32_t>(traits::CSR, csr, xrd | xrs1);
|
super::template write_mem<uint32_t>(traits::CSR, csr, xrd | xrs1);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS;
|
||||||
}
|
}
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = xrd;
|
*(X+rd) = xrd;
|
||||||
|
@ -1577,12 +1577,12 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC;
|
||||||
uint32_t xrd = read_res;
|
uint32_t xrd = read_res;
|
||||||
uint32_t xrs1 = *(X+rs1);
|
uint32_t xrs1 = *(X+rs1);
|
||||||
if(rs1 != 0) {
|
if(rs1 != 0) {
|
||||||
super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ xrs1);
|
super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ xrs1);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC;
|
||||||
}
|
}
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = xrd;
|
*(X+rd) = xrd;
|
||||||
|
@ -1612,10 +1612,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI;
|
||||||
uint32_t xrd = read_res;
|
uint32_t xrd = read_res;
|
||||||
super::template write_mem<uint32_t>(traits::CSR, csr, (uint32_t)zimm);
|
super::template write_mem<uint32_t>(traits::CSR, csr, (uint32_t)zimm);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI;
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = xrd;
|
*(X+rd) = xrd;
|
||||||
}
|
}
|
||||||
|
@ -1644,11 +1644,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI;
|
||||||
uint32_t xrd = read_res;
|
uint32_t xrd = read_res;
|
||||||
if(zimm != 0) {
|
if(zimm != 0) {
|
||||||
super::template write_mem<uint32_t>(traits::CSR, csr, xrd | (uint32_t)zimm);
|
super::template write_mem<uint32_t>(traits::CSR, csr, xrd | (uint32_t)zimm);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI;
|
||||||
}
|
}
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = xrd;
|
*(X+rd) = xrd;
|
||||||
|
@ -1678,11 +1678,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI;
|
||||||
uint32_t xrd = read_res;
|
uint32_t xrd = read_res;
|
||||||
if(zimm != 0) {
|
if(zimm != 0) {
|
||||||
super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ ((uint32_t)zimm));
|
super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ ((uint32_t)zimm));
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI;
|
||||||
}
|
}
|
||||||
if(rd != 0) {
|
if(rd != 0) {
|
||||||
*(X+rd) = xrd;
|
*(X+rd) = xrd;
|
||||||
|
@ -1707,7 +1707,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
// execute instruction
|
// execute instruction
|
||||||
{
|
{
|
||||||
super::template write_mem<uint16_t>(traits::FENCE, traits::fencei, imm);
|
super::template write_mem<uint16_t>(traits::FENCE, traits::fencei, imm);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE_I;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE_I;
|
||||||
}
|
}
|
||||||
TRAP_FENCE_I:break;
|
TRAP_FENCE_I:break;
|
||||||
}// @suppress("No break at end of case")
|
}// @suppress("No break at end of case")
|
||||||
|
@ -2015,7 +2015,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
{
|
{
|
||||||
uint32_t load_address = *(X+rs1 + 8) + uimm;
|
uint32_t load_address = *(X+rs1 + 8) + uimm;
|
||||||
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address);
|
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CLW;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLW;
|
||||||
*(X+rd + 8) = (int32_t)read_res;
|
*(X+rd + 8) = (int32_t)read_res;
|
||||||
}
|
}
|
||||||
TRAP_CLW:break;
|
TRAP_CLW:break;
|
||||||
|
@ -2038,7 +2038,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
{
|
{
|
||||||
uint32_t load_address = *(X+rs1 + 8) + uimm;
|
uint32_t load_address = *(X+rs1 + 8) + uimm;
|
||||||
super::template write_mem<uint32_t>(traits::MEM, load_address, (int32_t)*(X+rs2 + 8));
|
super::template write_mem<uint32_t>(traits::MEM, load_address, (int32_t)*(X+rs2 + 8));
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSW;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSW;
|
||||||
}
|
}
|
||||||
TRAP_CSW:break;
|
TRAP_CSW:break;
|
||||||
}// @suppress("No break at end of case")
|
}// @suppress("No break at end of case")
|
||||||
|
@ -2097,7 +2097,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
{
|
{
|
||||||
*(X+1) = *PC + 2;
|
*(X+1) = *PC + 2;
|
||||||
*NEXT_PC = *PC + (int16_t)sext<12>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<12>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
TRAP_CJAL:break;
|
TRAP_CJAL:break;
|
||||||
}// @suppress("No break at end of case")
|
}// @suppress("No break at end of case")
|
||||||
|
@ -2342,7 +2342,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
// execute instruction
|
// execute instruction
|
||||||
{
|
{
|
||||||
*NEXT_PC = *PC + (int16_t)sext<12>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<12>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
TRAP_CJ:break;
|
TRAP_CJ:break;
|
||||||
}// @suppress("No break at end of case")
|
}// @suppress("No break at end of case")
|
||||||
|
@ -2363,7 +2363,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
{
|
{
|
||||||
if(*(X+rs1 + 8) == 0) {
|
if(*(X+rs1 + 8) == 0) {
|
||||||
*NEXT_PC = *PC + (int16_t)sext<9>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<9>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRAP_CBEQZ:break;
|
TRAP_CBEQZ:break;
|
||||||
|
@ -2385,7 +2385,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
{
|
{
|
||||||
if(*(X+rs1 + 8) != 0) {
|
if(*(X+rs1 + 8) != 0) {
|
||||||
*NEXT_PC = *PC + (int16_t)sext<9>(imm);
|
*NEXT_PC = *PC + (int16_t)sext<9>(imm);
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRAP_CBNEZ:break;
|
TRAP_CBNEZ:break;
|
||||||
|
@ -2436,7 +2436,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, *(X+2) + uimm);
|
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, *(X+2) + uimm);
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CLWSP;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLWSP;
|
||||||
int32_t res = read_res;
|
int32_t res = read_res;
|
||||||
*(X+rd) = (int32_t)res;
|
*(X+rd) = (int32_t)res;
|
||||||
}
|
}
|
||||||
|
@ -2485,7 +2485,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
{
|
{
|
||||||
if(rs1 && rs1 < traits::RFS) {
|
if(rs1 && rs1 < traits::RFS) {
|
||||||
*NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1;
|
*NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1;
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
raise(0, 2);
|
raise(0, 2);
|
||||||
|
@ -2553,7 +2553,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
uint32_t new_pc = *(X+rs1);
|
uint32_t new_pc = *(X+rs1);
|
||||||
*(X+1) = *PC + 2;
|
*(X+1) = *PC + 2;
|
||||||
*NEXT_PC = new_pc & ~ 0x1;
|
*NEXT_PC = new_pc & ~ 0x1;
|
||||||
this->core.last_branch = 1;
|
this->core.reg.last_branch = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRAP_CJALR:break;
|
TRAP_CJALR:break;
|
||||||
|
@ -2592,7 +2592,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
else {
|
else {
|
||||||
uint32_t offs = *(X+2) + uimm;
|
uint32_t offs = *(X+2) + uimm;
|
||||||
super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2));
|
super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2));
|
||||||
if(this->core.trap_state>=0x80000000UL) goto TRAP_CSWSP;
|
if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSWSP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRAP_CSWSP:break;
|
TRAP_CSWSP:break;
|
||||||
|
@ -2618,8 +2618,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
// post execution stuff
|
// post execution stuff
|
||||||
process_spawn_blocks();
|
process_spawn_blocks();
|
||||||
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id));
|
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id));
|
||||||
// if(!this->core.trap_state) // update trap state if there is a pending interrupt
|
// if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt
|
||||||
// this->core.trap_state = this->core.pending_trap;
|
// this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||||
// trap check
|
// trap check
|
||||||
if(trap_state!=0){
|
if(trap_state!=0){
|
||||||
super::core.enter_trap(trap_state, pc.val, instr);
|
super::core.enter_trap(trap_state, pc.val, instr);
|
||||||
|
@ -2630,7 +2630,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||||
cycle++;
|
cycle++;
|
||||||
pc.val=*NEXT_PC;
|
pc.val=*NEXT_PC;
|
||||||
this->core.reg.PC = this->core.reg.NEXT_PC;
|
this->core.reg.PC = this->core.reg.NEXT_PC;
|
||||||
this->core.trap_state = this->core.pending_trap;
|
this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pc;
|
return pc;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue