iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0
Software Development

RISC-V 與處理器之架構學習及應用系列 第 10

[Day10] 使用 RISC-V 處理器的校驗碼與資料儲存實作:應用 Hamming Code 保護資料

  • 分享至 

  • xImage
  •  

如果計劃為太空總署客製化 RISC-V 處理器,在記憶體中提供額外的資料保護,可以實施 Hamming code with even parity 來保護我們的資料。

請參考下面的 parity table:

https://ithelp.ithome.com.tw/upload/images/20240924/20156517e79Izro0hP.jpg


實現名為 的 RISC-V 函數calc_parity,該函數接受 4 位元組輸入a0並計算其位元的奇偶校驗。對於奇校驗,它應該傳回 1;對於偶校驗,它應該傳回 0。例如:

https://ithelp.ithome.com.tw/upload/images/20240924/20156517UUIAGrujcN.jpg

calc_parity 必須遵守 RISC-V calling convention。

calc_parity:
    li t1, 0         # t1 holds current parity value in LSB
loop:
    xor t1, t1, a0   # adds the current least significant bit
                     # in a0 to the parity value in t1
    __A01__          # shift to the next bit in a0
    bne a0, x0, loop # loop if there are more than 1 bit left in a0
                     # 0 bits will never affect parity
    __A02__          # we only want the one parity bit
                     # in bit 0 of t1
    jr ra

程式碼解析

  1. li t1, 0:將暫存器 t1 設定為 0。t1 將用來累積計算校驗位。
  2. xor t1, t1, a0:這一行程式將 a0 的最不重要位(LSB)與 t1 進行 XOR 運算。XOR 運算可以檢測和累積每一位元的 1 或 0,這樣每次 XOR 運算會對奇偶性做累加:
    • 如果 a0 的 LSB 是 1,則 t1 會改變其值(即從 0 變成 1,或從 1 變成 0)。
    • 如果 a0 的 LSB 是 0,則 t1 保持不變。
  3. srli a0, a0, 1:這裡使用了 "Shift Right Logical Immediate" 指令,將 a0 向右位移一位。右移後,下一個最不重要位會進入 LSB,這樣在下一次迴圈中可以對該位進行處理。
  4. bne a0, x0, loop:這是個分支指令。它會檢查 a0 是否不等於 0,表示是否還有位元需要處理。如果 a0 仍然不為 0,則回到標籤 loop 繼續處理下一個位元;如果 a0 為 0,則所有位元都處理完畢,退出迴圈。
  5. andi a0, t1, 1:這個 AND 指令將 t1 的值與 1 進行邏輯 AND 運算,這樣可以只保留 t1 的最不重要位(LSB),因為最終的奇偶校驗結果就存儲在這個位上。其他位則被清除為 0。
  6. jr ra:跳轉並返回到呼叫這個函數的地方。

空格處

  • A01 = srli a0, a0, 1
    • 值得注意的是,這是一個邏輯移位,因為如果設定位元 31,則使用算術移位可能會導致無限循環。
    • 這是一個 "Shift Right Logical" 指令,將 a0 向右移動一位。這樣可以逐步處理每一位元(LSB到MSB)。
  • A02 = andi a0, t1, 1
    • 這個指令會將 t1 中的校驗位(即最不重要位)存入 a0,並且確保只保留該位,將其他位清除。這樣 a0 中的最不重要位(LSB)就會是最終的奇偶校驗結果。

實作store_nibbleRISC-V 函數,它會取得 a0 中的四位數據,將它們編碼為七位元(作為最高有效位元 [MSB] 為 0 的位元組),並將結果儲存在 a1 中指定的記憶體位址中。該函數不傳回任何值。您可以假設calc_parity已正確實現並遵守呼叫約定,但不要假設calc_parity另外,您可以假設 a0 中參數的最高有效 28 位元設定為 0。

