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,
+};

-- 

Reply via email to