浏览代码

feat(spec): add changelog entry for RV128I emulator example

Rearrange code.

Signed-off-by: Zhouqi Jiang <[email protected]>
Zhouqi Jiang 1 月之前
父节点
当前提交
b17aee8b9d
共有 2 个文件被更改,包括 84 次插入83 次删除
  1. 1 0
      library/sbi-spec/CHANGELOG.md
  2. 83 83
      sbi-spec/examples/simple-rv128i-emulator.rs

+ 1 - 0
library/sbi-spec/CHANGELOG.md

@@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 - binary: `impl From<Error> for SbiRet`, `impl IntoIterator for SbiRet`
 - binary: unsafe functions `SbiRet::{unwrap_unchecked, unwrap_err_unchecked}`
 - binary: internal unit tests for `SbiRet` constructors
+- examples: simple RV128I emulator example
 
 ### Modified
 

+ 83 - 83
sbi-spec/examples/simple-rv128i-emulator.rs

@@ -79,8 +79,89 @@ fn main() {
     }
 }
 
+/// Handle an SBI call given the extension and function numbers, along with its parameters.
+///
+/// This is a simple SBI implementation (without using RustSBI) that supports a few functions:
+/// - BASE probe_extension: checks if an SBI extension exists.
+/// - SRST system_reset: performs a system reset (shutdown).
+///
+/// Note that the returned `SbiRet<u128>` represents an `SbiRet` with `u128` as the SBI register
+/// type.
+///
+/// # Parameters
+/// - `extension`: The SBI extension identifier (from register A7).
+/// - `function`: The SBI function number (from register A6).
+/// - `param`: An array containing SBI call parameters (from registers A0-A5).
+///
+/// # Returns
+/// An `SbiRet` structure containing the error and return values.
+fn handle_sbi_call(extension: u128, function: u128, param: [u128; 6]) -> SbiRet<u128> {
+    match (extension, function) {
+        // BASE probe_extension: if the parameter matches the BASE extension identifier, return 1.
+        (0x10, 3) => {
+            if param[0] == 0x10 {
+                SbiRet::success(1)
+            } else {
+                SbiRet::success(0)
+            }
+        }
+        // SRST system_reset: perform a system reset if the reset type is shutdown.
+        (0x53525354, 0) => {
+            let (reset_type, reset_reason) = (param[0], param[1]);
+            if reset_type == sbi_spec::srst::RESET_TYPE_SHUTDOWN as u128 {
+                // Use a special SBI error value (0x114514) to signal platform shutdown.
+                SbiRet {
+                    value: reset_reason,
+                    error: 0x114514,
+                }
+            } else {
+                SbiRet::not_supported()
+            }
+        }
+        // All other SBI calls are not supported.
+        _ => SbiRet::not_supported(),
+    }
+}
+
 /* -- Implementations of SimpleRv128Platform -- */
 
+/// Handle the supervisor call (ecall) exception by performing an SBI call.
+///
+/// This function extracts the parameters from the hart's registers, performs the SBI call, and
+/// then updates the hart's registers and program counter with the results.
+///
+/// # Parameters
+/// - `hart`: A mutable reference to the RV128I hart emulator.
+///
+/// # Returns
+/// - `ControlFlow::Break(value)` if the SBI call indicates that the platform should shutdown.
+/// - `ControlFlow::Continue(())` if the emulation should continue.
+fn handle_ecall(hart: &mut SimpleRv128IHart) -> ControlFlow<u128> {
+    println!("Handle ecall, registers: {:x?}", hart.xregs);
+    // Extract SBI call parameters from registers A0-A5.
+    let param = [
+        hart.xregs[A0 as usize],
+        hart.xregs[A1 as usize],
+        hart.xregs[A2 as usize],
+        hart.xregs[A3 as usize],
+        hart.xregs[A4 as usize],
+        hart.xregs[A5 as usize],
+    ];
+    // Call the SBI handler with the extension and function numbers from registers A7 and A6.
+    let ret = handle_sbi_call(hart.xregs[A7 as usize], hart.xregs[A6 as usize], param);
+    println!("SbiRet: {:?}", ret);
+    // If the SBI call returns the special error value (0x114514), signal shutdown.
+    if ret.error == 0x114514 {
+        return ControlFlow::Break(ret.value);
+    }
+    // Otherwise, store the error and return values into registers A0 and A1, respectively.
+    hart.xregs[A0 as usize] = ret.error;
+    hart.xregs[A1 as usize] = ret.value;
+    // Advance the program counter past the ecall instruction.
+    hart.pc = hart.pc.wrapping_add(4);
+    ControlFlow::Continue(())
+}
+
 /// An instruction memory implementation that holds a fixed number of instructions.
 ///
 /// `BASE` defines the starting memory address, and `N_INSNS` is the number of 32-bit words.
