Skip to content

Commit

Permalink
riscv: add single register access, add csr access with an offset, exp…
Browse files Browse the repository at this point in the history
…ose some CSRs register in the xml description
  • Loading branch information
mean authored and dragonmux committed Oct 31, 2023
1 parent a032220 commit 11ec1f1
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/target/riscv32.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ typedef struct riscv32_regs {
#define RV32_MATCH_BEFORE 0x00000000U
#define RV32_MATCH_AFTER 0x00040000U

static ssize_t riscv32_reg_read(target_s *target, uint32_t c, void *data, size_t max);
static ssize_t riscv32_reg_write(target_s *target, uint32_t c, const void *data, size_t max);
static void riscv32_regs_read(target_s *target, void *data);
static void riscv32_regs_write(target_s *target, const void *data);
static void riscv32_mem_read(target_s *target, void *dest, target_addr_t src, size_t len);
Expand All @@ -81,6 +83,8 @@ bool riscv32_probe(target_s *const target)
target->regs_size = sizeof(riscv32_regs_s);
target->regs_read = riscv32_regs_read;
target->regs_write = riscv32_regs_write;
target->reg_write = riscv32_reg_write;
target->reg_read = riscv32_reg_read;
target->mem_read = riscv32_mem_read;
target->mem_write = riscv32_mem_write;

Expand Down Expand Up @@ -120,6 +124,41 @@ static void riscv32_regs_write(target_s *const target, const void *const data)
riscv_csr_write(hart, RV_DPC, &regs->pc);
}

static inline ssize_t riscv32_bool_to_4(const bool ret)
{
return ret ? 4 : -1;
}

static ssize_t riscv32_reg_read(target_s *target, const uint32_t reg, void *data, const size_t max)
{
if (max != 4)
return -1;
/* Grab the hart structure */
riscv_hart_s *const hart = riscv_hart_struct(target);
if (reg < 32)
return riscv32_bool_to_4(riscv_csr_read(hart, RV_GPR_BASE + reg, data));
if (reg == 32)
return riscv32_bool_to_4(riscv_csr_read(hart, RV_DPC, data));
if (reg >= RV_CSR_GDB_OFFSET)
return riscv32_bool_to_4(riscv_csr_read(hart, reg - RV_CSR_GDB_OFFSET, data));
return -1;
}

static ssize_t riscv32_reg_write(target_s *const target, const uint32_t reg, const void *data, const size_t max)
{
if (max != 4)
return -1;
/* Grab the hart structure */
riscv_hart_s *const hart = riscv_hart_struct(target);
if (reg < 32)
return riscv32_bool_to_4(riscv_csr_write(hart, RV_GPR_BASE + reg, data));
if (reg == 32)
return riscv32_bool_to_4(riscv_csr_write(hart, RV_DPC, data));
if (reg >= RV_CSR_GDB_OFFSET)
return riscv32_bool_to_4(riscv_csr_write(hart, reg - RV_CSR_GDB_OFFSET, data));
return -1;
}

/* Takes in data from abstract command arg0 and, based on the access width, unpacks it to dest */
void riscv32_unpack_data(void *const dest, const uint32_t data, const uint8_t access_width)
{
Expand Down
29 changes: 29 additions & 0 deletions src/target/riscv_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,24 @@ static const char *const riscv_gpr_names[RV_GPRS_COUNT] = {
"s8", "s9", "s10", "s11",
"t3", "t4", "t5", "t6",
};

typedef struct riscv_csr_descriptor {
const char *name;
const uint32_t csr_number; // fits in 16 bits actually (?)
} riscv_csr_descriptor_s;

static const riscv_csr_descriptor_s riscv_csrs[]={
{"mstatus",RV_CSR_STATUS},
{"misa",RV_CSR_MISA},
{"mie", RV_CSR_MIE},
{"mtvec", RV_CSR_MTVEC},
{"tscratch",RV_CSR_MSCRATCH},
{"mepc", RV_CSR_MEPC},
{"mcause",RV_CSR_MCAUSE},
{"mtval", RV_CSR_MTVAL},
{"mip", RV_CSR_MIP},
};

// clang-format on

/* General-purpose register types */
Expand Down Expand Up @@ -945,6 +963,17 @@ static size_t riscv_build_target_description(

/* XXX: TODO - implement generation of the FPU feature and registers */

/* Add main CSR registers*/
if (max_length != 0)
print_size = max_length - (size_t)offset;
offset += snprintf(buffer + offset, print_size, "</feature><feature name=\"org.gnu.gdb.riscv.csr\">");
for (size_t i = 0; i < ARRAY_LENGTH(riscv_csrs); i++) {
if (max_length != 0)
print_size = max_length - (size_t)offset;
offset += snprintf(buffer + offset, print_size, " <reg name=\"%s\" bitsize=\"%u\" regnum=\"%" PRIu32 "\" %s/>",
riscv_csrs[i].name, address_width, riscv_csrs[i].csr_number + RV_CSR_GDB_OFFSET,
gdb_reg_save_restore_strings[GDB_SAVE_RESTORE_NO]);
}
/* Add the closing tags required */
if (max_length != 0)
print_size = max_length - (size_t)offset;
Expand Down
14 changes: 14 additions & 0 deletions src/target/riscv_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,20 @@ typedef struct riscv_hart {
#define RV_TRIGGER_MODE_MASK 0xffff0000U
#define RV_TRIGGER_SUPPORT_BREAKWATCH 0x00000004U

// The CSR id when reported by GDB is shifted by RV_CSR_GDB_OFFSET
// so they cannot collide with GPR registers, so you have to substract
// RV_CSR_GDB_OFFSET from the value received from gdb
#define RV_CSR_GDB_OFFSET 128
#define RV_CSR_STATUS 0x300
#define RV_CSR_MISA 0x301
#define RV_CSR_MIE 0x304
#define RV_CSR_MTVEC 0x305
#define RV_CSR_MSCRATCH 0x340
#define RV_CSR_MEPC 0x341
#define RV_CSR_MCAUSE 0x342
#define RV_CSR_MTVAL 0x343
#define RV_CSR_MIP 0x344

#define RV_TOPT_INHIBIT_NRST 0x00000001U

void riscv_jtag_dtm_handler(uint8_t dev_index);
Expand Down

0 comments on commit 11ec1f1

Please sign in to comment.