4

I am about to write my own RV32I core with a CLINT. However there is something which is not fully clear to me. At least I could not find it in the docs. Here is what the privileged isa spec says for ecall/ebreak:

ECALL and EBREAK cause the receiving privilege mode’s epc register to be set to the address of the ECALL or EBREAK instruction itself, not the address of the following instruction.

So this means, that setting the right mepc for mret is the responsibility of the SW handler. I assume that this behavior applies to all other exceptions too.

What about asynchronous interrupts? Does the HW set mepc to PC+4 automatically? From what I saw in different SW handlers it seems that it is like this, but I actually could not find it in the docs.

Hopefully someone can point me to the right documentation.

Riking
  • 2,389
  • 1
  • 24
  • 36
developer123
  • 81
  • 1
  • 4
  • this question has nothing to do with 'c' or 'verilog'. At minimum you should remove those tags. This forum is about programming, so you might nee to ask the question at the 'electrical engineering' forum. – Serge Nov 06 '19 at 13:02
  • 3
    But it also has nothing to do with electrical engineering either. It is about the Instruction Set Architecture. I added C and Verilog in the hope to reach more of the low level devs here which may have experience with this question. qemu for example implemented the ISA in C and a lot of RV32I cores are written in Verilog, so in my opinion the selected tags are absolutely sufficient. – developer123 Nov 06 '19 at 14:24

1 Answers1

9

Section 1.6 of the unprivileged RISC-V specification defines that exceptions are raised by instructions and interrupts are raised by external events.

When an (synchronous) exception is raised, the triggering instruction cannot be completed properly. Hence, there are two possibilities for the return address: either the instruction itself or the following instruction. Both solutions make sense. If it points to the instruction itself it is easier to determine the problem and react accordingly. If it points to the next instruction, the address need not be incremented when returning from the exception handler

(Asynchronous) interrupts are different, they break the stream of executed instructions of an independent thread. Therefore, there is only one reasonable solution for the return address: the first instruction that has not completed yet. Thus, when returning from the interrupt handler, the execution continues exactly where it was interrupted.

With this background, the brief definition in section 3.1.15 of the privileged RISC-V specification

When a trap is taken into M-mode, mepc is written with the virtual address of the instruction that was interrupted or that encountered the exception.

is clear: mepc points to the first uncompleted instruction, when an interrupt is raised or to the instruction that raised an exception.

Jörg Mische
  • 131
  • 2
  • Thanks for this great answer! So for a very simple risc-v implementation where it is not possible to interrupt a single instruction the correct behavior would be: For (synchronous) exceptions mepc will be set to the instruction which triggered the exception and for (asynchronous) interrupts mepc will be set to PC+4, right? – developer123 Nov 13 '19 at 13:36
  • 1
    If the instruction at PC is the last instruction that is executed before the first instruction from the interrupt handler, PC+4 is correct. – Jörg Mische Nov 14 '19 at 09:24