memtester4.3.0 方法與 ARM A53 移植

前言

爲一究memtester原理,現對其每個函數均按照如下格式進行描述:

  • 方法
  • 原理
  • 時間花銷

以下是對每個測試項的簡要描述:

memtester-4.3.0 memtester-ARM
int test_stuck_address(bufa, count); (√ ) 先全部把地址值交替取反放入對應存儲位置,然後再讀出比較,重複2次(官網的重複了16次):測試address bus
int test_random_value(bufa, bufb, count); (√ )等效test_random_comparison(bufa, bufb, count):數據敏感型測試用例
int test_xor_comparison(bufa, bufb, count); (-) 與test_random_value比多了個異或操作,用戶場景之一,用例覆蓋。數據敏感/指令功能驗證,同時可驗證SAF;
int test_sub_comparison(bufa, bufb, count); (-)與test_random_value比多了個減法操作,用戶場景之一,用例覆蓋。數據敏感/指令功能驗證,同時可驗證SAF;
int test_mul_comparison(bufa, bufb, count); (-)與test_random_value比多了個乘法操作,用戶場景之一,用例覆蓋。數據敏感/指令功能驗證,同時可驗證SAF;
int test_div_comparison(bufa, bufb, count); (-)與test_random_value比多了個除法操作,用戶場景之一,用例覆蓋。數據敏感/指令功能驗證,同時可驗證SAF;
int test_or_comparison(bufa, bufb, count); (√ )在test_random_comparison()裏面合併了,用戶場景之一,用例覆蓋。數據敏感/指令功能驗證,同時可驗證SAF;
int test_and_comparison(bufa, bufb, count); (√ )在test_random_comparison()裏面合併了,用戶場景之一,用例覆蓋。數據敏感/指令功能驗證,同時可驗證SAF;
int test_seqinc_comparison(bufa, bufb, count); (√ )這是 test_blockseq_comparison的一個子集;模擬客戶壓力測試場景。
int test_solidbits_comparison(bufa, bufb, count); (√ )固定全1後寫入兩個buffer,然後讀出比較,然後全0寫入讀出比較;這就是Zero-One算法,Breuer & Friedman 1976 ,檢測SAF的,算法是{w0,r0,w1,r1}時間複雜度是4N,又叫做MSCAN,驗證每個cell能讀寫,間接測試了stuck at fault
int test_checkerboard_comparison(bufa, bufb, count); (√ )把設定好的幾組Data BackGround,依次寫入,然後讀出比較 (注:論文裏說設計良好的Data background可以檢測出state coupling faults時間複雜度是4N,這是驗證相鄰位置是否互相影響從而設計的用例。
int test_blockseq_comparison(bufa, bufb, count); (√ )一次寫一個count大小的塊,寫的值是拿byte級的數填充32bit,然後取出對比,接着重複256次;也是壓力用例,只是次數變多了;
int test_walkbits0_comparison(bufa, bufb, count); (√ )就是bit=1的位置在32bit裏面移動,每移動一次就全部填滿buffer,先是從低位往高位移,再是從高位往低位移動,(這麼做的目的是啥?其中的一個目的是檢測NPSF其次是CFs,其次是數據敏感型異常檢測,注這裏是32bit的,還有8bit的粒度更細了)
int test_walkbits1_comparison(bufa, bufb, count); (√ )與上同理,另注:早memtester86中這個算法叫做moving inversions algorithm
int test_bitspread_comparison(bufa, bufb, count); (√ )還是在32bit裏面移動,只是這次移動的不是單單的一個0或者1,而是兩個1,這兩個1之間隔着兩個空位,(是臨近耦合異常的一種data pattern變體:兩個1之間間隔1個位置,然後同步移動)
int test_bitflip_comparison(bufa, bufb, count); (√ )也是32bit裏面的一個bit=1不斷移動生成data pattern然後,每個pattern均執行:{取反交替寫入a、b緩衝區,寫完之後檢查一遍,然後不斷重複以下步驟八次{用八個DMA從a緩衝區搬數據到b緩衝區,並行搬,模擬短時間內反覆讀寫同一位置看是否有數據丟失異常}}核心思想:短時間內反覆讀寫同一位置。
int test_8bit_wide_random(bufa, bufb, count); (√ )以char指針存值,也就是每次存8bit,粒度更細;
int test_16bit_wide_random(bufa, bufb, count); (√ )以unsigned short指針存值,也就是每次存16bit,不同粒度檢測;
× int test_crosstalk_comparison(bufa, bufb, count):[32個0,接着32bit裏面1個0移動]以這樣的模型疊加寫入內存;(只有上行,沒像有moving inversions algorithm一樣進行反轉)

詳解函數

memtester-4.3.0 版本

方法test_stuck_address

函數名:int test_stuck_address(ulv *bufa, size_t count)
基本pattern按照下圖所示,j=0時,先把P1的地址值寫入對應的內存位置處,然後P2取反放入對應位置處,如此反覆;

然後下一輪開始,即j=1,把上述步驟反過來再進行一遍即可;

在這裏插入圖片描述

直到16輪結束,假若發生異常就把異常的地址直接返回即可!

目的(原理)

爲了驗證是否有地址無法訪問,驗證的是地址線。

時間花銷

條件:
全空間1G Byte ,DDR帶寬1600M32bit,CPU: ARM A53 (1460~1800)M 32bit單核跑。

時間成本:
___Sec.

int test_stuck_address(ulv *bufa, size_t count) {
    ulv *p1 = bufa;
    unsigned int j;
    size_t i;
    off_t physaddr;
    printf("           ");
    fflush(stdout);
    for (j = 0; j < 16; j++) {
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        p1 = (ulv *) bufa;
        printf("setting %3u", j);
        fflush(stdout);
        for (i = 0; i < count; i++) {
            *p1 = ((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1);
            *p1++;
        }
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        printf("testing %3u", j);
        fflush(stdout);
        p1 = (ulv *) bufa;
        for (i = 0; i < count; i++, p1++) {
            if (*p1 != (((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1))) {
                if (use_phys) {
                    physaddr = physaddrbase + (i * sizeof(ul));
                    fprintf(stderr, 
                            "FAILURE: possible bad address line at physical "
                            "address 0x%08lx.\n", 
                            physaddr);
                } else {
                    fprintf(stderr, 
                            "FAILURE: possible bad address line at offset "
                            "0x%08lx.\n", 
                            (ul) (i * sizeof(ul)));
                }
                printf("Skipping to next test...\n");
                fflush(stdout);
                return -1;
            }
        }
    }
    printf("\b\b\b\b\b\b\b\b\b\b\b  \b\b\b\b\b\b\b\b\b\b\b");
    fflush(stdout);
    return 0;
}

ARM A53移植版本

int test_stuck_address(unsigned int *bufa, unsigned int count)
{   
    unsigned int *p1 = bufa;
    unsigned int j;
    int i;
    for(j = 0; j < 2; j++){
        p1 = (unsigned int *)bufa;
        for(i = 0; i < count; i++){
            *p1 = ((j + i) % 2) == 0 ? (unsigned int)p1 : (~(unsigned int)p1);
            p1++;
        }
        p1 = (unsigned int *)bufa;
        for(i = 0; i < count; i++, p1++){
            if (*p1 != (((j + i) % 2) == 0 ? (unsigned int) p1 : ~((unsigned int) p1))){
                #ifdef PRINTK
                printk("[DRAM]test_stuck_address: %x is %x error\n", p1,(unsigned int)*p1);
                #endif
        if(((j + i) % 2) == 0){
            return (((unsigned int) p1)^(*p1));
        }
        else{
            return ((~((unsigned int) p1))^(*p1));
        }               
            }
        }
    }
    return 0;
}

方法test_random_value

函數名:int test_random_value(ulv *bufa, ulv *bufb, size_t count)

開了兩個Buffer區域,然後同時寫入隨機值,寫完count個之後,用compare_regions(bufa, bufb, count)函數來對比驗證。

int compare_regions(ulv *bufa, ulv *bufb, size_t count) {
    int r = 0;
    size_t i;
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    off_t physaddr;
    for (i = 0; i < count; i++, p1++, p2++) {
        if (*p1 != *p2) {
            if (use_phys) {
                physaddr = physaddrbase + (i * sizeof(ul));
                fprintf(stderr, 
                        "FAILURE: 0x%08lx != 0x%08lx at physical address "
                        "0x%08lx.\n", 
                        (ul) *p1, (ul) *p2, physaddr);
            } else {
                fprintf(stderr, 
                        "FAILURE: 0x%08lx != 0x%08lx at offset 0x%08lx.\n", 
                        (ul) *p1, (ul) *p2, (ul) (i * sizeof(ul)));
            }
            /* printf("Skipping to next test..."); */
            r = -1;
        }
    }
    return r;
}

目的(原理)

目的是測試data bus,以及某種數據pattern是否會導致cell無法讀寫,類似於軟件測試裏面的Monkey test;

其中有幾個注意點:

  • 這裏開源版本是沒有底層加速優化的,一個個地往內存地址寫數據,每寫一個就要fflush操作一些,免得數據在stdout緩衝區內堆積而不會立即寫入DRAM,因此我們底層優化的時候要考慮cache的影響;
  • 上述的對比函數就是一個一個值地對比,要是底層不做優化地話時間花銷基本上是neon加速後的四倍;

時間花銷

條件:
全空間1G Byte ,DDR帶寬1600M32bit,CPU: ARM A53 (1460~1800)M 32bit單核跑。

時間成本:
___Sec.

int test_random_value(ulv *bufa, ulv *bufb, size_t count) {
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    ul j = 0;
    size_t i;
    putchar(' ');
    fflush(stdout);
    for (i = 0; i < count; i++) {
        *p1++ = *p2++ = rand_ul();
        if (!(i % PROGRESSOFTEN)) {
            putchar('\b');
            putchar(progress[++j % PROGRESSLEN]);
            fflush(stdout);
        }
    }
    printf("\b \b");
    fflush(stdout);
    return compare_regions(bufa, bufb, count);
}

ARM A53移植版本

在公版的基礎上融合進來與或的操作,但是還是一個一個寫,驗證了一下全空間寫0的時間是neon寫的4倍。

arm平臺(平臺參數見上述描述)跑了24s左右。

int test_random_comparison(unsigned int *bufa, unsigned int *bufb, unsigned int count)
{
    unsigned int *p1 = bufa;
    unsigned int *p2 = bufb;
    int i;
    int q;
    for(i = 0; i < count; i++, p1++, p2++){
        *p1 = *p2 =  rand_ul();
    }
    p1 = bufa;
    p2 = bufb;
    for(i = 0; i < count; i++, p1++, p2++){
        if(i%2==0){
            q=rand_ul();
            *p1|=q;
            *p2|=q;
        }
        else{
            q=rand_ul();
            *p1&=q;
            *p2&=q;
        }
    }
    return compare_regions(bufa, bufb, count);
}
 

讀出對比的時間,全1GB空間實測大概花了6s的樣子(A53平臺單核1.46GHz 32bit),時間大大減少。

int compare_regions(unsigned int *bufa, unsigned int *bufb, unsigned int count)
{   
    unsigned int ret = 0,i,ERRO_ADDR[2];
 
    ret = mctl_neon_cmp(bufa,bufb,count<<2,&ERRO_ADDR[0]);
  
    if(ret)
    {       
    for(i=0;i<1000;i++)
    {
        if(__ADDR(ERRO_ADDR[0])==__ADDR(ERRO_ADDR[1]))
        {
            printk("[DRAM]addr0:%x!=addr1:%x___compare erro bit is :%x---read erro\n",ERRO_ADDR[0],ERRO_ADDR[1],ret);
            break;
        }
    }
    if(i==1000)
    {
        printk("[DRAM]addr0:%x!=addr1:%x___compare erro bit is :%x---write erro\n",ERRO_ADDR[0],ERRO_ADDR[1],ret);
    }mctl_neon_write
    }
    return ret;
}

而減少的時間主要是利用了neon底層加速:註釋見代碼

由於穿進來的參數是(bufa, bufb, count),因此:

  • r0 = bufa
  • r1 = bufb
  • r2 = count

在這裏插入圖片描述

基本思想就是對比,比完之後異或出現非零值就是出異常了,報警!返回異常值。

mctl_neon_cmp
        PUSH    {r3-r12, lr}
        ADD  r2,r2,r0  ;把count的值轉成最終的地址值了
 
neon_cmp
    VLDM r0!,{q0-q3} ;一次從bufa加載4*128bit數據到4個neon的Q寄存器
    VLDM r1!,{q4-q7} ;一次從bufb加載4*128bit數據到4個neon的Q寄存器
 
 
        VEOR q8,q0,q4
        VEOR q9,q1,q5
        VEOR q10,q2,q6
        VEOR q11,q3,q7
 
        VORR q12,q8,q9
        VORR q13,q11,q10
        VORR q14,q12,q13
        VORR d30,d28,d29
        VMOV r4, r5, d30
        ORR  r6,r4,r5
      
        CMP  r6,#0x0   
        ;上面這一段就是上圖的一個實現,爲什麼一次只操作2X4Q個數據,
        ;是因爲總共就16個Q,不夠用啊!
        ;要是支持VEOR q0, q0,q4的話這裏還可以加速的喲!
 
        BNE  rw_detect
        ;不爲0跳轉指令
        ;檢測是否出現異常了,出現異常則結果不爲0
        
 
        ;檢測是否全部對比完了
        CMP r0,r2
        BNE neon_cmp
 
       ;這裏應爲r0是返回值,因此測試正常則賦0
        MOV r0,#0x0
        POP {r3-r12, pc}
 
rw_detect
;這裏是假如中間出錯了要進行的操作
        SUB r0,r0,#0x40
        SUB r1,r1,#0x40
        ;bufa和bufb地址回退至4X16個32bit,及16個Q之前。
        ;(這裏是要對16個Q值均進行清算)
        
        VMOV r4,r5,d16   ;d16解開
        CMP r4,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
        CMP r5,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
      
        VMOV r4,r5,d17;d17
        CMP r4,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
        CMP r5,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
      
        VMOV r4,r5,d18;d18
        CMP r4,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
        CMP r5,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
      
        VMOV r4,r5,d19;d19
        CMP r4,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
        CMP r5,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
      
        VMOV r4,r5,d20;d20
        CMP r4,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
        CMP r5,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
      
        VMOV r4,r5,d21;d21
        CMP r4,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
        CMP r5,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
      
        VMOV r4,r5,d22;d22
        CMP r4,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
        CMP r5,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
      
        VMOV r4,r5,d23;d23
        CMP r4,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
        CMP r5,#0
        BNE rw_detect_done
        ADD r0,r0,#0x4
        ADD r1,r1,#0x4
 
rw_detect_done
        MOV r2,r3
        STR r0,[r2];save erro addr
      
        ADD r3,r3,#0x4
        MOV r2,r3
        STR r1,[r2];save erro addr
      
        MOV r0,r6
        POP {r3-r12, pc}

方法test_walkbits1_comparison/test_walkbits0_comparison

函數名:nt test_walkbits1_comparison(bufa, bufb, count);

首先設定一個初始值(以walk1爲例)爲0x00000001,然後左移一位之後寫入下一個地址,依此類推。

目的(原理)

This test is intended to uncover data or address bus problems both internal to the memory device as well as external.

同時也覆蓋測試臨近耦合缺陷。

時間花銷

條件:
全空間1G Byte ,DDR帶寬1600M32bit,CPU: ARM A53 (1460~1800)M 32bit單核跑。

時間成本:
___Sec.

int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count) {
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    unsigned int j;
    size_t i;
 
    printf("           ");
    fflush(stdout);
    for (j = 0; j < UL_LEN * 2; j++) {
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        p1 = (ulv *) bufa;
        p2 = (ulv *) bufb;
        printf("setting %3u", j);
        fflush(stdout);
        for (i = 0; i < count; i++) {
            if (j < UL_LEN) { /* Walk it up. */
                *p1++ = *p2++ = UL_ONEBITS ^ (ONE << j);
            } else { /* Walk it back down. */
                *p1++ = *p2++ = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - j - 1));
            }
        }
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        printf("testing %3u", j);
        fflush(stdout);
        if (compare_regions(bufa, bufb, count)) {
            return -1;
        }
    }
    printf("\b\b\b\b\b\b\b\b\b\b\b  \b\b\b\b\b\b\b\b\b\b\b");
    fflush(stdout);
    return 0;
}

