1 運行 FreeRTOS 的最低硬件要求
一個 RISC-V core 加片上存儲器,以及片上外設 uart,已經具備了計算機的5大組成部分——運算器、控制器、存儲器、輸入設備、輸出設備,可以構成一個最簡單的單片機。
給上面這個單片機再添加片上 timer 就具備了運行 FreeRTOS 的最低硬件條件。也就是說,有了下面的硬件,就具備了運行 FreeRTOS 的硬件條件:
- RISC-V core (要能夠處理 timer 中斷)
- 存儲器
- uart
- timer
RISC-V core 至少要包含下面的模塊:
- 控制單元(Control Unit, CU)
- 算術邏輯單元(Arithmetic Logic Unit, ALU)
- 寄存器(Registers): pc, gpr, csr
- CLINT (Core-Local Interruptor): 參考 SiFive FE310-G002 芯片。
- 總線接口單元(Bus Interface Unit, BIU)
2 至少應該實現(xiàn)的 RISC-V 指令集
- 要運行 FreeRTOS 至少要支持 RV32I 和 Zicsr 指令集
- RV32I was designed to be sufficient to form a compiler target and to support modern operating system environments.
- 中斷需要 CSR ,所以,需要支持 Zicsr 指令集
3 模擬器中的模塊
3.1 執(zhí)行一條指令的步驟
這里是開發(fā)功能精確 ISS,參照早期 ARM CPU 的三級流水——取指、譯碼、執(zhí)行,就夠用了。
RRV-ISS 中執(zhí)行一條指令,可以分為三步:取指、譯碼、執(zhí)行。
3.2 RRV-ISS 中大的功能模塊
- core
- 寄存器:pc,gpr,csr
- 取指:去 pc 指定的地址取指令,并把 pc 更新到下一條指令的起始地址
- 譯碼:解析指令,根據(jù)指令獲取操作數(shù)以及運算的函數(shù);執(zhí)行階段就是一行調用運算函數(shù)的代碼
- 外設
- 存儲器
- CLINT:其中包含了 timer
- uart
- bus:所有外設(片上外設、片外外設)都通過 bus 模塊的接口進行訪問
- loader:將程序加載到 memory
3.3 rust 工程的 crate & mod 結構
- 該工程使用 workspace 進行組織
- 將通過執(zhí)行一條 add 指令來打通各個 mod 之間的接口
- 隨著項目的深入,模塊/接口可能會變化
├── Cargo.toml
├── cpu_peripherals
│ ├── Cargo.toml
│ └── src
│ ├── clint.rs
│ ├── lib.rs
│ ├── mem.rs
│ └── uart.rs
├── iss # 指令集模擬器的 binary crate
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── rv_core
│ ├── Cargo.toml
│ └── src
│ ├── core.rs
│ ├── csr.rs
│ ├── decoder.rs
│ ├── fetch.rs
│ └── lib.rs
├── sim_lib # 模擬器的 mod 庫
│ ├── Cargo.toml
│ └── src
│ ├── bus.rs
│ ├── lib.rs
│ ├── loader.rs
│ └── simulator.rs
└── tests # 整個工程的集成測試
├── Cargo.toml
├── src
│ └── lib.rs
└── tests
└── exec_add_instr.rs # 執(zhí)行一條 add 指令
4 讓大模型生成工程的打樁代碼
4.1 生成打樁代碼提示詞
任務:請根據(jù)“cargo workspace 目錄結構”給工程打樁
角色:資深的指令集模擬器開發(fā)者,你同時具有豐富的軟件架構設計經驗、rust程序開發(fā)經驗以及RISC-V ISA設計經驗
背景:正在使用rust編寫RISC-V的ISS
要求
==============
1. 一步一步思考,給出完整代碼
2. 在 cpu_peripherals/src/lib.rs 中定義一個Device trait,Device提供按字節(jié)、半字、字、任意長度進行讀寫的接口,所有的讀寫都有可能失敗
3. 所有peripherals都需要實現(xiàn)Device trait
4. 在 cpu_peripherals/src/lib.rs 中定義Device type的enum,每個peripheral有對應的type,Device trait有獲取type的接口
5. bus 要管理各種實現(xiàn)了 Device 接口的設備,每個設備有對應的地址范圍,需要提供根據(jù)地址查找對應設備的接口,要盡可能提高查找設備的速度
6. 代碼中要有必要的錯誤處理
7. 添加單元測試
8. 添加集成測試,集成測試放在tests/tests/exec_add_instr.rs
9. 注釋使用英文
10. 實現(xiàn)所有的rs文件
cargo workspace 目錄結構:
```bash
├── Cargo.toml
├── cpu_peripherals
│ ├── Cargo.toml
│ └── src
│ ├── clint.rs
│ ├── lib.rs
│ ├── mem.rs
│ └── uart.rs
├── iss # 指令集模擬器的 binary crate
│ ├── Cargo.toml
│ └── src
│ └── main.rs # 作為入口文件,調用各個module的接口
├── rv_core
│ ├── Cargo.toml
│ └── src
│ ├── core.rs # core 的主體
│ ├── csr.rs # 模擬csr
│ ├── decoder.rs
│ ├── fetch.rs
│ └── lib.rs
├── sim_lib # 模擬器的 mod 庫
│ ├── Cargo.toml
│ └── src
│ ├── bus.rs # 模擬總線,管理各種設備
│ ├── lib.rs
│ ├── loader.rs # 加載 ELF 文件到模擬器內存
│ └── simulator.rs # 模擬器的主體
└── tests # 整個工程的集成測試
├── Cargo.toml
├── src
│ └── lib.rs
└── tests
└── exec_add_instr.rs # 執(zhí)行一條 add 指令的集成測試
```
4.2 調整生成的代碼
4.2.1 修改代碼,保證下面的命令結果都正常
cargo check
cargo test
cargo run
4.2.2 增加 log 機制
使用 tracing 庫,來做 ISS 的 log。
tracing 庫的介紹詳見:Rust 語言的全鏈路追蹤庫 tracing
4.2.3 統(tǒng)一的錯誤處理
- 基于 thiserror 庫,定義每個 library crate 的 error 類型。
- 參考資料:18|錯誤處理:為什么Rust的錯誤處理與眾不同?
- 使用 thiserror 定義 trap。
4.3 解碼
4.4 測試
riscv-software-src: Welcome to the RISC-V Software Repos
riscv: Welcome to the RISC-V Specifications