Adapted to log system
This commit is contained in:
parent
9a617dab57
commit
39150b68c0
2
dbt-core
2
dbt-core
|
@ -1 +1 @@
|
||||||
Subproject commit 1091afcc3045c1bea5508a6be785eed757632452
|
Subproject commit f23a45ab77d25ac42fd8df3e3f7206baad122c67
|
|
@ -66,9 +66,9 @@ add_dependent_header(util)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${PROJECT_SOURCE_DIR}/incl
|
${PROJECT_SOURCE_DIR}/incl
|
||||||
|
${PROJECT_SOURCE_DIR}/../riscv/incl
|
||||||
${PROJECT_SOURCE_DIR}/../external/elfio
|
${PROJECT_SOURCE_DIR}/../external/elfio
|
||||||
${PROJECT_SOURCE_DIR}/../external/libGIS
|
${PROJECT_SOURCE_DIR}/../external/libGIS
|
||||||
${PROJECT_SOURCE_DIR}/../riscv
|
|
||||||
${Boost_INCLUDE_DIRS}
|
${Boost_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ inline void configure_default_logger(boost::program_options::variables_map& vm){
|
||||||
|
|
||||||
inline void configure_debugger_logger() {
|
inline void configure_debugger_logger() {
|
||||||
// configure the connection logger
|
// configure the connection logger
|
||||||
// el::Logger* gdbServerLogger = el::Loggers::getLogger("connection");
|
// el::Logger* gdbServerLogger = el::Loggers::getLogger(connection);
|
||||||
// el::Configurations gdbServerConf;
|
// el::Configurations gdbServerConf;
|
||||||
// gdbServerConf.setToDefault();
|
// gdbServerConf.setToDefault();
|
||||||
// gdbServerConf.set(el::Level::Error, el::ConfigurationType::Format,
|
// gdbServerConf.set(el::Level::Error, el::ConfigurationType::Format,
|
||||||
|
@ -104,10 +104,10 @@ inline void configure_debugger_logger() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void configure_disass_logger(boost::program_options::variables_map& vm) {
|
inline void configure_disass_logger(boost::program_options::variables_map& vm) {
|
||||||
// el::Logger* disassLogger = el::Loggers::getLogger("disass");
|
// el::Logger* disassLogger = el::Loggers::getLogger(disass);
|
||||||
// el::Configurations disassConf;
|
// el::Configurations disassConf;
|
||||||
// if(vm.count("disass")){
|
// if(vm.count(disass)){
|
||||||
// auto file_name=vm["disass"].as<std::string>();
|
// auto file_name=vm[disass].as<std::string>();
|
||||||
// disassConf.setToDefault();
|
// disassConf.setToDefault();
|
||||||
// if (file_name.length() > 0) {
|
// if (file_name.length() > 0) {
|
||||||
// disassConf.set(el::Level::Global, el::ConfigurationType::ToFile,
|
// disassConf.set(el::Level::Global, el::ConfigurationType::ToFile,
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,200 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2017, MINRES Technologies GmbH
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// Created on: Thu Sep 21 17:01:54 CEST 2017
|
|
||||||
// * rv32imac.h Author: <CoreDSL Generator>
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _RV32IMAC_H_
|
|
||||||
#define _RV32IMAC_H_
|
|
||||||
|
|
||||||
#include <iss/arch_if.h>
|
|
||||||
#include <iss/vm_if.h>
|
|
||||||
#include <iss/arch/traits.h>
|
|
||||||
|
|
||||||
namespace iss {
|
|
||||||
namespace arch {
|
|
||||||
|
|
||||||
struct rv32imac;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct traits<rv32imac> {
|
|
||||||
|
|
||||||
enum constants {XLEN=32,XLEN2=64,XLEN_BIT_MASK=31,PCLEN=32,fence=0,fencei=1,fencevmal=2,fencevmau=3,MISA_VAL=1075056897,PGSIZE=4096,PGMASK=4095};
|
|
||||||
|
|
||||||
enum reg_e {
|
|
||||||
X0,
|
|
||||||
X1,
|
|
||||||
X2,
|
|
||||||
X3,
|
|
||||||
X4,
|
|
||||||
X5,
|
|
||||||
X6,
|
|
||||||
X7,
|
|
||||||
X8,
|
|
||||||
X9,
|
|
||||||
X10,
|
|
||||||
X11,
|
|
||||||
X12,
|
|
||||||
X13,
|
|
||||||
X14,
|
|
||||||
X15,
|
|
||||||
X16,
|
|
||||||
X17,
|
|
||||||
X18,
|
|
||||||
X19,
|
|
||||||
X20,
|
|
||||||
X21,
|
|
||||||
X22,
|
|
||||||
X23,
|
|
||||||
X24,
|
|
||||||
X25,
|
|
||||||
X26,
|
|
||||||
X27,
|
|
||||||
X28,
|
|
||||||
X29,
|
|
||||||
X30,
|
|
||||||
X31,
|
|
||||||
PC,
|
|
||||||
NUM_REGS,
|
|
||||||
NEXT_PC=NUM_REGS,
|
|
||||||
TRAP_STATE,
|
|
||||||
PENDING_TRAP,
|
|
||||||
MACHINE_STATE,
|
|
||||||
ICOUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint32_t reg_t;
|
|
||||||
|
|
||||||
typedef uint32_t addr_t;
|
|
||||||
|
|
||||||
typedef uint32_t code_word_t; //TODO: check removal
|
|
||||||
|
|
||||||
typedef iss::typed_addr_t<iss::VIRTUAL> virt_addr_t;
|
|
||||||
|
|
||||||
typedef iss::typed_addr_t<iss::PHYSICAL> phys_addr_t;
|
|
||||||
|
|
||||||
constexpr static unsigned reg_bit_width(unsigned r) {
|
|
||||||
const uint32_t RV32IMAC_reg_size[] = {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64};
|
|
||||||
return RV32IMAC_reg_size[r];
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr static unsigned reg_byte_offset(unsigned r) {
|
|
||||||
const uint32_t RV32IMAC_reg_byte_offset[] = {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,152,160};
|
|
||||||
return RV32IMAC_reg_byte_offset[r];
|
|
||||||
}
|
|
||||||
|
|
||||||
enum sreg_flag_e {FLAGS};
|
|
||||||
|
|
||||||
enum mem_type_e {MEM,CSR,FENCE,RES};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rv32imac: public arch_if {
|
|
||||||
|
|
||||||
using virt_addr_t = typename traits<rv32imac>::virt_addr_t;
|
|
||||||
using phys_addr_t = typename traits<rv32imac>::phys_addr_t;
|
|
||||||
using reg_t = typename traits<rv32imac>::reg_t;
|
|
||||||
using addr_t = typename traits<rv32imac>::addr_t;
|
|
||||||
|
|
||||||
rv32imac();
|
|
||||||
~rv32imac();
|
|
||||||
|
|
||||||
virtual void reset(uint64_t address=0) override;
|
|
||||||
|
|
||||||
virtual uint8_t* get_regs_base_ptr() override;
|
|
||||||
/// deprecated
|
|
||||||
virtual void get_reg(short idx, std::vector<uint8_t>& value) override {}
|
|
||||||
virtual void set_reg(short idx, const std::vector<uint8_t>& value) override {}
|
|
||||||
/// deprecated
|
|
||||||
virtual bool get_flag(int flag) override {return false;}
|
|
||||||
virtual void set_flag(int, bool value) override {};
|
|
||||||
/// deprecated
|
|
||||||
virtual void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
|
|
||||||
|
|
||||||
virtual void notify_phase(exec_phase phase){
|
|
||||||
if(phase==ISTART){
|
|
||||||
++reg.icount;
|
|
||||||
reg.PC=reg.NEXT_PC;
|
|
||||||
reg.trap_state=reg.pending_trap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t get_icount() { return reg.icount;}
|
|
||||||
|
|
||||||
virtual phys_addr_t v2p(const iss::addr_t& pc);
|
|
||||||
|
|
||||||
virtual iss::sync_type needed_sync() const { return iss::PRE_SYNC; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
struct RV32IMAC_regs {
|
|
||||||
uint32_t X0;
|
|
||||||
uint32_t X1;
|
|
||||||
uint32_t X2;
|
|
||||||
uint32_t X3;
|
|
||||||
uint32_t X4;
|
|
||||||
uint32_t X5;
|
|
||||||
uint32_t X6;
|
|
||||||
uint32_t X7;
|
|
||||||
uint32_t X8;
|
|
||||||
uint32_t X9;
|
|
||||||
uint32_t X10;
|
|
||||||
uint32_t X11;
|
|
||||||
uint32_t X12;
|
|
||||||
uint32_t X13;
|
|
||||||
uint32_t X14;
|
|
||||||
uint32_t X15;
|
|
||||||
uint32_t X16;
|
|
||||||
uint32_t X17;
|
|
||||||
uint32_t X18;
|
|
||||||
uint32_t X19;
|
|
||||||
uint32_t X20;
|
|
||||||
uint32_t X21;
|
|
||||||
uint32_t X22;
|
|
||||||
uint32_t X23;
|
|
||||||
uint32_t X24;
|
|
||||||
uint32_t X25;
|
|
||||||
uint32_t X26;
|
|
||||||
uint32_t X27;
|
|
||||||
uint32_t X28;
|
|
||||||
uint32_t X29;
|
|
||||||
uint32_t X30;
|
|
||||||
uint32_t X31;
|
|
||||||
uint32_t PC;
|
|
||||||
uint32_t NEXT_PC;
|
|
||||||
uint32_t trap_state, pending_trap, machine_state;
|
|
||||||
uint64_t icount;
|
|
||||||
} reg;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* _RV32IMAC_H_ */
|
|
|
@ -1,200 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2017, MINRES Technologies GmbH
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// Created on: Thu Sep 21 17:01:54 CEST 2017
|
|
||||||
// * rv64ia.h Author: <CoreDSL Generator>
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _RV64IA_H_
|
|
||||||
#define _RV64IA_H_
|
|
||||||
|
|
||||||
#include <iss/arch_if.h>
|
|
||||||
#include <iss/vm_if.h>
|
|
||||||
#include <iss/arch/traits.h>
|
|
||||||
|
|
||||||
namespace iss {
|
|
||||||
namespace arch {
|
|
||||||
|
|
||||||
struct rv64ia;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct traits<rv64ia> {
|
|
||||||
|
|
||||||
enum constants {XLEN=64,XLEN2=128,XLEN_BIT_MASK=63,PCLEN=64,fence=0,fencei=1,fencevmal=2,fencevmau=3,MISA_VAL=2147750144,PGSIZE=4096,PGMASK=4095};
|
|
||||||
|
|
||||||
enum reg_e {
|
|
||||||
X0,
|
|
||||||
X1,
|
|
||||||
X2,
|
|
||||||
X3,
|
|
||||||
X4,
|
|
||||||
X5,
|
|
||||||
X6,
|
|
||||||
X7,
|
|
||||||
X8,
|
|
||||||
X9,
|
|
||||||
X10,
|
|
||||||
X11,
|
|
||||||
X12,
|
|
||||||
X13,
|
|
||||||
X14,
|
|
||||||
X15,
|
|
||||||
X16,
|
|
||||||
X17,
|
|
||||||
X18,
|
|
||||||
X19,
|
|
||||||
X20,
|
|
||||||
X21,
|
|
||||||
X22,
|
|
||||||
X23,
|
|
||||||
X24,
|
|
||||||
X25,
|
|
||||||
X26,
|
|
||||||
X27,
|
|
||||||
X28,
|
|
||||||
X29,
|
|
||||||
X30,
|
|
||||||
X31,
|
|
||||||
PC,
|
|
||||||
NUM_REGS,
|
|
||||||
NEXT_PC=NUM_REGS,
|
|
||||||
TRAP_STATE,
|
|
||||||
PENDING_TRAP,
|
|
||||||
MACHINE_STATE,
|
|
||||||
ICOUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint64_t reg_t;
|
|
||||||
|
|
||||||
typedef uint64_t addr_t;
|
|
||||||
|
|
||||||
typedef uint64_t code_word_t; //TODO: check removal
|
|
||||||
|
|
||||||
typedef iss::typed_addr_t<iss::VIRTUAL> virt_addr_t;
|
|
||||||
|
|
||||||
typedef iss::typed_addr_t<iss::PHYSICAL> phys_addr_t;
|
|
||||||
|
|
||||||
constexpr static unsigned reg_bit_width(unsigned r) {
|
|
||||||
const uint32_t RV64IA_reg_size[] = {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,64};
|
|
||||||
return RV64IA_reg_size[r];
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr static unsigned reg_byte_offset(unsigned r) {
|
|
||||||
const uint32_t RV64IA_reg_byte_offset[] = {0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,288,296};
|
|
||||||
return RV64IA_reg_byte_offset[r];
|
|
||||||
}
|
|
||||||
|
|
||||||
enum sreg_flag_e {FLAGS};
|
|
||||||
|
|
||||||
enum mem_type_e {MEM,CSR,FENCE,RES};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rv64ia: public arch_if {
|
|
||||||
|
|
||||||
using virt_addr_t = typename traits<rv64ia>::virt_addr_t;
|
|
||||||
using phys_addr_t = typename traits<rv64ia>::phys_addr_t;
|
|
||||||
using reg_t = typename traits<rv64ia>::reg_t;
|
|
||||||
using addr_t = typename traits<rv64ia>::addr_t;
|
|
||||||
|
|
||||||
rv64ia();
|
|
||||||
~rv64ia();
|
|
||||||
|
|
||||||
virtual void reset(uint64_t address=0) override;
|
|
||||||
|
|
||||||
virtual uint8_t* get_regs_base_ptr() override;
|
|
||||||
/// deprecated
|
|
||||||
virtual void get_reg(short idx, std::vector<uint8_t>& value) override {}
|
|
||||||
virtual void set_reg(short idx, const std::vector<uint8_t>& value) override {}
|
|
||||||
/// deprecated
|
|
||||||
virtual bool get_flag(int flag) override {return false;}
|
|
||||||
virtual void set_flag(int, bool value) override {};
|
|
||||||
/// deprecated
|
|
||||||
virtual void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
|
|
||||||
|
|
||||||
virtual void notify_phase(exec_phase phase){
|
|
||||||
if(phase==ISTART){
|
|
||||||
++reg.icount;
|
|
||||||
reg.PC=reg.NEXT_PC;
|
|
||||||
reg.trap_state=reg.pending_trap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t get_icount() { return reg.icount;}
|
|
||||||
|
|
||||||
virtual phys_addr_t v2p(const iss::addr_t& pc);
|
|
||||||
|
|
||||||
virtual iss::sync_type needed_sync() const { return iss::PRE_SYNC; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
struct RV64IA_regs {
|
|
||||||
uint64_t X0;
|
|
||||||
uint64_t X1;
|
|
||||||
uint64_t X2;
|
|
||||||
uint64_t X3;
|
|
||||||
uint64_t X4;
|
|
||||||
uint64_t X5;
|
|
||||||
uint64_t X6;
|
|
||||||
uint64_t X7;
|
|
||||||
uint64_t X8;
|
|
||||||
uint64_t X9;
|
|
||||||
uint64_t X10;
|
|
||||||
uint64_t X11;
|
|
||||||
uint64_t X12;
|
|
||||||
uint64_t X13;
|
|
||||||
uint64_t X14;
|
|
||||||
uint64_t X15;
|
|
||||||
uint64_t X16;
|
|
||||||
uint64_t X17;
|
|
||||||
uint64_t X18;
|
|
||||||
uint64_t X19;
|
|
||||||
uint64_t X20;
|
|
||||||
uint64_t X21;
|
|
||||||
uint64_t X22;
|
|
||||||
uint64_t X23;
|
|
||||||
uint64_t X24;
|
|
||||||
uint64_t X25;
|
|
||||||
uint64_t X26;
|
|
||||||
uint64_t X27;
|
|
||||||
uint64_t X28;
|
|
||||||
uint64_t X29;
|
|
||||||
uint64_t X30;
|
|
||||||
uint64_t X31;
|
|
||||||
uint64_t PC;
|
|
||||||
uint64_t NEXT_PC;
|
|
||||||
uint32_t trap_state, pending_trap, machine_state;
|
|
||||||
uint64_t icount;
|
|
||||||
} reg;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* _RV64IA_H_ */
|
|
|
@ -1,695 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2017, MINRES Technologies GmbH
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// Contributors:
|
|
||||||
// eyck@minres.com - initial API and implementation
|
|
||||||
//
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <iss/iss.h>
|
|
||||||
#include <iss/debugger/gdb_session.h>
|
|
||||||
#include <util/logging.h>
|
|
||||||
#include <memory>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "iss/vm_base.h"
|
|
||||||
#include "iss/arch/CORE_DEF_NAME.h"
|
|
||||||
#include "iss/debugger/server.h"
|
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
|
||||||
#include "iss/arch/riscv_hart_msu_vp.h"
|
|
||||||
|
|
||||||
namespace iss {
|
|
||||||
namespace CORE_DEF_NAME {
|
|
||||||
using namespace iss::arch;
|
|
||||||
using namespace llvm;
|
|
||||||
using namespace iss::debugger;
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
struct vm_impl;
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
struct target_adapter: public target_adapter_base {
|
|
||||||
|
|
||||||
target_adapter(server_if* srv, vm_impl<ARCH>* vm)
|
|
||||||
: target_adapter_base(srv)
|
|
||||||
, vm(vm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*============== Thread Control ===============================*/
|
|
||||||
|
|
||||||
/* Set generic thread */
|
|
||||||
status set_gen_thread(rp_thread_ref& thread) override;
|
|
||||||
|
|
||||||
/* Set control thread */
|
|
||||||
status set_ctrl_thread(rp_thread_ref& thread) override;
|
|
||||||
|
|
||||||
/* Get thread status */
|
|
||||||
status is_thread_alive(rp_thread_ref& thread, bool& alive) override;
|
|
||||||
|
|
||||||
/*============= Register Access ================================*/
|
|
||||||
|
|
||||||
/* Read all registers. buf is 4-byte aligned and it is in
|
|
||||||
target byte order. If register is not available
|
|
||||||
corresponding bytes in avail_buf are 0, otherwise
|
|
||||||
avail buf is 1 */
|
|
||||||
status read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) override;
|
|
||||||
|
|
||||||
/* Write all registers. buf is 4-byte aligned and it is in target
|
|
||||||
byte order */
|
|
||||||
status write_registers(const std::vector<uint8_t>& data) override;
|
|
||||||
|
|
||||||
/* Read one register. buf is 4-byte aligned and it is in
|
|
||||||
target byte order. If register is not available
|
|
||||||
corresponding bytes in avail_buf are 0, otherwise
|
|
||||||
avail buf is 1 */
|
|
||||||
status read_single_register(unsigned int reg_no, std::vector<uint8_t>& buf, std::vector<uint8_t>& avail_buf) override;
|
|
||||||
|
|
||||||
/* Write one register. buf is 4-byte aligned and it is in target byte
|
|
||||||
order */
|
|
||||||
status write_single_register(unsigned int reg_no, const std::vector<uint8_t>& buf) override;
|
|
||||||
|
|
||||||
/*=================== Memory Access =====================*/
|
|
||||||
|
|
||||||
/* Read memory, buf is 4-bytes aligned and it is in target
|
|
||||||
byte order */
|
|
||||||
status read_mem(uint64_t addr, std::vector<uint8_t>& buf) override;
|
|
||||||
|
|
||||||
/* Write memory, buf is 4-bytes aligned and it is in target
|
|
||||||
byte order */
|
|
||||||
status write_mem(uint64_t addr, const std::vector<uint8_t>& buf) override;
|
|
||||||
|
|
||||||
status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override;
|
|
||||||
|
|
||||||
status thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result, size_t max_num, size_t& num, bool& done) override;
|
|
||||||
|
|
||||||
status current_thread_query(rp_thread_ref& thread) override;
|
|
||||||
|
|
||||||
status offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) override;
|
|
||||||
|
|
||||||
status crc_query(uint64_t addr, size_t len, uint32_t& val) override;
|
|
||||||
|
|
||||||
status raw_query(std::string in_buf, std::string& out_buf) override;
|
|
||||||
|
|
||||||
status threadinfo_query(int first, std::string& out_buf) override;
|
|
||||||
|
|
||||||
status threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) override;
|
|
||||||
|
|
||||||
status packetsize_query(std::string& out_buf) override;
|
|
||||||
|
|
||||||
status add_break(int type, uint64_t addr, unsigned int length) override;
|
|
||||||
|
|
||||||
status remove_break(int type, uint64_t addr, unsigned int length) override;
|
|
||||||
|
|
||||||
status resume_from_addr(bool step, int sig, uint64_t addr) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static inline constexpr addr_t map_addr(const addr_t& i){
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm_impl<ARCH>* vm;
|
|
||||||
rp_thread_ref thread_idx;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
struct vm_impl: public vm::vm_base<ARCH> {
|
|
||||||
using super = typename vm::vm_base<ARCH>;
|
|
||||||
using virt_addr_t = typename super::virt_addr_t;
|
|
||||||
using phys_addr_t = typename super::phys_addr_t;
|
|
||||||
using code_word_t = typename super::code_word_t;
|
|
||||||
using addr_t = typename super::addr_t ;
|
|
||||||
|
|
||||||
vm_impl();
|
|
||||||
|
|
||||||
vm_impl(ARCH& core, bool dump=false);
|
|
||||||
|
|
||||||
void enableDebug(bool enable) {
|
|
||||||
super::sync_exec=super::ALL_SYNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
target_adapter_if* accquire_target_adapter(server_if* srv){
|
|
||||||
debugger_if::dbg_enabled=true;
|
|
||||||
if(vm::vm_base<ARCH>::tgt_adapter==nullptr)
|
|
||||||
vm::vm_base<ARCH>::tgt_adapter=new target_adapter<ARCH>(srv, this);
|
|
||||||
return vm::vm_base<ARCH>::tgt_adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
template<typename T> inline
|
|
||||||
llvm::ConstantInt* size(T type){
|
|
||||||
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline llvm::Value * gen_choose(llvm::Value * cond, llvm::Value * trueVal, llvm::Value * falseVal, unsigned size) const {
|
|
||||||
return this->gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<vm::continuation_e, llvm::BasicBlock*> gen_single_inst_behavior(virt_addr_t&, unsigned int&, llvm::BasicBlock*) override;
|
|
||||||
|
|
||||||
void gen_leave_behavior(llvm::BasicBlock* leave_blk) override;
|
|
||||||
|
|
||||||
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
|
||||||
|
|
||||||
void gen_leave_trap(unsigned lvl);
|
|
||||||
|
|
||||||
void gen_wait(unsigned type);
|
|
||||||
|
|
||||||
void gen_trap_behavior(llvm::BasicBlock*) override;
|
|
||||||
|
|
||||||
void gen_trap_check(llvm::BasicBlock* bb);
|
|
||||||
|
|
||||||
inline
|
|
||||||
void gen_set_pc(virt_addr_t pc, unsigned reg_num){
|
|
||||||
llvm::Value* next_pc_v = this->builder->CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val), this->get_type(traits<ARCH>::XLEN));
|
|
||||||
this->builder->CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
llvm::Value* get_reg_ptr(unsigned i){
|
|
||||||
void* ptr = this->core.get_regs_base_ptr()+traits<ARCH>::reg_byte_offset(i);
|
|
||||||
llvm::PointerType* ptrType=nullptr;
|
|
||||||
switch (traits<ARCH>::reg_bit_width(i)>>3) {
|
|
||||||
case 8:
|
|
||||||
ptrType=llvm::Type::getInt64PtrTy(this->mod->getContext());
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
ptrType=llvm::Type::getInt32PtrTy(this->mod->getContext());
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ptrType=llvm::Type::getInt16PtrTy(this->mod->getContext());
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ptrType=llvm::Type::getInt8PtrTy(this->mod->getContext());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("unsupported access with");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return llvm::ConstantExpr::getIntToPtr(
|
|
||||||
llvm::ConstantInt::get(this->mod->getContext(), llvm::APInt(
|
|
||||||
8/*bits*/ * sizeof(uint8_t*),
|
|
||||||
reinterpret_cast<uint64_t>(ptr)
|
|
||||||
)),
|
|
||||||
ptrType);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
llvm::Value* gen_reg_load(unsigned i, unsigned level=0){
|
|
||||||
// if(level){
|
|
||||||
return this->builder->CreateLoad(get_reg_ptr(i), false);
|
|
||||||
// } else {
|
|
||||||
// if(!this->loaded_regs[i])
|
|
||||||
// this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i), false);
|
|
||||||
// return this->loaded_regs[i];
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
void gen_set_pc(virt_addr_t pc){
|
|
||||||
llvm::Value* pc_l = this->builder->CreateSExt(this->gen_const(traits<ARCH>::caddr_bit_width, (unsigned)pc), this->get_type(traits<ARCH>::caddr_bit_width));
|
|
||||||
super::gen_set_reg(traits<ARCH>::PC, pc_l);
|
|
||||||
}
|
|
||||||
|
|
||||||
// some compile time constants
|
|
||||||
enum {MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111};
|
|
||||||
enum {EXTR_MASK16 = MASK16>>2, EXTR_MASK32 = MASK32>>2};
|
|
||||||
enum {LUT_SIZE = 1<< bit_count(EXTR_MASK32), LUT_SIZE_C = 1<<bit_count(EXTR_MASK16)};
|
|
||||||
|
|
||||||
using this_class = vm_impl<ARCH>;
|
|
||||||
using compile_func = std::tuple<vm::continuation_e, llvm::BasicBlock*> (this_class::*)(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb);
|
|
||||||
compile_func lut[LUT_SIZE];
|
|
||||||
|
|
||||||
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
|
|
||||||
std::array<compile_func, LUT_SIZE> lut_11;
|
|
||||||
|
|
||||||
compile_func* qlut[4];// = {lut_00, lut_01, lut_10, lut_11};
|
|
||||||
|
|
||||||
const uint32_t lutmasks[4]={EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32};
|
|
||||||
|
|
||||||
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], compile_func f){
|
|
||||||
if(pos<0){
|
|
||||||
lut[idx]=f;
|
|
||||||
} else {
|
|
||||||
auto bitmask = 1UL<<pos;
|
|
||||||
if((mask & bitmask)==0){
|
|
||||||
expand_bit_mask(pos-1, mask, value, valid, idx, lut, f);
|
|
||||||
} else {
|
|
||||||
if((valid & bitmask) == 0) {
|
|
||||||
expand_bit_mask(pos-1, mask, value, valid, (idx<<1), lut, f);
|
|
||||||
expand_bit_mask(pos-1, mask, value, valid, (idx<<1)+1, lut, f);
|
|
||||||
} else {
|
|
||||||
auto new_val = idx<<1;
|
|
||||||
if((value&bitmask)!=0)
|
|
||||||
new_val++;
|
|
||||||
expand_bit_mask(pos-1, mask, value, valid, new_val, lut, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t extract_fields(uint32_t val){
|
|
||||||
return extract_fields(29, val>>2, lutmasks[val&0x3], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val){
|
|
||||||
if(pos>=0) {
|
|
||||||
auto bitmask = 1UL<<pos;
|
|
||||||
if((mask & bitmask)==0){
|
|
||||||
lut_val = extract_fields(pos-1, val, mask, lut_val);
|
|
||||||
} else {
|
|
||||||
auto new_val = lut_val<<1;
|
|
||||||
if((val&bitmask)!=0)
|
|
||||||
new_val++;
|
|
||||||
lut_val = extract_fields(pos-1, val, mask, new_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lut_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/****************************************************************************
|
|
||||||
* start opcode definitions
|
|
||||||
****************************************************************************/
|
|
||||||
struct InstructionDesriptor {
|
|
||||||
size_t length;
|
|
||||||
uint32_t value;
|
|
||||||
uint32_t mask;
|
|
||||||
compile_func op;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* «start generated code» */
|
|
||||||
InstructionDesriptor instr_descr[0] = {};
|
|
||||||
/* «end generated code» */
|
|
||||||
/****************************************************************************
|
|
||||||
* end opcode definitions
|
|
||||||
****************************************************************************/
|
|
||||||
std::tuple<vm::continuation_e, llvm::BasicBlock*> illegal_intruction(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
|
|
||||||
//this->gen_sync(iss::PRE_SYNC);
|
|
||||||
this->builder->CreateStore(
|
|
||||||
this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
|
|
||||||
get_reg_ptr(traits<ARCH>::PC), true);
|
|
||||||
this->builder->CreateStore(
|
|
||||||
this->builder->CreateAdd(
|
|
||||||
this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
|
|
||||||
this->gen_const(64U, 1)),
|
|
||||||
get_reg_ptr(traits<ARCH>::ICOUNT), true);
|
|
||||||
if(this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC);
|
|
||||||
pc=pc+((instr&3) == 3?4:2);
|
|
||||||
this->gen_raise_trap(0, 2); // illegal instruction trap
|
|
||||||
this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
|
|
||||||
this->gen_trap_check(this->leave_blk);
|
|
||||||
return std::make_tuple(iss::vm::BRANCH, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename CODE_WORD>
|
|
||||||
void debug_fn(CODE_WORD insn){
|
|
||||||
volatile CODE_WORD x=insn;
|
|
||||||
insn=2*x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
vm_impl<ARCH>::vm_impl(){
|
|
||||||
this(new ARCH());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
vm_impl<ARCH>::vm_impl(ARCH& core, bool dump) : vm::vm_base<ARCH>(core, dump) {
|
|
||||||
qlut[0] = lut_00.data();
|
|
||||||
qlut[1] = lut_01.data();
|
|
||||||
qlut[2] = lut_10.data();
|
|
||||||
qlut[3] = lut_11.data();
|
|
||||||
for(auto instr: instr_descr){
|
|
||||||
auto quantrant = instr.value&0x3;
|
|
||||||
expand_bit_mask(29, lutmasks[quantrant], instr.value>>2, instr.mask>>2, 0, qlut[quantrant], instr.op);
|
|
||||||
}
|
|
||||||
this->sync_exec=static_cast<sync_type>(this->sync_exec|core.needed_sync());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
std::tuple<vm::continuation_e, llvm::BasicBlock*> vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t& pc, unsigned int& inst_cnt, llvm::BasicBlock* this_block){
|
|
||||||
// we fetch at max 4 byte, alignment is 2
|
|
||||||
code_word_t insn = 0;
|
|
||||||
iss::addr_t paddr;
|
|
||||||
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
|
|
||||||
try {
|
|
||||||
uint8_t* const data = (uint8_t*)&insn;
|
|
||||||
paddr=this->core.v2p(pc);
|
|
||||||
if((pc.val&upper_bits) != ((pc.val+2)&upper_bits)){ // we may cross a page boundary
|
|
||||||
auto res = this->core.read(paddr, 2, data);
|
|
||||||
if(res!=iss::Ok)
|
|
||||||
throw trap_access(1, pc.val);
|
|
||||||
if((insn & 0x3) == 0x3){ // this is a 32bit instruction
|
|
||||||
res = this->core.read(this->core.v2p(pc+2), 2, data+2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto res = this->core.read(paddr, 4, data);
|
|
||||||
if(res!=iss::Ok)
|
|
||||||
throw trap_access(1, pc.val);
|
|
||||||
}
|
|
||||||
} catch(trap_access& ta){
|
|
||||||
throw trap_access(ta.id, pc.val);
|
|
||||||
}
|
|
||||||
if(insn==0x0000006f)
|
|
||||||
throw simulation_stopped(0);
|
|
||||||
// curr pc on stack
|
|
||||||
typename vm_impl<ARCH>::processing_pc_entry addr(*this, pc, paddr);
|
|
||||||
++inst_cnt;
|
|
||||||
auto lut_val = extract_fields(insn);
|
|
||||||
auto f = qlut[insn&0x3][lut_val];
|
|
||||||
if (f==nullptr){
|
|
||||||
f=&this_class::illegal_intruction;
|
|
||||||
}
|
|
||||||
return (this->*f)(pc, insn, this_block);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock* leave_blk){
|
|
||||||
this->builder->SetInsertPoint(leave_blk);
|
|
||||||
this->builder->CreateRet(this->builder->CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause){
|
|
||||||
auto* TRAP_val = this->gen_const(32, 0x80<<24| (cause<<16) | trap_id );
|
|
||||||
this->builder->CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
void vm_impl<ARCH>::gen_leave_trap(unsigned lvl){
|
|
||||||
std::vector<llvm::Value*> args {
|
|
||||||
this->core_ptr,
|
|
||||||
llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)),
|
|
||||||
};
|
|
||||||
this->builder->CreateCall(this->mod->getFunction("leave_trap"), args);
|
|
||||||
auto* PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl<<8)+0x41, traits<ARCH>::XLEN/8);
|
|
||||||
this->builder->CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
void vm_impl<ARCH>::gen_wait(unsigned type){
|
|
||||||
std::vector<llvm::Value*> args {
|
|
||||||
this->core_ptr,
|
|
||||||
llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)),
|
|
||||||
};
|
|
||||||
this->builder->CreateCall(this->mod->getFunction("wait"), args);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock* trap_blk){
|
|
||||||
this->builder->SetInsertPoint(trap_blk);
|
|
||||||
auto* trap_state_val = this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
|
|
||||||
std::vector<llvm::Value*> args {
|
|
||||||
this->core_ptr,
|
|
||||||
this->adj_to64(trap_state_val),
|
|
||||||
this->adj_to64(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))
|
|
||||||
};
|
|
||||||
this->builder->CreateCall(this->mod->getFunction("enter_trap"), args);
|
|
||||||
auto* trap_addr_val = this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
|
|
||||||
this->builder->CreateRet(trap_addr_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH> inline
|
|
||||||
void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock* bb){
|
|
||||||
auto* v = this->builder->CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
|
|
||||||
this->gen_cond_branch(
|
|
||||||
this->builder->CreateICmp(
|
|
||||||
ICmpInst::ICMP_EQ,
|
|
||||||
v,
|
|
||||||
llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))),
|
|
||||||
bb,
|
|
||||||
this->trap_blk, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace CORE_DEF_NAME
|
|
||||||
|
|
||||||
#define CREATE_FUNCS(ARCH) \
|
|
||||||
template<> std::unique_ptr<vm_if> create<ARCH>(ARCH* core, unsigned short port, bool dump) {\
|
|
||||||
std::unique_ptr<CORE_DEF_NAME::vm_impl<ARCH> > ret = std::make_unique<CORE_DEF_NAME::vm_impl<ARCH> >(*core, dump);\
|
|
||||||
debugger::server<debugger::gdb_session>::run_server(ret.get(), port);\
|
|
||||||
return ret;\
|
|
||||||
}\
|
|
||||||
template<> std::unique_ptr<vm_if> create<ARCH>(std::string inst_name, unsigned short port, bool dump) {\
|
|
||||||
return create<ARCH>(new arch::riscv_hart_msu_vp<ARCH>(), port, dump); /* FIXME: memory leak!!!!!!! */\
|
|
||||||
}\
|
|
||||||
template<> std::unique_ptr<vm_if> create<ARCH>(ARCH* core, bool dump) {\
|
|
||||||
return std::make_unique<CORE_DEF_NAME::vm_impl<ARCH> >(*core, dump); /* FIXME: memory leak!!!!!!! */ \
|
|
||||||
}\
|
|
||||||
template<> std::unique_ptr<vm_if> create<ARCH>(std::string inst_name, bool dump) { \
|
|
||||||
return create<ARCH>(new arch::riscv_hart_msu_vp<ARCH>(), dump);\
|
|
||||||
}
|
|
||||||
|
|
||||||
CREATE_FUNCS(arch::CORE_DEF_NAME)
|
|
||||||
|
|
||||||
namespace CORE_DEF_NAME {
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::set_gen_thread(rp_thread_ref& thread) {
|
|
||||||
thread_idx=thread;
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref& thread) {
|
|
||||||
thread_idx=thread;
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::is_thread_alive(rp_thread_ref& thread, bool& alive) {
|
|
||||||
alive=1;
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* List threads. If first is non-zero then start from the first thread,
|
|
||||||
* otherwise start from arg, result points to array of threads to be
|
|
||||||
* filled out, result size is number of elements in the result,
|
|
||||||
* num points to the actual number of threads found, done is
|
|
||||||
* set if all threads are processed.
|
|
||||||
*/
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result, size_t max_num,
|
|
||||||
size_t& num, bool& done) {
|
|
||||||
if(first==0){
|
|
||||||
result.clear();
|
|
||||||
result.push_back(thread_idx);
|
|
||||||
num=1;
|
|
||||||
done=true;
|
|
||||||
return Ok;
|
|
||||||
} else
|
|
||||||
return NotSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::current_thread_query(rp_thread_ref& thread) {
|
|
||||||
thread=thread_idx;
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
|
||||||
LOG(logging::TRACE)<<"reading target registers";
|
|
||||||
//return idx<0?:;
|
|
||||||
data.clear();
|
|
||||||
avail.clear();
|
|
||||||
std::vector<uint8_t> reg_data;
|
|
||||||
for(size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no){
|
|
||||||
auto reg_bit_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no));
|
|
||||||
auto reg_width=reg_bit_width/8;
|
|
||||||
reg_data.resize(reg_width);
|
|
||||||
vm->get_arch()->get_reg(reg_no, reg_data);
|
|
||||||
for(size_t j=0; j<reg_data.size(); ++j){
|
|
||||||
data.push_back(reg_data[j]);
|
|
||||||
avail.push_back(0xff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// work around fill with F type registers
|
|
||||||
if(arch::traits<ARCH>::NUM_REGS < 65){
|
|
||||||
auto reg_width=sizeof(typename arch::traits<ARCH>::reg_t);
|
|
||||||
for(size_t reg_no = 0; reg_no < 33; ++reg_no){
|
|
||||||
for(size_t j=0; j<reg_width; ++j){
|
|
||||||
data.push_back(0x0);
|
|
||||||
avail.push_back(0x00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::write_registers(const std::vector<uint8_t>& data) {
|
|
||||||
size_t data_index=0;
|
|
||||||
auto reg_count=arch::traits<ARCH>::NUM_REGS;
|
|
||||||
std::vector<uint8_t> reg_data;
|
|
||||||
for(size_t reg_no = 0; reg_no < reg_count; ++reg_no){
|
|
||||||
auto reg_bit_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no));
|
|
||||||
auto reg_width=reg_bit_width/8;
|
|
||||||
vm->get_arch()->set_reg(reg_no, std::vector<uint8_t>(data.begin()+data_index, data.begin()+data_index+reg_width));
|
|
||||||
data_index+=reg_width;
|
|
||||||
}
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
|
||||||
if(reg_no<65){
|
|
||||||
//auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8;
|
|
||||||
data.resize(0);
|
|
||||||
vm->get_arch()->get_reg(reg_no, data);
|
|
||||||
avail.resize(data.size());
|
|
||||||
std::fill(avail.begin(), avail.end(), 0xff);
|
|
||||||
} else {
|
|
||||||
typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_READ, traits<ARCH>::CSR, reg_no-65);
|
|
||||||
data.resize(sizeof(typename traits<ARCH>::reg_t));
|
|
||||||
avail.resize(sizeof(typename traits<ARCH>::reg_t));
|
|
||||||
std::fill(avail.begin(), avail.end(), 0xff);
|
|
||||||
vm->get_arch()->read(a, data.size(), data.data());
|
|
||||||
}
|
|
||||||
return data.size()>0?Ok:Err;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t>& data) {
|
|
||||||
if(reg_no<65)
|
|
||||||
vm->get_arch()->set_reg(reg_no, data);
|
|
||||||
else {
|
|
||||||
typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_WRITE, traits<ARCH>::CSR, reg_no-65);
|
|
||||||
vm->get_arch()->write(a, data.size(), data.data());
|
|
||||||
}
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t>& data) {
|
|
||||||
auto a=map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr});
|
|
||||||
auto f = [&]()->status {
|
|
||||||
return vm->get_arch()->read(a, data.size(), data.data());
|
|
||||||
};
|
|
||||||
return srv->execute_syncronized(f);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t>& data) {
|
|
||||||
auto a=map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr});
|
|
||||||
return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) {
|
|
||||||
return NotSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) {
|
|
||||||
text=0;
|
|
||||||
data=0;
|
|
||||||
bss=0;
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t& val) {
|
|
||||||
return NotSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::raw_query(std::string in_buf, std::string& out_buf) {
|
|
||||||
return NotSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::threadinfo_query(int first, std::string& out_buf) {
|
|
||||||
if(first){
|
|
||||||
std::stringstream ss;
|
|
||||||
ss<<"m"<<std::hex<<thread_idx.val;
|
|
||||||
out_buf=ss.str();
|
|
||||||
} else {
|
|
||||||
out_buf="l";
|
|
||||||
}
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) {
|
|
||||||
char buf[20];
|
|
||||||
memset(buf, 0, 20);
|
|
||||||
sprintf (buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
|
|
||||||
out_buf=buf;
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::packetsize_query(std::string& out_buf) {
|
|
||||||
out_buf="PacketSize=1000";
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) {
|
|
||||||
auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr});
|
|
||||||
auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length});
|
|
||||||
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val);
|
|
||||||
LOG(logging::TRACE)<<"Adding breakpoint with handle "<<target_adapter_base::bp_count<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) {
|
|
||||||
auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr});
|
|
||||||
unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val);
|
|
||||||
// TODO: check length of addr range
|
|
||||||
if(handle){
|
|
||||||
LOG(logging::TRACE)<<"Removing breakpoint with handle "<<handle<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
|
||||||
target_adapter_base::bp_lut.removeEntry(handle);
|
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
|
||||||
return Ok;
|
|
||||||
}
|
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
|
||||||
return Err;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ARCH>
|
|
||||||
status target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr) {
|
|
||||||
unsigned reg_no = arch::traits<ARCH>::PC;
|
|
||||||
std::vector<uint8_t> data(8);
|
|
||||||
*(reinterpret_cast<uint64_t*>(&data[0]))=addr;
|
|
||||||
vm->get_arch()->set_reg(reg_no, data);
|
|
||||||
return resume_from_current(step, sig);
|
|
||||||
}
|
|
||||||
} // namespace CORE_DEF_NAME
|
|
||||||
} // namespace iss
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,76 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2017, MINRES Technologies GmbH
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// Created on: Tue Aug 29 16:45:20 CEST 2017
|
|
||||||
// * rv32imac.cpp Author: <CoreDSL Generator>
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "util/ities.h"
|
|
||||||
#include <util/logging.h>
|
|
||||||
|
|
||||||
#include <elfio/elfio.hpp>
|
|
||||||
#include <iss/arch/rv32imac.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#include <ihex.h>
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#include <fstream>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace iss::arch;
|
|
||||||
|
|
||||||
rv32imac::rv32imac() {
|
|
||||||
reg.icount=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv32imac::~rv32imac(){
|
|
||||||
}
|
|
||||||
|
|
||||||
void rv32imac::reset(uint64_t address) {
|
|
||||||
for(size_t i=0; i<traits<rv32imac>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<rv32imac>::reg_t),0));
|
|
||||||
reg.PC=address;
|
|
||||||
reg.NEXT_PC=reg.PC;
|
|
||||||
reg.trap_state=0;
|
|
||||||
reg.machine_state=0x3;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* rv32imac::get_regs_base_ptr(){
|
|
||||||
return reinterpret_cast<uint8_t*>(®);
|
|
||||||
}
|
|
||||||
|
|
||||||
rv32imac::phys_addr_t rv32imac::v2p(const iss::addr_t& pc) {
|
|
||||||
return phys_addr_t(pc); //change logical address to physical address
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2017, MINRES Technologies GmbH
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// Created on: Tue Sep 05 18:57:24 CEST 2017
|
|
||||||
// * rv64ia.cpp Author: <CoreDSL Generator>
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "util/ities.h"
|
|
||||||
#include <util/logging.h>
|
|
||||||
|
|
||||||
#include <elfio/elfio.hpp>
|
|
||||||
#include <iss/arch/rv64ia.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#include <ihex.h>
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#include <fstream>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace iss::arch;
|
|
||||||
|
|
||||||
rv64ia::rv64ia() {
|
|
||||||
reg.icount=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv64ia::~rv64ia(){
|
|
||||||
}
|
|
||||||
|
|
||||||
void rv64ia::reset(uint64_t address) {
|
|
||||||
for(size_t i=0; i<traits<rv64ia>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<rv64ia>::reg_t),0));
|
|
||||||
reg.PC=address;
|
|
||||||
reg.NEXT_PC=reg.PC;
|
|
||||||
reg.trap_state=0;
|
|
||||||
reg.machine_state=0x0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* rv64ia::get_regs_base_ptr(){
|
|
||||||
return reinterpret_cast<uint8_t*>(®);
|
|
||||||
}
|
|
||||||
|
|
||||||
rv64ia::phys_addr_t rv64ia::v2p(const iss::addr_t& pc) {
|
|
||||||
return phys_addr_t(pc); //change logical address to physical address
|
|
||||||
}
|
|
|
@ -39,98 +39,10 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
namespace {
|
|
||||||
const size_t ERROR_IN_COMMAND_LINE = 1;
|
const size_t ERROR_IN_COMMAND_LINE = 1;
|
||||||
const size_t SUCCESS = 0;
|
const size_t SUCCESS = 0;
|
||||||
const size_t ERROR_UNHANDLED_EXCEPTION = 2;
|
const size_t ERROR_UNHANDLED_EXCEPTION = 2;
|
||||||
|
|
||||||
|
|
||||||
inline void enable_log_level(int level){
|
|
||||||
switch(level){
|
|
||||||
case 0:
|
|
||||||
logging::Logger::reporting_level()= logging::FATAL;
|
|
||||||
/* no break */
|
|
||||||
case 1:
|
|
||||||
logging::Logger::reporting_level()= logging::ERROR;
|
|
||||||
/* no break */
|
|
||||||
case 2:
|
|
||||||
logging::Logger::reporting_level()= logging::WARNING;
|
|
||||||
/* no break */
|
|
||||||
case 3:
|
|
||||||
logging::Logger::reporting_level()= logging::INFO;
|
|
||||||
/* no break */
|
|
||||||
case 4:
|
|
||||||
logging::Logger::reporting_level()= logging::DEBUG;
|
|
||||||
/* no break */
|
|
||||||
case 5:
|
|
||||||
logging::Logger::reporting_level()= logging::TRACE;
|
|
||||||
/* no break */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void configure_default_logger(boost::program_options::variables_map& vm){
|
|
||||||
// el::Configurations defaultConf;
|
|
||||||
// defaultConf.setToDefault();
|
|
||||||
// defaultConf.set(el::Level::Error, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg");
|
|
||||||
// defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg");
|
|
||||||
// defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg");
|
|
||||||
// defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg");
|
|
||||||
// defaultConf.set(el::Level::Trace, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg");
|
|
||||||
if(vm.count("verbose"))
|
|
||||||
enable_log_level(vm["verbose"].as<int>());
|
|
||||||
if(vm.count("log-file"))
|
|
||||||
logging::Output2FILE::stream() = fopen(vm["log-file"].as<std::string>().c_str(), "w");
|
|
||||||
// default logger uses default configurations
|
|
||||||
// el::Loggers::reconfigureLogger("default", defaultConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void configure_debugger_logger() {
|
|
||||||
// configure the connection logger
|
|
||||||
// el::Logger* gdbServerLogger = el::Loggers::getLogger("connection");
|
|
||||||
// el::Configurations gdbServerConf;
|
|
||||||
// gdbServerConf.setToDefault();
|
|
||||||
// gdbServerConf.set(el::Level::Error, el::ConfigurationType::Format,
|
|
||||||
// "%datetime{%H:%m:%s.%g} %level [%logger] %msg");
|
|
||||||
// gdbServerConf.set(el::Level::Warning, el::ConfigurationType::Format,
|
|
||||||
// "%datetime{%H:%m:%s.%g} %level [%logger] %msg");
|
|
||||||
// gdbServerConf.set(el::Level::Info, el::ConfigurationType::Format,
|
|
||||||
// "%datetime{%H:%m:%s.%g} %level [%logger] %msg");
|
|
||||||
// gdbServerConf.set(el::Level::Debug, el::ConfigurationType::Format,
|
|
||||||
// "%datetime{%H:%m:%s.%g} %level [%logger] %msg");
|
|
||||||
// gdbServerConf.set(el::Level::Trace, el::ConfigurationType::Format,
|
|
||||||
// "%datetime{%H:%m:%s.%g} %level [%logger] %msg");
|
|
||||||
// enable_log_level(gdbServerConf, 5);
|
|
||||||
// gdbServerLogger->configure(gdbServerConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void configure_disass_logger(boost::program_options::variables_map& vm) {
|
|
||||||
// el::Logger* disassLogger = el::Loggers::getLogger("disass");
|
|
||||||
// el::Configurations disassConf;
|
|
||||||
// if(vm.count("disass")){
|
|
||||||
// auto file_name=vm["disass"].as<std::string>();
|
|
||||||
// disassConf.setToDefault();
|
|
||||||
// if (file_name.length() > 0) {
|
|
||||||
// disassConf.set(el::Level::Global, el::ConfigurationType::ToFile,
|
|
||||||
// std::string("true"));
|
|
||||||
// disassConf.set(el::Level::Global,
|
|
||||||
// el::ConfigurationType::ToStandardOutput, std::string("false"));
|
|
||||||
// disassConf.set(el::Level::Global, el::ConfigurationType::Format,
|
|
||||||
// std::string("%msg"));
|
|
||||||
// disassConf.set(el::Level::Global, el::ConfigurationType::Filename,
|
|
||||||
// file_name);
|
|
||||||
// std::ofstream str(file_name); // just to clear the file
|
|
||||||
// } else {
|
|
||||||
// disassConf.set(el::Level::Global, el::ConfigurationType::Format,
|
|
||||||
// "%datetime{%H:%m:%s.%g} [%logger] %msg");
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// enable_log_level(disassConf, 0);
|
|
||||||
// }
|
|
||||||
// disassLogger->configure(disassConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
inline int parse_cli_options(boost::program_options::variables_map& vm, int argc, char *argv[]){
|
inline int parse_cli_options(boost::program_options::variables_map& vm, int argc, char *argv[]){
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
po::options_description desc("Options");
|
po::options_description desc("Options");
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <util/sparse_array.h>
|
#include <util/sparse_array.h>
|
||||||
#include <elfio/elfio.hpp>
|
#include <elfio/elfio.hpp>
|
||||||
#include <util/logging.h>
|
#include <iss/log_categories.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -628,9 +628,9 @@ template<typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t& addr, unsigned length, uint8_t* const data){
|
iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t& addr, unsigned length, uint8_t* const data){
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if(addr.type& iss::DEBUG){
|
if(addr.type& iss::DEBUG){
|
||||||
LOG(logging::DEBUG)<<"debug read of "<<length<<" bytes @addr "<<addr;
|
LOG(DEBUG)<<"debug read of "<<length<<" bytes @addr "<<addr;
|
||||||
} else {
|
} else {
|
||||||
LOG(logging::DEBUG)<<"read of "<<length<<" bytes @addr "<<addr;
|
LOG(DEBUG)<<"read of "<<length<<" bytes @addr "<<addr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
switch(addr.space){
|
switch(addr.space){
|
||||||
|
@ -726,19 +726,19 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t& addr, unsigned len
|
||||||
const char* prefix = addr.type & iss::DEBUG?"debug ":"";
|
const char* prefix = addr.type & iss::DEBUG?"debug ":"";
|
||||||
switch(length){
|
switch(length){
|
||||||
case 8:
|
case 8:
|
||||||
LOG(logging::DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint64_t*)&data[0]<<std::dec<<") @addr "<<addr;
|
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint64_t*)&data[0]<<std::dec<<") @addr "<<addr;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
LOG(logging::DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint32_t*)&data[0]<<std::dec<<") @addr "<<addr;
|
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint32_t*)&data[0]<<std::dec<<") @addr "<<addr;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
LOG(logging::DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint16_t*)&data[0]<<std::dec<<") @addr "<<addr;
|
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint16_t*)&data[0]<<std::dec<<") @addr "<<addr;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
LOG(logging::DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<(uint16_t)data[0]<<std::dec<<") @addr "<<addr;
|
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<(uint16_t)data[0]<<std::dec<<") @addr "<<addr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(logging::DEBUG)<<prefix<<"write of "<<length<<" bytes @addr "<<addr;
|
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes @addr "<<addr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
|
@ -965,14 +965,14 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t addr, unsigned length
|
||||||
switch(hostvar>>48){
|
switch(hostvar>>48){
|
||||||
case 0:
|
case 0:
|
||||||
if(hostvar!=0x1)
|
if(hostvar!=0x1)
|
||||||
LOG(logging::FATAL)<<"tohost value is 0x"<<std::hex<<hostvar<<std::dec<<" ("<<hostvar<<"), stopping simulation";
|
LOG(FATAL)<<"tohost value is 0x"<<std::hex<<hostvar<<std::dec<<" ("<<hostvar<<"), stopping simulation";
|
||||||
else
|
else
|
||||||
LOG(logging::INFO)<<"tohost value is 0x"<<std::hex<<hostvar<<std::dec<<" ("<<hostvar<<"), stopping simulation";
|
LOG(INFO)<<"tohost value is 0x"<<std::hex<<hostvar<<std::dec<<" ("<<hostvar<<"), stopping simulation";
|
||||||
throw(iss::simulation_stopped(hostvar));
|
throw(iss::simulation_stopped(hostvar));
|
||||||
case 0x0101:{
|
case 0x0101:{
|
||||||
char c = static_cast<char>(hostvar & 0xff);
|
char c = static_cast<char>(hostvar & 0xff);
|
||||||
if(c=='\n' || c==0){
|
if(c=='\n' || c==0){
|
||||||
LOG(logging::INFO)<<"tohost send '"<<uart_buf.str()<<"'";
|
LOG(INFO)<<"tohost send '"<<uart_buf.str()<<"'";
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
} else
|
} else
|
||||||
uart_buf<<c;
|
uart_buf<<c;
|
||||||
|
@ -1190,7 +1190,7 @@ uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr) {
|
||||||
this->reg.trap_state=0;
|
this->reg.trap_state=0;
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "0x%016lx", addr);
|
sprintf(buffer, "0x%016lx", addr);
|
||||||
CLOG(logging::INFO, "disass")<<(trap_id?"Interrupt ":"Trap ")<<trap_id<<" with cause '"<<irq_str[cause]<<"' at address "<<buffer
|
CLOG(INFO, disass)<<(trap_id?"Interrupt ":"Trap ")<<trap_id<<" with cause '"<<irq_str[cause]<<"' at address "<<buffer
|
||||||
<<" occurred, changing privilege level from "<<lvl[cur_priv]<<" to "<<lvl[new_priv];
|
<<" occurred, changing privilege level from "<<lvl[cur_priv]<<" to "<<lvl[new_priv];
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
@ -1230,7 +1230,7 @@ uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t flags) {
|
||||||
status|= pie<<inst_priv; // and set the pie
|
status|= pie<<inst_priv; // and set the pie
|
||||||
csr[mstatus]=status;
|
csr[mstatus]=status;
|
||||||
this->reg.machine_state=ppl;
|
this->reg.machine_state=ppl;
|
||||||
CLOG(logging::INFO, "disass")<<"Executing xRET , changing privilege level from "<<lvl[cur_priv]<<" to "<<lvl[ppl];
|
CLOG(INFO, disass)<<"Executing xRET , changing privilege level from "<<lvl[cur_priv]<<" to "<<lvl[ppl];
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -521,7 +521,7 @@ namespace CORE_DEF_NAME {
|
||||||
|
|
||||||
template<typename ARCH>
|
template<typename ARCH>
|
||||||
status target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
status target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
||||||
LOG(logging::TRACE)<<"reading target registers";
|
LOG(TRACE)<<"reading target registers";
|
||||||
//return idx<0?:;
|
//return idx<0?:;
|
||||||
data.clear();
|
data.clear();
|
||||||
avail.clear();
|
avail.clear();
|
||||||
|
@ -663,8 +663,8 @@ namespace CORE_DEF_NAME {
|
||||||
auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr});
|
auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr});
|
||||||
auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length});
|
auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length});
|
||||||
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val);
|
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val);
|
||||||
LOG(logging::TRACE)<<"Adding breakpoint with handle "<<target_adapter_base::bp_count<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
LOG(TRACE)<<"Adding breakpoint with handle "<<target_adapter_base::bp_count<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,12 +674,12 @@ namespace CORE_DEF_NAME {
|
||||||
unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val);
|
unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val);
|
||||||
// TODO: check length of addr range
|
// TODO: check length of addr range
|
||||||
if(handle){
|
if(handle){
|
||||||
LOG(logging::TRACE)<<"Removing breakpoint with handle "<<handle<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
LOG(TRACE)<<"Removing breakpoint with handle "<<handle<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
||||||
target_adapter_base::bp_lut.removeEntry(handle);
|
target_adapter_base::bp_lut.removeEntry(handle);
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Err;
|
return Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4708,7 +4708,7 @@ namespace rv32imac {
|
||||||
|
|
||||||
template<typename ARCH>
|
template<typename ARCH>
|
||||||
status target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
status target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
||||||
LOG(logging::TRACE)<<"reading target registers";
|
LOG(TRACE)<<"reading target registers";
|
||||||
//return idx<0?:;
|
//return idx<0?:;
|
||||||
data.clear();
|
data.clear();
|
||||||
avail.clear();
|
avail.clear();
|
||||||
|
@ -4850,8 +4850,8 @@ namespace rv32imac {
|
||||||
auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr});
|
auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr});
|
||||||
auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length});
|
auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length});
|
||||||
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val);
|
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val);
|
||||||
LOG(logging::TRACE)<<"Adding breakpoint with handle "<<target_adapter_base::bp_count<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
LOG(TRACE)<<"Adding breakpoint with handle "<<target_adapter_base::bp_count<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4861,12 +4861,12 @@ namespace rv32imac {
|
||||||
unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val);
|
unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val);
|
||||||
// TODO: check length of addr range
|
// TODO: check length of addr range
|
||||||
if(handle){
|
if(handle){
|
||||||
LOG(logging::TRACE)<<"Removing breakpoint with handle "<<handle<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
LOG(TRACE)<<"Removing breakpoint with handle "<<handle<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
||||||
target_adapter_base::bp_lut.removeEntry(handle);
|
target_adapter_base::bp_lut.removeEntry(handle);
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Err;
|
return Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3710,7 +3710,7 @@ namespace rv64ia {
|
||||||
|
|
||||||
template<typename ARCH>
|
template<typename ARCH>
|
||||||
status target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
status target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
||||||
LOG(logging::TRACE)<<"reading target registers";
|
LOG(TRACE)<<"reading target registers";
|
||||||
//return idx<0?:;
|
//return idx<0?:;
|
||||||
data.clear();
|
data.clear();
|
||||||
avail.clear();
|
avail.clear();
|
||||||
|
@ -3852,8 +3852,8 @@ namespace rv64ia {
|
||||||
auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr});
|
auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr});
|
||||||
auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length});
|
auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length});
|
||||||
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val);
|
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val);
|
||||||
LOG(logging::TRACE)<<"Adding breakpoint with handle "<<target_adapter_base::bp_count<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
LOG(TRACE)<<"Adding breakpoint with handle "<<target_adapter_base::bp_count<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3863,12 +3863,12 @@ namespace rv64ia {
|
||||||
unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val);
|
unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val);
|
||||||
// TODO: check length of addr range
|
// TODO: check length of addr range
|
||||||
if(handle){
|
if(handle){
|
||||||
LOG(logging::TRACE)<<"Removing breakpoint with handle "<<handle<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
LOG(TRACE)<<"Removing breakpoint with handle "<<handle<<" for addr 0x"<<std::hex<<saddr.val<<std::dec;
|
||||||
target_adapter_base::bp_lut.removeEntry(handle);
|
target_adapter_base::bp_lut.removeEntry(handle);
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
LOG(logging::TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
LOG(TRACE)<<"Now having "<<target_adapter_base::bp_lut.size()<<" breakpoints";
|
||||||
return Err;
|
return Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <iss/iss.h>
|
#include <iss/iss.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <iss/log_categories.h>
|
||||||
#include <iss/arch/rv32imac.h>
|
#include <iss/arch/rv32imac.h>
|
||||||
#include <iss/arch/rv64ia.h>
|
#include <iss/arch/rv64ia.h>
|
||||||
#include <iss/jit/MCJIThelper.h>
|
#include <iss/jit/MCJIThelper.h>
|
||||||
|
@ -46,13 +47,22 @@ namespace po= boost::program_options;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
try{
|
try{
|
||||||
/** Define and parse the program options
|
/*
|
||||||
|
* Define and parse the program options
|
||||||
*/
|
*/
|
||||||
po::variables_map vm;
|
po::variables_map vm;
|
||||||
if(parse_cli_options(vm, argc, argv)) return ERROR_IN_COMMAND_LINE;
|
if(parse_cli_options(vm, argc, argv)) return ERROR_IN_COMMAND_LINE;
|
||||||
configure_default_logger(vm);
|
if(vm.count("verbose")){
|
||||||
|
auto l = logging::as_log_level(vm["verbose"].as<int>());
|
||||||
|
LOGGER(DEFAULT)::reporting_level() = l;
|
||||||
|
LOGGER(connection)::reporting_level()=l;
|
||||||
|
}
|
||||||
|
if(vm.count("log-file")){
|
||||||
// configure the connection logger
|
// configure the connection logger
|
||||||
configure_debugger_logger();
|
auto f = fopen(vm["log-file"].as<std::string>().c_str(), "w");
|
||||||
|
LOG_OUTPUT(DEFAULT)::stream() = f;
|
||||||
|
LOG_OUTPUT(connection)::stream() = f;
|
||||||
|
}
|
||||||
|
|
||||||
// application code comes here //
|
// application code comes here //
|
||||||
iss::init_jit(argc, argv);
|
iss::init_jit(argc, argv);
|
||||||
|
@ -77,9 +87,15 @@ int main(int argc, char *argv[]) {
|
||||||
cpu->get_arch()->load_file(vm["mem"].as<std::string>() , iss::arch::traits<iss::arch::rv32imac>::MEM);
|
cpu->get_arch()->load_file(vm["mem"].as<std::string>() , iss::arch::traits<iss::arch::rv32imac>::MEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_disass_logger(vm);
|
|
||||||
if(vm.count("disass")){
|
if(vm.count("disass")){
|
||||||
cpu->setDisassEnabled(true);
|
cpu->setDisassEnabled(true);
|
||||||
|
LOGGER(disass)::reporting_level()=logging::INFO;
|
||||||
|
auto file_name=vm["disass"].as<std::string>();
|
||||||
|
if (file_name.length() > 0) {
|
||||||
|
LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w");
|
||||||
|
LOGGER(disass)::print_time() = false;
|
||||||
|
LOGGER(disass)::print_severity() = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(vm.count("reset")){
|
if(vm.count("reset")){
|
||||||
auto str = vm["reset"].as<std::string>();
|
auto str = vm["reset"].as<std::string>();
|
||||||
|
@ -90,7 +106,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
return cpu->start(vm["cycles"].as<int64_t>());
|
return cpu->start(vm["cycles"].as<int64_t>());
|
||||||
} catch(std::exception& e){
|
} catch(std::exception& e){
|
||||||
LOG(logging::ERROR) << "Unhandled Exception reached the top of main: "
|
LOG(ERROR) << "Unhandled Exception reached the top of main: "
|
||||||
<< e.what() << ", application will now exit" << std::endl;
|
<< e.what() << ", application will now exit" << std::endl;
|
||||||
return ERROR_UNHANDLED_EXCEPTION;
|
return ERROR_UNHANDLED_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4bc26642e349906f6e81619ea8a26bf533c3f46f
|
Subproject commit 46d79504a8a5a6a9541b19a6774fb8161350a0a4
|
Loading…
Reference in New Issue