ARM A53移植版本

int test_walkbits1_comparison(unsigned int *bufa, unsigned int *bufb, unsigned int count)
{
    unsigned int *p1 = bufa;
    unsigned int *p2 = bufb;
    unsigned int j;
    int ret = 0;
 
    for(j = 0; j <UL_LEN * 2; j++){
        p1 = bufa;
        p2 = bufb;
        if(j < UL_LEN) {
            neon_write(p1,p1+(count<<0),(ONE << j));
            neon_write(p2,p2+(count<<0),(ONE << j));
        }
        else{
            neon_write(p1,p1+(count<<0),(ONE << (UL_LEN * 2 - j - 1)));
            neon_write(p2,p2+(count<<0),(ONE << (UL_LEN * 2 - j - 1)));         
        }
        ret = compare_regions(bufa, bufb, count);
        if(ret){
            return ret;
        }
    }
    return 0;

方法test_seqinc_comparison/test_blockseq_comparison

函數名:int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) /``

目的(原理)

驗證連續按順序寫是否功能正常;

block模式則加上了壓力部分;

時間花銷

條件:
全空間1G Byte ,DDR帶寬1600M32bit,CPU: ARM A53 (1460~1800)M 32bit單核跑。

時間成本:
___Sec.

int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) {
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    size_t i;
    ul q = rand_ul();
    for (i = 0; i < count; i++) {
        *p1++ = *p2++ = (i + q);
    }
    return compare_regions(bufa, bufb, count);
}
 
