8. 執(zhí)行一段程序后正常退出 (下)

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

  1. 設(shè)計模擬器架構(gòu)
  2. 執(zhí)行一條 add 指令
  3. 執(zhí)行 branch 和 jump & link 指令
  4. 執(zhí)行 load/store 指令
  5. 執(zhí)行 ecall/ebreak/csr 指令
  6. 執(zhí)行一段程序,并正常退出~~
  7. 與 Spike 的 trace 文件對比
  8. 運行 RISC-V 官方的測試
  9. 添加 timer 并處理 timer 中斷
    11. 添加 uart
  10. 運行 FreeRTOS

6 源碼倉庫

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容