Improved disassembly of running ISS
This commit is contained in:
@ -40,6 +40,7 @@
|
||||
#include "iss/instrumentation_if.h"
|
||||
#include "iss/log_categories.h"
|
||||
#include "iss/vm_if.h"
|
||||
#include <fmt/format.h>
|
||||
#include <array>
|
||||
#include <elfio/elfio.hpp>
|
||||
#include <iomanip>
|
||||
@ -478,10 +479,8 @@ public:
|
||||
void wait_until(uint64_t flags) override;
|
||||
|
||||
void disass_output(uint64_t pc, const std::string instr) override {
|
||||
std::stringstream s;
|
||||
s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0')
|
||||
<< std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]";
|
||||
CLOG(INFO, disass) << "0x" << std::setw(16) << std::setfill('0') << std::hex << pc << "\t\t" << instr << "\t" << s.str();
|
||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]",
|
||||
pc, instr, lvl[this->reg.machine_state], (reg_t)state.mstatus, this->reg.icount);
|
||||
};
|
||||
|
||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||
|
@ -1,53 +1,59 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017, MINRES Technologies GmbH
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef _RV32GC_H_
|
||||
#define _RV32GC_H_
|
||||
|
||||
#include <array>
|
||||
#include <iss/arch/traits.h>
|
||||
#include <iss/arch_if.h>
|
||||
#include <iss/vm_if.h>
|
||||
#include <iss/arch/traits.h>
|
||||
#include <array>
|
||||
|
||||
namespace iss {
|
||||
namespace arch {
|
||||
|
||||
struct rv32gc;
|
||||
|
||||
template<>
|
||||
struct traits<rv32gc> {
|
||||
template <> struct traits<rv32gc> {
|
||||
|
||||
constexpr static char const* const core_type = "RV32GC";
|
||||
|
||||
static constexpr std::array<const char*, 66> reg_names{
|
||||
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}};
|
||||
|
||||
static constexpr std::array<const char*, 66> reg_aliases{
|
||||
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}};
|
||||
|
||||
enum constants {XLEN=32, FLEN=64, PCLEN=32, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff};
|
||||
|
||||
constexpr static unsigned FP_REGS_SIZE = 64;
|
||||
@ -125,7 +131,39 @@ struct traits<rv32gc> {
|
||||
PENDING_TRAP,
|
||||
MACHINE_STATE,
|
||||
LAST_BRANCH,
|
||||
ICOUNT
|
||||
ICOUNT,
|
||||
ZERO = X0,
|
||||
RA = X1,
|
||||
SP = X2,
|
||||
GP = X3,
|
||||
TP = X4,
|
||||
T0 = X5,
|
||||
T1 = X6,
|
||||
T2 = X7,
|
||||
S0 = X8,
|
||||
S1 = X9,
|
||||
A0 = X10,
|
||||
A1 = X11,
|
||||
A2 = X12,
|
||||
A3 = X13,
|
||||
A4 = X14,
|
||||
A5 = X15,
|
||||
A6 = X16,
|
||||
A7 = X17,
|
||||
S2 = X18,
|
||||
S3 = X19,
|
||||
S4 = X20,
|
||||
S5 = X21,
|
||||
S6 = X22,
|
||||
S7 = X23,
|
||||
S8 = X24,
|
||||
S9 = X25,
|
||||
S10 = X26,
|
||||
S11 = X27,
|
||||
T3 = X28,
|
||||
T4 = X29,
|
||||
T5 = X30,
|
||||
T6 = X31
|
||||
};
|
||||
|
||||
using reg_t = uint32_t;
|
||||
@ -138,21 +176,17 @@ struct traits<rv32gc> {
|
||||
|
||||
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
|
||||
|
||||
constexpr static unsigned reg_bit_width(unsigned r) {
|
||||
constexpr std::array<const uint32_t, 72> RV32GC_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,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,32,32,32,64}};
|
||||
return RV32GC_reg_size[r];
|
||||
}
|
||||
static constexpr std::array<const uint32_t, 72> reg_bit_widths{
|
||||
{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,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,32,32,32,64}};
|
||||
|
||||
constexpr static unsigned reg_byte_offset(unsigned r) {
|
||||
constexpr std::array<const uint32_t, 73> RV32GC_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,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}};
|
||||
return RV32GC_reg_byte_offset[r];
|
||||
}
|
||||
static constexpr std::array<const uint32_t, 73> reg_byte_offsets{
|
||||
{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}};
|
||||
|
||||
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
|
||||
|
||||
enum sreg_flag_e {FLAGS};
|
||||
enum sreg_flag_e { FLAGS };
|
||||
|
||||
enum mem_type_e {MEM, CSR, FENCE, RES};
|
||||
enum mem_type_e { MEM, CSR, FENCE, RES };
|
||||
};
|
||||
|
||||
struct rv32gc: public arch_if {
|
||||
@ -177,14 +211,13 @@ struct rv32gc: public arch_if {
|
||||
/// deprecated
|
||||
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
|
||||
|
||||
uint64_t get_icount() { return reg.icount;}
|
||||
inline uint64_t get_icount() { return reg.icount; }
|
||||
|
||||
inline bool should_stop() { return interrupt_sim; }
|
||||
|
||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
||||
if(addr.space != traits<rv32gc>::MEM ||
|
||||
addr.type == iss::address_type::PHYSICAL ||
|
||||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){
|
||||
if (addr.space != traits<rv32gc>::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<rv32gc>::addr_mask);
|
||||
} else
|
||||
return virt2phys(addr);
|
||||
@ -194,8 +227,7 @@ struct rv32gc: public arch_if {
|
||||
|
||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||
|
||||
inline
|
||||
uint32_t get_last_branch(){return reg.last_branch;}
|
||||
inline uint32_t get_last_branch() { return reg.last_branch; }
|
||||
|
||||
protected:
|
||||
struct RV32GC_regs {
|
||||
|
@ -30,6 +30,7 @@
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef _RV32IMAC_H_
|
||||
#define _RV32IMAC_H_
|
||||
|
||||
@ -45,15 +46,15 @@ struct rv32imac;
|
||||
|
||||
template <> struct traits<rv32imac> {
|
||||
|
||||
constexpr static char const *const core_type = "RV32IMAC";
|
||||
constexpr static char const* const core_type = "RV32IMAC";
|
||||
|
||||
static constexpr std::array<const char*, 33> reg_names{
|
||||
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc"}};
|
||||
|
||||
static constexpr std::array<const char*, 33> reg_aliases{
|
||||
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}};
|
||||
|
||||
enum constants {
|
||||
XLEN = 32,
|
||||
PCLEN = 32,
|
||||
MISA_VAL = 0b1000000000101000001000100000101,
|
||||
PGSIZE = 0x1000,
|
||||
PGMASK = 0xfff
|
||||
};
|
||||
enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000101000001000100000101, PGSIZE=0x1000, PGMASK=0xfff};
|
||||
|
||||
constexpr static unsigned FP_REGS_SIZE = 0;
|
||||
|
||||
@ -92,35 +93,61 @@ template <> struct traits<rv32imac> {
|
||||
X31,
|
||||
PC,
|
||||
NUM_REGS,
|
||||
NEXT_PC = NUM_REGS,
|
||||
NEXT_PC=NUM_REGS,
|
||||
TRAP_STATE,
|
||||
PENDING_TRAP,
|
||||
MACHINE_STATE,
|
||||
LAST_BRANCH,
|
||||
ICOUNT
|
||||
ICOUNT,
|
||||
ZERO = X0,
|
||||
RA = X1,
|
||||
SP = X2,
|
||||
GP = X3,
|
||||
TP = X4,
|
||||
T0 = X5,
|
||||
T1 = X6,
|
||||
T2 = X7,
|
||||
S0 = X8,
|
||||
S1 = X9,
|
||||
A0 = X10,
|
||||
A1 = X11,
|
||||
A2 = X12,
|
||||
A3 = X13,
|
||||
A4 = X14,
|
||||
A5 = X15,
|
||||
A6 = X16,
|
||||
A7 = X17,
|
||||
S2 = X18,
|
||||
S3 = X19,
|
||||
S4 = X20,
|
||||
S5 = X21,
|
||||
S6 = X22,
|
||||
S7 = X23,
|
||||
S8 = X24,
|
||||
S9 = X25,
|
||||
S10 = X26,
|
||||
S11 = X27,
|
||||
T3 = X28,
|
||||
T4 = X29,
|
||||
T5 = X30,
|
||||
T6 = X31
|
||||
};
|
||||
|
||||
using reg_t = uint32_t;
|
||||
|
||||
using addr_t = uint32_t;
|
||||
|
||||
using code_word_t = uint32_t; // TODO: check removal
|
||||
using code_word_t = uint32_t; //TODO: check removal
|
||||
|
||||
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
|
||||
|
||||
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
|
||||
|
||||
static constexpr std::array<const uint32_t, 39> RV32IMAC_reg_size{
|
||||
{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 64}};
|
||||
static constexpr std::array<const uint32_t, 39> reg_bit_widths{
|
||||
{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}};
|
||||
|
||||
constexpr static unsigned reg_bit_width(unsigned r) { return RV32IMAC_reg_size[r]; }
|
||||
|
||||
static constexpr std::array<const uint32_t, 40> RV32IMAC_reg_byte_offset{
|
||||
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76,
|
||||
80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 160}};
|
||||
|
||||
constexpr static unsigned reg_byte_offset(unsigned r) { return RV32IMAC_reg_byte_offset[r]; }
|
||||
static constexpr std::array<const uint32_t, 40> reg_byte_offsets{
|
||||
{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,160}};
|
||||
|
||||
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
|
||||
|
||||
@ -129,41 +156,41 @@ template <> struct traits<rv32imac> {
|
||||
enum mem_type_e { MEM, CSR, FENCE, RES };
|
||||
};
|
||||
|
||||
struct rv32imac : public arch_if {
|
||||
struct rv32imac: public arch_if {
|
||||
|
||||
using virt_addr_t = typename traits<rv32imac>::virt_addr_t;
|
||||
using phys_addr_t = typename traits<rv32imac>::phys_addr_t;
|
||||
using reg_t = typename traits<rv32imac>::reg_t;
|
||||
using reg_t = typename traits<rv32imac>::reg_t;
|
||||
using addr_t = typename traits<rv32imac>::addr_t;
|
||||
|
||||
rv32imac();
|
||||
~rv32imac();
|
||||
|
||||
void reset(uint64_t address = 0) override;
|
||||
void reset(uint64_t address=0) override;
|
||||
|
||||
uint8_t *get_regs_base_ptr() override;
|
||||
uint8_t* get_regs_base_ptr() override;
|
||||
/// deprecated
|
||||
void get_reg(short idx, std::vector<uint8_t> &value) override {}
|
||||
void set_reg(short idx, const std::vector<uint8_t> &value) override {}
|
||||
void get_reg(short idx, std::vector<uint8_t>& value) override {}
|
||||
void set_reg(short idx, const std::vector<uint8_t>& value) override {}
|
||||
/// deprecated
|
||||
bool get_flag(int flag) override { return false; }
|
||||
void set_flag(int, bool value) override{};
|
||||
bool get_flag(int flag) override {return false;}
|
||||
void set_flag(int, bool value) override {};
|
||||
/// deprecated
|
||||
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{};
|
||||
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
|
||||
|
||||
inline uint64_t get_icount() { return reg.icount; }
|
||||
|
||||
inline bool should_stop() { return interrupt_sim; }
|
||||
|
||||
inline phys_addr_t v2p(const iss::addr_t &addr) {
|
||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
||||
if (addr.space != traits<rv32imac>::MEM || addr.type == iss::address_type::PHYSICAL ||
|
||||
addr_mode[static_cast<uint16_t>(addr.access) & 0x3] == address_type::PHYSICAL) {
|
||||
return phys_addr_t(addr.access, addr.space, addr.val & traits<rv32imac>::addr_mask);
|
||||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
|
||||
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32imac>::addr_mask);
|
||||
} else
|
||||
return virt2phys(addr);
|
||||
}
|
||||
|
||||
virtual phys_addr_t virt2phys(const iss::addr_t &addr);
|
||||
virtual phys_addr_t virt2phys(const iss::addr_t& addr);
|
||||
|
||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||
|
||||
@ -210,12 +237,14 @@ protected:
|
||||
} reg;
|
||||
|
||||
std::array<address_type, 4> addr_mode;
|
||||
|
||||
bool interrupt_sim=false;
|
||||
|
||||
bool interrupt_sim = false;
|
||||
uint32_t get_fcsr(){return 0;}
|
||||
void set_fcsr(uint32_t val){}
|
||||
|
||||
uint32_t get_fcsr() { return 0; }
|
||||
void set_fcsr(uint32_t val) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* _RV32IMAC_H_ */
|
||||
|
@ -1,53 +1,59 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017, MINRES Technologies GmbH
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifndef _RV64IA_H_
|
||||
#define _RV64IA_H_
|
||||
|
||||
#include <array>
|
||||
#include <iss/arch/traits.h>
|
||||
#include <iss/arch_if.h>
|
||||
#include <iss/vm_if.h>
|
||||
#include <iss/arch/traits.h>
|
||||
#include <array>
|
||||
|
||||
namespace iss {
|
||||
namespace arch {
|
||||
|
||||
struct rv64ia;
|
||||
|
||||
template<>
|
||||
struct traits<rv64ia> {
|
||||
template <> struct traits<rv64ia> {
|
||||
|
||||
constexpr static char const* const core_type = "RV64IA";
|
||||
|
||||
static constexpr std::array<const char*, 33> reg_names{
|
||||
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc"}};
|
||||
|
||||
static constexpr std::array<const char*, 33> reg_aliases{
|
||||
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}};
|
||||
|
||||
enum constants {XLEN=64, PCLEN=64, MISA_VAL=0b10000000000001000000000100000001, PGSIZE=0x1000, PGMASK=0xfff};
|
||||
|
||||
constexpr static unsigned FP_REGS_SIZE = 0;
|
||||
@ -92,7 +98,39 @@ struct traits<rv64ia> {
|
||||
PENDING_TRAP,
|
||||
MACHINE_STATE,
|
||||
LAST_BRANCH,
|
||||
ICOUNT
|
||||
ICOUNT,
|
||||
ZERO = X0,
|
||||
RA = X1,
|
||||
SP = X2,
|
||||
GP = X3,
|
||||
TP = X4,
|
||||
T0 = X5,
|
||||
T1 = X6,
|
||||
T2 = X7,
|
||||
S0 = X8,
|
||||
S1 = X9,
|
||||
A0 = X10,
|
||||
A1 = X11,
|
||||
A2 = X12,
|
||||
A3 = X13,
|
||||
A4 = X14,
|
||||
A5 = X15,
|
||||
A6 = X16,
|
||||
A7 = X17,
|
||||
S2 = X18,
|
||||
S3 = X19,
|
||||
S4 = X20,
|
||||
S5 = X21,
|
||||
S6 = X22,
|
||||
S7 = X23,
|
||||
S8 = X24,
|
||||
S9 = X25,
|
||||
S10 = X26,
|
||||
S11 = X27,
|
||||
T3 = X28,
|
||||
T4 = X29,
|
||||
T5 = X30,
|
||||
T6 = X31
|
||||
};
|
||||
|
||||
using reg_t = uint64_t;
|
||||
@ -105,21 +143,17 @@ struct traits<rv64ia> {
|
||||
|
||||
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
|
||||
|
||||
constexpr static unsigned reg_bit_width(unsigned r) {
|
||||
constexpr std::array<const uint32_t, 39> 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,32,64}};
|
||||
return RV64IA_reg_size[r];
|
||||
}
|
||||
static constexpr std::array<const uint32_t, 39> reg_bit_widths{
|
||||
{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,32,64}};
|
||||
|
||||
constexpr static unsigned reg_byte_offset(unsigned r) {
|
||||
constexpr std::array<const uint32_t, 40> 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,284,288,296}};
|
||||
return RV64IA_reg_byte_offset[r];
|
||||
}
|
||||
static constexpr std::array<const uint32_t, 40> reg_byte_offsets{
|
||||
{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,284,288,296}};
|
||||
|
||||
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
|
||||
|
||||
enum sreg_flag_e {FLAGS};
|
||||
enum sreg_flag_e { FLAGS };
|
||||
|
||||
enum mem_type_e {MEM, CSR, FENCE, RES};
|
||||
enum mem_type_e { MEM, CSR, FENCE, RES };
|
||||
};
|
||||
|
||||
struct rv64ia: public arch_if {
|
||||
@ -149,9 +183,8 @@ struct rv64ia: public arch_if {
|
||||
inline bool should_stop() { return interrupt_sim; }
|
||||
|
||||
inline phys_addr_t v2p(const iss::addr_t& addr){
|
||||
if(addr.space != traits<rv64ia>::MEM ||
|
||||
addr.type == iss::address_type::PHYSICAL ||
|
||||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){
|
||||
if (addr.space != traits<rv64ia>::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<rv64ia>::addr_mask);
|
||||
} else
|
||||
return virt2phys(addr);
|
||||
@ -161,8 +194,7 @@ struct rv64ia: public arch_if {
|
||||
|
||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||
|
||||
inline
|
||||
uint32_t get_last_branch(){return reg.last_branch;}
|
||||
inline uint32_t get_last_branch() { return reg.last_branch; }
|
||||
|
||||
protected:
|
||||
struct RV64IA_regs {
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <fmt/format.h>
|
||||
#include <util/logging.h>
|
||||
|
||||
namespace iss {
|
||||
@ -180,8 +181,8 @@ status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, st
|
||||
avail.clear();
|
||||
const uint8_t *reg_base = core->get_regs_base_ptr();
|
||||
for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) {
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8;
|
||||
unsigned offset = traits<ARCH>::reg_byte_offset(reg_no);
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
|
||||
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||
for (size_t j = 0; j < reg_width; ++j) {
|
||||
data.push_back(*(reg_base + offset + j));
|
||||
avail.push_back(0xff);
|
||||
@ -215,8 +216,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
|
||||
auto *reg_base = core->get_regs_base_ptr();
|
||||
auto iter = data.data();
|
||||
for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) {
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8;
|
||||
auto offset = traits<ARCH>::reg_byte_offset(reg_no);
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
|
||||
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||
std::copy(iter, iter + reg_width, reg_base);
|
||||
iter += 4;
|
||||
reg_base += offset;
|
||||
@ -231,10 +232,10 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
|
||||
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
|
||||
// arch::traits<ARCH>::reg_e>(reg_no))/8;
|
||||
auto *reg_base = core->get_regs_base_ptr();
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_width(reg_no) / 8;
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
|
||||
data.resize(reg_width);
|
||||
avail.resize(reg_width);
|
||||
auto offset = traits<ARCH>::reg_byte_offset(reg_no);
|
||||
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
|
||||
std::fill(avail.begin(), avail.end(), 0xff);
|
||||
} else {
|
||||
@ -251,8 +252,8 @@ template <typename ARCH>
|
||||
status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) {
|
||||
if (reg_no < 65) {
|
||||
auto *reg_base = core->get_regs_base_ptr();
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8;
|
||||
auto offset = traits<ARCH>::reg_byte_offset(reg_no);
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
|
||||
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
|
||||
} else {
|
||||
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65);
|
||||
@ -296,9 +297,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::strin
|
||||
|
||||
template <typename ARCH> status riscv_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();
|
||||
out_buf = fmt::format("m{:x}", thread_idx.val);
|
||||
} else {
|
||||
out_buf = "l";
|
||||
}
|
||||
@ -348,8 +347,8 @@ template <typename ARCH>
|
||||
status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
|
||||
std::function<void(unsigned)> stop_callback) {
|
||||
auto *reg_base = core->get_regs_base_ptr();
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_width(arch::traits<ARCH>::PC) / 8;
|
||||
auto offset = traits<ARCH>::reg_byte_offset(arch::traits<ARCH>::PC);
|
||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8;
|
||||
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
|
||||
const uint8_t *iter = reinterpret_cast<const uint8_t *>(&addr);
|
||||
std::copy(iter, iter + reg_width, reg_base);
|
||||
return resume_from_current(step, sig, thread, stop_callback);
|
||||
|
Reference in New Issue
Block a user