Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes and cleanup in riscv batch and related functions #1014

Merged
merged 2 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 54 additions & 43 deletions src/target/riscv/batch.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,58 +13,66 @@
#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))

/* Reserve extra room in the batch (needed for the last NOP operation) */
#define BATCH_RESERVED_SCANS 1

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;
scans += BATCH_RESERVED_SCANS;
struct riscv_batch *out = calloc(1, sizeof(*out));
if (!out)
goto error0;
if (!out) {
LOG_ERROR("Failed to allocate struct riscv_batch");
return NULL;
}

out->target = target;
out->allocated_scans = scans;
out->idle_count = idle;
out->data_out = malloc(sizeof(*out->data_out) * (scans) * DMI_SCAN_BUF_SIZE);
out->last_scan = RISCV_SCAN_TYPE_INVALID;

out->data_out = NULL;
out->data_in = NULL;
out->fields = NULL;
out->bscan_ctxt = NULL;
out->read_keys = NULL;

/* FIXME: There is potential for memory usage reduction. We could allocate
* smaller buffers than DMI_SCAN_BUF_SIZE (that is, buffers that correspond to
* the real DR scan length on the given target) */
out->data_out = malloc(sizeof(*out->data_out) * scans * DMI_SCAN_BUF_SIZE);
en-sc marked this conversation as resolved.
Show resolved Hide resolved
if (!out->data_out) {
LOG_ERROR("Failed to allocate data_out in RISC-V batch.");
goto error1;
goto alloc_error;
};
out->data_in = malloc(sizeof(*out->data_in) * (scans) * DMI_SCAN_BUF_SIZE);
out->data_in = malloc(sizeof(*out->data_in) * scans * DMI_SCAN_BUF_SIZE);
if (!out->data_in) {
LOG_ERROR("Failed to allocate data_in in RISC-V batch.");
goto error2;
goto alloc_error;
}
out->fields = malloc(sizeof(*out->fields) * (scans));
out->fields = malloc(sizeof(*out->fields) * scans);
if (!out->fields) {
LOG_ERROR("Failed to allocate fields in RISC-V batch.");
goto error3;
goto alloc_error;
}
if (bscan_tunnel_ir_width != 0) {
out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * (scans));
out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * scans);
if (!out->bscan_ctxt) {
LOG_ERROR("Failed to allocate bscan_ctxt in RISC-V batch.");
goto error4;
goto alloc_error;
}
}
out->last_scan = RISCV_SCAN_TYPE_INVALID;
out->read_keys = malloc(sizeof(*out->read_keys) * (scans));
out->read_keys = malloc(sizeof(*out->read_keys) * scans);
if (!out->read_keys) {
LOG_ERROR("Failed to allocate read_keys in RISC-V batch.");
goto error5;
goto alloc_error;
}

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:
alloc_error:
riscv_batch_free(out);
return NULL;
}

Expand All @@ -80,7 +88,7 @@ void riscv_batch_free(struct riscv_batch *batch)

bool riscv_batch_full(struct riscv_batch *batch)
{
return batch->used_scans > (batch->allocated_scans - 4);
return riscv_batch_available_scans(batch) == 0;
}

int riscv_batch_run(struct riscv_batch *batch)
Expand All @@ -94,7 +102,7 @@ int riscv_batch_run(struct riscv_batch *batch)

for (size_t i = 0; i < batch->used_scans; ++i) {
if (bscan_tunnel_ir_width != 0)
riscv_add_bscan_tunneled_scan(batch->target, batch->fields+i, batch->bscan_ctxt+i);
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);

Expand Down Expand Up @@ -125,33 +133,33 @@ int riscv_batch_run(struct riscv_batch *batch)
return ERROR_OK;
}

void riscv_batch_add_dm_write(struct riscv_batch *batch, unsigned int address, uint64_t data,
void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data,
en-sc marked this conversation as resolved.
Show resolved Hide resolved
bool read_back)
{
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->num_bits = riscv_get_dmi_scan_length(batch->target);
field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
riscv_fill_dm_write_u64(batch->target, (char *)field->out_value, address, data);
riscv_fill_dm_write(batch->target, (char *)field->out_value, address, data);
if (read_back) {
field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
riscv_fill_dm_nop(batch->target, (char *)field->in_value);
} else {
field->in_value = NULL;
}
batch->last_scan = RISCV_SCAN_TYPE_WRITE;
batch->used_scans++;
}

size_t riscv_batch_add_dm_read(struct riscv_batch *batch, unsigned int address)
size_t riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t 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->num_bits = riscv_get_dmi_scan_length(batch->target);
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_dm_read_u64(batch->target, (char *)field->out_value, address);
riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
riscv_fill_dm_read(batch->target, (char *)field->out_value, address);
riscv_fill_dm_nop(batch->target, (char *)field->in_value);
batch->last_scan = RISCV_SCAN_TYPE_READ;
batch->used_scans++;

Expand All @@ -163,17 +171,17 @@ unsigned int riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t
{
assert(key < batch->read_keys_used);
size_t index = batch->read_keys[key];
assert(index <= batch->used_scans);
assert(index < batch->used_scans);
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);
return (unsigned int)buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
}