int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count) {
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    unsigned int j;
    size_t i;
    printf("           ");
    fflush(stdout);
    for (j = 0; j < 256; j++) {
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        p1 = (ulv *) bufa;
        p2 = (ulv *) bufb;
        printf("setting %3u", j);
        fflush(stdout);
        for (i = 0; i < count; i++) {
            *p1++ = *p2++ = (ul) UL_BYTE(j);
        }
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        printf("testing %3u", j);
        fflush(stdout);
        if (compare_regions(bufa, bufb, count)) {
            return -1;
        }
    }
    printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
    fflush(stdout);
    return 0;
}

ARM A53移植版本

int test_blockseq_comparison(unsigned int *bufa, unsigned int *bufb, unsigned int count){
    unsigned int *p1 = bufa;
    unsigned int *p2 = bufb;
    unsigned int j;
    int i;
    int ret = 0;
    for(j = 0; j < 256; j++){
        p1 = (unsigned int*)bufa;
        p2 = (unsigned int*)bufb;
        for(i = 0; i < count; i++, p1++, p2++){
            *p1 = *p2 = (unsigned int)UL_BYTE(j);
        }
        ret = compare_regions(bufa, bufb, count);
        if(ret){
            return ret;
        }
    }
    return 0;
}

方法 test_solidbits_comparison

