1 概述
- 到目前為止實現(xiàn)的主要功能:
- 實現(xiàn)全部目標(biāo)指令集 (RV32I, Zicsr)
- 實現(xiàn) load ELF 文件的功能
- 這次要能成功運行計算 MD5 的程序.
2 啟動代碼&鏈接腳本
- 用于 RRV-ISS 的 C 程序要使用這里的啟動代碼和鏈接腳本.
- 使用的啟動代碼
.section .text.init,"ax",@progbits
.globl main # Declare the main function
.globl trap_vector # Declare the trap handler
.globl _start
_start:
# Initialize stack pointer (SP)
la sp, _stack_top # Load the stack top address into SP
# Set the trap vector address
la t0, trap_vector
csrw mtvec, t0
# csrw mtvec trap_vector
# Clear the BSS section (all variables in .bss should be zeroed)
la t0, _bss_start # Load start address of .bss into t0
la t1, _bss_end # Load end address of .bss into t1
li t2, 0 # Load 0 into t2 (the value to clear)
clear_bss:
bgeu t0, t1, bss_cleared # If t0 >= t1, jump to bss_cleared
sw t2, 0(t0) # Store 0 to memory at address t0
addi t0, t0, 4 # Increment t0 (move to the next word)
j clear_bss # Repeat until the whole .bss section is cleared
bss_cleared:
call main # Call the main function
li a7, 93 # Load the syscall NO into a7 (93 for exit)
ecall
# Infinite loop if main returns (bare-metal systems typically don't return from main)
hang:
j hang # Infinite loop to prevent falling off the edge
trap_vector:
j hang # Trap handler (for this example, just loop)
# .section .stack # Define the stack section
# .space 1024 # Allocate 1024 bytes for the stack
# _stack_top:
- 使用的鏈接腳本
/* Linker script for a bare-metal RISC-V program */
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv",
"elf32-littleriscv")
OUTPUT_ARCH(riscv)
ENTRY(_start)
/* Define the memory layout */
MEMORY
{
FLASH (rx) : ORIGIN = 0x80000000, LENGTH = 512K /* Flash memory */
RAM (rwx) : ORIGIN = 0x80080000, LENGTH = 512K /* RAM for stack and data */
}
/* Sections definition */
SECTIONS
{
/* Code section */
.text :
{
/*_start = .; Define the program entry point */
*(.text.init)
} > FLASH
.text :
{
*(.text) /* All .text sections (code) */
*(.text.*) /* All other text sections */
} > FLASH
/* Read-only data section */
.rodata :
{
*(.rodata) /* Read-only data section */
*(.rodata.*)
} > FLASH
/* Initialized data section */
.data :
{
_data_start = .; /* Start of data */
*(.data) /* Initialized data */
_data_end = .; /* End of data */
} > RAM AT> FLASH
/* Uninitialized data section (BSS) */
.bss :
{
_bss_start = .; /* Start of BSS */
*(.bss) /* Uninitialized data */
*(COMMON)
_bss_end = .; /* End of BSS */
} > RAM
/* Stack section */
.stack (NOLOAD) :
{
_stack_top = ORIGIN(RAM) + LENGTH(RAM); /* Stack top address */
} > RAM
}
/* Provide symbols to be used in the assembly code */
PROVIDE(_stack_top = ORIGIN(RAM) + LENGTH(RAM)); /* Stack pointer initialized to the top of RAM */
3 RRV-ISS 退出機制實現(xiàn)
攔截 target 中, 編號為 93 的 ecall, 從而退出模擬器.
- 用于測試退出 RRV-ISS 的程序 1
int main(void)
{
return 0;
}
- 用于測試退出 RRV-ISS 的程序 2
int main(void)
{
return 0x1234;
}
4 運行計算 MD5-sum 的程序
同樣的 MD5 程序在 Ubuntu 24.04 上運行成功,在 RRV-ISS 上運行失敗.
4.1 為 MD5 程序用的 RISC-V 指令做集成測試
- 使用下面的代碼加載一條指令到 RRV-ISS
let add_instr = instr.to_le_bytes();
let _ = sim.load_bin_program(&add_instr, MEMORY_BASE_ADDRESS);
// step 3. set the reset vector
sim.set_reset_vector(MEMORY_BASE_ADDRESS.try_into().unwrap());
- 讓 RRV-ISS 在執(zhí)行時,把運行的 RISC-V 的匯編指令按順序?qū)懭胛募?每條指令的打印格式如下:
0x80000000 (0x00100117) AUIPC x2, 1048576 - 使用 python 腳本,把重復(fù)的指令刪除;把指令做了集成測試后沒有發(fā)現(xiàn)問題.
#!/usr/bin/env python3
def process_file(input_file, output_file):
# Set to store unique values encountered in the third column
seen_third_columns = set()
# List to store lines that should be written to the output file
lines_to_keep = []
with open(input_file, 'r') as file:
for line in file:
# Strip newline characters and split the line
parts = line.strip().split()
if len(parts) < 3:
# If the line has fewer than three columns, skip it
# lines_to_keep.append(line)
continue
# Get the value of the third column
third_column = parts[2]
# Skip if the third column is not alphabetic
if not third_column.isalpha():
continue
if third_column not in seen_third_columns:
# If the value in the third column hasn't been seen before, add it to the set and keep the line
seen_third_columns.add(third_column)
lines_to_keep.append(line)
with open(output_file, 'w') as file:
for line in lines_to_keep:
file.write(line)
input_file = 'md5_bare.asm'
output_file = 'md5_bare_unique.asm'
process_file(input_file, output_file)
4.2 使用打印定位問題
4.2.1 在 RRV-ISS 中實現(xiàn) uart_printf
- 實現(xiàn) UART
- 這里只是為了能夠打印消息, UART 是簡易的實現(xiàn)
- 打印有行緩沖
- 實現(xiàn) uart_printf
4.2.2 在 MD5 程序中添加打印
- 問題打印
rl=bedf9dfb, x:dfbbedf9, n:0000000c // X86 上的打印
[UART0] rl=fffffdfb, x:dfbbedf9, n:0000000c // RRV-ISS上的打印
- 問題相關(guān)代碼
static void md5Step(uint32_t *buffer, const uint32_t *input){
...
for(unsigned int i = 0; i < 64; ++i){
...
uint32_t rl = rotateLeft(AA + E + K[i] + input[j], S[i]);
usr_printf("rl=%08x, x:%08x, n:%08x\n", rl, AA + E + K[i] + input[j], S[i]);
...
}
...
}
/*
* Rotates a 32-bit word left by n bits
*/
uint32_t rotateLeft(uint32_t x, uint32_t n){
return (x << n) | (x >> (32 - n));
}
4.2.3 定位問題并解決
- rotateLeft 反匯編
uint32_t rotateLeft(uint32_t x, uint32_t n){
80000130: fe010113 addi sp,sp,-32
80000134: 00812e23 sw s0,28(sp)
80000138: 02010413 addi s0,sp,32
8000013c: fea42623 sw a0,-20(s0)
80000140: feb42423 sw a1,-24(s0)
/home/zsw/workspace/ws_develop/ISS-PG/ISS-PG/RRV-ISS-WS-formal/tests/tests/data/md5/md5.c:73
return (x << n) | (x >> (32 - n));
80000144: fec42783 lw a5,-20(s0)
80000148: fe842703 lw a4,-24(s0)
8000014c: 00e79733 sll a4,a5,a4
80000150: fe842683 lw a3,-24(s0)
80000154: 40d006b3 neg a3,a3
80000158: 01f6f693 andi a3,a3,31
8000015c: 00d7d7b3 srl a5,a5,a3
80000160: 00e7e7b3 or a5,a5,a4
/home/zsw/workspace/ws_develop/ISS-PG/ISS-PG/RRV-ISS-WS-formal/tests/tests/data/md5/md5.c:74
}
80000164: 00078513 mv a0,a5
80000168: 01c12403 lw s0,28(sp)
8000016c: 02010113 addi sp,sp,32
80000170: 00008067 ret
- srl 的執(zhí)行有bug: 應(yīng)該是無符號數(shù)右移;集成測試中沒有發(fā)現(xiàn) srl 的 bug 的原因是,集成測試時被移位的數(shù)值是正數(shù); MD5 中的 srl 移位的數(shù)值是負(fù)數(shù).
--- a/rv_core/src/execute/rv_i.rs
+++ b/rv_core/src/execute/rv_i.rs
@@ -529,7 +529,7 @@ pub(crate) fn execute_srl(
raw,
core,
disasm,
- |rs1, rs2| (rs1 >> rs2) as GprUnsigned,
+ |rs1, rs2| ((rs1 as GprUnsigned) >> rs2) as GprUnsigned,
"SRL",
)
}
4.3 RRV-ISS 成功運行 MD5 程序
在定位問題的過程中,還做了下面的兩個事情:
- 調(diào)整 log 信息: log 級別, log 格式;
- 使用 clap 解析命令行參數(shù),添加了下面的幾個參數(shù):
Usage: rrv-iss [OPTIONS] --file-path <FILE_PATH>
Options:
-f, --file-path <FILE_PATH> Path to the ELF/bin file
-e, --entry-point <ENTRY_POINT> Entry point address
-i, --instr-file <INSTR_FILE> The path to instruction log file
-l, --log-level <LOG_LEVEL> The log level for RVV-ISS [default: warn] [possible values: error, warn, info, debug, trace]
-n, --no-ansi If log file of RVV-ISS running with no ansi color
-h, --help Print help
-V, --version Print version
5 開發(fā)進(jìn)度整理
在 "0. 概述" 中, 計劃的 12 個步驟中的 1-7, 11 已經(jīng)完成.
~~1. 準(zhǔn)備開發(fā)環(huán)境:Rust開發(fā)環(huán)境、RISC-V GNU toolchain
- 設(shè)計模擬器架構(gòu)
- 執(zhí)行一條 add 指令
- 執(zhí)行 branch 和 jump & link 指令
- 執(zhí)行 load/store 指令
- 執(zhí)行 ecall/ebreak/csr 指令
- 執(zhí)行一段程序,并正常退出~~
- 與 Spike 的 trace 文件對比
- 運行 RISC-V 官方的測試
- 添加 timer 并處理 timer 中斷
11. 添加 uart - 運行 FreeRTOS