uint32_t riscv_batch_get_dmi_read_data(const 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);
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);
Expand All @@ -183,11 +191,11 @@ 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->num_bits = riscv_get_dmi_scan_length(batch->target);
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_dm_nop_u64(batch->target, (char *)field->out_value);
riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
riscv_fill_dm_nop(batch->target, (char *)field->out_value);
riscv_fill_dm_nop(batch->target, (char *)field->in_value);
batch->last_scan = RISCV_SCAN_TYPE_NOP;
batch->used_scans++;
}
Expand Down Expand Up @@ -226,13 +234,16 @@ static void dump_field(int idle, const struct scan_field *field)

size_t riscv_batch_available_scans(struct riscv_batch *batch)
{
return batch->allocated_scans - batch->used_scans - 4;
assert(batch->allocated_scans >= (batch->used_scans + BATCH_RESERVED_SCANS));
return batch->allocated_scans - batch->used_scans - BATCH_RESERVED_SCANS;
}

bool riscv_batch_dmi_busy_encountered(const struct riscv_batch *batch)
{
if (!batch->used_scans)
if (batch->used_scans == 0)
/* Empty batch */
return false;

assert(batch->last_scan == RISCV_SCAN_TYPE_NOP);
const struct scan_field *field = batch->fields + batch->used_scans - 1;
const uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits);
Expand Down
4 changes: 2 additions & 2 deletions src/target/riscv/batch.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ bool riscv_batch_full(struct riscv_batch *batch);
int riscv_batch_run(struct riscv_batch *batch);

/* Adds a DM register write to this batch. */
void riscv_batch_add_dm_write(struct riscv_batch *batch, unsigned int address, uint64_t data,
void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data,
bool read_back);

/* DM register reads must be handled in two parts: the first one schedules a read and
* provides a key, the second one actually obtains the result of the read -
* status (op) and the actual data. */
size_t riscv_batch_add_dm_read(struct riscv_batch *batch, unsigned int address);
size_t riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t address);
unsigned int riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t key);
uint32_t riscv_batch_get_dmi_read_data(const struct riscv_batch *batch, size_t key);

Expand Down
42 changes: 21 additions & 21 deletions src/target/riscv/riscv-013.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ static riscv_insn_t riscv013_read_progbuf(struct target *target, unsigned int
index);
static int riscv013_invalidate_cached_progbuf(struct target *target);
static int riscv013_execute_progbuf(struct target *target, uint32_t *cmderr);
static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a, uint64_t d);
static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a);
static int riscv013_dmi_write_u64_bits(struct target *target);
static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf);
static void riscv013_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d);
static void riscv013_fill_dm_read_u64(struct target *target, char *buf, int a);
static void riscv013_fill_dm_nop_u64(struct target *target, char *buf);
static void riscv013_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d);
static void riscv013_fill_dmi_read(struct target *target, char *buf, uint64_t a);
static void riscv013_fill_dmi_nop(struct target *target, char *buf);
JanMatCodasip marked this conversation as resolved.
Show resolved Hide resolved
static int riscv013_get_dmi_scan_length(struct target *target);
static void riscv013_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d);
static void riscv013_fill_dm_read(struct target *target, char *buf, uint64_t a);
static void riscv013_fill_dm_nop(struct target *target, char *buf);
static unsigned int register_size(struct target *target, enum gdb_regno number);
static int register_read_direct(struct target *target, riscv_reg_t *value,
enum gdb_regno number);
Expand Down Expand Up @@ -2767,10 +2767,10 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->write_progbuf = &riscv013_write_progbuf;
generic_info->execute_progbuf = &riscv013_execute_progbuf;
generic_info->invalidate_cached_progbuf = &riscv013_invalidate_cached_progbuf;
generic_info->fill_dm_write_u64 = &riscv013_fill_dm_write_u64;
generic_info->fill_dm_read_u64 = &riscv013_fill_dm_read_u64;
generic_info->fill_dm_nop_u64 = &riscv013_fill_dm_nop_u64;
generic_info->dmi_write_u64_bits = &riscv013_dmi_write_u64_bits;
generic_info->fill_dm_write = &riscv013_fill_dm_write;
generic_info->fill_dm_read = &riscv013_fill_dm_read;
generic_info->fill_dm_nop = &riscv013_fill_dm_nop;
generic_info->get_dmi_scan_length = &riscv013_get_dmi_scan_length;
generic_info->authdata_read = &riscv013_authdata_read;
generic_info->authdata_write = &riscv013_authdata_write;
generic_info->dmi_read = &dmi_read;
Expand Down Expand Up @@ -5169,55 +5169,55 @@ static int riscv013_execute_progbuf(struct target *target, uint32_t *cmderr)
return execute_abstract_command(target, run_program, cmderr);
}

static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a, uint64_t d)
static void riscv013_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d)
{
RISCV013_INFO(info);
buf_set_u64((unsigned char *)buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_WRITE);
buf_set_u64((unsigned char *)buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, d);
buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, a);
}

