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/+/9216

-- gerrit

commit fd0bd8e6432a4f1d9a687d86378b480d4c52d087
Author: liangzhen <[email protected]>
Date:   Sat Nov 1 23:03:13 2025 +0800

    target/riscv: rvtrace: Add trace encoder support
    
    Add support for the trace encoder component.
    
    Change-Id: I10e0f023a5252c1c317df69f868dbf276279d9de
    Signed-off-by: liangzhen <[email protected]>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 2aee6f92b7..9ebec22821 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -11697,6 +11697,9 @@ or @option{-target} @emph{target_name} here.
 @deffn {Command} {rvtrace types}
 Lists all supported rvtrace component types. At this writing, the supported
 rvtrace component types are:
+@itemize
+@item @code{encoder} - this a rvtrace encoder component.
+@end itemize
 @end deffn
 
 @deffn {Command} {rvtrace names}
@@ -11757,6 +11760,55 @@ Write @var{value} to the rvtrace component register 
with the symbolic name @var{
 Print the value read from the rvtrace component register with the symbolic 
name @var{reg_name}.
 @end deffn
 
+@subsection Encoder Component
+When the rvtrace component is a @code{encoder} type, the configure configparams
+specific to the @code{encoder} are:
+@itemize
+@item @option{-inst-mode} @code{off|resv1|resv2|btm|resv4|resv5|htm|resv7} - 
sets
+the instruction trace generation mode
+@item @option{-context} @code{on|off} - sets to allow sending trace 
messages/fields
+and/or privilege levels using sontext/mcontext values.
+@item @option{-trigger} @code{on|off} - sets to allow trTeInstTracing to be 
set or
+cleared by Trace-on and Traceoff signals generated by the corresponding 
trigger module.
+@item @option{-stall} @code{on|off} - sets if encoder cannot send a message, 
the
+hart is stalled until it can.
+@item @option{-inhb-src} @code{on|off} - disable inclusion of source field in 
trace
+messages/packets.
+@item @option{-sync-mode} @code{off|messages|clock|instruction} - sets the 
periodic
+instruction trace synchronization message/packet generation mechanism.
+@item @option{-sync-max} @emph{value} - The maximum interval (determined by
+@option{-sync-mode}) between instruction trace synchronization 
messages/packets.
+@item @option{-fulladdr} @code{on|off} - sets the trace messages/packets always
+carry a full address.
+@item @option{-no-trapaddr} @code{on|off} - sets do not include trap handler
+address in trap messages/packets.
+@item @option{-seq-jump} @code{on|off} - sets to treat sequentially inferrable
+jumps as inferable PC discontinuities.
+@item @option{-implicit-return} @code{on|off} - sets to treat returns as 
inferable
+PC discontinuities when returning from a recent call on a stack.
+@item @option{-branch-prediction} @code{on|off} - sets the Branch Predictor 
based
+compression is enabled.
+@item @option{-jump-target-cache} @code{on|off} - sets the Jump Target Cache 
based
+compression is enabled.
+@item @option{-implicit-return-mode} @code{no|simple|partial|full} - sets how 
the
+decoder is handling stack of return addresses(if @option{-implicit-return} 
@code{on}).
+@item @option{-repeated-history} @code{on|off} - sets enable repeated branch
+history/map detection.
+@item @option{-all-jumps} @code{on|off} - sets Enable emitting of trace message
+or add history/map bit for direct unconditional/inferable control flow changes
+(jumps or calls).
+@item @option{-ext-msb} @code{on|off} - sets to allow extended handing of MSB
+address bits.
+@item @option{-srcid} @emph{id} - Trace source ID assigned to this trace 
encoder.
+@item @option{-srcbits} @emph{num} - The number of bits in the trace source
+field (0..12), unless disabled by @option{-inhb-src} @code{on}.
+@end itemize
+The commands specific to the @code{encoder} are:
+@itemize
+@item @command{component_name encoder start} - start instruction trace.
+@item @command{component_name encoder stop} - stop instruction trace.
+@end itemize
+
 @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 8d53da48ee..541ab38386 100644
--- a/src/target/riscv/Makefile.am
+++ b/src/target/riscv/Makefile.am
@@ -17,4 +17,5 @@ noinst_LTLIBRARIES += %D%/libriscv.la
        %D%/riscv-013.c \
        %D%/riscv.c \
        %D%/riscv_semihosting.c \
-       %D%/riscv_trace.c
+       %D%/riscv_trace.c \
+       %D%/trace_encoder.c
diff --git a/src/target/riscv/riscv_trace.c b/src/target/riscv/riscv_trace.c
index 88321e6d9b..c3fc36a00a 100644
--- a/src/target/riscv/riscv_trace.c
+++ b/src/target/riscv/riscv_trace.c
@@ -25,6 +25,7 @@
 static OOCD_LIST_HEAD(all_rvtrace_component);
 
 static struct rvtrace_type *rvtrace_type[] = {
+       &rvtrace_encoder,
 };
 
 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 0aea588258..5d039f836a 100644
--- a/src/target/riscv/riscv_trace.h
+++ b/src/target/riscv/riscv_trace.h
@@ -102,4 +102,6 @@ int rvtrace_cleanup_all(void);
 
 int rvtrace_register_commands(struct command_context *cmd_ctx);
 
+extern struct rvtrace_type rvtrace_encoder;
+
 #endif /* OPENOCD_TARGET_RISCV_RISCV_TRACE_H */
diff --git a/src/target/riscv/trace_encoder.c b/src/target/riscv/trace_encoder.c
new file mode 100644
index 0000000000..b752775033
--- /dev/null
+++ b/src/target/riscv/trace_encoder.c
@@ -0,0 +1,912 @@
+/* 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_ENCODER_CTRL                               0x000
+#define RVTRACE_ENCODER_IMPL                               0x004
+#define RVTRACE_ENCODER_INSTFEAT                           0x008
+
+/* register description */
+/* trTeControl - 0x000 */
+#define RVTRACE_ENCODER_CTRL_ACTIVE                        0x1
+#define RVTRACE_ENCODER_CTRL_ENABLE                        0x2
+#define RVTRACE_ENCODER_CTRL_ITRACE                        0x4
+#define RVTRACE_ENCODER_CTRL_EMPTY                         0x8
+#define RVTRACE_ENCODER_CTRL_INSTMODE                      0x70
+#define RVTRACE_ENCODER_CTRL_CONTEXT                       0x200
+#define RVTRACE_ENCODER_CTRL_INSTTRIGENABLE                0x800
+#define RVTRACE_ENCODER_CTRL_INSTSTALLOROVERFLOW           0x1000
+#define RVTRACE_ENCODER_CTRL_INSTSTALLENA                  0x2000
+#define RVTRACE_ENCODER_CTRL_INHIBITSRC                            0x8000
+#define RVTRACE_ENCODER_CTRL_INSTSYNCMODE                  0x30000
+#define RVTRACE_ENCODER_CTRL_INSTSYNCMAX                   0xf00000
+#define RVTRACE_ENCODER_CTRL_FORMAT                        0x7000000
+/* trTeInstFeatures - 0x008 */
+#define RVTRACE_ENCODER_INSTFEAT_NOADDRDIFF                0x1
+#define RVTRACE_ENCODER_INSTFEAT_NOTRAPADDR                0x2
+#define RVTRACE_ENCODER_INSTFEAT_ENSEQUENTIALJUMP          0x4
+#define RVTRACE_ENCODER_INSTFEAT_ENIMPLICITRETURN          0x8
+#define RVTRACE_ENCODER_INSTFEAT_ENBRANCHPREDICTION        0x10
+#define RVTRACE_ENCODER_INSTFEAT_ENJUMPTARGETCACHE         0x20
+#define RVTRACE_ENCODER_INSTFEAT_IMPLICITRETURNMODE        0xc0
+#define RVTRACE_ENCODER_INSTFEAT_ENREPEATEDHISTORT         0x100
+#define RVTRACE_ENCODER_INSTFEAT_ENALLJUMPS                0x200
+#define RVTRACE_ENCODER_INSTFEAT_EXTENDADDRMSB             0x400
+#define RVTRACE_ENCODER_INSTFEAT_SRCID                     0xfff0000
+#define RVTRACE_ENCODER_INSTFEAT_SRCBITS                   0xf0000000
+
+#define RVTRACE_ENCODER_CTRL_INSTSYNCMAX_MAXVAL                    0xf
+
+#define RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAXVAL                    0xc
+
+enum rvtrace_format {
+       RVTRACE_FORMAT_ETRACE,
+       RVTRACE_FORMAT_NTRACE,
+       RVTRACE_FORMAT_UNKNOWN = 7
+};
+
+struct rv_encoder_info {
+       bool was_enabled;
+       enum rvtrace_format format;
+};
+
+enum inst_mode {
+       INSTMODE_OFF,
+       INSTMODE_RESV1,
+       INSTMODE_RESV2,
+       INSTMODE_BTM,
+       INSTMODE_RESV4,
+       INSTMODE_RESV5,
+       INSTMODE_HTM,
+       INSTMODE_RESV7
+};
+
+enum sync_mode {
+       SYNCMODE_OFF,
+       SYNCMODE_MESSAGES,
+       SYNCMODE_CLOCK,
+       SYNCMODE_INSTRUCTION
+};
+
+enum implicit_return_mode {
+       IMPLICITRETURNMODE_NOT_SUPPORTED,
+       IMPLICITRETURNMODE_SIMPLE_COUNTING,
+       IMPLICITRETURNMODE_PARTIAL_ADDRESS,
+       IMPLICITRETURNMODE_FULL_ADDRESS
+};
+
+struct rv_encoder_private_config {
+       uint32_t inst_mode;
+       bool context;
+       bool trigger;
+       bool stall;
+       bool inhb_src;
+       enum sync_mode sync_mode;
+       uint32_t sync_max;
+       bool fulladdr;
+       bool no_trapaddr;
+       bool seq_jump;
+       bool implicit_return;
+       bool branch_prediction;
+       bool jump_target_cache;
+       enum implicit_return_mode implicit_return_mode;
+       bool repeated_history;
+       bool all_jumps;
+       bool ext_msb;
+       uint32_t srcid;
+       uint32_t srcbits;
+};
+
+static inline struct rv_encoder_info *rv_encoder_info(struct rvtrace_component 
*comp)
+{
+       assert(comp->component_info);
+       return comp->component_info;
+}
+
+static inline struct rv_encoder_private_config 
*rv_encoder_private_config(struct rvtrace_component *comp)
+{
+       assert(comp->private_config);
+       return comp->private_config;
+}
+
+#define RV_ENCODER_INFO(R) struct rv_encoder_info *R = rv_encoder_info(comp);
+
+static struct rv_encoder_private_config 
*alloc_default_rv_encoder_private_config(void)
+{
+       struct rv_encoder_private_config *config =  malloc(sizeof(struct 
rv_encoder_private_config));
+       if (!config) {
+               LOG_ERROR("Out of memory!");
+               return NULL;
+       }
+
+       /* The trTeInstMode WARL field should be set to 6 - it may revert to 
different mode */
+       config->inst_mode = INSTMODE_HTM;
+       config->context = true;
+       config->trigger = true;
+       config->sync_mode = SYNCMODE_CLOCK;
+       config->sync_max = RVTRACE_ENCODER_CTRL_INSTSYNCMAX_MAXVAL;
+
+       return config;
+}
+
+static const struct {
+       uint32_t offset;
+       const char *label;
+} encoder_names[] = {
+       { RVTRACE_ENCODER_CTRL, "CONTROL" },
+       { RVTRACE_ENCODER_IMPL, "IMPL" },
+       { RVTRACE_ENCODER_INSTFEAT, "INSTFEATURES" },
+};
+
+static int encoder_find_reg_offset(const char *name)
+{
+       for (size_t i = 0; i < ARRAY_SIZE(encoder_names); i++) {
+               if (!strcasecmp(name, encoder_names[i].label))
+                       return encoder_names[i].offset;
+       }
+
+       LOG_ERROR("unknown coresight encoder register %s", name);
+       return -1;
+}
+
+static int encoder_create(struct rvtrace_component *comp)
+{
+       LOG_DEBUG("encoder_create()");
+       struct rv_encoder_private_config *config = comp->private_config;
+       if (!config) {
+               config = alloc_default_rv_encoder_private_config();
+               if (!config)
+                       return ERROR_FAIL;
+               comp->private_config = config;
+       }
+       comp->component_info = calloc(1, sizeof(struct rv_encoder_info));
+       if (!comp->component_info) {
+               LOG_ERROR("Failed to allocate encoder info structure.");
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
+static struct jim_nvp nvp_inst_mode_opts[] = {
+       { .name = "off", .value = INSTMODE_OFF },
+       { .name = "resv1", .value = INSTMODE_RESV1 },
+       { .name = "resv2", .value = INSTMODE_RESV2 },
+       { .name = "btm", .value = INSTMODE_BTM },
+       { .name = "resv4", .value = INSTMODE_RESV4 },
+       { .name = "resv5", .value = INSTMODE_RESV5 },
+       { .name = "htm", .value = INSTMODE_HTM },
+       { .name = "resv7", .value = INSTMODE_RESV7 },
+       { .name = NULL, .value = -1 },
+};
+
+static struct jim_nvp nvp_sync_mode_opts[] = {
+       { .name = "off", .value = SYNCMODE_OFF },
+       { .name = "messages", .value = SYNCMODE_MESSAGES },
+       { .name = "clock", .value = SYNCMODE_CLOCK },
+       { .name = "instruction", .value = SYNCMODE_INSTRUCTION },
+       { .name = NULL, .value = -1 },
+};
+
+static struct jim_nvp nvp_implicit_return_mode_opts[] = {
+       { .name = "no", .value = IMPLICITRETURNMODE_NOT_SUPPORTED },
+       { .name = "simple", .value = IMPLICITRETURNMODE_SIMPLE_COUNTING},
+       { .name = "partial", .value = IMPLICITRETURNMODE_PARTIAL_ADDRESS },
+       { .name = "full", .value = IMPLICITRETURNMODE_FULL_ADDRESS },
+       { .name = NULL, .value = -1 },
+};
+
+static struct jim_nvp nvp_on_off_opts[] = {
+       { .name = "off", .value = false },
+       { .name = "on", .value = true },
+       { .name = NULL, .value = -1 }
+};
+
+enum rv_encoder_cfg_opts {
+       RV_ENCODER_CFG_INST_MODE,
+       RV_ENCODER_CFG_CONTEXT,
+       RV_ENCODER_CFG_TRIGGER,
+       RV_ENCODER_CFG_STALL,
+       RV_ENCODER_CFG_INHB_SRC,
+       RV_ENCODER_CFG_SYNC_MODE,
+       RV_ENCODER_CFG_SYNC_MAX,
+       RV_ENCODER_CFG_FULLADDR,
+       RV_ENCODER_CFG_NO_TRAPADDR,
+       RV_ENCODER_CFG_SEQ_JUMP,
+       RV_ENCODER_CFG_IMPLICIT_RETURN,
+       RV_ENCODER_CFG_BRANCH_PREDICTION,
+       RV_ENCODER_CFG_JUMP_TARGET_CACHE,
+       RV_ENCODER_CFG_IMPLICIT_RETURN_MODE,
+       RV_ENCODER_CFG_REPEATED_HISTORY,
+       RV_ENCODER_CFG_ALL_JUMPS,
+       RV_ENCODER_CFG_EXT_MSB,
+       RV_ENCODER_CFG_SRCID,
+       RV_ENCODER_CFG_SRCBITS
+};
+
+static struct jim_nvp nvp_config_opts[] = {
+       { .name = "-inst-mode", .value = RV_ENCODER_CFG_INST_MODE },
+       { .name = "-context", .value = RV_ENCODER_CFG_CONTEXT },
+       { .name = "-trigger", .value = RV_ENCODER_CFG_TRIGGER },
+       { .name = "-stall", .value = RV_ENCODER_CFG_STALL },
+       { .name = "-inhb-src", .value = RV_ENCODER_CFG_INHB_SRC },
+       { .name = "-sync-mode", .value = RV_ENCODER_CFG_SYNC_MODE },
+       { .name = "-sync-max", .value = RV_ENCODER_CFG_SYNC_MAX },
+       { .name = "-fulladdr", .value = RV_ENCODER_CFG_FULLADDR },
+       { .name = "-no-trapaddr", .value = RV_ENCODER_CFG_NO_TRAPADDR },
+       { .name = "-seq-jump", .value = RV_ENCODER_CFG_SEQ_JUMP },
+       { .name = "-implicit-return", .value = RV_ENCODER_CFG_IMPLICIT_RETURN },
+       { .name = "-branch-prediction", .value = 
RV_ENCODER_CFG_BRANCH_PREDICTION },
+       { .name = "-jump-target-cache", .value = 
RV_ENCODER_CFG_JUMP_TARGET_CACHE },
+       { .name = "-implicit-return-mode", .value = 
RV_ENCODER_CFG_IMPLICIT_RETURN_MODE },
+       { .name = "-repeated-history", .value = RV_ENCODER_CFG_REPEATED_HISTORY 
},
+       { .name = "-all-jumps", .value = RV_ENCODER_CFG_ALL_JUMPS },
+       { .name = "-ext-msb", .value = RV_ENCODER_CFG_EXT_MSB },
+       { .name = "-srcid", .value = RV_ENCODER_CFG_SRCID },
+       { .name = "-srcbits", .value = RV_ENCODER_CFG_SRCBITS },
+       { .name = NULL, .value = -1 }
+};
+
+static int encoder_jim_configure(struct rvtrace_component *comp, struct 
jim_getopt_info *goi)
+{
+       struct rv_encoder_private_config *config = comp->private_config;
+       if (!config) {
+               config = alloc_default_rv_encoder_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 RV_ENCODER_CFG_INST_MODE:
+               if (goi->is_configure) {
+                       struct jim_nvp *inst_mode_nvp;
+                       e = jim_getopt_nvp(goi, nvp_inst_mode_opts, 
&inst_mode_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_inst_mode_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->inst_mode = inst_mode_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_inst_mode_opts, 
config->inst_mode)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_CONTEXT:
+               if (goi->is_configure) {
+                       struct jim_nvp *context_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, &context_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->context = context_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->context)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_TRIGGER:
+               if (goi->is_configure) {
+                       struct jim_nvp *trigger_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, &trigger_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->trigger = trigger_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->trigger)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_STALL:
+               if (goi->is_configure) {
+                       struct jim_nvp *stall_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, &stall_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->stall = stall_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->stall)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_INHB_SRC:
+               if (goi->is_configure) {
+                       struct jim_nvp *inhb_src_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, &inhb_src_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->inhb_src = inhb_src_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->inhb_src)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_SYNC_MODE:
+               if (goi->is_configure) {
+                       struct jim_nvp *sync_mode_nvp;
+                       e = jim_getopt_nvp(goi, nvp_sync_mode_opts, 
&sync_mode_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_sync_mode_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->sync_mode = sync_mode_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_sync_mode_opts, 
config->sync_mode)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_SYNC_MAX:
+               if (goi->is_configure) {
+                       jim_wide w;
+                       e = jim_getopt_wide(goi, &w);
+                       if (e != JIM_OK)
+                               return e;
+                       if (w > RVTRACE_ENCODER_CTRL_INSTSYNCMAX_MAXVAL) {
+                               Jim_SetResultString(goi->interp, "Invalid sync 
max value(>15)!", -1);
+                       }
+                       config->sync_max = (uint32_t)w;
+               } else {
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, 
config->sync_max));
+               }
+               break;
+       case RV_ENCODER_CFG_FULLADDR:
+               if (goi->is_configure) {
+                       struct jim_nvp *fulladdr_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, &fulladdr_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->fulladdr = fulladdr_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->fulladdr)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_NO_TRAPADDR:
+               if (goi->is_configure) {
+                       struct jim_nvp *no_trapaddr_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, 
&no_trapaddr_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->no_trapaddr = no_trapaddr_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->no_trapaddr)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_SEQ_JUMP:
+               if (goi->is_configure) {
+                       struct jim_nvp *seq_jump_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, &seq_jump_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->seq_jump = seq_jump_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->seq_jump)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_IMPLICIT_RETURN:
+               if (goi->is_configure) {
+                       struct jim_nvp *implicit_return_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, 
&implicit_return_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->implicit_return = implicit_return_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->implicit_return)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_BRANCH_PREDICTION:
+               if (goi->is_configure) {
+                       struct jim_nvp *branch_prediction_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, 
&branch_prediction_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->branch_prediction = 
branch_prediction_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->branch_prediction)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_JUMP_TARGET_CACHE:
+               if (goi->is_configure) {
+                       struct jim_nvp *jump_target_cache_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, 
&jump_target_cache_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->jump_target_cache = 
jump_target_cache_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->jump_target_cache)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_IMPLICIT_RETURN_MODE:
+               if (goi->is_configure) {
+                       struct jim_nvp *implicit_return_mode_nvp;
+                       e = jim_getopt_nvp(goi, nvp_implicit_return_mode_opts, 
&implicit_return_mode_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, 
nvp_implicit_return_mode_opts, /*hadprefix*/ true);
+                               return e;
+                       }
+                       config->implicit_return_mode = 
implicit_return_mode_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_sync_mode_opts, 
config->implicit_return_mode)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_REPEATED_HISTORY:
+               if (goi->is_configure) {
+                       struct jim_nvp *repeated_history_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, 
&repeated_history_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->repeated_history = repeated_history_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->repeated_history)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_ALL_JUMPS:
+               if (goi->is_configure) {
+                       struct jim_nvp *all_jumps_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, 
&all_jumps_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->all_jumps = all_jumps_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->all_jumps)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_EXT_MSB:
+               if (goi->is_configure) {
+                       struct jim_nvp *ext_msb_nvp;
+                       e = jim_getopt_nvp(goi, nvp_on_off_opts, &ext_msb_nvp);
+                       if (e != JIM_OK) {
+                               jim_getopt_nvp_unknown(goi, nvp_on_off_opts, 
/*hadprefix*/ true);
+                               return e;
+                       }
+                       config->ext_msb = ext_msb_nvp->value;
+               } else {
+                       Jim_SetResultString(goi->interp,
+                               jim_nvp_value2name_simple(nvp_on_off_opts, 
config->ext_msb)->name, -1);
+               }
+               break;
+       case RV_ENCODER_CFG_SRCID:
+               if (goi->is_configure) {
+                       jim_wide w;
+                       e = jim_getopt_wide(goi, &w);
+                       if (e != JIM_OK)
+                               return e;
+                       if (w > (1 << RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAXVAL) 
- 1) {
+                               Jim_SetResultString(goi->interp, "Invalid 
source id(>4095)!", -1);
+                       }
+                       config->srcid = (uint32_t)w;
+               } else {
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, 
config->srcid));
+               }
+               break;
+       case RV_ENCODER_CFG_SRCBITS:
+               if (goi->is_configure) {
+                       jim_wide w;
+                       e = jim_getopt_wide(goi, &w);
+                       if (e != JIM_OK)
+                               return e;
+                       if (w > RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAXVAL) {
+                               Jim_SetResultString(goi->interp, "Invalid 
source bits (>12)!", -1);
+                       }
+                       config->srcid = (uint32_t)w;
+               } else {
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, 
config->srcid));
+               }
+               break;
+       }
+       return JIM_OK;
+}
+
+static int encoder_set_config(struct rvtrace_component *comp)
+{
+       struct rv_encoder_private_config *config = 
rv_encoder_private_config(comp);
+       uint32_t ctrl, features, field_rb;
+
+       if (rvtrace_read_reg(comp, RVTRACE_ENCODER_CTRL, &ctrl) != ERROR_OK)
+               return ERROR_FAIL;
+
+       ctrl = set_field(ctrl, RVTRACE_ENCODER_CTRL_INSTMODE, 
config->inst_mode);
+       ctrl = set_field(ctrl, RVTRACE_ENCODER_CTRL_CONTEXT, config->context);
+       ctrl = set_field(ctrl, RVTRACE_ENCODER_CTRL_INSTTRIGENABLE, 
config->trigger);
+       ctrl = set_field(ctrl, RVTRACE_ENCODER_CTRL_INSTSTALLENA, 
config->stall);
+       ctrl = set_field(ctrl, RVTRACE_ENCODER_CTRL_INHIBITSRC, 
config->inhb_src);
+       ctrl = set_field(ctrl, RVTRACE_ENCODER_CTRL_INSTSYNCMODE, 
config->sync_mode);
+       ctrl = set_field(ctrl, RVTRACE_ENCODER_CTRL_INSTSYNCMAX, 
config->sync_max);
+
+       if (rvtrace_write_reg(comp, RVTRACE_ENCODER_CTRL, ctrl) != ERROR_OK)
+               return ERROR_FAIL;
+
+       /* read back ctrl register and check WARL bits */
+       if (rvtrace_read_reg(comp, RVTRACE_ENCODER_CTRL, &ctrl) != ERROR_OK)
+               return ERROR_FAIL;
+
+       field_rb = get_field(ctrl, RVTRACE_ENCODER_CTRL_INSTMODE);
+       if (field_rb != config->inst_mode)
+               LOG_WARNING("%s: `-inst-mode` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_inst_mode_opts, 
config->inst_mode)->name,
+                       jim_nvp_value2name_simple(nvp_inst_mode_opts, 
field_rb)->name);
+
+       field_rb = get_field(ctrl, RVTRACE_ENCODER_CTRL_CONTEXT);
+       if (field_rb != config->context)
+               LOG_WARNING("%s: `-context` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->context)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(ctrl, RVTRACE_ENCODER_CTRL_INSTTRIGENABLE);
+       if (field_rb != config->trigger)
+               LOG_WARNING("%s: `-trigger` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->trigger)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(ctrl, RVTRACE_ENCODER_CTRL_INSTSTALLENA);
+       if (field_rb != config->stall)
+               LOG_WARNING("%s: `-stall` %s is not supported, revert to %s.", 
comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->stall)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(ctrl, RVTRACE_ENCODER_CTRL_INHIBITSRC);
+       if (field_rb != config->inhb_src)
+               LOG_WARNING("%s: `-inhb-src` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->inhb_src)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(ctrl, RVTRACE_ENCODER_CTRL_INSTSYNCMODE);
+       if (field_rb != config->sync_mode)
+               LOG_WARNING("%s: `-sync-mode` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_sync_mode_opts, 
config->sync_mode)->name,
+                       jim_nvp_value2name_simple(nvp_sync_mode_opts, 
field_rb)->name);
+
+       field_rb = get_field(ctrl, RVTRACE_ENCODER_CTRL_INSTSYNCMAX);
+       if (field_rb != config->sync_max)
+               LOG_WARNING("%s: `-sync-max` 0x%x is not supported, revert to 
0x%x.", comp->name,
+                       config->sync_max, field_rb);
+
+       if (rvtrace_read_reg(comp, RVTRACE_ENCODER_INSTFEAT, &features) != 
ERROR_OK)
+               return ERROR_FAIL;
+
+       features = set_field(features, RVTRACE_ENCODER_INSTFEAT_NOADDRDIFF, 
config->fulladdr);
+       features = set_field(features, RVTRACE_ENCODER_INSTFEAT_NOTRAPADDR, 
config->no_trapaddr);
+       features = set_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENSEQUENTIALJUMP, config->seq_jump);
+       features = set_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENIMPLICITRETURN, config->implicit_return);
+       features = set_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENBRANCHPREDICTION, config->branch_prediction);
+       features = set_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENJUMPTARGETCACHE, config->jump_target_cache);
+       features = set_field(features, 
RVTRACE_ENCODER_INSTFEAT_IMPLICITRETURNMODE, config->implicit_return_mode);
+       features = set_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENREPEATEDHISTORT, config->repeated_history);
+       features = set_field(features, RVTRACE_ENCODER_INSTFEAT_ENALLJUMPS, 
config->all_jumps);
+       features = set_field(features, RVTRACE_ENCODER_INSTFEAT_EXTENDADDRMSB, 
config->ext_msb);
+       features = set_field(features, RVTRACE_ENCODER_INSTFEAT_SRCID, 
config->srcid);
+       features = set_field(features, RVTRACE_ENCODER_INSTFEAT_SRCBITS, 
config->srcbits);
+
+       if (rvtrace_write_reg(comp, RVTRACE_ENCODER_INSTFEAT, features) != 
ERROR_OK)
+               return ERROR_FAIL;
+
+       /* read back features register and check WARL bits */
+       field_rb = get_field(features, RVTRACE_ENCODER_INSTFEAT_NOADDRDIFF);
+       if (field_rb != config->fulladdr)
+               LOG_WARNING("%s: `-fulladdr` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->fulladdr)->name,
+                       jim_nvp_value2name_simple(nvp_inst_mode_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, RVTRACE_ENCODER_INSTFEAT_NOTRAPADDR);
+       if (field_rb != config->no_trapaddr)
+               LOG_WARNING("%s: `-no-trapaddr` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->no_trapaddr)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENSEQUENTIALJUMP);
+       if (field_rb != config->seq_jump)
+               LOG_WARNING("%s: `-seq-jump` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->seq_jump)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENIMPLICITRETURN);
+       if (field_rb != config->implicit_return)
+               LOG_WARNING("%s: `-implicit-return` %s is not supported, revert 
to %s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->implicit_return)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENBRANCHPREDICTION);
+       if (field_rb != config->branch_prediction)
+               LOG_WARNING("%s: `-branch-prediction` %s is not supported, 
revert to %s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->branch_prediction)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENJUMPTARGETCACHE);
+       if (field_rb != config->jump_target_cache)
+               LOG_WARNING("%s: `-jump-target-cache` %s is not supported, 
revert to %s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->jump_target_cache)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, 
RVTRACE_ENCODER_INSTFEAT_IMPLICITRETURNMODE);
+       if (field_rb != config->implicit_return_mode)
+               LOG_WARNING("%s: `-implicit-return-mode` %s is not supported, 
revert to %s.", comp->name,
+                       
jim_nvp_value2name_simple(nvp_implicit_return_mode_opts, 
config->implicit_return_mode)->name,
+                       
jim_nvp_value2name_simple(nvp_implicit_return_mode_opts, field_rb)->name);
+
+       field_rb = get_field(features, 
RVTRACE_ENCODER_INSTFEAT_ENREPEATEDHISTORT);
+       if (field_rb != config->repeated_history)
+               LOG_WARNING("%s: `-repeated-history` %s is not supported, 
revert to %s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->repeated_history)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, RVTRACE_ENCODER_INSTFEAT_ENALLJUMPS);
+       if (field_rb != config->all_jumps)
+               LOG_WARNING("%s: `-all-jumps` %s is not supported, revert to 
%s.", comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->all_jumps)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, RVTRACE_ENCODER_INSTFEAT_EXTENDADDRMSB);
+       if (field_rb != config->ext_msb)
+               LOG_WARNING("%s: `ext-msb` %s is not supported, revert to %s.", 
comp->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
config->ext_msb)->name,
+                       jim_nvp_value2name_simple(nvp_on_off_opts, 
field_rb)->name);
+
+       field_rb = get_field(features, RVTRACE_ENCODER_INSTFEAT_SRCID);
+       if (field_rb != config->srcid)
+               LOG_WARNING("%s: `-srcid` 0x%x is not supported, revert to 
0x%x.", comp->name,
+                       config->srcid, field_rb);
+
+       field_rb = get_field(features, RVTRACE_ENCODER_INSTFEAT_SRCBITS);
+       if (field_rb != config->srcbits)
+               LOG_WARNING("%s: `-srcbits` 0x%x is not supported, revert to 
0x%x.", comp->name,
+                       config->srcid, field_rb);
+
+       return ERROR_OK;
+}
+
+static int encoder_examine(struct rvtrace_component *comp)
+{
+       RV_ENCODER_INFO(info);
+       uint32_t ctrl;
+       if (rvtrace_read_reg(comp, RVTRACE_ENCODER_CTRL, &ctrl) != ERROR_OK)
+               return ERROR_FAIL;
+
+       info->format = get_field(ctrl, RVTRACE_ENCODER_CTRL_FORMAT);
+
+       LOG_INFO("[%s] Trace recording/protocol format: %s", comp->name,
+               (info->format == 0) ? "E-Trace" : (info->format == 1) ? 
"N-Trace" : "Unknown");
+
+       return ERROR_OK;
+}
+
+static int encoder_enable(struct rvtrace_component *comp)
+{
+       RV_ENCODER_INFO(info);
+       if (info->was_enabled)
+               return ERROR_OK;
+
+       if (encoder_set_config(comp) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (rvtrace_enable_component(comp) != ERROR_OK)
+               return ERROR_FAIL;
+
+       info->was_enabled = true;
+
+       return ERROR_OK;
+}
+
+static int encoder_disable(struct rvtrace_component *comp)
+{
+       RV_ENCODER_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_ENCODER_CTRL, 
RVTRACE_ENCODER_CTRL_EMPTY, 1) != ERROR_OK)
+               return ERROR_FAIL;
+
+       info->was_enabled = false;
+
+       return ERROR_OK;
+}
+
+static int encoder_status(struct rvtrace_component *comp,struct 
command_invocation *cmd)
+{
+       uint32_t ctrl;
+       if (rvtrace_read_reg(comp, RVTRACE_ENCODER_CTRL, &ctrl) != ERROR_OK)
+               return ERROR_FAIL;
+
+       command_print(cmd, "Control: %s",
+                       get_field(ctrl, RVTRACE_ENCODER_CTRL_ENABLE) ? 
"enabled" : "disabled");
+       command_print(cmd, "InstTracing: %s",
+                       get_field(ctrl, RVTRACE_ENCODER_CTRL_ITRACE) ? 
"enabled" : "disabled");
+       command_print(cmd, "Empty: %d", get_field(ctrl, 
RVTRACE_ENCODER_CTRL_EMPTY));
+
+       return ERROR_OK;
+}
+
+static int encoder_write(struct rvtrace_component *comp, const char *reg_name, 
uint32_t value)
+{
+       int offset = encoder_find_reg_offset(reg_name);
+       if (offset < 0)
+               return ERROR_FAIL;
+
+       return rvtrace_write_reg(comp, offset, value);
+}
+
+static int encoder_read(struct rvtrace_component *comp, const char *reg_name, 
uint32_t *value)
+{
+       int offset = encoder_find_reg_offset(reg_name);
+       if (offset < 0)
+               return ERROR_FAIL;
+
+       return rvtrace_read_reg(comp, offset, value);
+}
+
+static int encoder_start(struct rvtrace_component *comp)
+{
+       uint32_t value;
+
+       if (encoder_enable(comp) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (rvtrace_read_reg(comp, RVTRACE_ENCODER_CTRL, &value) != ERROR_OK)
+               return ERROR_FAIL;
+
+       value |= RVTRACE_ENCODER_CTRL_ITRACE;
+
+       if (rvtrace_write_reg(comp, RVTRACE_ENCODER_CTRL, value) != ERROR_OK)
+               return ERROR_FAIL;
+
+       return rvtrace_poll_register(comp, RVTRACE_ENCODER_CTRL, 
RVTRACE_ENCODER_CTRL_ITRACE, 1);
+}
+
+static int encoder_stop(struct rvtrace_component *comp)
+{
+       RV_ENCODER_INFO(info);
+       if (!info->was_enabled)
+               return ERROR_OK;
+
+       uint32_t value;
+       if (rvtrace_read_reg(comp, RVTRACE_ENCODER_CTRL, &value) != ERROR_OK)
+               return ERROR_FAIL;
+
+       value &= ~RVTRACE_ENCODER_CTRL_ITRACE;
+
+       if (rvtrace_write_reg(comp, RVTRACE_ENCODER_CTRL, value) != ERROR_OK)
+               return ERROR_FAIL;
+
+       return rvtrace_poll_register(comp, RVTRACE_ENCODER_CTRL, 
RVTRACE_ENCODER_CTRL_ITRACE, 0);
+}
+
+COMMAND_HANDLER(handle_encoder_start)
+{
+       struct rvtrace_component *comp = CMD_DATA;
+
+       if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (encoder_start(comp) != ERROR_OK)
+               return ERROR_FAIL;
+
+       command_print(CMD, "%s: Instruction trace is being generated", 
comp->name);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_encoder_stop)
+{
+       struct rvtrace_component *comp = CMD_DATA;
+
+       if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (encoder_stop(comp) != ERROR_OK)
+               return ERROR_FAIL;
+
+       command_print(CMD, "%s: Instruction trace is not being generated", 
comp->name);
+
+       return ERROR_OK;
+}
+
+static const struct command_registration encoder_exec_command_handlers[] = {
+       {
+               .name  = "start",
+               .mode  = COMMAND_EXEC,
+               .handler = handle_encoder_start,
+               .help  = "start encoder trace",
+               .usage = "",
+       },
+       {
+               .name  = "stop",
+               .mode  = COMMAND_EXEC,
+               .handler = handle_encoder_stop,
+               .help  = "stop encoder trace",
+               .usage = "",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration encoder_command_handlers[] = {
+       {
+               .name = "encoder",
+               .mode = COMMAND_ANY,
+               .help = "Encoder Command Group",
+               .usage = "",
+               .chain = encoder_exec_command_handlers
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct rvtrace_type rvtrace_encoder = {
+       .name = "encoder",
+       .id_type = RVTRACE_COMPONENT_TYPE_ENCODER,
+       .version = rvtrace_component_mkversion(1, 0),
+
+       .rvtrace_create = encoder_create,
+       .rvtrace_jim_configure = encoder_jim_configure,
+
+       .examine = encoder_examine,
+
+       .enable = encoder_enable,
+       .disable = encoder_disable,
+       .status = encoder_status,
+       .write = encoder_write,
+       .read = encoder_read,
+
+       .commands = encoder_command_handlers,
+};

-- 

Reply via email to