自動實現(xiàn)半導體器件系統(tǒng)強化測試的方法
檢驗芯片的各項功能需要編寫診斷軟件,目的是確保器件的各項功能按要求工作,但是無論各項測試有多么詳盡,它都無法找出大部分系統(tǒng)層次的問題。因此,要利用系統(tǒng)級強化測試(stress testing)來使多種功能以高強度和隨機的方式共同執(zhí)行,從而迫使這些設計問題浮出表面。本文將探討用于檢驗半導體器件設計的系統(tǒng)強化測試方法。
強化測試
強化測試是指將產品置于比實際正常應用苛刻得多的條件下使用,其目的是通過各種方式對設備進行考驗,迅速發(fā)現(xiàn)其設計缺陷。例如,對于一件機械產品,可能讓它面對惡劣的環(huán)境條件,如高壓、高溫和震動。如果該產品能在這樣的條件下成功經(jīng)受一個月的考驗,那么在正常使用條件下,它應該能工作長得多的時間。
同樣的概念也適用于芯片的設計。此時,強化測試的表現(xiàn)形式是執(zhí)行診斷軟件,其目的是使大量的芯片功能同時、連續(xù)、隨機、密集地工作,其程度遠遠超過芯片正常使用時的狀況。這些測試通常連續(xù)運行,大多數(shù)時候無人照管,夜間和周末也不停止。通過這些測試,可以在產品發(fā)貨之前迫使隱藏的系統(tǒng)問題盡快地暴露出來。
為什么強化測試對半導體設計如此重要呢?為了解釋這一問題,假設一個半導體器件常常為了不同用途而應用在各種電子系統(tǒng)之中,因此,這些電子產品將被幾千甚至幾百萬用戶使用,每個用戶使用產品的方式各不相同。在如此大量的使用中,當芯片上的功能和事件出現(xiàn)某種在器件測試過程中從未遇到過的順序或組合時,可能就會發(fā)生問題。這些問題通常表現(xiàn)為:不時被鎖住、數(shù)據(jù)出錯或其它難以復現(xiàn)的異常現(xiàn)象。如果這些問題出現(xiàn)太多(或者在執(zhí)行重要任務的產品中僅僅偶然出現(xiàn)),用戶將會認為這些產品是不可靠甚至不穩(wěn)定的。
強化測試概念的引出
最初嘗試創(chuàng)建系統(tǒng)強化測試時,方法是研究和編寫直接激活盡可能多的芯片功能并使它同時執(zhí)行軟件,使用定時器中斷并讓它執(zhí)行隨機測試,同時主程序不停地復制數(shù)據(jù),并隨機地不時啟動其它芯片操作。當想出向芯片內引入更多無序和隨機事件的招數(shù)時,便將它添加到軟件中去。很快就可以發(fā)現(xiàn),雖然陸續(xù)發(fā)現(xiàn)了許多問題,但它大多發(fā)生在自己編寫的軟件上。
由于不時使用同一塊存儲區(qū)域或外設資源,測試軟件中的測試功能相互干擾。例如,當一個測試正在使用某一通用I/O時,另一個隨機啟動的測試卻更改了它的狀態(tài)。由此不時導致的故障耗用了大量的調試時間。
第二次,嘗試開發(fā)組織得非常好的強化測試軟件。它安排隨機選擇的測試功能輪流運行,在許多地方將中斷鎖住,以防止軟件沖突和保證其它安全措施。這種謹慎的編程使得測試非常穩(wěn)定,但與直接測試相比,同樣不能有效地發(fā)現(xiàn)芯片的問題,因為它是按照一種很大程度上可預期的順序方式來執(zhí)行測試。畢竟測試的目的是為了測試半導體器件的設計,而不是為了獲得穩(wěn)定的測試軟件。
在理論上希望避免這兩種極端情況。測試的根本目的是為了暴露芯片中系統(tǒng)級的相互作用問題,為了達到這個目的,就必須將操作搞亂,使得許多不同事件以隨機方式發(fā)生。其中的訣竅是,以一種有組織的方式來保持測試的無序特點,從而獲得可靠的測試軟件,并可進行擴展,還可以盡可能地幫助調試。要達到這些目的,需要仔細進行考慮和規(guī)劃。這就是構建一個強化測試框架的思路。
測試框架
本文介紹一個軟件框架(framework)的設計,讀者可以使用這個框架來為半導體器件構建一個可擴展的強化測試。雖然本文沒有提供完整的框架,但這些內容應當能夠激發(fā)讀者的靈感來幫助構建自己的強化測試框架。
軟件框架通過提供一個公共操作引擎和環(huán)境來簡化特定類型的應用開發(fā)工作,具體的應用經(jīng)由一個定義好的接口來與框架連接。強化測試框架也采用了同樣的思路,它提供一個軟件引擎來處理強化測試的基本操作和公共功能。
強化測試框架本身不測試任何芯片功能,但它允許嵌入測試事件模塊。測試事件模塊是實現(xiàn)一項具體的半導體器件測試或事件的函數(shù),通常要使用一組隨機產生的測試參數(shù)。執(zhí)行強化測試時,框架引擎將隨機選擇并以不同方式來啟動這些測試事件模塊。
這個框架還為測試事件模塊提供了基本服務供其使用,包括保留系統(tǒng)資源的功能、選擇隨機測試參數(shù)的功能和數(shù)據(jù)記錄功能。大部分預先規(guī)劃和設計都位于框架本身內部,因為框架處理強化測試復雜和“混亂無序”的一面。然后,根據(jù)需要增加單個測試事件模塊,擴展強化測試。由于框架負責處理公共的強化測試軟件部分,測試事件模塊的開發(fā)人員可以專注于為目標芯片功能編寫優(yōu)秀的測試程序。圖1為強化測試框架各個組成部分的高層次示意圖。
隨機測試池是強化測試的核心部分,實際的半導體器件測試就位于其中。它是為了對芯片的某項具體功能啟動事件和(或)執(zhí)行測試而編寫的測試事件模塊的集合。開發(fā)新的測試事件模塊時,可將它添加到隨機測試池中,以便在下一次運行強化測試時將其包含在內。本文后面還將更詳細地介紹測試事件模塊,因為這是為芯片開發(fā)并由框架啟動和支持的實際半導體器件測試。
執(zhí)行過程中,強化測試引擎隨機地從池中選擇和運行測試事件模塊。為了使測試變得更加雜亂無序(從而對器件設計施加更大的強化測試),框架采用異步時隙來按照任意時間間隔隨機選擇和啟動測試。
“時隙”使用一個硬件定時器來實現(xiàn),器件或測試板卡上的多個定時器可以擁有各自的時隙??蚣転槊總€時隙定時器選擇隨機的時間間隔,當時隙截止時,引擎中斷當前的測試模塊,定時器的中斷處理程序將選擇另一個模塊來執(zhí)行,同時引擎為下一個時隙操作選擇另一個隨機的時間間隔。這樣,測試將以一種交織的風格執(zhí)行,引發(fā)各種各樣的執(zhí)行方式,同時還實現(xiàn)了執(zhí)行的并行性,這一點將在后面看到。
選擇和啟動一項測試的框架代碼很簡單,因為測試事件模塊只不過是一個C語言函數(shù)而已。列表1是啟動程序的一段代碼。一般而言,框架保持有一組C函數(shù),這些函數(shù)即為測試模塊,讀者可以選擇任意一個索引來查看函數(shù)并加以執(zhí)行。
(列表1)
測試模塊
如前所述,測試事件模塊是一個函數(shù),它針對半導體器件的某個具體特性執(zhí)行一個動作或一次檢驗。雖然框架將測試模塊作為一個C函數(shù)來激活,但如果需要,模塊也可以調用匯編級代碼。框架的編寫方式使得設計人員可以開發(fā)新的模塊并添加到測試池中,供強化測試期間框架隨機選擇。后面框架實例中的測試模塊是void C函數(shù),它不需要任何參數(shù)。在框架支持功能的幫助下,模塊本身可以啟動測試并調用相應的功能來記錄結果。
測試事件模塊共有三種類型:
1. 純事件
2. 檢驗測試
3. 延遲檢驗測試
正如其名稱所表明的那樣,純事件模塊啟動一個系統(tǒng)事件后不做任何檢驗工作,包括以某種方式改變系統(tǒng)或啟動某項后臺功能。那么,啟動一個事件而不執(zhí)行任何檢驗有什么意義呢?為了解釋這個問題,來考察一個測試事件模塊,它僅僅切換處理器高速緩存的當前設置。每次框架隨機選擇這個模塊時,高速緩存就從1切換到0或從0切換到1。這增加了一個變化因素,因為對于運行時需要用到這個高速緩存的測試模塊而言,它的值有時為1有時為0。
第二種測試事件模塊是檢驗測試,它執(zhí)行一個動作,并在測試模塊函數(shù)退出之前對這個動作進行檢驗。例如,這種測試可以用任意數(shù)據(jù)來填充隨機選擇的存儲器區(qū)域,然后采用任意CPU讀寫寬度來將這個區(qū)域復制到一個隨機的目的存儲器區(qū)域,再檢驗其結果。
第三種測試模塊是延遲檢驗測試,這是功能最強的測試,雖然通常只能用于可以對總線進行控制的芯片功能(換句話說,運行在CPU的后臺)。這種測試模塊將啟動一個測試然后退出,使得在原測試繼續(xù)運行時,其它測試模塊可以執(zhí)行。在大多數(shù)情況下,測試的完成用一個中斷來表示。當中斷發(fā)生時,中斷處理程序將檢驗測試的結果。
延遲檢驗測試的例子如DMA (直接存儲器訪問)傳輸??梢跃帉懸粋€測試模塊來選擇隨機的源、目的存儲器區(qū)域和DMA通道。這個測試模塊可以用任意數(shù)值來填充源存儲器,并配置一個用來檢驗測試結果的DMA結束中斷處理程序。這個中斷處理程序即為“延遲檢驗測試”,它可訪問包含有被啟動測試的詳細信息的數(shù)據(jù)結構,在被調用時,它還將檢驗測試的結果。
測試框架實例
為了展示這些測試的強大功能,來考察一個簡單的測試框架實例,它包含以下四個測試模塊。
1) 簡單的基于CPU的存儲器復制(TE_CPU_COPY):
將隨機數(shù)據(jù)樣式填充到一個任意大小的隨機源地址存儲器塊中,然后使用一種隨機混合的讀寫寬度來將數(shù)據(jù)樣式復制到任意選擇的目的地址。復制完成后,檢驗目的區(qū)域中的數(shù)據(jù)是否包含了先前選擇的數(shù)據(jù)樣式。
2) DMA存儲器---存儲器復制(TE_DMA_M2M):
將任意數(shù)據(jù)樣式填充到隨機源地址的任意大小的存儲器塊中,然后任意選擇一個存儲器---存儲器DMA通道,編程為將源地址的數(shù)據(jù)樣式復制到隨機選擇的目的地址。當DMA結束中斷發(fā)生時,檢查兩個存儲器區(qū)域是否匹配。
3) DMA---外設(TE_DMA_M2P):
將任意數(shù)據(jù)樣式填充到隨機源地址的任意大小的存儲器塊中,然后任意選擇一個存儲器---存儲器DMA通道,編程為將數(shù)據(jù)樣式復制到特定外設的任意端口號中。當DMA結束中斷發(fā)生時,檢查外設的FIFO中是否包含了正確的數(shù)據(jù)(或者被發(fā)送到外設)。
4) 高速緩存切換(TE_CACHE):
將高速緩存從1切換到0或從0切換到1并退出。這個測試模塊是一個純事件測試模塊,運行時不執(zhí)行檢驗操作。
假設框架有三個時隙定時器用來啟動測試事件模塊,那么啟動它的main( )例程位于時隙0,具體運行時可能與列表2所示類似。
(列表2)
運行開始時執(zhí)行存儲器復制測試。執(zhí)行過程中,時隙2定時器在復制中途定時截止。此時,高速緩存測試事件模塊被啟動,它切換高速緩存的狀態(tài)并退出。復制測試在高速緩存處于新設置的狀況下繼續(xù)執(zhí)行。在測試完成之前,時隙1定時器又截止,此時一個DMA存儲器---端口測試模塊被啟動,它設置任意的DMA通道并退出?,F(xiàn)在,DMA已在后臺執(zhí)行,而原來的復制測試又重新運行。隨后又發(fā)生一個時隙3定時器中斷,使用DMA通道5啟動存儲器---存儲器傳輸并退出。這種安排還可以繼續(xù)下去,但已經(jīng)可以看到,通過這個測試,可以讓所有的DMA通道同時運行,高速緩存隨機切換,而且CPU在測試過程中隨機訪問不同的存儲器區(qū)域。
測試參數(shù)
測試事件模塊將使用一個或多個隨機選擇的測試參數(shù)來執(zhí)行測試操作。常見的測試參數(shù)如:源和目的存儲器地址、塊大小、數(shù)據(jù)樣式、讀寫寬度(如8、16或32位)、DMA通道和UART端口。
雖然隨機地選擇測試事件函數(shù)看起來比較簡單,但究竟應當如何選擇隨機測試參數(shù)值,同時確保這些值對系統(tǒng)有效,而且不與其它測試發(fā)生交疊從而導致干擾呢?例如,如果某個測試選擇一個隨機的存儲器地址和大小,需要知道(1)存儲器確實存在;(2)其它測試沒有選擇與這片存儲器交疊的存儲器區(qū)域(因為一個測試有可能改寫另一個測試的存儲器并導致故障)。另一個資源競爭的例子是,兩個測試都隨機地選中同一個DMA通道來進行數(shù)據(jù)傳輸。
框架提供的支持功能使測試模塊可以安全地選擇任意測試參數(shù)。為了幫助理解這一點,這里舉一個最常用的測試參數(shù)的例子:隨機選擇的系統(tǒng)存儲器塊。隨機選擇的存儲器塊有一個起始地址值和一個大小值,它都是隨機數(shù)值。這個存儲器塊可以位于CPU地址空間的任何位置,包括在SRAM、PCMCIA或Flash存儲器中。
在列表3所示的例子中,memPool數(shù)組中填入了存儲器段的起始地址和大小,它位于系統(tǒng)的地址空間中,可供測試進行隨機選擇。每個條目都有一個保留標志(inUse項)。為了選擇一個隨機存儲器塊,函數(shù)首先選擇一個隨機的指向存儲器段數(shù)組的索引。然后在這個段中選擇一個隨機的起始地址和大小。最大塊的大小值是存儲器段的結束地址減去所選的起始地址。一旦隨機塊的起始地址和大小選定了,整個存儲器段就通過設置保留標志被標記為保留。
列表3:隨機存儲器塊選擇
============================
typedef struct
{
uint32_t start_addr;
uint32_t size;
bool inUse;
} memSeg;
memSeg memPool[] =
{
/* start addr size inUse */
{ 0x10000000,0x00040000, 0},
{ 0x10040000,0x00040000, 0},
{ 0x10080000,0x00040000, 0},
{ 0x100c0000,0x00040000, 0},
{ 0x30000000,0x00040000, 0},
{ 0x30040000,0x00040000, 0},
{ 0x30080000,0x00040000, 0},
{ 0x300c0000,0x00040000, 0},
{ 0x30100000,0x00008000, 0},
{ 0x40004000,0x00004000, 0},
{ 0x40008000,0x00004000, 0},
{ 0x4000c000,0x00004000, 0},
{ 0xa0000000,0x00002000, 0},
{ 0xb0000000,0x00008000, 0},
{ 0xb0008000,0x00008000, 0},
{ 0xb0010000,0x00004000, 0}
};
int SelectAndReserveBlock(unsigned int *addr, unsigned int *size)
{
int retries=0; /* limit the number of times we try to get a segment */
int seg;
while(retries MAX_RETRY_COUNT)
{
/* Select a random memory segment (index into memPool array) */
seg = GetRandomNumber(sizeof(memPool)/sizeof(memSeg));
if (memPool[seg].inUse)
{
retries++;
continue;
}
/* reserve the segment */
memPool[seg].inUse = 1;
/* select random block in segment, and don't let it run past the end
of the segment. */
*addr = memPool[seg].start_addr + GetRandomNumber(memPool[seg].size);
max_size = memPool[seg].size - (*addr - memPool[seg].start_addr);
if (max_size > MAX_BLOCK_SIZE)
max_size = MAX_BLOCK_SIZE;
*size = GetRandomNumber(max_size);
break;
}
/* return the segment number so it can be used to free it later,
or return -1 if we gave up looking for a free segment */
return (retries >= MAX_RETRY_COUNT) ? -1 : seg;
}
void FreeMemorySegment(int seg)
{
memPool[seg].inUse = 0;
}
===============================================
這種方法的一個缺點是,使用存儲器段中的某個隨機存儲器塊時,按照存儲器段數(shù)組中的定義方式,整個存儲器段都將被保留。如果所有存儲器段都被保留了,還有存儲器可用嗎?解決的辦法是將存儲器分為更小的段??赡芟M圆煌姆绞絹矸指畲鎯ζ鞫危员阆缭綌?shù)據(jù)寬度和類型各不相同的多個存儲器器件來選擇存儲器塊的可能性。注意這些方案都比較簡單,也可以加強它的功能,關鍵只是直接控制指示哪些存儲器區(qū)域可以使用。
管理其它資源的選擇和保留可能更加簡單。例如,保留標志數(shù)組可用來管理DMA通道,數(shù)組的索引代表通道。設計人員可以編寫一個ReserveDmaChannel()函數(shù),它返回一個隨機DMA通道號,這個通道號處于芯片上的DMA通道數(shù)目范圍之內,并且其保留標志未被設置。然后,函數(shù)將設置保留標志來保留這個通道。測試完成時,可以調用FreeDmaChannel()來清除該標志。
調試技巧
調試和分離與系統(tǒng)相互作用有關的問題可能比較困難,在這個過程中可以通過設計強化測試框架來提供幫助。根據(jù)運行是在芯片生產前的仿真環(huán)境下進行,還是在一個安裝有實際芯片的板卡上進行,所遇到的問題將會有差異。
在仿真環(huán)境下運行時,速度是最大的問題,仿真CPU的運行速度要比實際器件慢得多。仿真環(huán)境的優(yōu)勢在于仿真工具可以輸出芯片設計內部信號的詳細記錄,這將簡化調試工作,但它也有一個很大的缺點,即問題復現(xiàn)困難。如果為了暴露問題要花費太長的時間來運行強化測試,這將是難以接受的。
解決的辦法是將強化測試作為許多較短(例如30分鐘)的測試來運行,這可以通過用一組測試事件模塊來創(chuàng)建不同的測試來實現(xiàn)。此外,還應該給每個測試分配一個專門的隨機數(shù)種子(seed),以便使用這個種子的其它測試每次運行時,都能重新產生準確的測試事件和測試參數(shù)序列。
好的運行腳本可以隨機產生種子值,然后創(chuàng)建一個測試并加以運行。種子值應當與運行結果一起記錄下來。為了復現(xiàn)一個故障,可以用這個種子重新創(chuàng)建測試(因為可能不希望保留所有的可運行測試程序,其數(shù)量可能達到幾千個),然后在短時間內復現(xiàn)這個問題。
在實際的芯片上可以運行更多強化測試,因為其執(zhí)行速度要快得多。但在理論上,它可能還是要花費同樣長的時間,因為比較常見的問題應該在芯片生產前的強化測試中就已經(jīng)暴露出來了。在這里,問題的復現(xiàn)同樣是一個很大的困難,讀者可以嘗試在芯片生產前的測試中應用所介紹的技術,但它可能不會同樣有效,因為實際系統(tǒng)可能不如在仿真環(huán)境下那樣確定。換句話說,兩個采用同一隨機測試種子運行的測試可能不會每次都獲得精確相同的運行序列。另外,此時也無法記錄內部信號的行為,因此應該依靠一些技術,如將檢測點的信息記錄到存儲器或高速端口、插入各種邏輯分析儀觸發(fā)事件,以及采用其它技術來幫助深入跟蹤問題的詳細情況。
在實際芯片上調試系統(tǒng)問題時,沒有什么通用的方法。設計人員應當周密考慮,并象即將遇到難以捉摸的故障一樣來進行計劃,編寫程序代碼,為分析問題提供盡可能多的線索。
此外,測試框架還應該包含這樣一種能力,它創(chuàng)建的測試運行程序能將某些測試模塊排除在外,從而使強化測試無需在已知的問題上停止下來而得以繼續(xù)運行。另一方面,將其余功能排除在外也將使設計人員能夠對某些特定的芯片功能進行重點測試。
框架需要組織良好的軟件代碼來生成種子、創(chuàng)建測試、運行、存儲測試記錄和后續(xù)處理,并向設計人員報告所遇到的問題。這個過程應當是完全自動化的,這樣就可長時間運行測試而無需人員維護。
記錄測試過程
強化測試框架最少應該記錄哪個測試模塊在運行,以及發(fā)生的所有故障。完善的記錄將包括更多的信息,如選擇的隨機參數(shù),各個測試事件是何時啟動、退出和檢驗 (針對延遲檢驗函數(shù))的。這樣,設計人員就可以了解各個測試是如何相互聯(lián)系地運行的。后續(xù)處理軟件可以生成一些有用的報告,以顯示測試的覆蓋范圍。
開發(fā)記錄功能時,應使強化測試軟件盡可能簡單方便地記錄事件。在仿真環(huán)境下,可編寫HDL代碼來提供一個記錄外設,這樣設計人員只需寫下一個數(shù)值記號, HDL就將產生完整的記錄信息。在實際芯片上,可以將字節(jié)記號和數(shù)值發(fā)送到存儲器板卡或輸出到調試端口。關鍵之處是要避免記錄操作本身過多占用寶貴的測試運行時間,并導致過度干擾。通過后續(xù)處理軟件,可以使記錄更清楚、更美觀。
本文小結
由于框架將涉及對中斷處理程序所讀寫的共享數(shù)據(jù)結構的使用,因此訪問這些數(shù)據(jù)結構時,應在軟件代碼中對重要的存儲器段進行保護。例如,如果一個測試事件剛剛讀取了一個存儲器段的inUse標志并發(fā)現(xiàn)它未被使用,但在它將該存儲器段設置為保留之前,又發(fā)生了一個時隙中斷,中斷啟動的測試模塊結束時,可能將同一存儲器段設置為保留,因為此時該存儲器段仍表現(xiàn)為未被使用。在這種類似的重要全局數(shù)據(jù)訪問期間,應該將時隙定時器中斷予以禁止。
設計一個強化測試框架時,有許多擴展可能性。如可以調節(jié)測試事件模塊的概率權重,或調整測試參數(shù)以便對強化測試進行精密調節(jié)。舉個例子,高速緩存切換事件可能是100個測試事件模塊之一,但測試時可能希望它運行比1%多得多的時間,此時便可通過調整測試參數(shù)來實現(xiàn)。規(guī)劃、設計和實現(xiàn)性能優(yōu)良可靠的半導體器件強化測試框架是一項重大投入,雖然需要花費大量的時間,但它可以幫助提高產品的質量。
作者: Steve Babin
IBM公司負責開發(fā)靈巧電話軟件的深入計算事業(yè)部擔任顧問職務。在嵌入式系統(tǒng)領域擁有16年以上的工作經(jīng)驗,Steve
Babin持有路易斯安那州立大學的電子工程學士學位。
Email: sbabin@austin.rr.com
評論