函數名:int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count)

取一個pattern(全1)然後取反交替寫入buffer區間,然後再檢測時候有問題,反覆64次;

移植版本里面假如了hammer操作,也即短時間內不斷快速讀寫同一個位置,看功能是否正常。

目的(原理)

hammer異常檢測;
全空間scan測試;

時間花銷

條件:
全空間1G Byte ,DDR帶寬1600M32bit,CPU: ARM A53 (1460~1800)M 32bit單核跑。

時間成本:
___Sec.

int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count) {
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    unsigned int j;
    ul q;
    size_t i;
    printf("           ");
    fflush(stdout);
    for (j = 0; j < 64; j++) {
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        q = (j % 2) == 0 ? UL_ONEBITS : 0;
        printf("setting %3u", j);
        fflush(stdout);
        p1 = (ulv *) bufa;
        p2 = (ulv *) bufb;
        for (i = 0; i < count; i++) {
            *p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
        }
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        printf("testing %3u", j);
        fflush(stdout);
        if (compare_regions(bufa, bufb, count)) {
            return -1;
        }
    }
    printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
    fflush(stdout);
    return 0;
}

ARM A53移植版本

增加了並行讀寫操作(DMA部分)

**DMA_TRAN(1,(s32)bufa,(s32)bufb,0,count << 2)**參數解釋:

  • “1”:是從sdram到sdram
  • src_addr = bufa
  • dst_addr = bufb
  • 0~7八個DMA來並行搬運數據,搬運四分之一,那這裏模擬的就是對同一個位置反覆不斷地讀寫8次,最後再檢查一下有沒有出錯;
