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  buffer_shr((batch->fields + i)->in_value, DMI_SCAN_BUF_SIZE, 1);
120  }
121 
122  for (size_t i = 0; i < batch->used_scans; ++i)
123  dump_field(batch->idle_count, batch->fields + i);
124 
125  return ERROR_OK;
126 }
127 
128 void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data)
129 {
130  assert(batch->used_scans < batch->allocated_scans);
131  struct scan_field *field = batch->fields + batch->used_scans;
132  field->num_bits = riscv_dmi_write_u64_bits(batch->target);
133  field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
134  field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
135  riscv_fill_dmi_write_u64(batch->target, (char *)field->out_value, address, data);
136  riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
138  batch->used_scans++;
139 }
140 
141 size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address)
142 {
143  assert(batch->used_scans < batch->allocated_scans);
144  struct scan_field *field = batch->fields + batch->used_scans;
145  field->num_bits = riscv_dmi_write_u64_bits(batch->target);
146  field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
147  field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
148  riscv_fill_dmi_read_u64(batch->target, (char *)field->out_value, address);
149  riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
151  batch->used_scans++;
152 
153  batch->read_keys[batch->read_keys_used] = batch->used_scans;
154  return batch->read_keys_used++;
155 }
156 
157 unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key)
158 {
159  assert(key < batch->read_keys_used);
160  size_t index = batch->read_keys[key];
161  assert(index <= batch->used_scans);
162  uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
163  /* extract "op" field from the DMI read result */
164  return (unsigned)buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
165 }
166 
167 uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key)
168 {
169  assert(key < batch->read_keys_used);
170  size_t index = batch->read_keys[key];
171  assert(index <= batch->used_scans);
172  uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
173  /* extract "data" field from the DMI read result */
175 }
176 
177 void riscv_batch_add_nop(struct riscv_batch *batch)
178 {
179  assert(batch->used_scans < batch->allocated_scans);
180  struct scan_field *field = batch->fields + batch->used_scans;
181  field->num_bits = riscv_dmi_write_u64_bits(batch->target);
182  field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
183  field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
184  riscv_fill_dmi_nop_u64(batch->target, (char *)field->out_value);
185  riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
187  batch->used_scans++;
188 }
189 
190 void dump_field(int idle, const struct scan_field *field)
191 {
192  static const char * const op_string[] = {"-", "r", "w", "?"};
193  static const char * const status_string[] = {"+", "?", "F", "b"};
194 
196  return;
197 
198  assert(field->out_value);
199  uint64_t out = buf_get_u64(field->out_value, 0, field->num_bits);
200  unsigned int out_op = get_field(out, DTM_DMI_OP);
201  unsigned int out_data = get_field(out, DTM_DMI_DATA);
202  unsigned int out_address = out >> DTM_DMI_ADDRESS_OFFSET;
203 
204  if (field->in_value) {
205  uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits);
206  unsigned int in_op = get_field(in, DTM_DMI_OP);
207  unsigned int in_data = get_field(in, DTM_DMI_DATA);
208  unsigned int in_address = in >> DTM_DMI_ADDRESS_OFFSET;
209 
211  __FILE__, __LINE__, __PRETTY_FUNCTION__,
212  "%db %s %08x @%02x -> %s %08x @%02x; %di",
213  field->num_bits, op_string[out_op], out_data, out_address,
214  status_string[in_op], in_data, in_address, idle);
215  } else {
217  __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?; %di",
218  field->num_bits, op_string[out_op], out_data, out_address, idle);
219  }
220 }
221 
223 {
224  return batch->allocated_scans - batch->used_scans - 4;
225 }
uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key)
Definition: batch.c:167
void riscv_batch_add_nop(struct riscv_batch *batch)
Definition: batch.c:177
size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address)
Definition: batch.c:141
#define DMI_SCAN_BUF_SIZE
Definition: batch.c:16
size_t riscv_batch_available_scans(struct riscv_batch *batch)
Definition: batch.c:222
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:128
unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key)
Definition: batch.c:157
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:190
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:98
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:127
#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:52
void log_printf_lf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format,...)
Definition: log.c:182
int debug_level
Definition: log.c:34
void keep_alive(void)
Definition: log.c:419
#define ERROR_FAIL
Definition: log.h:161
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:155
@ LOG_LVL_DEBUG
Definition: log.h:47
void riscv_fill_dmi_nop_u64(struct target *target, char *buf)
Definition: riscv.c:3511
void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field, riscv_bscan_tunneled_scan_context_t *ctxt)
Definition: riscv.c:4501
int riscv_dmi_write_u64_bits(struct target *target)
Definition: riscv.c:3517
void riscv_fill_dmi_write_u64(struct target *target, char *buf, int a, uint64_t d)
Definition: riscv.c:3499
void riscv_fill_dmi_read_u64(struct target *target, char *buf, int a)
Definition: riscv.c:3505
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:86
int num_bits
The number of bits this field specifies.
Definition: jtag.h:88
uint8_t * in_value
A pointer to a 32-bit memory location for data scanned out.
Definition: jtag.h:92
const uint8_t * out_value
A pointer to value to be scanned into the device.
Definition: jtag.h:90
Definition: target.h:120
struct jtag_tap * tap
Definition: target.h:124
#define NULL
Definition: usb.h:16