memtester4.3.0

前言

為一究memtester原理,現(xiàn)對(duì)其每個(gè)函數(shù)均按照如下格式進(jìn)行描述:

  • 方法
  • 原理
  • 時(shí)間花銷

以下是對(duì)每個(gè)測(cè)試項(xiàng)的簡(jiǎn)要描述:

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

詳解函數(shù)

memtester-4.3.0 版本

方法test_stuck_address

函數(shù)名:int test_stuck_address(ulv *bufa, size_t count)
基本pattern按照下圖所示,j=0時(shí),先把P1的地址值寫(xiě)入對(duì)應(yīng)的內(nèi)存位置處,然后P2取反放入對(duì)應(yīng)位置處,如此反復(fù);

然后下一輪開(kāi)始,即j=1,把上述步驟反過(guò)來(lái)再進(jìn)行一遍即可;


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

目的(原理)

為了驗(yàn)證是否有地址無(wú)法訪問(wèn),驗(yàn)證的是地址線。

時(shí)間花銷

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

時(shí)間成本:
___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

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

開(kāi)了兩個(gè)Buffer區(qū)域,然后同時(shí)寫(xiě)入隨機(jī)值,寫(xiě)完count個(gè)之后,用compare_regions(bufa, bufb, count)函數(shù)來(lái)對(duì)比驗(yàn)證。

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;
}

目的(原理)

目的是測(cè)試data bus,以及某種數(shù)據(jù)pattern是否會(huì)導(dǎo)致cell無(wú)法讀寫(xiě),類似于軟件測(cè)試?yán)锩娴腗onkey test;

其中有幾個(gè)注意點(diǎn):

  • 這里開(kāi)源版本是沒(méi)有底層加速優(yōu)化的,一個(gè)個(gè)地往內(nèi)存地址寫(xiě)數(shù)據(jù),每寫(xiě)一個(gè)就要fflush操作一些,免得數(shù)據(jù)在stdout緩沖區(qū)內(nèi)堆積而不會(huì)立即寫(xiě)入DRAM,因此我們底層優(yōu)化的時(shí)候要考慮cache的影響;

  • 上述的對(duì)比函數(shù)就是一個(gè)一個(gè)值地對(duì)比,要是底層不做優(yōu)化地話時(shí)間花銷基本上是neon加速后的四倍;

時(shí)間花銷

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

時(shí)間成本:
___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移植版本

在公版的基礎(chǔ)上融合進(jìn)來(lái)與或的操作,但是還是一個(gè)一個(gè)寫(xiě),驗(yàn)證了一下全空間寫(xiě)0的時(shí)間是neon寫(xiě)的4倍。

arm平臺(tái)(平臺(tái)參數(shù)見(jiàn)上述描述)跑了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);
}

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

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;
}

而減少的時(shí)間主要是利用了neon底層加速:注釋見(jiàn)代碼

由于穿進(jìn)來(lái)的參數(shù)是(bufa, bufb, count),因此:

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

基本思想就是對(duì)比,比完之后異或出現(xiàn)非零值就是出異常了,報(bào)警!返回異常值。

mctl_neon_cmp
        PUSH    {r3-r12, lr}
        ADD  r2,r2,r0  ;把count的值轉(zhuǎn)成最終的地址值了

neon_cmp
    VLDM r0!,{q0-q3} ;一次從bufa加載4*128bit數(shù)據(jù)到4個(gè)neon的Q寄存器
    VLDM r1!,{q4-q7} ;一次從bufb加載4*128bit數(shù)據(jù)到4個(gè)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   
        ;上面這一段就是上圖的一個(gè)實(shí)現(xiàn),為什么一次只操作2X4Q個(gè)數(shù)據(jù),
        ;是因?yàn)榭偣簿?6個(gè)Q,不夠用啊!
        ;要是支持VEOR q0, q0,q4的話這里還可以加速的喲!

        BNE  rw_detect
        ;不為0跳轉(zhuǎn)指令
        ;檢測(cè)是否出現(xiàn)異常了,出現(xiàn)異常則結(jié)果不為0
        

        ;檢測(cè)是否全部對(duì)比完了
        CMP r0,r2
        BNE neon_cmp

       ;這里應(yīng)為r0是返回值,因此測(cè)試正常則賦0
        MOV r0,#0x0
        POP {r3-r12, pc}

rw_detect
;這里是假如中間出錯(cuò)了要進(jìn)行的操作
        SUB r0,r0,#0x40
        SUB r1,r1,#0x40
        ;bufa和bufb地址回退至4X16個(gè)32bit,及16個(gè)Q之前。
        ;(這里是要對(duì)16個(gè)Q值均進(jìn)行清算)
        
        VMOV r4,r5,d16   ;d16解開(kāi)
        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

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

首先設(shè)定一個(gè)初始值(以walk1為例)為0x00000001,然后左移一位之后寫(xiě)入下一個(gè)地址,依此類推。

目的(原理)

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

同時(shí)也覆蓋測(cè)試臨近耦合缺陷。

時(shí)間花銷

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

時(shí)間成本:
___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

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

目的(原理)

驗(yàn)證連續(xù)按順序?qū)懯欠窆δ苷#?/p>

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

時(shí)間花銷

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

時(shí)間成本:
___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

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

取一個(gè)pattern(全1)然后取反交替寫(xiě)入buffer區(qū)間,然后再檢測(cè)時(shí)候有問(wèn)題,反復(fù)64次;