int test_solidbits_comparison(unsigned int *bufa, unsigned int *bufb, unsigned int count)
{
    unsigned int *p1 = bufa;
    unsigned int *p2 = bufb;
    unsigned int j;
    unsigned int q;
    int ret = 0,done;
    for(j = 0; j <64; j++){
        q = (j% 2) == 0 ? UL_ONEBITS:~UL_ONEBITS;
        p1 = (unsigned int *)bufa;
        p2 = (unsigned int *)bufb;
        mctl_neon_write(p1,p1+(count<<0),q);
        mctl_neon_write(p2,p2+(count<<0),q);
        ret = compare_regions(bufa, bufb, count);
        if(ret==0){
            DMA_TRAN(1,(s32)bufa,(s32)bufb,0,count << 2);
            DMA_TRAN(1,(s32)bufa,(s32)bufb,1,count << 2);
            DMA_TRAN(1,(s32)bufa,(s32)bufb,2,count << 2);
            DMA_TRAN(1,(s32)bufa,(s32)bufb,3,count << 2);
            DMA_TRAN(1,(s32)bufa,(s32)bufb,4,count << 2);
            DMA_TRAN(1,(s32)bufa,(s32)bufb,5,count << 2);
            DMA_TRAN(1,(s32)bufa,(s32)bufb,6,count << 2);
            DMA_TRAN(1,(s32)bufa,(s32)bufb,7,count << 2);
            ret = (ret|compare_regions0(bufa, bufb, count));
            done = (0xffff);
            do{
               done = (get_wvalue(0x03002000+0x30) & 0xfff);
            }while(done != 0x0);        //wait for dma transfor finish
        }
        if(ret)
            return ret;     
    }
    return ret;
}

