Hi. Regarding RISC-V Exceptions, Traps, interrupts and CSRs

463 views
Skip to first unread message

ariyosko

unread,
Aug 12, 2022, 11:28:11 AM8/12/22
to RISC-V ISA Dev
Hi.

I am very new to RISC-V and trying to write my own simplest implementation as a project. I am aiming at the simplest option - RV32I. Currently I have consumed only the required (or so I hope) parts of the "unprivileged" document, again because I am trying to show myself how the most minimal implementation can look like.

I can see that the interrupt vector implementation is open (EEI decision). I can also see that RV32I defines software trap commands (ECALL, EBREAK). I was originally working off the May 7 2017 version of the spec (which is BTW the first Google result I get for "risc V documentation"), and figured that trap information, specifically the return address (the one that caused the trap, or the next one) will be stored in a CSR, allowing for a proper "return from trap handler" operation. However looking at the doc from December 23 2019, all CSR instructions were removed from the RV32I specification.

So my question is - first, am I wrong to think I can complete a standard RV32I implementation reading just the "unprivileged" document? Moreover - given that ECALL/EBREAK are mandatory in RV32I (while it is mentioned they can have an identical implementation) and also that instructions like JAL should generate an exception on misaligned targets, evidently RV32I needs to handle trap-like operations.

Most importantly: How can the trap handler know the very basic data item of where the PC came from?

Thanks.

Tommy Murphy

unread,
Aug 12, 2022, 12:11:37 PM8/12/22
to ariyosko, RISC-V ISA Dev
From the privileged spec:

"All hardware implementations must provide M-mode, as this is the only mode that has unfettered access to the whole machine. "

That being the case it seems that your RV32I implementation must, at least, implement M mode and, as such, you cannot implement it without reference to the privileged spec as well as the unprivileged ISA spec.

Ideally you should refer to ratified versions of each and not pre-ratification drafts.

In terms of trap handling, certain CSRs such as mepc, mcause and mtval will almost certainly be relevant.

Allen Baum

