天天看點

ECC原理和RocketChip Cache ECC實作一、ECC原理說明二、RocketChip Cache ECC配置三、RocketChip Cache ECC實作四、仿真問題

一、ECC原理說明

ECC(Error Correcting Code)全稱為錯誤糾正碼,用于對存儲器的資料進行完整性檢查和糾正,主要用在SRAM、DDR、NAND等存儲器裝置上。ECC可以對資料進行單比特的糾錯和多比特的檢錯,其原理基于漢明碼編碼而來。下圖是ECC編碼的主要方法示例,其中藍色位置為插入的ECC校驗位,灰色位置為原始資料。資料下面的藍色部分為進行奇偶校驗計算的資料段。

ECC原理和RocketChip Cache ECC實作一、ECC原理說明二、RocketChip Cache ECC配置三、RocketChip Cache ECC實作四、仿真問題

ECC編碼方法說明

ECC編碼基于二分法原理,圖中第0個(bit[0])ECC位是對全資料段(包括資料+ECC位)進行奇偶校驗後的結果,填入的數值保證全資料段奇偶校驗值為0。bit[16]、bit[8]、bit[4]、bit[2]和bit[1] ECC位分别對資料進行二分并對一半資料進行奇偶校驗,例如bit[16]校驗的是資料的後半段,即資料高16bits,并在資料最高位插入ECC校驗數值。實際編碼過程首先從bit[16]開始,最終完成bit[0]的全資料段奇偶校驗位插入。産生的ECC位可以和資料一起放置,存儲在資料高位或者按照圖示位置放入,但無論ECC位放在哪裡,都需要保證編碼和解碼的方式一緻。

從上圖可以看出,如果需要檢測8bits原始資料,需要額外添加5bits ECC校驗位;如果需要檢測16bits原始資料,則隻需在5bits ECC校驗的基礎上再添加1bit即可。也就是說,原始資料翻倍而ECC校驗位加1,這樣的特性使得ECC校驗在資料位寬較寬時更有優勢。

ECC解碼過程和編碼過程相反,在接收到上圖所示的資料後,首先從bit[16]ECC位置進行判斷,如果計算的奇偶校驗值和接收的一緻,則表明高16bits資料沒有錯誤;如果不一緻,則表明高16bits資料可能存在錯誤。再繼續二分檢查bit[8] ECC位,依次完成所有ECC位的計算和比較,直到bit[1] ECC位。在計算完bit[1] ECC位後,如果資料中存在單bit錯誤,就可以最終确定出錯的資料位置在哪,并完成對應的資料糾錯。但如果原始資料中存在2bit翻轉或ECC位本身出錯,這個就需要bit[0]的ECC位對全資料段(包括資料+ECC位)進行一次奇偶校驗。如果bit[0]是判斷一緻(全資料段奇偶校驗正确),但各個ECC位不一緻,則表明置資料可能出現了2bit或以上的錯誤。

對于2bits以上資料位出錯,那麼各個ECC位判斷的結果會有沖突的地方,比如全資料段奇偶校驗正确,但各二分點ECC位校驗不一緻,或者各個ECC位校驗出現不一緻和沖突的地方。ECC隻能糾正1bit錯誤,對于2bit以上錯誤,隻能檢測而無法完全定位2bit錯誤位置。對于一般資料的軟錯誤而言,例如瞬态的電磁幹擾,産生多bit錯誤的機率非常低,是以ECC在資料完整性校驗上商用廣泛。

目前ECC在記憶體中用途非常廣,多數DDR記憶體條采用64bits資料+8bits ECC的方案,這樣在做DDR顆粒時,可以使用8個1G顆粒再加1個1G顆粒組成ECC備援。ECC在SRAM中也用途廣泛,用于功能安全車載和航天級電子電路中,一般采用32bits資料+7bits ECC方案,根據具體SRAM位寬決定。在NAND/NOR Flash中,一般采用256bytes資料+22bits ECC的方案。

二、RocketChip Cache ECC配置

RISC-V RocketChip生成器帶有Cache ECC選項,預設情況下是關閉狀态,有三種類型的ECC校驗可以選擇,分别是:parity、sec、secded,其各個類型的含義:

  • parity:對輸入Cache SRAM的資料進行奇偶校驗,每8bits産生一個奇偶校驗位;
  • sec:對輸入Cache SRAM的資料進行單比特糾錯,硬體自動糾錯;
  • secded:對輸入Cache SRAM的資料進行單比特糾錯,多比特檢錯,硬體自動糾錯;

