This is an automated email from Gerrit. "liangzhen <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9219
-- gerrit commit cb45fd55181af39c9d009054bdbff9fcd4993146 Author: liangzhen <[email protected]> Date: Sat Nov 1 21:37:01 2025 +0800 target/riscv: rvtrace: Add trace atbbridge support Add support for the trace atbbridge component. Change-Id: I5c882dede3d24888910428b58069f24925aa93e0 Signed-off-by: liangzhen <[email protected]> diff --git a/doc/openocd.texi b/doc/openocd.texi index 28c7102c2c..be091f6d1f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11700,6 +11700,7 @@ rvtrace component types are: @itemize @item @code{encoder} - this a rvtrace encoder component. @item @code{funnel} - this a rvtrace funnel component. +@item @code{atbbridge} - this a rvtrace atbbridge component. @end itemize @end deffn @@ -11845,6 +11846,11 @@ The commands specific to the @code{funnel} are: read from the funnel timestamp register with the symbolic name @var{reg_name}. @end itemize +@subsection ATB-Bridge Component +When the rvtrace component is a @code{atbbridge} type, the configure configparams +specific to the @code{atbbridge} is @option{-id} @emph{id}. @emph{id} Values of +0x00 and 0x70-0x7F are reserved by the ATB specification and should not be used. + @section RISC-V Architecture @uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG diff --git a/src/target/riscv/Makefile.am b/src/target/riscv/Makefile.am index 5460506135..ce23b1f88e 100644 --- a/src/target/riscv/Makefile.am +++ b/src/target/riscv/Makefile.am @@ -20,4 +20,5 @@ noinst_LTLIBRARIES += %D%/libriscv.la %D%/riscv_trace.c \ %D%/trace_encoder.c \ %D%/trace_funnel.c \ - %D%/trace_timestamp.c + %D%/trace_timestamp.c \ + %D%/trace_atbbridge.c diff --git a/src/target/riscv/riscv_trace.c b/src/target/riscv/riscv_trace.c index c50c585daf..2c8d358e5d 100644 --- a/src/target/riscv/riscv_trace.c +++ b/src/target/riscv/riscv_trace.c @@ -27,6 +27,7 @@ static OOCD_LIST_HEAD(all_rvtrace_component); static struct rvtrace_type *rvtrace_type[] = { &rvtrace_encoder, &rvtrace_funnel, + &rvtrace_atbbridge, }; int rvtrace_write_reg(const struct rvtrace_component *comp, unsigned int reg, uint32_t value) diff --git a/src/target/riscv/riscv_trace.h b/src/target/riscv/riscv_trace.h index fe881cbc4c..9c0ad19853 100644 --- a/src/target/riscv/riscv_trace.h +++ b/src/target/riscv/riscv_trace.h @@ -127,5 +127,6 @@ extern const struct command_registration rv_timestamp_command_handlers[]; extern struct rvtrace_type rvtrace_encoder; extern struct rvtrace_type rvtrace_funnel; +extern struct rvtrace_type rvtrace_atbbridge; #endif /* OPENOCD_TARGET_RISCV_RISCV_TRACE_H */ diff --git a/src/target/riscv/trace_atbbridge.c b/src/target/riscv/trace_atbbridge.c new file mode 100644 index 0000000000..c1a6c4adf1 --- /dev/null +++ b/src/target/riscv/trace_atbbridge.c @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/*************************************************************************** + * Copyright (C) 2025 by liangzhen * + * [email protected] * + ***************************************************************************/ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <helper/log.h> +#include <helper/types.h> +#include <helper/command.h> +#include <helper/jim-nvp.h> +#include "riscv_trace.h" + +#define RVTRACE_ATBBRIDGE_CTRL 0x000 +#define RVTRACE_ATBBRIDGE_IMPL 0x004 + +/* register description */ +/* trAtbBridgeControl */ +#define RVTRACE_ATBBRIDGE_CTRL_ACTIVE 0x1 +#define RVTRACE_ATBBRIDGE_CTRL_ENABLE 0x2 +#define RVTRACE_ATBBRIDGE_CTRL_EMPTY 0x8 +#define RVTRACE_ATBBRIDGE_CTRL_ID 0x7f00 + +#define RVTRACE_ATBBRIDGE_CTRL_ID_MAX 0x6f + +struct rv_atbbridge_info { + bool was_enabled; +}; + +struct rv_atbbridge_private_config { + uint32_t id; +}; + +static inline struct rv_atbbridge_info *rv_atbbridge_info(struct rvtrace_component *comp) +{ + assert(comp->component_info); + return comp->component_info; +} + +static inline struct rv_atbbridge_private_config *rv_atbbridge_private_config(struct rvtrace_component *comp) +{ + assert(comp->private_config); + return comp->private_config; +} + +#define RV_ATBBRIDGE_INFO(R) struct rv_atbbridge_info *R = rv_atbbridge_info(comp); + +static struct rv_atbbridge_private_config *alloc_default_rv_atbbridge_private_config(void) +{ + struct rv_atbbridge_private_config *config = malloc(sizeof(struct rv_atbbridge_private_config)); + if (!config) { + LOG_ERROR("Out of memory!"); + return NULL; + } + + /* 0 is reserved by the ATB specification and should not be used. */ + config->id = 1; + + return config; +} + +static const struct { + uint32_t offset; + const char *label; +} atbbridge_names[] = { + { RVTRACE_ATBBRIDGE_CTRL, "CONTROL" }, + { RVTRACE_ATBBRIDGE_IMPL, "IMPL" }, +}; + +static int atbbridge_find_reg_offset(const char *name) +{ + for (size_t i = 0; i < ARRAY_SIZE(atbbridge_names); i++) { + if (!strcasecmp(name, atbbridge_names[i].label)) + return atbbridge_names[i].offset; + } + + LOG_ERROR("unknown rvtrace atbbridge register %s", name); + return -1; +} + +static int atbbridge_create(struct rvtrace_component *comp) +{ + LOG_DEBUG("atbbridge_create()"); + struct rv_atbbridge_private_config *config = comp->private_config; + if (!config) { + config = alloc_default_rv_atbbridge_private_config(); + if (!config) + return ERROR_FAIL; + comp->private_config = config; + } + comp->component_info = calloc(1, sizeof(struct rv_atbbridge_info)); + if (!comp->component_info) { + LOG_ERROR("Failed to allocate atbbridge info structure."); + return ERROR_FAIL; + } + return ERROR_OK; +} +enum rv_atbbridge_cfg_opts { + CS_ATBBRIDGE_CFG_ID, +}; + +static struct jim_nvp nvp_config_opts[] = { + { .name = "-id", .value = CS_ATBBRIDGE_CFG_ID }, + { .name = NULL, .value = -1 } +}; + +static int atbbridge_jim_configure(struct rvtrace_component *comp, struct jim_getopt_info *goi) +{ + struct rv_atbbridge_private_config *config = comp->private_config; + if (!config) { + config = alloc_default_rv_atbbridge_private_config(); + if (!config) + return JIM_ERR; + comp->private_config = config; + } + + if (!goi->argc) + return JIM_OK; + + struct jim_nvp *n; + int e = jim_nvp_name2value_obj(goi->interp, nvp_config_opts, goi->argv[0], &n); + + if (e != JIM_OK) + return JIM_CONTINUE; + + e = jim_getopt_obj(goi, NULL); + if (e != JIM_OK) + return e; + + if (!goi->is_configure && goi->argc > 0) { + /*no arguments */ + Jim_WrongNumArgs(goi->interp, 2, goi->argv - 2, ""); + return JIM_ERR; + } + + switch (n->value) { + case CS_ATBBRIDGE_CFG_ID: + if (goi->is_configure) { + jim_wide w; + e = jim_getopt_wide(goi, &w); + if (e != JIM_OK) + return e; + if (w < 1 && w > RVTRACE_ATBBRIDGE_CTRL_ID_MAX) { + Jim_SetResultString(goi->interp, "Invalid ID!", -1); + return JIM_ERR; + } + config->id = (uint32_t)w; + } else { + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, config->id)); + } + break; + } + return JIM_OK; +} +static int atbbridge_enable(struct rvtrace_component *comp) +{ + RV_ATBBRIDGE_INFO(info); + + if (info->was_enabled) + return ERROR_OK; + + struct rv_atbbridge_private_config *config = rv_atbbridge_private_config(comp); + + uint32_t ctrl = set_field(0, RVTRACE_ATBBRIDGE_CTRL_ID, config->id); + if (rvtrace_write_reg(comp, RVTRACE_ATBBRIDGE_CTRL, ctrl) != ERROR_OK) + return ERROR_FAIL; + + if (rvtrace_enable_component(comp) != ERROR_OK) + return ERROR_FAIL; + + info->was_enabled = true; + + return ERROR_OK; +} + +static int atbbridge_disable(struct rvtrace_component *comp) +{ + RV_ATBBRIDGE_INFO(info); + + if (!info->was_enabled) + return ERROR_OK; + + if (rvtrace_disable_component(comp) != ERROR_OK) + return ERROR_FAIL; + + if (rvtrace_poll_register(comp, RVTRACE_ATBBRIDGE_CTRL, RVTRACE_ATBBRIDGE_CTRL_EMPTY, 1) != ERROR_OK) + return ERROR_FAIL; + + info->was_enabled = false; + + return ERROR_OK; +} + +static int atbbridge_status(struct rvtrace_component *comp,struct command_invocation *cmd) +{ + uint32_t ctrl; + + if (rvtrace_read_reg(comp, RVTRACE_ATBBRIDGE_CTRL, &ctrl) != ERROR_OK) + return ERROR_FAIL; + + command_print(cmd, "Control: %s", + get_field(ctrl, RVTRACE_ATBBRIDGE_CTRL_ENABLE) ? "enabled" : "disabled"); + command_print(cmd, "Empty: %d", get_field(ctrl, RVTRACE_ATBBRIDGE_CTRL_EMPTY)); + command_print(cmd, "ID: 0x%x", get_field(ctrl, RVTRACE_ATBBRIDGE_CTRL_ID)); + + return ERROR_OK; +} + +static int atbbridge_write(struct rvtrace_component *comp, const char *reg_name, uint32_t value) +{ + int offset = atbbridge_find_reg_offset(reg_name); + if (offset < 0) + return ERROR_FAIL; + + return rvtrace_write_reg(comp, offset, value); +} + +static int atbbridge_read(struct rvtrace_component *comp, const char *reg_name, uint32_t *value) +{ + int offset = atbbridge_find_reg_offset(reg_name); + if (offset < 0) + return ERROR_FAIL; + + return rvtrace_read_reg(comp, offset, value); +} + +struct rvtrace_type rvtrace_atbbridge = { + .name = "atbbridge", + .id_type = RVTRACE_COMPONENT_TYPE_ATBBRIDGE, + .version = rvtrace_component_mkversion(1, 0), + + .rvtrace_create = atbbridge_create, + .rvtrace_jim_configure = atbbridge_jim_configure, + + .enable = atbbridge_enable, + .disable = atbbridge_disable, + .status = atbbridge_status, + .write = atbbridge_write, + .read = atbbridge_read, +}; --