unread,
Aug 12, 2022, 2:24:01 PM8/12/22
to Tommy Murphy, ariyosko, RISC-V ISA Dev
Well, yes and no.  The privileged spec is intended to be separable from the unpriv spec. How practical that is a separate issue.
So, you could implement a custom, proprietary trap mechanism and priv spec - and if your underlying semantics are equivalent, then app-level should run properly.
E.g. ECALL and EBREAK are defined in terms of calling the execution environment, which is not necessarily the Risc-V execution environment as defined by the priv spec.
Of course, compatibility with standard distros - and probably tool-chains, will not be an option in that case.
Note that some unpriv extensions do require the Zicsr extension -  and those extensions might require that specific CSRs be accessible using CSRxx opcode encodings and semantics
(I'm not positive about that)


--
You received this message because you are subscribed to the Google Groups "RISC-V ISA Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isa-dev+u...@groups.riscv.org.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/isa-dev/LO0P265MB6866D6A7F7A3C0C730D1F3E5F9679%40LO0P265MB6866.GBRP265.PROD.OUTLOOK.COM.

BGB

unread,
Aug 12, 2022, 4:49:58 PM8/12/22
to isa...@groups.riscv.org
On 8/12/2022 10:28 AM, ariyosko wrote:
> Hi.
>
> I am very new to RISC-V and trying to write my own simplest
> implementation as a project. I am aiming at the simplest option - RV32I.
> Currently I have consumed only the required (or so I hope) parts of the
> "unprivileged" document, again because I am trying to show myself how
> the most minimal implementation can look like.
>
> I can see that the interrupt vector implementation is open (EEI
> decision). I can also see that RV32I defines software trap commands
> (ECALL, EBREAK). I was originally working off the May 7 2017 version of
> the spec (which is BTW the first Google result I get for "risc V
> documentation"), and figured that trap information, specifically the
> return address (the one that caused the trap, or the next one) will be
> stored in a CSR, allowing for a proper "return from trap handler"
> operation. However looking at the doc from December 23 2019, all CSR
> instructions were removed from the RV32I specification.
>
> *So my question is *- first, am I wrong to think I can complete a
> standard RV32I implementation reading just the "unprivileged" document?
> Moreover - given that ECALL/EBREAK are mandatory in RV32I (while it is
> mentioned they can have an identical implementation) and also that
> instructions like JAL should generate an exception on misaligned
> targets, evidently RV32I needs to handle trap-like operations.
>
> *Most importantly: *How can the trap handler know the very basic data
> item of where the PC came from?
>

I can imagine a few scenarios:
* No privileged-mode features or similar:
** Effectively, one would have a CPU which can't handle interrupts.
** This would severely limit utility.

* A privileged mode exists, but is different from the spec.
** This could work for microcontrollers or similar (*1).
** One still needs to come up with "something" here.

* One implements the privileged mode according to the spec.
** Better compatibility, but likely more cost.



*1: This is also effectively the situation with my core, but my core is
not (actually) a RISC-V core (it primarily runs my own ISA), but rather
has RISC-V (RV64IM for now) as a sub-mode.

Was able to add 'M' features via a dedicated Shift-Add unit, adds cost,
but not really aware of any cheaper option (and, it is technically
faster than doing a shift-add loop in software).

I may be able to expand to add 'A', as I had implemented some similar
functionality as an experiment and the cost isn't too unreasonable.

Some of the 'A' style functionality was handled by sticking an ALU into
the L1 D$ (where the Load and Store paths cross, they cross paths with a
specialized ALU).

F/D are a little more of an issue as they don't map over very well to my
FPU design.


The RISC-V privileged ISA seems like a more expensive way to approach
some problems:
* Multiple sets of registers.
** Would push the RegFile size well outside the limits of a LUT6 (*2);
** More expensive HW than having ISRs manually save/restore registers.
* Seems to also require page-table walking to be done in hardware.
** More expensive than using a software-managed TLB.
** If the TLB misses, raise an exception.

2: At least on Xilinx (7 series) FPGAs, 64 is a magic number. An array
with 32 or 64 entries can be cheap, whereas an array with more than this
is "significantly less cheap". Using Block-RAM for CPU registers is also
undesirable.

If one has, say:
* 32 GPRs + 32 FPRs;
* 3 modes, each with their own copy of the registers;
* This is 192 registers, which is kind of a problem.


Hardware page table walking also adds costs, and limits flexibility:
Say, one is stuck with an N-level page table, can't have the OS decide
it wants to use a B-Tree or similar for virtual memory management
(rather than a nested page table). And, if one wants to do hypervisor
stuff, they need hardware support rather than being able to do it in
software.

Some things, like doing ACL based access-rights checking on memory
pages, would be a lot harder to pull off with a hardware page-table
walker (say, if one wants to be able to have multiple processes in the
same virtual address space, but wants to use ACL checks and similar to
stop them from stomping each others memory).

Say, for cheaper MMU:
* ISR does its thing, and shoves the fetched data back into the TLB via
a special-purpose instruction (say, 'LDTLB' which copies the contents of
a few hard-wired registers into the TLB).


In my case, I have a 4-way set-associative TLB; but can note that this
is basically the minimum if one doesn't want to risk getting stuck in an
infinite loop of TLB misses in certain edge cases. With a 2-way TLB, it
is possible to run into cases where the I$ and D$ land in the same spots
in the TLB and mutually evict each other (and thus prevent forward
progress). In this case, the TLB is shared by both the I$ and D$.

Not really figured out a cheaper option here.

Granted, one disadvantage of software-managed TLB is that now TLB misses
eat significantly more clock-cycles and also involve an interrupt (well,
probably doesn't help if one is also using a B-Tree, which in turn
roughly doubles the clock cycle cost for each TLB miss).

Implicitly, interrupt handlers also can only run in physically-mapped
memory ranges in this case (say, when one enters an interrupt, the L1
caches also disable address translation).


Say, for example, a cheaper approach to interrupt handling:
* There is only one set of registers;
* Interrupt entry does something like:
** Save some internal status/control flag state;
** Save the PC value at the point where the interrupt happened;
** Set mode bits to an ISR / Machine mode;
** Swap main stack register with a different stack register;
** Perform a computed branch relative to an interrupt vector register.
*** The interrupt-entry table is an array of branch instructions.

Return from interrupt:
* Restore the status-flag bits to their original state;
* Branch to the saved PC register.

Once an ISR gets control, it would then need to save all the registers
to the stack or similar, and then restore all of them when the ISR
returns. This would not be needed with multiple sets of registers.

Currently, it deals with the stack swapping by switching the registers
in the instruction decoder. Previously, it had had caused the values to
switch places in the register file, but handling this case in
instruction the decoders turned out to be cheaper.


This would be mostly a speed/cost tradeoff.
This was admittedly, also, the cheapest mechanism I could come up with
at the time.

...


Granted, I guess not really much other option (to the privileged spec)
if one wants to have much hope of running an existing OS.

So, for example, in my case, even if I did implement RV64IMAFD, still
couldn't run normal Linux on it...


Well, that and also the hardware-device level interfaces:
It would not know about my MMIO device interfaces;
I am not using a traditional bitmapped framebuffer.

It has a bitmapped 320x200 mode, but the memory is organized in blocks
rather than in raster order. It has 640x400 and 800x600 modes, but they
are color-cell based rather than raster.

640x400: 2 colors per 4x4 block, 2-bit interpolation (or, alternately,
4-bpp / 16-color RGBI).
800x600: 2 colors per 8x8 block, 1-bit selector (or, alternately, 2-bpp
/ 4-color, sorta like CGA).

The screen memory is now mapped into RAM, but it can't really do higher
resolution bitmap modes due to still not having enough RAM bandwidth
available to pull off the screen refresh.

GUI is sorta possible in the 640x400 or 800x600 modes, but generally
involves needing to feed everything through a color-cell encoder, which
eats a lot of performance (along with degrading image quality; albeit
not quite as badly as in RGBI or 4-color modes).

Well, and also other issues, like my FPGA board not allowing for both a
mouse and keyboard at the same time (would need a PMod or similar for this).

All this would quickly turn into an uphill battle (and, say, one needs
to pick their battles).

...



> Thanks.
>
> --
> You received this message because you are subscribed to the Google
> Groups "RISC-V ISA Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to isa-dev+u...@groups.riscv.org
> <mailto:isa-dev+u...@groups.riscv.org>.
> To view this discussion on the web visit
> https://groups.google.com/a/groups.riscv.org/d/msgid/isa-dev/15be3d00-ef1e-4881-aed5-73184930ac9fn%40groups.riscv.org
> <https://groups.google.com/a/groups.riscv.org/d/msgid/isa-dev/15be3d00-ef1e-4881-aed5-73184930ac9fn%40groups.riscv.org?utm_medium=email&utm_source=footer>.

Reply all
Reply to author
Forward
0 new messages