除了可以選擇ECC類型,DCache還可以配置糾錯的資料長度,通過dataECCBytes選擇每多少bits進行ECC校驗,例如dataECCBytes設定成1,對于原始32bits位寬的SRAM,添加ECC後會變成52bits((8bits+5bits)x4)位寬,如果設定成4,則會變成39bits(32bits+7bits)位寬。

除了dataECCBytes參數對位寬有影響外,配置的ECC類型對位寬也有影響,這裡以dataECCByte=1為例,說明不同ECC類型對應的SRAM讀寫資料位寬,假設原始讀寫位寬為32bits,則:

  • parity:讀寫位寬(8bits資料+1bit奇偶校驗)x4 = 36bits;
  • sec:讀寫位寬(8bits資料+4bits ECC)x4 = 48bits;
  • secded:讀寫位寬(8bits資料+5bits ECC)x4 = 52bits;

位寬越寬,需要的SRAM大小越大,而其中有用的SRAM資料占用比例越小,如果dataECCBytes設定成1,意味着實際有效資料隻占實際面積的一半。由于ICache和DCache不會太大,一般嵌入式系統16KB起步,推薦dataECCBytes配置成4。

最終配置的subsyste/Config.scala項如下所示:

dcache = Some(DCacheParams(
        rowBits = site(SystemBusKey).beatBits,
        nSets = 64,
        nWays = 1,
        nTLBSets = 1,
        nTLBWays = 4,
        nMSHRs = 0,
        //add none/identity/parity/sec/secded/
        tagECC = Some("secded"),
        dataECC = Some("secded"),
        dataECCBytes = 4,
        blockBytes = site(CacheBlockBytes))),
      icache = Some(ICacheParams(
        rowBits = site(SystemBusKey).beatBits,
        nSets = 64,
        nWays = 1,
        nTLBSets = 1,
        nTLBWays = 4,
        //add none/identity/parity/sec/secded/
        tagECC = Some("secded"),
        dataECC = Some("secded"),
        blockBytes = site(CacheBlockBytes))))
           

三、RocketChip Cache ECC實作

在系統複位釋放後,RISC-V核心會從BootROM中取出程式段,并填入ICache中,一次填入一個CacheLine的資料。加入ECC後,BootROM中的原始資料會首先添加ECC校驗位,并放在資料的高位和資料一起寫入ICache的SRAM中。随後,核心的指令取指子產品會從ICache中取出資料,資料取出來後會首先檢查ECC,保證資料的正确性,單bit的資料錯誤會直接糾正。

ECC原理和RocketChip Cache ECC實作一、ECC原理說明二、RocketChip Cache ECC配置三、RocketChip Cache ECC實作四、仿真問題

ECC不可糾正錯誤實作代碼

ECC校驗會産生可糾正錯誤和不可糾正錯誤信号,對于多bit錯誤,ICache和DCache的處理方法不同。如果ECC輸出端檢測到不可糾正錯誤,ICache會通過io_resp_bits_replay信号上報核心,核心會判定為資料損壞,并會重新發出對應位址的讀請求指令。如果ECC輸出一直出錯,核心會一直重複對該位址進行取指請求。對于DCache,如果出現不可糾正錯誤,則會通過io_errors_uncorrectable_valid信号上報錯誤,但需要注意該信号預設并沒有作為中斷接入RISC-V中斷輸入端,使用者可能需要手動處理該error信号的上報事情。

四、仿真問題

在對帶有ECC的Cache進行仿真時,可能會遇到ICache hang住的情況,觀察波形會發現BootROM中的程式寫不進ICache的SRAM中,核心一直重複從BootROM取資料但寫使能一直無效,而讀出來的資料一直産生不可糾正錯誤和disparity有效,進而導緻寫使能一直無效。

ECC原理和RocketChip Cache ECC實作一、ECC原理說明二、RocketChip Cache ECC配置三、RocketChip Cache ECC實作四、仿真問題

Cache ECC仿真出現的問題

該問題可參考下篇連結解決,但這并不是最終的解決方法,因為SRAM中初始數值在流片後就是随機值,很難通過複位後在對SRAM進行一次全0的初始化。該問題可以通過修改生成的RTL代碼解決,将不可糾正錯誤在上電複位後到BootROM寫入第16個數之前屏蔽掉,等BootROM中寫入16個數後,讀出來的資料是經過ECC編碼和ECC解碼的,後續就不會出現仿真的問題。

https://github.com/chipsalliance/rocket-chip/issues/3019

繼續閱讀