前言
為一究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è)臨近耦合缺陷;
時(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)而不是底層的缺陷。