store_nibble:
    # prologue omitted
    mv s0, a0
    mv s1, a1
    srli s7, s0, 1      # set d3 through d1
    slli s7, s7, 1      # make space for next bit
    andi a0, s0, 0b1110 # parity of d1, d2, and d3
    jal ra, calc_parity # compute p2
    add s7, s7, a0
    slli s7, s7, 1      # make space for next bit
    andi t0, s0, 1      # extract d0
    add s7, s7, t0
    slli s7, s7, 1      # make space for next bit
    andi a0, s0, 0b1101 # parity of d0, d2, and d3
    jal ra, calc_parity # compute p1
    add s7, s7, a0
    slli s7, s7, 1      # make space for next bit
    andi a0, s0, 0b1011 # parity of d0, d1, and d3
    jal ra, calc_parity # compute p0
    add s7, s7, __A03__
    sb __A04__, __A05__ # s1 contains the memory address passed in as a1
    # epilogue omitted
    jr ra

程式碼解析

  1. 初始化部分

    • mv s0, a0:將傳入的數據複製到 s0
    • mv s1, a1:將記憶體地址複製到 s1,最終要將編碼後的數據存入此地址。
  2. 設置數據位

    • srli s7, s0, 1:將 s0 中的數據右移 1 位,這樣 d3d2d1 分別是 s7 的第 3、2、1 位。
    • slli s7, s7, 1:將 s7 左移一位,為後續添加其他位做準備。
  3. 計算 p2(校驗位)

    • andi a0, s0, 0b1110:提取 d1, d2, 和 d3,這三個位要用來計算 p2
    • jal ra, calc_parity:調用 calc_parity 計算這三位的奇偶校驗位 p2
    • add s7, s7, a0:將 p2 加入到 s7
  4. 處理 d0

    • slli s7, s7, 1:左移一位,準備加入 d0
    • andi t0, s0, 1:提取 d0
    • add s7, s7, t0:將 d0 加入 s7
  5. 計算 p1(校驗位)

    • slli s7, s7, 1:左移一位,為加入下一個位(p1)做準備。
    • andi a0, s0, 0b1101:提取 d0, d2, 和 d3,這三個位要用來計算 p1
    • jal ra, calc_parity:調用 calc_parity 計算這三位的奇偶校驗位 p1
    • add s7, s7, a0:將 p1 加入 s7
  6. 計算 p0(校驗位)

    • slli s7, s7, 1:左移一位,為加入下一個位(p0)做準備。
    • andi a0, s0, 0b1011:提取 d0, d1, 和 d3,這三個位要用來計算 p0
    • jal ra, calc_parity:調用 calc_parity 計算這三位的奇偶校驗位 p0
  7. 將編碼的數據存入記憶體

    • add s7, s7, a0:將 p0 加入到 s7。這裡 A03 應該是 a0,因為 a0calc_parity 返回的結果(p0)。
    • sb s7, 0(s1):將 s7 中的數據存入 s1 所指的記憶體地址。這裡 A04s7,因為 s7 包含了編碼好的數據,A050(s1),因為 s1 中存放的是記憶體地址,而 0(s1) 表示在該地址處存儲數據。

空格處

  • A03 = a0
    • 在這裡,a0calc_parity 返回的結果,即校驗位 p0。因此,我們需要將 p0 加入到 s7 中,這樣最終的 s7 包含所有數據位和校驗位。
  • A04 = s7
    • s7 是編碼後的數據,它包含了 d3, d2, d1, d0 以及三個校驗位 p2, p1, p0。所以,sb s7, 0(s1) 是將 s7 中的數據存到記憶體。
  • A05 = 0(s1)
    • s1 是傳入的記憶體地址,而 0(s1) 表示在該地址存儲數據。這是 RISC-V 的一種記憶體存取方式,將 s7 的內容存入 s1 所指的地址。

上一篇
[Day09] RISC-V Procedures
下一篇
[Day11] 檔案與目錄的創建與資料保護
系列文
RISC-V 與處理器之架構學習及應用21
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言