aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Savin <43152568+SiFiveGregS@users.noreply.github.com>2019-11-12 09:00:35 -0800
committerTim Newsome <tim@sifive.com>2019-11-12 09:00:35 -0800
commitb7bd3f8d47b1c73d1e250a2476ee11b422494a35 (patch)
tree8dbcafc559eada241ffc83ee4e466554c7b018c6
parentf93ede5401c711e55d9852986aa399c0318efb22 (diff)
downloadriscv-openocd-b7bd3f8d47b1c73d1e250a2476ee11b422494a35.zip
riscv-openocd-b7bd3f8d47b1c73d1e250a2476ee11b422494a35.tar.gz
riscv-openocd-b7bd3f8d47b1c73d1e250a2476ee11b422494a35.tar.bz2
BSCAN batch fix (#422)
* fix for batch scans not honoring presence of BSCAN tunnel * fix formatting to placate checkpatch * replace DIM with ARRAY_SIZE * Refactor code that adds a bscan tunneled scan. * Move bscan tunnel context to the batch structure, and in array form, one per scan * adjust code that was inconsistent with project code formatting standards
-rw-r--r--src/target/riscv/batch.c16
-rw-r--r--src/target/riscv/batch.h6
-rw-r--r--src/target/riscv/riscv-013.c46
-rw-r--r--src/target/riscv/riscv.c40
-rw-r--r--src/target/riscv/riscv.h10
5 files changed, 73 insertions, 45 deletions
diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c
index 5c5e78c..0d84c42 100644
--- a/src/target/riscv/batch.c
+++ b/src/target/riscv/batch.c
@@ -21,6 +21,8 @@ struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans, size_
out->data_out = malloc(sizeof(*out->data_out) * (scans) * sizeof(uint64_t));
out->data_in = malloc(sizeof(*out->data_in) * (scans) * sizeof(uint64_t));
out->fields = malloc(sizeof(*out->fields) * (scans));
+ if (bscan_tunnel_ir_width != 0)
+ out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * (scans));
out->last_scan = RISCV_SCAN_TYPE_INVALID;
out->read_keys = malloc(sizeof(*out->read_keys) * (scans));
return out;
@@ -31,6 +33,8 @@ void riscv_batch_free(struct riscv_batch *batch)
free(batch->data_in);
free(batch->data_out);
free(batch->fields);
+ if (batch->bscan_ctxt)
+ free(batch->bscan_ctxt);
free(batch->read_keys);
free(batch);
}
@@ -52,7 +56,11 @@ int riscv_batch_run(struct riscv_batch *batch)
riscv_batch_add_nop(batch);
for (size_t i = 0; i < batch->used_scans; ++i) {
- jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
+ if (bscan_tunnel_ir_width != 0)
+ riscv_add_bscan_tunneled_scan(batch->target, batch->fields+i, batch->bscan_ctxt+i);
+ else
+ jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
+
if (batch->idle_count > 0)
jtag_add_runtest(batch->idle_count, TAP_IDLE);
}
@@ -62,6 +70,12 @@ int riscv_batch_run(struct riscv_batch *batch)
return ERROR_FAIL;
}
+ if (bscan_tunnel_ir_width != 0) {
+ /* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */
+ for (size_t i = 0; i < batch->used_scans; ++i)
+ buffer_shr((batch->fields + i)->in_value, sizeof(uint64_t), 1);
+ }
+
for (size_t i = 0; i < batch->used_scans; ++i)
dump_field(batch->idle_count, batch->fields + i);
diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h
index 2ae2472..c409625 100644
--- a/src/target/riscv/batch.h
+++ b/src/target/riscv/batch.h
@@ -3,6 +3,7 @@
#include "target/target.h"
#include "jtag/jtag.h"
+#include "riscv.h"
enum riscv_scan_type {
RISCV_SCAN_TYPE_INVALID,
@@ -27,6 +28,11 @@ struct riscv_batch {
uint8_t *data_in;
struct scan_field *fields;
+ /* If in BSCAN mode, this field will be allocated (one per scan),
+ and utilized to tunnel all the scans in the batch. If not in
+ BSCAN mode, this field is unallocated and stays NULL */
+ riscv_bscan_tunneled_scan_context_t *bscan_ctxt;
+
/* In JTAG we scan out the previous value's output when performing a
* scan. This is a pain for users, so we just provide them the
* illusion of not having to do this by eliding all but the last NOP.
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index dda639e..26f8b20 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -484,8 +484,7 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
.out_value = out,
.in_value = in
};
- uint8_t tunneled_dr_width;
- struct scan_field tunneled_dr[4];
+ riscv_bscan_tunneled_scan_context_t bscan_ctxt;
if (r->reset_delays_wait >= 0) {
r->reset_delays_wait--;
@@ -510,48 +509,7 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
the best fit. Declaring stack based field values in a subsidiary function call wouldn't
work. */
if (bscan_tunnel_ir_width != 0) {
- jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);
-
- /* I wanted to use struct initialization syntax, but that would involve either
- declaring the variable within this scope (which would go out of scope at runtime
- before the JTAG queue gets executed, which is an error waiting to happen), or
- initializing outside of the check for whether a BSCAN tunnel was active (which
- would be a waste of CPU time when BSCAN tunnel is not being used. So I declared the
- struct at the function's top-level, so its lifetime exceeds the point at which
- the queue is executed, and initializing with assignments here. */
- memset(tunneled_dr, 0, sizeof(tunneled_dr));
- if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER) {
- tunneled_dr[3].num_bits = 1;
- tunneled_dr[3].out_value = bscan_one;
- tunneled_dr[2].num_bits = 7;
- tunneled_dr_width = num_bits;
- tunneled_dr[2].out_value = &tunneled_dr_width;
- /* for BSCAN tunnel, there is a one-TCK skew between shift in and shift out, so
- scanning num_bits + 1, and then will right shift the input field after executing the queues */
-
- tunneled_dr[1].num_bits = num_bits+1;
- tunneled_dr[1].out_value = out;
- tunneled_dr[1].in_value = in;
-
-
- tunneled_dr[0].num_bits = 3;
- tunneled_dr[0].out_value = bscan_zero;
- } else {
- /* BSCAN_TUNNEL_NESTED_TAP */
- tunneled_dr[0].num_bits = 1;
- tunneled_dr[0].out_value = bscan_one;
- tunneled_dr[1].num_bits = 7;
- tunneled_dr_width = num_bits;
- tunneled_dr[1].out_value = &tunneled_dr_width;
- /* for BSCAN tunnel, there is a one-TCK skew between shift in and shift out, so
- scanning num_bits + 1, and then will right shift the input field after executing the queues */
- tunneled_dr[2].num_bits = num_bits+1;
- tunneled_dr[2].out_value = out;
- tunneled_dr[2].in_value = in;
- tunneled_dr[3].num_bits = 3;
- tunneled_dr[3].out_value = bscan_zero;
- }
- jtag_add_dr_scan(target->tap, DIM(tunneled_dr), tunneled_dr, TAP_IDLE);
+ riscv_add_bscan_tunneled_scan(target, &field, &bscan_ctxt);
} else {
/* Assume dbus is already selected. */
jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 963f670..41ac87c 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -3550,3 +3550,43 @@ int riscv_init_registers(struct target *target)
return ERROR_OK;
}
+
+
+void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field,
+ riscv_bscan_tunneled_scan_context_t *ctxt)
+{
+ jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);
+
+ memset(ctxt->tunneled_dr, 0, sizeof(ctxt->tunneled_dr));
+ if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER) {
+ ctxt->tunneled_dr[3].num_bits = 1;
+ ctxt->tunneled_dr[3].out_value = bscan_one;
+ ctxt->tunneled_dr[2].num_bits = 7;
+ ctxt->tunneled_dr_width = field->num_bits;
+ ctxt->tunneled_dr[2].out_value = &ctxt->tunneled_dr_width;
+ /* for BSCAN tunnel, there is a one-TCK skew between shift in and shift out, so
+ scanning num_bits + 1, and then will right shift the input field after executing the queues */
+
+ ctxt->tunneled_dr[1].num_bits = field->num_bits+1;
+ ctxt->tunneled_dr[1].out_value = field->out_value;
+ ctxt->tunneled_dr[1].in_value = field->in_value;
+
+ ctxt->tunneled_dr[0].num_bits = 3;
+ ctxt->tunneled_dr[0].out_value = bscan_zero;
+ } else {
+ /* BSCAN_TUNNEL_NESTED_TAP */
+ ctxt->tunneled_dr[0].num_bits = 1;
+ ctxt->tunneled_dr[0].out_value = bscan_one;
+ ctxt->tunneled_dr[1].num_bits = 7;
+ ctxt->tunneled_dr_width = field->num_bits;
+ ctxt->tunneled_dr[1].out_value = &ctxt->tunneled_dr_width;
+ /* for BSCAN tunnel, there is a one-TCK skew between shift in and shift out, so
+ scanning num_bits + 1, and then will right shift the input field after executing the queues */
+ ctxt->tunneled_dr[2].num_bits = field->num_bits+1;
+ ctxt->tunneled_dr[2].out_value = field->out_value;
+ ctxt->tunneled_dr[2].in_value = field->in_value;
+ ctxt->tunneled_dr[3].num_bits = 3;
+ ctxt->tunneled_dr[3].out_value = bscan_zero;
+ }
+ jtag_add_dr_scan(target->tap, ARRAY_SIZE(ctxt->tunneled_dr), ctxt->tunneled_dr, TAP_IDLE);
+}
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 0b0bc50..3dfb4e5 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -6,6 +6,7 @@ struct riscv_program;
#include <stdint.h>
#include "opcodes.h"
#include "gdb_regs.h"
+#include "jtag/jtag.h"
/* The register cache is statically allocated. */
#define RISCV_MAX_HARTS 32
@@ -147,6 +148,12 @@ typedef struct {
int (*hart_count)(struct target *target);
} riscv_info_t;
+typedef struct {
+ uint8_t tunneled_dr_width;
+ struct scan_field tunneled_dr[4];
+} riscv_bscan_tunneled_scan_context_t;
+
+
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
extern int riscv_command_timeout_sec;
@@ -291,4 +298,7 @@ int riscv_init_registers(struct target *target);
void riscv_semihosting_init(struct target *target);
int riscv_semihosting(struct target *target, int *retval);
+void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field,
+ riscv_bscan_tunneled_scan_context_t *ctxt);
+
#endif