Upstream tons of RISC-V changes.
[openocd.git] / src / target / riscv / batch.c
index d041ed119205d282fa0ea6fd52a17e9af93ebfcc..43f2ffb8c09a3b22d61b3620af02c830c140806f 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
 #define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
 
+#define DTM_DMI_MAX_ADDRESS_LENGTH     ((1<<DTM_DTMCS_ABITS_LENGTH)-1)
+#define DMI_SCAN_MAX_BIT_LENGTH (DTM_DMI_MAX_ADDRESS_LENGTH + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH)
+#define DMI_SCAN_BUF_SIZE (DIV_ROUND_UP(DMI_SCAN_MAX_BIT_LENGTH, 8))
+
 static void dump_field(int idle, const struct scan_field *field);
 
 struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans, size_t idle)
 {
        scans += 4;
        struct riscv_batch *out = calloc(1, sizeof(*out));
+       if (!out)
+               goto error0;
        out->target = target;
        out->allocated_scans = scans;
        out->idle_count = idle;
-       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->data_out = malloc(sizeof(*out->data_out) * (scans) * DMI_SCAN_BUF_SIZE);
+       if (!out->data_out)
+               goto error1;
+       out->data_in = malloc(sizeof(*out->data_in) * (scans) * DMI_SCAN_BUF_SIZE);
+       if (!out->data_in)
+               goto error2;
        out->fields = malloc(sizeof(*out->fields) * (scans));
+       if (!out->fields)
+               goto error3;
+       if (bscan_tunnel_ir_width != 0) {
+               out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * (scans));
+               if (!out->bscan_ctxt)
+                       goto error4;
+       }
        out->last_scan = RISCV_SCAN_TYPE_INVALID;
        out->read_keys = malloc(sizeof(*out->read_keys) * (scans));
+       if (!out->read_keys)
+               goto error5;
        return out;
+
+error5:
+       free(out->bscan_ctxt);
+error4:
+       free(out->fields);
+error3:
+       free(out->data_in);
+error2:
+       free(out->data_out);
+error1:
+       free(out);
+error0:
+       return NULL;
 }
 
 void riscv_batch_free(struct riscv_batch *batch)
@@ -31,6 +65,8 @@ void riscv_batch_free(struct riscv_batch *batch)
        free(batch->data_in);
        free(batch->data_out);
        free(batch->fields);
+       free(batch->bscan_ctxt);
+       free(batch->read_keys);
        free(batch);
 }
 
@@ -51,7 +87,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);
        }
@@ -61,6 +101,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, DMI_SCAN_BUF_SIZE, 1);
+       }
+
        for (size_t i = 0; i < batch->used_scans; ++i)
                dump_field(batch->idle_count, batch->fields + i);
 
@@ -72,8 +118,8 @@ void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint
        assert(batch->used_scans < batch->allocated_scans);
        struct scan_field *field = batch->fields + batch->used_scans;
        field->num_bits = riscv_dmi_write_u64_bits(batch->target);
-       field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t));
-       field->in_value  = (void *)(batch->data_in  + batch->used_scans * sizeof(uint64_t));
+       field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
+       field->in_value  = (void *)(batch->data_in  + batch->used_scans * DMI_SCAN_BUF_SIZE);
        riscv_fill_dmi_write_u64(batch->target, (char *)field->out_value, address, data);
        riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_WRITE;
@@ -85,35 +131,35 @@ size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address)
        assert(batch->used_scans < batch->allocated_scans);
        struct scan_field *field = batch->fields + batch->used_scans;
        field->num_bits = riscv_dmi_write_u64_bits(batch->target);
-       field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t));
-       field->in_value  = (void *)(batch->data_in  + batch->used_scans * sizeof(uint64_t));
+       field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
+       field->in_value  = (void *)(batch->data_in  + batch->used_scans * DMI_SCAN_BUF_SIZE);
        riscv_fill_dmi_read_u64(batch->target, (char *)field->out_value, address);
        riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_READ;
        batch->used_scans++;
 
-       /* FIXME We get the read response back on the next scan.  For now I'm
-        * just sticking a NOP in there, but this should be coalesced away. */
-       riscv_batch_add_nop(batch);
-
-       batch->read_keys[batch->read_keys_used] = batch->used_scans - 1;
+       batch->read_keys[batch->read_keys_used] = batch->used_scans;
        return batch->read_keys_used++;
 }
 
-uint64_t riscv_batch_get_dmi_read(struct riscv_batch *batch, size_t key)
+unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key)
 {
        assert(key < batch->read_keys_used);
        size_t index = batch->read_keys[key];
        assert(index <= batch->used_scans);
-       uint8_t *base = batch->data_in + 8 * index;
-       return base[0] |
-               ((uint64_t) base[1]) << 8 |
-               ((uint64_t) base[2]) << 16 |
-               ((uint64_t) base[3]) << 24 |
-               ((uint64_t) base[4]) << 32 |
-               ((uint64_t) base[5]) << 40 |
-               ((uint64_t) base[6]) << 48 |
-               ((uint64_t) base[7]) << 56;
+       uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
+       /* extract "op" field from the DMI read result */
+       return (unsigned)buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
+}
+
+uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key)
+{
+       assert(key < batch->read_keys_used);
+       size_t index = batch->read_keys[key];
+       assert(index <= batch->used_scans);
+       uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
+       /* extract "data" field from the DMI read result */
+       return buf_get_u32(base, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH);
 }
 
 void riscv_batch_add_nop(struct riscv_batch *batch)
@@ -121,8 +167,8 @@ void riscv_batch_add_nop(struct riscv_batch *batch)
        assert(batch->used_scans < batch->allocated_scans);
        struct scan_field *field = batch->fields + batch->used_scans;
        field->num_bits = riscv_dmi_write_u64_bits(batch->target);
-       field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t));
-       field->in_value  = (void *)(batch->data_in  + batch->used_scans * sizeof(uint64_t));
+       field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
+       field->in_value  = (void *)(batch->data_in  + batch->used_scans * DMI_SCAN_BUF_SIZE);
        riscv_fill_dmi_nop_u64(batch->target, (char *)field->out_value);
        riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_NOP;
@@ -151,13 +197,17 @@ void dump_field(int idle, const struct scan_field *field)
 
                log_printf_lf(LOG_LVL_DEBUG,
                                __FILE__, __LINE__, __PRETTY_FUNCTION__,
-                               "%db %di %s %08x @%02x -> %s %08x @%02x",
-                               field->num_bits, idle,
-                               op_string[out_op], out_data, out_address,
-                               status_string[in_op], in_data, in_address);
+                               "%db %s %08x @%02x -> %s %08x @%02x; %di",
+                               field->num_bits, op_string[out_op], out_data, out_address,
+                               status_string[in_op], in_data, in_address, idle);
        } else {
                log_printf_lf(LOG_LVL_DEBUG,
-                               __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %di %s %08x @%02x -> ?",
-                               field->num_bits, idle, op_string[out_op], out_data, out_address);
+                               __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?; %di",
+                               field->num_bits, op_string[out_op], out_data, out_address, idle);
        }
 }
+
+size_t riscv_batch_available_scans(struct riscv_batch *batch)
+{
+       return batch->allocated_scans - batch->used_scans - 4;
+}

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)