移植版本里面假如了hammer操作,也即短時(shí)間內(nèi)不斷快速讀寫(xiě)同一個(gè)位置,看功能是否正常。

目的(原理)

hammer異常檢測(cè);
全空間scan測(cè)試;

時(shí)間花銷

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

時(shí)間成本:
___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移植版本

增加了并行讀寫(xiě)操作(DMA部分)

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

  • “1”:是從sdram到sdram
  • src_addr = bufa
  • dst_addr = bufb
  • 0~7八個(gè)DMA來(lái)并行搬運(yùn)數(shù)據(jù),搬運(yùn)四分之一,那這里模擬的就是對(duì)同一個(gè)位置反復(fù)不斷地讀寫(xiě)8次,最后再檢查一下有沒(méi)有出錯(cuò);
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;
}

方法

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

也是32bit里面的一個(gè)bit=1不斷移動(dòng)生成data pattern然后,每個(gè)pattern均執(zhí)行:{
取反交替寫(xiě)入a、b緩沖區(qū),寫(xiě)完之后檢查一遍,然后不斷重復(fù)以下步驟八次{
用八個(gè)DMA從a緩沖區(qū)搬數(shù)據(jù)到b緩沖區(qū),并行搬,模擬短時(shí)間內(nèi)反復(fù)讀寫(xiě)同一位置看是否有數(shù)據(jù)丟失異常}}

核心思想:短時(shí)間內(nèi)反復(fù)讀寫(xiě)同一位置。

目的(原理)

對(duì)比上面的 test_solidbits_comparison可以發(fā)現(xiàn)不同之處就在于data pattern的設(shè)計(jì),上面是固定的兩個(gè)值,這里是walking bit 1,因此這個(gè)用例是 test_solidbits_comparison和test_walkbits1_comparison的組合技能。

時(shí)間花銷

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

時(shí)間成本:
___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八個(gè)DMA來(lái)并行搬運(yùn)數(shù)據(jù),搬運(yùn)四分之一,那這里模擬的就是對(duì)同一個(gè)位置反復(fù)不斷地讀寫(xiě)8次,最后再檢查一下有沒(méi)有出錯(cuò);
              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

函數(shù)名:int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count)
測(cè)64輪,每輪都是從兩個(gè)表格中取出一個(gè)data pattern來(lái)寫(xiě)入內(nèi)存,最后讀出對(duì)比即可;

目的(原理)

數(shù)據(jù)敏感型功能缺陷檢測(cè),也就是說(shuō)有可能memory就是無(wú)法存取某個(gè)值的情況,這也是從用戶視角出發(fā)的。

注:這里并沒(méi)有給出checkboard的值。

注2: 雖然這里有點(diǎn)類似于底層的NPSF(neighborhood pattern sensitive fault),但是這里的錨點(diǎn)卻不是這個(gè),而是:比如說(shuō)我的客戶在把內(nèi)存插入電腦后,使用過(guò)程中有這種pattern的數(shù)據(jù)寫(xiě)入內(nèi)存,會(huì)不會(huì)存在數(shù)據(jù)互相影響從而丟失的問(wèn)題呢?這搞不好就是藍(lán)屏了啊!也就是說(shuō)我們關(guān)注的是表層的狀態(tài)而不是底層的缺陷。

時(shí)間花銷

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

時(shí)間成本:
___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交替寫(xiě), 檢測(cè)stuck bit cases and many adjacent cell dependency cases.

標(biāo)準(zhǔn)算法描述如下:

然后這個(gè)地方的移植······

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;
}

方法

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

跟walkbits1比起就是data pattern變了一點(diǎn)點(diǎn)而已,其余不變,因此可以看作是walkbit1的一個(gè)擴(kuò)展測(cè)試;
walkbit1: 00000001 -> 00000010
bitspread: 00000101 -> 00001010

目的(原理)

也是主要為了檢測(cè)臨近耦合缺陷;


這是內(nèi)部結(jié)構(gòu)圖,有助于理解它內(nèi)部的尋址

時(shí)間花銷

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

時(shí)間成本:
___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;
}

總結(jié)

整個(gè)memtester測(cè)試的視角就是從用戶的角度來(lái)看的,從用戶角度設(shè)立不同的測(cè)試場(chǎng)景即測(cè)試用例,然后針對(duì)性地進(jìn)行功能測(cè)試,注意是從系統(tǒng)級(jí)來(lái)測(cè)試,也就是說(shuō)關(guān)注的不單單是內(nèi)存顆粒了,還有系統(tǒng)板級(jí)的連線、IO性能、PCB等等相關(guān)的因素,在這些因素的影響下,你的memory是否還能正常工作

注2: checkboard這里雖然有點(diǎn)類似于底層的NPSF(neighborhood pattern sensitive fault),但是這里的錨點(diǎn)卻不是這個(gè),而是:比如說(shuō)我的客戶在把內(nèi)存插入電腦后,使用過(guò)程中有這種pattern的數(shù)據(jù)寫(xiě)入內(nèi)存,會(huì)不會(huì)存在數(shù)據(jù)互相影響從而丟失的問(wèn)題呢?這搞不好就是藍(lán)屏了啊!也就是說(shuō)我們關(guān)注的是表層的狀態(tài)而不是底層的缺陷。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,196評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,688評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,654評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,456評(píng)論 6 406
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,955評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,195評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,725評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,608評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,802評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,048評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,422評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,673評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,424評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,762評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容