@@ -274,6 +355,8 @@ impl SimpleRv128IHart {
     }
 }
 
+/* -- RISC-V ISA enumerations and structures -- */
+
 /// RISC-V exceptions that may occur during emulation.
 #[derive(Debug)]
 pub enum Exception {
@@ -458,86 +541,3 @@ impl From<u32> for Offset {
         Self(ans)
     }
 }
-
-// A simple SBI implementation without using RustSBI.
-
-/// Handle the supervisor call (ecall) exception by performing an SBI call.
-///
-/// This function extracts the parameters from the hart's registers, performs the SBI call, and
-/// then updates the hart's registers and program counter with the results.
-///
-/// # Parameters
-/// - `hart`: A mutable reference to the RV128I hart emulator.
-///
-/// # Returns
-/// - `ControlFlow::Break(value)` if the SBI call indicates that the platform should shutdown.
-/// - `ControlFlow::Continue(())` if the emulation should continue.
-fn handle_ecall(hart: &mut SimpleRv128IHart) -> ControlFlow<u128> {
-    println!("Handle ecall, registers: {:x?}", hart.xregs);
-    // Extract SBI call parameters from registers A0-A5.
-    let param = [
-        hart.xregs[A0 as usize],
-        hart.xregs[A1 as usize],
-        hart.xregs[A2 as usize],
-        hart.xregs[A3 as usize],
-        hart.xregs[A4 as usize],
-        hart.xregs[A5 as usize],
-    ];
-    // Call the SBI handler with the extension and function numbers from registers A7 and A6.
-    let ret = handle_sbi_call(hart.xregs[A7 as usize], hart.xregs[A6 as usize], param);
-    println!("SbiRet: {:?}", ret);
-    // If the SBI call returns the special error value (0x114514), signal shutdown.
-    if ret.error == 0x114514 {
-        return ControlFlow::Break(ret.value);
-    }
-    // Otherwise, store the error and return values into registers A0 and A1, respectively.
-    hart.xregs[A0 as usize] = ret.error;
-    hart.xregs[A1 as usize] = ret.value;
-    // Advance the program counter past the ecall instruction.
-    hart.pc = hart.pc.wrapping_add(4);
-    ControlFlow::Continue(())
-}
-
-/// Handle an SBI call given the extension and function numbers, along with its parameters.
-///
-/// This is a simple SBI implementation (without using RustSBI) that supports a few functions:
-/// - BASE probe_extension: checks if an SBI extension exists.
-/// - SRST system_reset: performs a system reset (shutdown).
-///
-/// Note that the returned `SbiRet<u128>` represents an `SbiRet` with `u128` as the SBI register
-/// type.
-///
-/// # Parameters
-/// - `extension`: The SBI extension identifier (from register A7).
-/// - `function`: The SBI function number (from register A6).
-/// - `param`: An array containing SBI call parameters (from registers A0-A5).
-///
-/// # Returns
-/// An `SbiRet` structure containing the error and return values.
-fn handle_sbi_call(extension: u128, function: u128, param: [u128; 6]) -> SbiRet<u128> {
-    match (extension, function) {
-        // BASE probe_extension: if the parameter matches the BASE extension identifier, return 1.
-        (0x10, 3) => {
-            if param[0] == 0x10 {
-                SbiRet::success(1)
-            } else {
-                SbiRet::success(0)
-            }
-        }
-        // SRST system_reset: perform a system reset if the reset type is shutdown.
-        (0x53525354, 0) => {
-            let (reset_type, reset_reason) = (param[0], param[1]);
-            if reset_type == sbi_spec::srst::RESET_TYPE_SHUTDOWN as u128 {
-                // Use a special SBI error value (0x114514) to signal platform shutdown.
-                SbiRet {
-                    value: reset_reason,
-                    error: 0x114514,
-                }
-            } else {
-                SbiRet::not_supported()
-            }
-        }
-        // All other SBI calls are not supported.
-        _ => SbiRet::not_supported(),
-    }
-}