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后寫入兩個(gè)buffer歧寺,然后讀出比較,然后全0寫入讀出比較棘脐;這就是Zero-One算法,Breuer & Friedman 1976 龙致,檢測(cè)SAF的蛀缝,算法是{w0,r0,w1,r1}時(shí)間復(fù)雜度是4N,又叫做MSCAN目代,驗(yàn)證每個(gè)cell能讀寫屈梁,間接測(cè)試了stuck at fault
int test_checkerboard_comparison(bufa, bufb, count); (√ )把設(shè)定好的幾組Data BackGround,依次寫入榛了,然后讀出比較 (注:論文里說設(shè)計(jì)良好的Data background可以檢測(cè)出state coupling faults時(shí)間復(fù)雜度是4N在讶,這是驗(yàn)證相鄰位置是否互相影響從而設(shè)計(jì)的用例。
int test_blockseq_comparison(bufa, bufb, count); (√ )一次寫一個(gè)count大小的塊霜大,寫的值是拿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í)行:{取反交替寫入a、b緩沖區(qū)脱吱,寫完之后檢查一遍智政,然后不斷重復(fù)以下步驟八次{用八個(gè)DMA從a緩沖區(qū)搬數(shù)據(jù)到b緩沖區(qū),并行搬箱蝠,模擬短時(shí)間內(nèi)反復(fù)讀寫同一位置看是否有數(shù)據(jù)丟失異常}}核心思想:短時(shí)間內(nèi)反復(fù)讀寫同一位置续捂。
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)]以這樣的模型疊加寫入內(nè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的地址值寫入對(duì)應(yīng)的內(nèi)存位置處滓彰,然后P2取反放入對(duì)應(yīng)位置處控妻,如此反復(fù);

然后下一輪開始揭绑,即j=1弓候,把上述步驟反過來再進(jìn)行一遍即可;


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

目的(原理)

為了驗(yà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)

開了兩個(gè)Buffer區(qū)域毕籽,然后同時(shí)寫入隨機(jī)值抬闯,寫完count個(gè)之后,用compare_regions(bufa, bufb, count)函數(shù)來對(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無法讀寫,類似于軟件測(cè)試?yán)锩娴腗onkey test蒸播;

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

  • 這里開源版本是沒有底層加速優(yōu)化的睡榆,一個(gè)個(gè)地往內(nèi)存地址寫數(shù)據(jù),每寫一個(gè)就要fflush操作一些袍榆,免得數(shù)據(jù)在stdout緩沖區(qū)內(nèi)堆積而不會(huì)立即寫入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)來與或的操作,但是還是一個(gè)一個(gè)寫赞草,驗(yàn)證了一下全空間寫0的時(shí)間是neon寫的4倍讹堤。

arm平臺(tái)(平臺(tái)參數(shù)見上述描述)跑了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底層加速:注釋見代碼

由于穿進(jìn)來的參數(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解開
        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瘾境,然后左移一位之后寫入下一個(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)然后取反交替寫入buffer區(qū)間龄捡,然后再檢測(cè)時(shí)候有問題卓嫂,反復(fù)64次;

移植版本里面假如了hammer操作聘殖,也即短時(shí)間內(nèi)不斷快速讀寫同一個(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移植版本

增加了并行讀寫操作(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來并行搬運(yùn)數(shù)據(jù),搬運(yùn)四分之一讹蘑,那這里模擬的就是對(duì)同一個(gè)位置反復(fù)不斷地讀寫8次末盔,最后再檢查一下有沒有出錯(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í)行:{
取反交替寫入a陨舱、b緩沖區(qū),寫完之后檢查一遍版仔,然后不斷重復(fù)以下步驟八次{
用八個(gè)DMA從a緩沖區(qū)搬數(shù)據(jù)到b緩沖區(qū)游盲,并行搬,模擬短時(shí)間內(nèi)反復(fù)讀寫同一位置看是否有數(shù)據(jù)丟失異常}}

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

目的(原理)

對(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來并行搬運(yùn)數(shù)據(jù)熙卡,搬運(yùn)四分之一,那這里模擬的就是對(duì)同一個(gè)位置反復(fù)不斷地讀寫8次励饵,最后再檢查一下有沒有出錯(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來寫入內(nèi)存役听,最后讀出對(duì)比即可颓鲜;

目的(原理)

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

注:這里并沒有給出checkboard的值。

注2: 雖然這里有點(diǎn)類似于底層的NPSF(neighborhood pattern sensitive fault)瘤袖,但是這里的錨點(diǎn)卻不是這個(gè)衣摩,而是:比如說我的客戶在把內(nèi)存插入電腦后,使用過程中有這種pattern的數(shù)據(jù)寫入內(nèi)存捂敌,會(huì)不會(huì)存在數(shù)據(jù)互相影響從而丟失的問題呢艾扮?這搞不好就是藍(lán)屏了啊占婉!也就是說我們關(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選擇好隨意啊=被拧E壮妗!
checkboard一般是選擇0x55跟0xaa交替寫简僧, 檢測(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è)試的視角就是從用戶的角度來看的蹦浦,從用戶角度設(shè)立不同的測(cè)試場(chǎng)景即測(cè)試用例,然后針對(duì)性地進(jìn)行功能測(cè)試撞蜂,注意是從系統(tǒng)級(jí)來測(cè)試盲镶,也就是說關(guān)注的不單單是內(nèi)存顆粒了侥袜,還有系統(tǒng)板級(jí)的連線、IO性能溉贿、PCB等等相關(guān)的因素枫吧,在這些因素的影響下,你的memory是否還能正常工作宇色;

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末皿曲,一起剝皮案震驚了整個(gè)濱河市唱逢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谷饿,老刑警劉巖惶我,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異博投,居然都是意外死亡绸贡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門毅哗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來听怕,“玉大人,你說我怎么就攤上這事虑绵∧虿t!?“怎么了?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵翅睛,是天一觀的道長(zhǎng)声搁。 經(jīng)常有香客問我,道長(zhǎng)捕发,這世上最難降的妖魔是什么疏旨? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮扎酷,結(jié)果婚禮上檐涝,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好谁榜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布幅聘。 她就那樣靜靜地躺著,像睡著了一般窃植。 火紅的嫁衣襯著肌膚如雪帝蒿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天撕瞧,我揣著相機(jī)與錄音陵叽,去河邊找鬼。 笑死丛版,一個(gè)胖子當(dāng)著我的面吹牛巩掺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播页畦,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胖替,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了豫缨?” 一聲冷哼從身側(cè)響起独令,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎好芭,沒想到半個(gè)月后燃箭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舍败,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年招狸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邻薯。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡裙戏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厕诡,到底是詐尸還是另有隱情累榜,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布灵嫌,位于F島的核電站壹罚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏寿羞。R本人自食惡果不足惜猖凛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稠曼。 院中可真熱鬧形病,春花似錦、人聲如沸霞幅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽司恳。三九已至途乃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扔傅,已是汗流浹背耍共。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猎塞,地道東北人试读。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像荠耽,于是被迫代替她去往敵國(guó)和親钩骇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

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