方法

函數名:int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count)

也是32bit裏面的一個bit=1不斷移動生成data pattern然後,每個pattern均執行:{
取反交替寫入a、b緩衝區,寫完之後檢查一遍,然後不斷重複以下步驟八次{
用八個DMA從a緩衝區搬數據到b緩衝區,並行搬,模擬短時間內反覆讀寫同一位置看是否有數據丟失異常}}

核心思想:短時間內反覆讀寫同一位置。

目的(原理)

對比上面的 test_solidbits_comparison可以發現不同之處就在於data pattern的設計,上面是固定的兩個值,這裏是walking bit 1,因此這個用例是 test_solidbits_comparison和test_walkbits1_comparison的組合技能。

時間花銷

條件:
全空間1G Byte ,DDR帶寬1600M32bit,CPU: ARM A53 (1460~1800)M 32bit單核跑。

時間成本:
___Sec.

int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count) {
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    unsigned int j, k;
    ul q;
    size_t i;
 
    printf("           ");
    fflush(stdout);
    for (k = 0; k < UL_LEN; k++) {
        q = ONE << k;
        for (j = 0; j < 8; j++) {
            printf("\b\b\b\b\b\b\b\b\b\b\b");
            q = ~q;
            printf("setting %3u", k * 8 + j);
            fflush(stdout);
            p1 = (ulv *) bufa;
            p2 = (ulv *) bufb;
            for (i = 0; i < count; i++) {
                *p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
            }
            printf("\b\b\b\b\b\b\b\b\b\b\b");
            printf("testing %3u", k * 8 + j);
            fflush(stdout);
            if (compare_regions(bufa, bufb, count)) {
                return -1;
            }
        }
    }
    printf("\b\b\b\b\b\b\b\b\b\b\b           \b\b\b\b\b\b\b\b\b\b\b");
    fflush(stdout);
    return 0;
}

ARM A53移植版本

