aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2023-02-10 12:36:48 -0800
committerGitHub <noreply@github.com>2023-02-10 12:36:48 -0800
commit2b4826cd322628d3ee7425a0cb86a7c878b5525a (patch)
treef3e658c03ca8c8ecda612e3ea7e817f238a23f61 /src
parent282ac9884ee777831e9a8ecf1817e9d2056d25b1 (diff)
parentf4f3ce7db7a1f5a264a0a957e338e71c9d583ea2 (diff)
downloadriscv-openocd-2b4826cd322628d3ee7425a0cb86a7c878b5525a.zip
riscv-openocd-2b4826cd322628d3ee7425a0cb86a7c878b5525a.tar.gz
riscv-openocd-2b4826cd322628d3ee7425a0cb86a7c878b5525a.tar.bz2
Merge pull request #797 from riscv/Zve32
If XLEN=64 and vsew=64 fails, fall back to vsew=32.
Diffstat (limited to 'src')
-rw-r--r--src/target/riscv/riscv-013.c94
-rw-r--r--src/target/riscv/riscv.c2
-rw-r--r--src/target/riscv/riscv.h8
3 files changed, 65 insertions, 39 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 661197c..71cf287 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -116,12 +116,6 @@ struct trigger {
int unique_id;
};
-typedef enum {
- YNM_MAYBE,
- YNM_YES,
- YNM_NO
-} yes_no_maybe_t;
-
#define HART_INDEX_MULTIPLE -1
#define HART_INDEX_UNKNOWN -2
@@ -1738,8 +1732,8 @@ static int examine(struct target *target)
LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work.");
r->vlenb = 0;
} else {
- LOG_TARGET_INFO(target, "Vector support with vlenb=%d", r->vlenb);
r->vlenb = vlenb;
+ LOG_TARGET_INFO(target, "Vector support with vlenb=%d", r->vlenb);
}
/* Now init registers based on what we discovered. */
@@ -1911,34 +1905,54 @@ COMMAND_HELPER(riscv013_print_info, struct target *target)
return 0;
}
-static int prep_for_vector_access(struct target *target, uint64_t *vtype,
- uint64_t *vl, unsigned *debug_vl)
+static int prep_for_vector_access(struct target *target, uint64_t *saved_vtype,
+ uint64_t *saved_vl, unsigned *debug_vl, unsigned *debug_vsew)
{
RISCV_INFO(r);
/* TODO: this continuous save/restore is terrible for performance. */
/* Write vtype and vl. */
- unsigned encoded_vsew;
- switch (riscv_xlen(target)) {
- case 32:
- encoded_vsew = 2;
- break;
- case 64:
- encoded_vsew = 3;
- break;
- default:
- LOG_ERROR("Unsupported xlen: %d", riscv_xlen(target));
- return ERROR_FAIL;
- }
/* Save vtype and vl. */
- if (register_read_direct(target, vtype, GDB_REGNO_VTYPE) != ERROR_OK)
+ if (register_read_direct(target, saved_vtype, GDB_REGNO_VTYPE) != ERROR_OK)
return ERROR_FAIL;
- if (register_read_direct(target, vl, GDB_REGNO_VL) != ERROR_OK)
+ if (register_read_direct(target, saved_vl, GDB_REGNO_VL) != ERROR_OK)
return ERROR_FAIL;
- if (register_write_direct(target, GDB_REGNO_VTYPE, encoded_vsew << 3) != ERROR_OK)
- return ERROR_FAIL;
- *debug_vl = DIV_ROUND_UP(r->vlenb * 8, riscv_xlen(target));
+ while (true) {
+ unsigned int encoded_vsew;
+ if (riscv_xlen(target) == 64 && r->vsew64_supported != YNM_NO) {
+ encoded_vsew = 3;
+ *debug_vsew = 64;
+ } else {
+ encoded_vsew = 2;
+ *debug_vsew = 32;
+ }
+
+ /* Set standard element width to match XLEN, for vmv instruction to move
+ * the least significant bits into a GPR. */
+ if (register_write_direct(target, GDB_REGNO_VTYPE, encoded_vsew << 3) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (*debug_vsew == 64 && r->vsew64_supported == YNM_MAYBE) {
+ /* Check that it's supported. */
+ uint64_t vtype;
+ if (register_read_direct(target, &vtype, GDB_REGNO_VTYPE) != ERROR_OK)
+ return ERROR_FAIL;
+ if (vtype >> (riscv_xlen(target) - 1)) {
+ r->vsew64_supported = YNM_NO;
+ /* Try again. */
+ continue;
+ } else {
+ r->vsew64_supported = YNM_YES;
+ }
+ }
+ break;
+ }
+
+ /* Set the number of elements to be updated with results from a vector
+ * instruction, for the vslide1down instruction.
+ * Set it so the entire V register is updated. */
+ *debug_vl = DIV_ROUND_UP(r->vlenb * 8, *debug_vsew);
if (register_write_direct(target, GDB_REGNO_VL, *debug_vl) != ERROR_OK)
return ERROR_FAIL;
@@ -1972,20 +1986,21 @@ static int riscv013_get_register_buf(struct target *target,
return ERROR_FAIL;
uint64_t vtype, vl;
- unsigned debug_vl;
- if (prep_for_vector_access(target, &vtype, &vl, &debug_vl) != ERROR_OK)
+ unsigned int debug_vl, debug_vsew;
+ if (prep_for_vector_access(target, &vtype, &vl, &debug_vl, &debug_vsew) != ERROR_OK)
return ERROR_FAIL;
unsigned vnum = regno - GDB_REGNO_V0;
- unsigned xlen = riscv_xlen(target);
-
- struct riscv_program program;
- riscv_program_init(&program, target);
- riscv_program_insert(&program, vmv_x_s(S0, vnum));
- riscv_program_insert(&program, vslide1down_vx(vnum, vnum, S0, true));
int result = ERROR_OK;
for (unsigned i = 0; i < debug_vl; i++) {
+ /* Can't reuse the same program because riscv_program_exec() adds
+ * ebreak to the end every time. */
+ struct riscv_program program;
+ riscv_program_init(&program, target);
+ riscv_program_insert(&program, vmv_x_s(S0, vnum));
+ riscv_program_insert(&program, vslide1down_vx(vnum, vnum, S0, true));
+
/* Executing the program might result in an exception if there is some
* issue with the vector implementation/instructions we're using. If that
* happens, attempt to restore as usual. We may have clobbered the
@@ -1997,8 +2012,10 @@ static int riscv013_get_register_buf(struct target *target,
uint64_t v;
if (register_read_direct(target, &v, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
- buf_set_u64(value, xlen * i, xlen, v);
+ buf_set_u64(value, debug_vsew * i, debug_vsew, v);
} else {
+ LOG_TARGET_ERROR(target, "Failed to execute vmv/vslide1down while reading %s",
+ gdb_regno_name(regno));
break;
}
}
@@ -2028,12 +2045,11 @@ static int riscv013_set_register_buf(struct target *target,
return ERROR_FAIL;
uint64_t vtype, vl;
- unsigned debug_vl;
- if (prep_for_vector_access(target, &vtype, &vl, &debug_vl) != ERROR_OK)
+ unsigned int debug_vl, debug_vsew;
+ if (prep_for_vector_access(target, &vtype, &vl, &debug_vl, &debug_vsew) != ERROR_OK)
return ERROR_FAIL;
unsigned vnum = regno - GDB_REGNO_V0;
- unsigned xlen = riscv_xlen(target);
struct riscv_program program;
riscv_program_init(&program, target);
@@ -2041,7 +2057,7 @@ static int riscv013_set_register_buf(struct target *target,
int result = ERROR_OK;
for (unsigned i = 0; i < debug_vl; i++) {
if (register_write_direct(target, GDB_REGNO_S0,
- buf_get_u64(value, xlen * i, xlen)) != ERROR_OK)
+ buf_get_u64(value, debug_vsew * i, debug_vsew)) != ERROR_OK)
return ERROR_FAIL;
result = riscv_program_exec(&program, target);
if (result != ERROR_OK)
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index d198010..058a810 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -3926,6 +3926,8 @@ void riscv_info_init(struct target *target, riscv_info_t *r)
INIT_LIST_HEAD(&r->expose_csr);
INIT_LIST_HEAD(&r->expose_custom);
+
+ r->vsew64_supported = YNM_MAYBE;
}
static int riscv_resume_go_all_harts(struct target *target)
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 87ec13f..6a1d7a4 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -41,6 +41,12 @@ typedef uint64_t riscv_reg_t;
typedef uint32_t riscv_insn_t;
typedef uint64_t riscv_addr_t;
+typedef enum {
+ YNM_MAYBE,
+ YNM_YES,
+ YNM_NO
+} yes_no_maybe_t;
+
enum riscv_mem_access_method {
RISCV_MEM_ACCESS_UNSPECIFIED,
RISCV_MEM_ACCESS_PROGBUF,
@@ -253,6 +259,8 @@ typedef struct {
/* Track when we were last asked to do something substantial. */
int64_t last_activity;
+
+ yes_no_maybe_t vsew64_supported;
} riscv_info_t;
COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key,