static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a)
static void riscv013_fill_dmi_read(struct target *target, char *buf, uint64_t a)
{
RISCV013_INFO(info);
buf_set_u64((unsigned char *)buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_READ);
buf_set_u64((unsigned char *)buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, 0);
buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, a);
}

static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf)
static void riscv013_fill_dmi_nop(struct target *target, char *buf)
{
RISCV013_INFO(info);
buf_set_u64((unsigned char *)buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_NOP);
buf_set_u64((unsigned char *)buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, 0);
buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, 0);
}

static int riscv013_dmi_write_u64_bits(struct target *target)
static int riscv013_get_dmi_scan_length(struct target *target)
{
RISCV013_INFO(info);
return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH;
}

void riscv013_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d)
void riscv013_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d)
{
dm013_info_t *dm = get_dm(target);
if (!dm)
return;
riscv013_fill_dmi_write_u64(target, buf, a + dm->base, d);
riscv013_fill_dmi_write(target, buf, a + dm->base, d);
}

void riscv013_fill_dm_read_u64(struct target *target, char *buf, int a)
void riscv013_fill_dm_read(struct target *target, char *buf, uint64_t a)
{
dm013_info_t *dm = get_dm(target);
if (!dm)
return;
riscv013_fill_dmi_read_u64(target, buf, a + dm->base);
riscv013_fill_dmi_read(target, buf, a + dm->base);
}

void riscv013_fill_dm_nop_u64(struct target *target, char *buf)
void riscv013_fill_dm_nop(struct target *target, char *buf)
{
riscv013_fill_dmi_nop_u64(target, buf);
riscv013_fill_dmi_nop(target, buf);
}

static int maybe_execute_fence_i(struct target *target)
Expand Down
16 changes: 8 additions & 8 deletions src/target/riscv/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -5354,28 +5354,28 @@ int riscv_execute_progbuf(struct target *target, uint32_t *cmderr)
return r->execute_progbuf(target, cmderr);
}

void riscv_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d)
void riscv_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d)
{
RISCV_INFO(r);
r->fill_dm_write_u64(target, buf, a, d);
r->fill_dm_write(target, buf, a, d);
}

void riscv_fill_dm_read_u64(struct target *target, char *buf, int a)
void riscv_fill_dm_read(struct target *target, char *buf, uint64_t a)
{
RISCV_INFO(r);
r->fill_dm_read_u64(target, buf, a);
r->fill_dm_read(target, buf, a);
}

void riscv_fill_dm_nop_u64(struct target *target, char *buf)
void riscv_fill_dm_nop(struct target *target, char *buf)
{
RISCV_INFO(r);
r->fill_dm_nop_u64(target, buf);
r->fill_dm_nop(target, buf);
}

int riscv_dmi_write_u64_bits(struct target *target)
int riscv_get_dmi_scan_length(struct target *target)
{
RISCV_INFO(r);
return r->dmi_write_u64_bits(target);
return r->get_dmi_scan_length(target);
}

static int check_if_trigger_exists(struct target *target, unsigned int index)
Expand Down
16 changes: 8 additions & 8 deletions src/target/riscv/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,10 @@ struct riscv_info {
riscv_insn_t (*read_progbuf)(struct target *target, unsigned int index);
int (*execute_progbuf)(struct target *target, uint32_t *cmderr);
int (*invalidate_cached_progbuf)(struct target *target);
int (*dmi_write_u64_bits)(struct target *target);
void (*fill_dm_write_u64)(struct target *target, char *buf, int a, uint64_t d);
void (*fill_dm_read_u64)(struct target *target, char *buf, int a);
void (*fill_dm_nop_u64)(struct target *target, char *buf);
int (*get_dmi_scan_length)(struct target *target);
void (*fill_dm_write)(struct target *target, char *buf, uint64_t a, uint32_t d);
void (*fill_dm_read)(struct target *target, char *buf, uint64_t a);
void (*fill_dm_nop)(struct target *target, char *buf);

int (*authdata_read)(struct target *target, uint32_t *value, unsigned int index);
int (*authdata_write)(struct target *target, uint32_t value, unsigned int index);
Expand Down Expand Up @@ -429,10 +429,10 @@ riscv_insn_t riscv_read_progbuf(struct target *target, int index);
int riscv_write_progbuf(struct target *target, int index, riscv_insn_t insn);
int riscv_execute_progbuf(struct target *target, uint32_t *cmderr);

void riscv_fill_dm_nop_u64(struct target *target, char *buf);
void riscv_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d);
void riscv_fill_dm_read_u64(struct target *target, char *buf, int a);
int riscv_dmi_write_u64_bits(struct target *target);
void riscv_fill_dm_nop(struct target *target, char *buf);
void riscv_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d);
void riscv_fill_dm_read(struct target *target, char *buf, uint64_t a);
int riscv_get_dmi_scan_length(struct target *target);

int riscv_enumerate_triggers(struct target *target);

Expand Down
Loading