int test_bitflip_comparison(unsigned int *bufa, unsigned int *bufb, unsigned int count){
    unsigned int *p1 = bufa;
    unsigned int *p2 = bufb;
    unsigned int j;
    int k,q;
    int ret = 0,done;
    for (k = 0; k <UL_LEN; k++){
       q = ONE << k;
       for (j = 0; j < 8; j++){
          q = ~q;
          p1 = bufa;
          p2 = bufb;
          mctl_neon_write(p1,p1+(count<<0),q);
          mctl_neon_write(p2,p2+(count<<0),q);
          ret = compare_regions(bufa, bufb, count);
          if(ret==0) {
            //1:是從sdram到sdram
            //src_addr = bufa
            //dst_addr = bufb
            //0~7八個DMA來並行搬運數據,搬運四分之一,那這裏模擬的就是對同一個位置反覆不斷地讀寫8次,最後再檢查一下有沒有出錯;
              DMA_TRAN(1,(s32)bufa,(s32)bufb,0,count << 2);
              DMA_TRAN(1,(s32)bufa,(s32)bufb,1,count << 2);
              DMA_TRAN(1,(s32)bufa,(s32)bufb,2,count << 2);
              DMA_TRAN(1,(s32)bufa,(s32)bufb,3,count << 2);
              DMA_TRAN(1,(s32)bufa,(s32)bufb,4,count << 2);
              DMA_TRAN(1,(s32)bufa,(s32)bufb,5,count << 2);
              DMA_TRAN(1,(s32)bufa,(s32)bufb,6,count << 2);
              DMA_TRAN(1,(s32)bufa,(s32)bufb,7,count << 2);
              ret = (ret|compare_regions0(bufa, bufb, count));
              done = (0xff);
              do{
                 done = (get_wvalue(0x03002000+0x30) & 0xff);
              }while(done != 0x0);      //wait for dma transfor finish
          }
          if(ret) {
             return ret;
          }
     }
  }
    return 0;
}

方法 test_checkerboard_comparison

函數名:int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count)
測64輪,每輪都是從兩個表格中取出一個data pattern來寫入內存,最後讀出對比即可;

目的(原理)

數據敏感型功能缺陷檢測,也就是說有可能memory就是無法存取某個值的情況,這也是從用戶視角出發的。

注:這裏並沒有給出checkboard的值。

注2: 雖然這裏有點類似於底層的NPSF(neighborhood pattern sensitive fault),但是這裏的錨點卻不是這個,而是:比如說我的客戶在把內存插入電腦後,使用過程中有這種pattern的數據寫入內存,會不會存在數據互相影響從而丟失的問題呢?這搞不好就是藍屏了啊!也就是說我們關注的是表層的狀態而不是底層的缺陷。

時間花銷

條件:
全空間1G Byte ,DDR帶寬1600M32bit,CPU: ARM A53 (1460~1800)M 32bit單核跑。

時間成本:
___Sec.

int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count) {
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    unsigned int j;
    ul q;
    size_t i;
 
    printf("           ");
    fflush(stdout);
    for (j = 0; j < 64; j++) {
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2;
        printf("setting %3u", j);
        fflush(stdout);
        p1 = (ulv *) bufa;
        p2 = (ulv *) bufb;
        for (i = 0; i < count; i++) {
            *p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
        }
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        printf("testing %3u", j);
        fflush(stdout);
        if (compare_regions(bufa, bufb, count)) {
            return -1;
        }
    }
    printf("\b\b\b\b\b\b\b\b\b\b\b           \b\b\b\b\b\b\b\b\b\b\b");
    fflush(stdout);
    return 0;
}

ARM A53移植版本

這裏的checkboard選擇好隨意啊!!!
checkboard一般是選擇0x55跟0xaa交替寫, 檢測stuck bit cases and many adjacent cell dependency cases.

標準算法描述如下:

在這裏插入圖片描述

然後這個地方的移植······

int test_checkrboard_comparison(unsigned int *bufa, unsigned int *bufb, unsigned int count){
    unsigned int *p1 = bufa;
    unsigned int *p2 = bufb;
    unsigned int j;
    unsigned int q;
    int ret = 0;
    unsigned int CHECKERBOARD1[16]={0x00000000,0x11111111,0x22222222,0x33333333,
                                    0x44444444,0x55555555,0x66666666,0x77777777,
                                    0x88888888,0x99999999,0xaaaaaaaa,0xbbbbbbbb,
                                    0xcccccccc,0xdddddddd,0xeeeeeeee,0xffffffff};
    unsigned int CHECKERBOARD2[16]={0xffffffff,0xeeeeeeee,0xdddddddd,0xcccccccc,
                                    0xbbbbbbbb,0xaaaaaaaa,0x99999999,0x88888888,
                                    0x77777777,0x66666666,0x55555555,0x44444444,
                                    0x33333333,0x22222222,0x11111111,0x00000000};
    for(j = 0; j < 64; j++){
        q = (j % 2) == 0 ? CHECKERBOARD1[(j/2)%16] : CHECKERBOARD2[(j/2)%16];
        p1 = (unsigned int *)bufa;
        p2 = (unsigned int *)bufb;
        mctl_neon_write(p1,p1+(count<<0),q);
        mctl_neon_write(p2,p2+(count<<0),q);
        ret = compare_regions(bufa, bufb, count);
        if(ret){
            return ret;
        }
    }
    return 0;
}

