OpenOCD
batch.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 
7 #include "batch.h"
8 #include "debug_defines.h"
9 #include "riscv.h"
10 
11 #define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
12 #define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
13 
14 #define DTM_DMI_MAX_ADDRESS_LENGTH ((1<<DTM_DTMCS_ABITS_LENGTH)-1)
15 #define DMI_SCAN_MAX_BIT_LENGTH (DTM_DMI_MAX_ADDRESS_LENGTH + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH)
16 #define DMI_SCAN_BUF_SIZE (DIV_ROUND_UP(DMI_SCAN_MAX_BIT_LENGTH, 8))
17 
18 static void dump_field(int idle, const struct scan_field *field);
19 
20 struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans, size_t idle)
21 {
22  scans += 4;
23  struct riscv_batch *out = calloc(1, sizeof(*out));
24  if (!out)
25  goto error0;
26  out->target = target;
27  out->allocated_scans = scans;
28  out->idle_count = idle;
29  out->data_out = malloc(sizeof(*out->data_out) * (scans) * DMI_SCAN_BUF_SIZE);
30  if (!out->data_out) {
31  LOG_ERROR("Failed to allocate data_out in RISC-V batch.");
32  goto error1;
33  };
34  out->data_in = malloc(sizeof(*out->data_in) * (scans) * DMI_SCAN_BUF_SIZE);
35  if (!out->data_in) {
36  LOG_ERROR("Failed to allocate data_in in RISC-V batch.");
37  goto error2;
38  }
39  out->fields = malloc(sizeof(*out->fields) * (scans));
40  if (!out->fields) {
41  LOG_ERROR("Failed to allocate fields in RISC-V batch.");
42  goto error3;
43  }
44  if (bscan_tunnel_ir_width != 0) {
45  out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * (scans));
46  if (!out->bscan_ctxt) {
47  LOG_ERROR("Failed to allocate bscan_ctxt in RISC-V batch.");
48  goto error4;
49  }
50  }
52  out->read_keys = malloc(sizeof(*out->read_keys) * (scans));
53  if (!out->read_keys) {
54  LOG_ERROR("Failed to allocate read_keys in RISC-V batch.");
55  goto error5;
56  }
57  return out;
58 
59 error5:
60  free(out->bscan_ctxt);
61 error4:
62  free(out->fields);
63 error3:
64  free(out->data_in);
65 error2:
66  free(out->data_out);
67 error1:
68  free(out);
69 error0:
70  return NULL;
71 }
72 
73 void riscv_batch_free(struct riscv_batch *batch)
74 {
75  free(batch->data_in);
76  free(batch->data_out);
77  free(batch->fields);
78  free(batch->bscan_ctxt);
79  free(batch->read_keys);
80  free(batch);
81 }
82 
83 bool riscv_batch_full(struct riscv_batch *batch)
84 {
85  return batch->used_scans > (batch->allocated_scans - 4);
86 }
87 
88 int riscv_batch_run(struct riscv_batch *batch)
89 {
90  if (batch->used_scans == 0) {
91  LOG_DEBUG("Ignoring empty batch.");
92  return ERROR_OK;
93  }
94 
95  riscv_batch_add_nop(batch);
96 
97  for (size_t i = 0; i < batch->used_scans; ++i) {
98  if (bscan_tunnel_ir_width != 0)
99  riscv_add_bscan_tunneled_scan(batch->target, batch->fields+i, batch->bscan_ctxt+i);
100  else
101  jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
102 
103  if (batch->idle_count > 0)
105  }
106 
107  keep_alive();
108 
109  if (jtag_execute_queue() != ERROR_OK) {
110  LOG_ERROR("Unable to execute JTAG queue");
111  return ERROR_FAIL;
112  }
113 
114  keep_alive();
115 
116  if (bscan_tunnel_ir_width != 0) {
117  /* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */
118  for (size_t i = 0; i < batch->used_scans; ++i) {
119  if ((batch->fields + i)->in_value)
120  buffer_shr((batch->fields + i)->in_value, DMI_SCAN_BUF_SIZE, 1);
121  }
122  }
123 
124  for (size_t i = 0; i < batch->used_scans; ++i)
125  dump_field(batch->idle_count, batch->fields + i);
126 
127  return ERROR_OK;
128 }
129 
130 void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data)
131 {
132  assert(batch->used_scans < batch->allocated_scans);
133  struct scan_field *field = batch->fields + batch->used_scans;
134  field->num_bits = riscv_dmi_write_u64_bits(batch->target);
135  field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
136  field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
137  riscv_fill_dmi_write_u64(batch->target, (char *)field->out_value, address, data);
138  riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
140  batch->used_scans++;
141 }
142 
143 size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address)
144 {
145  assert(batch->used_scans < batch->allocated_scans);
146  struct scan_field *field = batch->fields + batch->used_scans;
147  field->num_bits = riscv_dmi_write_u64_bits(batch->target);
148  field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
149  field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
150  riscv_fill_dmi_read_u64(batch->target, (char *)field->out_value, address);
151  riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
153  batch->used_scans++;
154 
155  batch->read_keys[batch->read_keys_used] = batch->used_scans;
156  return batch->read_keys_used++;
157 }
158 
159 unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key)
160 {
161  assert(key < batch->read_keys_used);
162  size_t index = batch->read_keys[key];
163  assert(index <= batch->used_scans);
164  uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
165  /* extract "op" field from the DMI read result */
166  return (unsigned)buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
167 }
168 
169 uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key)
170 {
171  assert(key < batch->read_keys_used);
172  size_t index = batch->read_keys[key];
173  assert(index <= batch->used_scans);
174  uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
175  /* extract "data" field from the DMI read result */
177 }
178 
179 void riscv_batch_add_nop(struct riscv_batch *batch)
180 {
181  assert(batch->used_scans < batch->allocated_scans);
182  struct scan_field *field = batch->fields + batch->used_scans;
183  field->num_bits = riscv_dmi_write_u64_bits(batch->target);
184  field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
185  field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
186  riscv_fill_dmi_nop_u64(batch->target, (char *)field->out_value);
187  riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
189  batch->used_scans++;
190 }
191 
192 void dump_field(int idle, const struct scan_field *field)
193 {
194  static const char * const op_string[] = {"-", "r", "w", "?"};
195  static const char * const status_string[] = {"+", "?", "F", "b"};
196 
198  return;
199 
200  assert(field->out_value);
201  uint64_t out = buf_get_u64(field->out_value, 0, field->num_bits);
202  unsigned int out_op = get_field(out, DTM_DMI_OP);
203  unsigned int out_data = get_field(out, DTM_DMI_DATA);
204  unsigned int out_address = out >> DTM_DMI_ADDRESS_OFFSET;
205 
206  if (field->in_value) {
207  uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits);
208  unsigned int in_op = get_field(in, DTM_DMI_OP);
209  unsigned int in_data = get_field(in, DTM_DMI_DATA);
210  unsigned int in_address = in >> DTM_DMI_ADDRESS_OFFSET;
211 
213  __FILE__, __LINE__, __PRETTY_FUNCTION__,
214  "%db %s %08x @%02x -> %s %08x @%02x; %di",
215  field->num_bits, op_string[out_op], out_data, out_address,
216  status_string[in_op], in_data, in_address, idle);
217  } else {
219  __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?; %di",
220  field->num_bits, op_string[out_op], out_data, out_address, idle);
221  }
222 }
223 
225 {
226  return batch->allocated_scans - batch->used_scans - 4;
227 }
uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key)
Definition: batch.c:169
void riscv_batch_add_nop(struct riscv_batch *batch)
Definition: batch.c:179
size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address)
Definition: batch.c:143
#define DMI_SCAN_BUF_SIZE
Definition: batch.c:16
size_t riscv_batch_available_scans(struct riscv_batch *batch)
Definition: batch.c:224
struct riscv_batch * riscv_batch_alloc(struct target *target, size_t scans, size_t idle)
Definition: batch.c:20
int riscv_batch_run(struct riscv_batch *batch)
Definition: batch.c:88
#define get_field(reg, mask)
Definition: batch.c:11
void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data)
Definition: batch.c:130
unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key)
Definition: batch.c:159
void riscv_batch_free(struct riscv_batch *batch)
Definition: batch.c:73
static void dump_field(int idle, const struct scan_field *field)
Definition: batch.c:192
bool riscv_batch_full(struct riscv_batch *batch)
Definition: batch.c:83
@ RISCV_SCAN_TYPE_INVALID
Definition: batch.h:11
@ RISCV_SCAN_TYPE_WRITE
Definition: batch.h:14
@ RISCV_SCAN_TYPE_NOP
Definition: batch.h:12
@ RISCV_SCAN_TYPE_READ
Definition: batch.h:13
void buffer_shr(void *_buf, unsigned buf_len, unsigned count)
Definition: binarybuffer.c:410
static uint32_t buf_get_u32(const uint8_t *_buffer, unsigned first, unsigned num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 32-bit word.
Definition: binarybuffer.h:99
static uint64_t buf_get_u64(const uint8_t *_buffer, unsigned first, unsigned num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 64-bit word.
Definition: binarybuffer.h:128
#define DTM_DMI_OP
#define DTM_DMI_DATA_OFFSET
#define DTM_DMI_OP_OFFSET
#define DTM_DMI_ADDRESS_OFFSET
#define DTM_DMI_DATA_LENGTH
#define DTM_DMI_DATA
#define DTM_DMI_OP_LENGTH
int jtag_execute_queue(void)
For software FIFO implementations, the queued commands can be executed during this call or earlier.
Definition: jtag/core.c:1037
void jtag_add_runtest(int num_cycles, tap_state_t state)
Goes to TAP_IDLE (if we're not already there), cycle precisely num_cycles in the TAP_IDLE state,...
Definition: jtag/core.c:592
void jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state)
Generate a DR SCAN using the fields passed to the function.
Definition: jtag/core.c:451
@ TAP_IDLE
Definition: jtag.h:53
void log_printf_lf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format,...)
Definition: log.c:183
int debug_level
Definition: log.c:35
void keep_alive(void)
Definition: log.c:415
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
@ LOG_LVL_DEBUG
Definition: log.h:47
void riscv_fill_dmi_nop_u64(struct target *target, char *buf)
Definition: riscv.c:3425
void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field, riscv_bscan_tunneled_scan_context_t *ctxt)
Definition: riscv.c:4415
int riscv_dmi_write_u64_bits(struct target *target)
Definition: riscv.c:3431
void riscv_fill_dmi_write_u64(struct target *target, char *buf, int a, uint64_t d)
Definition: riscv.c:3413
void riscv_fill_dmi_read_u64(struct target *target, char *buf, int a)
Definition: riscv.c:3419
int bscan_tunnel_ir_width
Definition: riscv.c:129
struct target * target
Definition: rtt/rtt.c:26
uint8_t * data_in
Definition: batch.h:30
riscv_bscan_tunneled_scan_context_t * bscan_ctxt
Definition: batch.h:36
size_t allocated_scans
Definition: batch.h:24
struct target * target
Definition: batch.h:22
enum riscv_scan_type last_scan
Definition: batch.h:42
size_t idle_count
Definition: batch.h:27
size_t * read_keys
Definition: batch.h:45
uint8_t * data_out
Definition: batch.h:29
size_t read_keys_used
Definition: batch.h:46
size_t used_scans
Definition: batch.h:25
struct scan_field * fields
Definition: batch.h:31
This structure defines a single scan field in the scan.
Definition: jtag.h:87
int num_bits
The number of bits this field specifies.
Definition: jtag.h:89
uint8_t * in_value
A pointer to a 32-bit memory location for data scanned out.
Definition: jtag.h:93
const uint8_t * out_value
A pointer to value to be scanned into the device.
Definition: jtag.h:91
Definition: target.h:116
struct jtag_tap * tap
Definition: target.h:119
#define NULL
Definition: usb.h:16