riscv-non-isa/riscv-trace-spec

Decoder pseudo code: add comments as to where to emit a PC that was "executed"

bmcspadd-seagate opened this issue · 0 comments

The Decoder pseudo code is a dense bit of code that tells a user how to take the etrace messages and convert them
into an executed instruction stream (given that you also have access to the assembly code, usually in the form of an
.elf file).

One thing that is not clear when reading the code, is... just where in the code does it say that an instruction can be
reported as executed?

The short answer to this question is: you can report that an instruction was executed when the global variable, 'pc',
changes. This text, at least, should be added as a comment at the top of the pseudo code.

I would also propose that you add 2 user-optional functions in the pseudo code, report_pc() and report_exception_pc(),
and then insert them into the code flow at the appropriate places.

Why "user-optional"? Because it's up to the user how they wish to utilize the pseudo code. A user may not wish to
do anything when the 'pc' changes. On the other hand, almost every user is interested in reconstructing the instruction
trace on a PC by PC basis. As such, it would be helpful to show the user where to emit the PC.

Why 2 functions (as opposed to just one)? Normally, the user would use "report_pc()" to reconstruct trace for most
all messages (format 1 and format 2 messages). However, we have a special case when dealing with exceptions.
The RISCV spec explicitly states that PCs that cause exceptions are not to be considered "retired". However, while
not retired, these PCs cause a non-inferrable change in instruction flow. Well, most users want to know about that
and will want to report the PC that caused the change in control flow. (Note: If the PC that caused the change of control
flow, is itself the target of an uninferrable jump, then it is difficult to understand the instruction flow. See issue #66
for a proposal to handle this problem.) The user may or may not want to report this PC: a case could be made for
both. Therefore, I suggest that we show where this instruction reconstruction should occur.

Where should these function calls be put in the pseudo code?

Here is where I think the function calls should be made (based on my implementation of the decoder):

On page 84, add the following:

if (te_inst.format == 3)
if (te_inst.subformat == 3) # Support packet
process_support(te_inst)
return
if (te_inst.subformat == 2) # Context packet
return
if (te_inst.subformat == 1) # trap <==== PROPOSED ADDITION
report_exception_pc(te_inst.tvalepc) <==== PROPOSED ADDITION

On page 84:

else
pc = address
report_pc(pc) <==== PROPOSED ADDITION
last_pc = pc # previous pc not known but ensures correct
# operation for is_sequential_jump()

On page 86:

if (is_call(instr))
push_return_stack(this_pc)
report_pc(pc) <++++ PROPOSED ADDITION
last_pc = this_pc

At end of pseudo code:

function report_pc(pc) # User optional, user supplied
return

function report_exception_pc() # User optional, user supplied
return