方法

函數名:int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count)

跟walkbits1比起就是data pattern變了一點點而已,其餘不變,因此可以看作是walkbit1的一個擴展測試;
walkbit1: 00000001 -> 00000010
bitspread: 00000101 -> 00001010

目的(原理)

也是主要爲了檢測臨近耦合缺陷;

在這裏插入圖片描述

這是內部結構圖,有助於理解它內部的尋址

時間花銷

條件:
全空間1G Byte ,DDR帶寬1600M32bit,CPU: ARM A53 (1460~1800)M 32bit單核跑。

時間成本:
___Sec.

int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count) {
    ulv *p1 = bufa;
    ulv *p2 = bufb;
    unsigned int j;
    size_t i;
 
    printf("           ");
    fflush(stdout);
    for (j = 0; j < UL_LEN * 2; j++) {
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        p1 = (ulv *) bufa;
        p2 = (ulv *) bufb;
        printf("setting %3u", j);
        fflush(stdout);
        for (i = 0; i < count; i++) {
            if (j < UL_LEN) { /* Walk it up. */
                *p1++ = *p2++ = (i % 2 == 0)
                    ? (ONE << j) | (ONE << (j + 2))
                    : UL_ONEBITS ^ ((ONE << j) | (ONE << (j + 2)));
            } else { /* Walk it back down. */
                *p1++ = *p2++ = (i % 2 == 0)
                    ? (ONE << (UL_LEN * 2 - 1 - j)) | (ONE << (UL_LEN * 2 + 1 - j))
                    : UL_ONEBITS ^ (ONE << (UL_LEN * 2 - 1 - j)
                                    | (ONE << (UL_LEN * 2 + 1 - j)));
            }
        }
        printf("\b\b\b\b\b\b\b\b\b\b\b");
        printf("testing %3u", j);
        fflush(stdout);
        if (compare_regions(bufa, bufb, count)) {
            return -1;
        }
    }
    printf("\b\b\b\b\b\b\b\b\b\b\b           \b\b\b\b\b\b\b\b\b\b\b");
    fflush(stdout);
    return 0;
}

ARM A53移植版本

int test_bitspread_comparison(unsigned int *bufa, unsigned int *bufb, unsigned int count){
#define Q  2
    unsigned int *p1 = bufa;
    unsigned int *p2 = bufb;
    unsigned int j;
    int ret = 0;
for(j = 0; j <UL_LEN * 2; j++){
        p1 = bufa;
        p2 = bufb;
        if(j < UL_LEN) {
            mctl_neon_write(p1,p1+(count<<0),((ONE << j) | (ONE << (j + Q))));
            mctl_neon_write(p2,p2+(count<<0),((ONE << j) | (ONE << (j + Q))));
        }
        else{
            mctl_neon_write(p1,p1+(count<<0),((ONE << (UL_LEN * 2 - 1 - j)) | (ONE << (UL_LEN * 2 +Q- 1 - j))));
            mctl_neon_write(p2,p2+(count<<0),((ONE << (UL_LEN * 2 - 1 - j)) | (ONE << (UL_LEN * 2 +Q- 1 - j))));            
        }
        ret = compare_regions(bufa, bufb, count);
        if(ret){
            return ret;
        }
}
    return 0;
}

總結

整個memtester測試的視角就是從用戶的角度來看的,從用戶角度設立不同的測試場景即測試用例,然後針對性地進行功能測試,注意是從系統級來測試,也就是說關注的不單單是內存顆粒了,還有系統板級的連線、IO性能、PCB等等相關的因素,在這些因素的影響下,你的memory是否還能正常工作

注2: checkboard這裏雖然有點類似於底層的NPSF(neighborhood pattern sensitive fault),但是這裏的錨點卻不是這個,而是:比如說我的客戶在把內存插入電腦後,使用過程中有這種pattern的數據寫入內存,會不會存在數據互相影響從而丟失的問題呢?這搞不好就是藍屏了啊!也就是說我們關注的是表層的狀態而不是底層的缺陷。

版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。本文鏈接:https://blog.csdn.net/weixin_34119545/article/details/87096872

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章