Skip to content

Drop the use of has_sufficient_progbuf() with riscv_program_exec() #1301

@en-sc

Description

@en-sc

Having a program buffer that fits at least one instruction allows to execute any number of consecutive instructions (with no control flow changes).
You can see an example in execute_autofence():

if (has_sufficient_progbuf(target, 3)) {
riscv_program_init(&program, target);
riscv_program_fence_i(&program);
riscv_program_fence_rw_rw(&program);
if (riscv_program_exec(&program, target) != ERROR_OK) {
if (program.execution_result != RISCV_PROGBUF_EXEC_RESULT_EXCEPTION) {
LOG_TARGET_ERROR(target, "Unexpected error during fence execution");
return ERROR_FAIL;
}
LOG_TARGET_DEBUG(target, "Unable to execute fence.i and fence rw, rw");
}
LOG_TARGET_DEBUG(target, "Successfully executed fence.i and fence rw, rw");
return ERROR_OK;
}
if (has_sufficient_progbuf(target, 2)) {
riscv_program_init(&program, target);
riscv_program_fence_i(&program);
if (riscv_program_exec(&program, target) != ERROR_OK) {
if (program.execution_result != RISCV_PROGBUF_EXEC_RESULT_EXCEPTION) {
LOG_TARGET_ERROR(target, "Unexpected error during fence.i execution");
return ERROR_FAIL;
}
LOG_TARGET_DEBUG(target, "Unable to execute fence.i");
}
LOG_TARGET_DEBUG(target, "Successfully executed fence.i");
riscv_program_init(&program, target);
riscv_program_fence_rw_rw(&program);
if (riscv_program_exec(&program, target) != ERROR_OK) {
if (program.execution_result != RISCV_PROGBUF_EXEC_RESULT_EXCEPTION) {
LOG_TARGET_ERROR(target, "Unexpected error during fence rw, rw execution");
return ERROR_FAIL;
}
LOG_TARGET_DEBUG(target, "Unable to execute fence rw, rw");
}
LOG_TARGET_DEBUG(target, "Successfully executed fence rw, rw");
return ERROR_OK;
}
return ERROR_FAIL;
}

Here the debugger attempts to execute two consecutive fences. However, if both fences do not fit into the program buffer, it executes one fence after another with two calls to riscv_program_exec().

This approach can be generalized to any program. If the size of a program is grater than the size of the Program Buffer the debugger can:

  • Fill the Program Buffer with the instructions until it is full.
  • Execute the Program Buffer.
  • If the execution is successful, fill the program buffer with the next batch of instructions
  • Loop until all the instructions are executed or an execution fails.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions