B1 Exception Handling and Simple Operating Systems
After implementing IOE, we will next implement CTE on NEMU and NPC. Once implemented, we will be able to run operating systems that are no longer trivial!
Running RT-Thread in NEMU
Implement Trap Operations in NEMU
Complete Phase 1 of PA3 according to the PA lecture notes until you see the following prompt box:
Friendly Reminder
Stage 1 of PA3 ends here.
Run RT-Thread in NEMU
Complete Phase 1 of PA4 according to the PA lecture notes until RT-Thread boots. The Nanos-lite related content afterwards is not required for now.
Adding CSRs to NPC
In RISC-V, there is a class of system registers used to indicate the processor state, called Control and Status Registers (CSR). Unlike general-purpose registers, ordinary computational instructions cannot directly access CSRs. Therefore, RISC-V also provides CSR instructions for exchanging data between CSRs and general-purpose registers. Unlike ordinary instructions, CSR instructions atomically read and write the same CSR.
The CSR address space in RISC-V is 12 bits, i.e., 4096 registers, but RISC-V defines only a little over 300 CSRs; if we exclude performance counters and PMP (Physical Memory Protection) related CSRs, there are only 78 left; if we further only count M-mode CSRs, there are only 28; if we only consider the few CSRs necessary for running RT-Thread that were implemented in NEMU, fewer than five. Therefore, there is no need for us to instantiate hundreds or even 4096 CSRs. Although this would only take up some memory for NEMU, it would result in significant area overhead for NPC. Specifically, we only need to instantiate the CSRs we need, and then read and write them according to their addresses.
The first CSR you need to add is mcycle, a counter that increments by 1 every cycle. With it, we can convert the cycle count into time based on the processor's frequency, thereby implementing AM clock-related functionality. According to the RISC-V manual, mcycle itself is a 64-bit counter. In RV32, since the width of general-purpose registers is 32 bits, this counter needs to be split into two 32-bit CSRs, mcycle and mcycleh, for access.
Add mcycle
Specifically, you need to implement the csrrs instruction in NPC and add mcycle. To do this, you need to read the RISC-V privileged architecture manual, and find the numbers of mcycle and mcycleh and other information.
After implementation, try reading the mcycle register multiple times through inline assembly, and check whether its value increments automatically. In inline assembly, you can use the pseudo-instruction csrr, whose corresponding real instruction is csrrs.
To identify the NPC of different students, we can use the identification registers in the CSR. Specifically, RISC-V defines two CSRs, mvendorid and marchid, which we can use to store some identification information. Afterwards, a program can read this identification information into general-purpose registers through CSR instructions at runtime, and further print them.
Add Student ID CSRs and Output the Student ID
Specifically, you need to implement the csrrs instruction in NPC, and add the following two CSRs:
mvendorid- read out the ASCII code ofysyx, i.e.,0x79737978marchid- read out the decimal representation of the numeric part of your student ID. Assuming your student ID isysyx_22068888, if the read information is interpreted as an integer, it should be22068888, i.e.,0x150be98
After implementation, before TRM enters the main() function, read out the values of the above two CSRs through inline assembly, and then output them through printf().
Running RT-Thread in NPC
With the help of AM, we can run RT-Thread at a very low cost. In terms of hardware, we only need to implement a few CSRs, several CSR instructions, the ecall and mret instructions, and the corresponding exception response mechanism. You already learned about these when implementing NEMU. Here we briefly discuss how to implement them through RTL.
The CSRs that need to be implemented currently do not have any special side effects. Although the RISC-V manual describes various functions for mstatus, we don't need to use them at present. We just need to initialize them correctly to pass DiffTest.
Currently we can ignore the read/write properties in the CSRs (if you haven't heard of them, you need to carefully RTFM), including WPRI, WLRL, and WARL, which define the behavior when illegal values are written to CSR fields. The programs we are running currently do not depend on these behaviors, so we can temporarily skip implementing these read and write attributes.
Both ecall and mret will cause NPC to jump, which can be easily implemented by reusing the data path of the next address logic.
Currently, we only need to implement the ecall exception, which is a trap exception that NPC must respond to unconditionally. We just need to set mcause and mepc simultaneously, then jump to the exception entry stored in mtvec.
Run RT-Thread in NPC
Implement a simple exception handling mechanism in NPC and run RT-Thread.
Fix the Issue Where RT-Thread Doesn't Output the Final Command Prompt
You will notice that, unlike in NEMU, when running RT-Thread on NPC, the final msh /> is not output. If you are interested in this issue, you can think about how to solve it now. You can also choose to ignore this issue, as you will encounter similar problems when connecting to the SoC later.
The complete exception handling mechanism in RISC-V is much more complex than what we are implementing now, and commercial RISC-V processors must accurately implement every detail described in the manual, regardless of whether customers will use them. Implementing all CSRs and carefully handling each bit is actually a rather engineering-oriented task that requires a lot of effort from the engineering team. However, "One Student One Chip" is ultimately an educational project, and its goal is not to design a RISC-V processor that meets commercial delivery requirements. Therefore, we can simplify various complex mechanisms on the premise that the demonstration programs run correctly, allowing everyone to focus on learning key principles and developing core functions. As we run more programs in the A phase in the future, we will gradually add various CSRs and their core functions.
Apply for the C Stage Completion Assessment
Apply for the C Stage Completion Assessment
Congratulations! You have completed all the content in the C stage. You can apply for the C stage completion assessment to test your learning outcomes. If you pass the assessment, we will issue you a certificate.
- Click here to jump to the C stage completion assessment application entry
- Click here to jump to the C stage completion assessment certificate inquiry entry
However, this is not mandatory. You can continue learning, but you can only participate in the B stage tapeout assessment after passing the C stage completion assessment.
yyz
