作者:David Katz,Tomasz Lukasiak,Rick Gentile
數(shù)字信號處理器(DSP)在性能、外設、功耗和價格上已經結合得非常好了,許多系統(tǒng)工程師希望利用DSP的優(yōu)勢,取代傳統(tǒng)設計方案中使用的處理器,但一個潛在難題是設計工程師已經為他們的應用開發(fā)了大量C和C++代碼。很明顯,工程師都愿意在DSP平臺上利用現(xiàn)有的高級代碼,同時利用DSP的體系結構特性以獲得更好的性能。
HLL與匯編語言
當開發(fā)基于DSP的軟件時,必須要做的一項工作就是確定使用哪一種程序設計方法學,通常是在匯編語言和高級語言(HLL)(例如C或C++語言)之間進行選擇。
C和C++的優(yōu)點包括模塊性、便攜性以及可重復利用性。
傳統(tǒng)的匯編語言由于其語法和縮寫難以理解和使用,長期以來不被人們所看好。目前的“代數(shù)語法”體系結構有了很大改進。表1是使用傳統(tǒng)風格和使用代數(shù)格式的典型DSP指令實例,很顯然后者的結構更加直觀。在所提供的實例中,r寄存器是數(shù)據寄存器,p寄存器是指針寄存器。
用匯編語言編程困難的一個原因是由于其數(shù)據流集中在DSP實際寄存器組、計算單元和存儲器之間。用C或C++語言編程,這種操作通常通過使用變量和函數(shù),或過程調用出現(xiàn)在更加抽象的處理等級之間,從而使得代碼更容易跟隨。
為提高DSP執(zhí)行效率,工具開發(fā)商會使用匯編語言對重要的數(shù)據密集代碼模塊進行優(yōu)化。HLL編譯優(yōu)化轉換可以很好地完成該項工作,而且對DSP數(shù)據流和計算的直接控制能力是極為出色的。這就是為什么設計工程師通常結合使用C/C++和匯編語言。HLL適合于控制和基本的數(shù)據操作,而匯編語言適合于高效的數(shù)字計算。
適合高效編程的體系結構的特性
為了使匯編語言程序員能夠有效地完成工作,需要了解處理器的結構類型,以便能夠區(qū)分不適合高速數(shù)字計算的那些DSP處理器。這些適合高效編程的體系結構結構特性包括:
● 專用尋址模式
● 硬件環(huán)路結構
● 高速緩沖存儲器
● 每周期多次操作
● 互鎖流水線
● 靈活的數(shù)據寄存器文擋
專用尋址模式
允許處理器在單周期內訪問多個數(shù)據字需要靈活的地址產生方式。除了需要更大的以DSP為中心的16bit和32bit邊界的訪問尺寸外,還需要字節(jié)尋址以達到最有效的處理。這是非常重要的,因為一些普通應用(例如許多基于視頻的系統(tǒng))都是按照8bit數(shù)據操作。當處理器訪問限制在單一邊界內時,處理器可能需要額外的周期來掩蔽掉相關的位。
另外一種有利的尋址能力是“循環(huán)緩沖”。該特性必須直接由處理器支持,無須專門的軟件管理開銷。循環(huán)緩沖允許程序員定義存儲器中的緩沖器,并且自動跨越它們。一旦緩沖器設置好,則無須專門的軟件交互操作數(shù)據。地址發(fā)生器處理非同式跨幅,更重要的是可以處理圖1所示的“環(huán)繞式”特性。如果沒有這種自動地址產生功能,程序員必須手動跟蹤緩沖器,從而浪費了寶貴的處理周期。
圖1 環(huán)繞式緩沖的例子
在此例中,基地址和起始索引地址=0x0;索引地址寄存器I0指向地址0x0;緩沖器長度L=44(11個數(shù)據元素×4字節(jié)/元素);修改寄存器M0=16(4個數(shù)據元素×4字節(jié)/元素)
實例代碼:
R0 = [I0++M0]; //R0 = 1,I0在代碼執(zhí)行后指向0x10
R1 = [I0++M0]; //R1 = 5,I0在代碼執(zhí)行后指向0x20
R2 = [I0++M0]; //R2 = 9,I0在代碼執(zhí)行后指向0x04
R3 = [I0++M0]; //R3 = 2,I0在代碼執(zhí)行后指向0x14
R4 = [I0++M0]; //R4 = 6,I0在代碼執(zhí)行后指向0x24
用于高效信號處理運算(例如快速傅立葉變換(FFT)和離散余弦變換(DCT))的一種重要尋址模式是比特翻轉。顧名思義,“比特翻轉”就是將二進制地址中的比特翻轉,也就是說將權值最小的比特與權值最大的比特交換位置。由基為2的蝶形所要求的數(shù)據順序是“已翻轉比特”的順序,因此比特翻轉索引用來組合FFT級。可以計算軟件中的這些比特翻轉索引,但是這樣做的效率非常低。圖2所示是比特翻轉地址流實例。
圖2 硬件比特翻轉機理
實例代碼:
LSETUP(起始, 終止)LC0=P0; //循環(huán)數(shù)P0=8
起始:R0 = [I0] || I0 += M0(BREV); //I0指向輸入緩沖器,在比特翻轉過程中自動增加
終止:[I2++] = R0; ; //I2指向比特翻轉緩沖器
硬件循環(huán)結構
循環(huán)在通信處理算法中是一項很重要的特性。有兩個與循環(huán)有關的關鍵特性能夠改進多種算法的性能。第一個特性稱作“零開銷硬件循環(huán)”。隨著尋址能力的提高,循環(huán)結構可以在硬件中實現(xiàn)。此外,當該項功能用軟件實現(xiàn)時,相關的開銷可減小到實時處理預算。零開銷循環(huán)允許程序員通過設置計數(shù)值并且定義循環(huán)邊界初始化循環(huán)。處理器將繼續(xù)執(zhí)行循環(huán)直到計數(shù)結束。
零開銷循環(huán)是大多數(shù)處理器必不可少的一部分,但“硬件循環(huán)緩沖器”實際上可以提高循環(huán)結構的性能。它們用作循環(huán)中所執(zhí)行指令的一種高速緩沖存儲器。例如,在第一次執(zhí)行完一個循環(huán)之后,可將該指令保存在循環(huán)緩沖器中,從而無須在每一次循環(huán)都反復重取相同指令。通過將循環(huán)指令保存在能夠在單周期內訪問的緩沖器中,能夠節(jié)省大量的周期數(shù)。該特性不需要程序員進行額外的設置,但是需要知道循環(huán)緩沖器的尺寸以合理地選擇循環(huán)大小。
高速緩沖存儲器
通常典型的DSP具有少量的快速、內置存儲器。MCU通??梢栽L問大量的外部存儲器。分層存儲器體系結構將這兩種方案的優(yōu)點結合在一起,從而可提供幾種等級具有不同性能的存儲器。對于需要最高性能應用,可以在單個核心時鐘周期內訪問內置SRAM。對于具有大代碼尺寸的系統(tǒng),可提供大量、較長等待延遲的片內和片外存儲器。
這種分層存儲器體系結構本身僅僅是發(fā)揮一定的作用,由于現(xiàn)在的高性能處理器常常運行在較低的時鐘頻率下,因此大的應用程序只能裝在較慢的外部存儲器中。此外,程序員被迫手動將關鍵代碼移入和移出內部SRAM。但是,通過將數(shù)據和指令高速緩沖存儲器加到該體系結構中后,外部存儲器更易于管理,高速緩沖存儲器可以減少將指令和數(shù)據移入處理器內核的手工操作。由于不需要考慮進入內核的數(shù)據和指令流管理,可以大大簡化編程模式。
指令高速緩存通常采用了某種類型的最近最少使用(LRU)算法,從而確保更常用的指令代替較少使用的指令。將一些內置數(shù)據存儲器配置為高速緩存和部分SRAM的能力可以優(yōu)化性能。直接存儲器訪問(DMA)控制器能夠直接控制內核,同時當需要表中數(shù)據時將其讀入數(shù)據高速緩存。一旦高速緩存允許并且DMA控制器配置完畢,則程序員即可集中精力于內核算法的開發(fā)。
每周期多次操作
通常以每秒執(zhí)行多少百萬條指令(MIPS)來衡量處理器。曾經被保留用在高成本并行處理器中的多發(fā)布指令目前也可用在低成本、定點處理器中。除了在每個核心處理器周期內完成多條ALU或MAC操作外,在相同周期內還可完成額外的數(shù)據處理和數(shù)據存儲。存儲器通常劃分為子若干個存儲器組,這些存儲器組可以被內核雙向訪問并且被DMA控制器隨機訪問。鑒于上述的基于硬件的尋址算法的分解方法,很明顯其可以在單個周期內完成許多操作。
圖3示出多操作指令的一個實例。如圖3所示,在一個周期內除了完成兩條獨立的MAC操作外,在相同的處理器時鐘周期內還完成了數(shù)據讀取和數(shù)據存儲。
圖3 Blackfin多發(fā)布指令在單周期內完成幾次操作
互鎖流水線
隨著處理器速度的增加,從整個電路級來看處理流水線必定會變得更深。然而,有些處理器具有“互鎖”流水線。這意味著當完成匯編語言編程時,程序員不必手動調度或跟蹤通過流水線的數(shù)據和指令。處理器會自動處理這些時序的事情。
靈活的數(shù)據寄存器文檔
最后,另外一個補充特性是通用數(shù)據寄存器集。在傳統(tǒng)的定點DSP中,字長通常是固定的。然而,具有能夠用作一個32bit(例如R0)或兩個16bit(例如分別用于低8bit和高8bit的R0.L和R0.H)的數(shù)據寄存器是非常有利的。在雙MAC系統(tǒng)中,這允許在單周期內操作四個16bit的數(shù)據。
內積
內積或者標量積在度量兩個向量的正交性時是很有效的操作。大多數(shù)C語言程序員應該熟悉以下的內積操作: short dot(short a[], short b[], int size) {
int i;
int output = 0;
for(i=0; i }
return output;
下面是Blackfin處理器匯編代碼的主要部分:
//P0=loop count, I0 & P1 are address registers
A1 = A0 = 0; // A0 & A1 are accumulators
LSETUP (loop1,loop1) LC0 = P0 ;// Setup hardware loop starting at label loop1:
loop1: A1 +=R1.H*R0.H, A0+=R1.L*R0.L||R1=[P1++]||R0=[I0++];
下面幾點說明了簡化這種緊湊編碼的DSP體系結構特性。
硬件循環(huán)緩沖器和循環(huán)計數(shù)器在每次迭代的末端不需要跳轉指令。由于內積是乘積總和,因此可在一次循環(huán)中完成。該匯編程序所示是LSETUP指令,它是執(zhí)行循環(huán)所需的唯一指令。
多發(fā)布指令允許在相同的周期內執(zhí)行多條指令和兩次數(shù)據訪問。在每一次迭代時,必須先讀取a和b值,然后相乘,最后寫回到可變輸出的運行總和中。在許多MCU平臺上,這實際上等于四條指令。匯編代碼的最后一行示出在一個周期內可執(zhí)行的所有操作。
并行ALU操作允許同時執(zhí)行兩條16bit指令。匯編代碼示出在每次迭代中使用的兩個累加器單元(A0和A1),這將迭代次數(shù)減少了50%,從而將原來的執(zhí)行時間減少了一半。
FIR算法
有限脈沖響應(FIR)濾波器是一種等價于卷積操作很常見的濾波器結構。A通過C操作看起來非常類似于內積。
//將信號取樣到循環(huán)緩沖器中
x[cur] = sampling_function();
cur = (cur+1)%TAPS; // 在循環(huán)中增加cur指針
//完成乘加
y = 0;
for (k=0; k }
使用匯編語言編寫的FIR內核格式有些類似于內積。在這個特定的例子中,取樣值存儲在R0寄存器中,同時系數(shù)存儲在R1寄存器中。
// P0 存有濾波器抽頭
R0=[I0++] || R1=[I1++]; // 設置R0和R1的初始值
A1=A0=0; // 將累加器置零
LSETUP (loop1, loop1) LC0 = P0;//設置內部循環(huán)
loop1: A1+=R0.L*R1.L, A0+=R0.H*R1.H||R0=[I0++]||R1=[I1++]; //計算
除了具有所描述的用于內積的特性外,上面所示的FIR算法也可使用循環(huán)緩沖。
循環(huán)緩沖器不需要直接取余運算。在C代碼片段中,%(取余)運算符可提供一種用于循環(huán)緩沖的機理。正如匯編內核中所示,這些取余運算符不能被編譯為內循環(huán)中的其他指令。相反,數(shù)據地址發(fā)生器寄存器I0和I1可在外循環(huán)中配置,以便在循環(huán)到達系數(shù)緩沖器邊界時能夠自動返回起始處。
FFT算法
快速傅立葉變換(FFT)是許多信號處理算法不可缺少的一部分,其特點之一是輸入向量按照連續(xù)時間順序排列,但輸出按比特翻轉順序排列。大多數(shù)傳統(tǒng)的通用處理器要求程序員用單獨的程序整理比特翻轉輸出。在DSP平臺上,比特翻轉可用于尋址引擎。
比特翻轉尋址在實現(xiàn)FFT時不需要單獨的比特翻轉程序,允許硬件自動將FFT算法的輸出進行比特翻轉,無須程序員編寫額外的程序,從而改進了性能。
除了上面所提到的指令外,有些處理器也包括額外一套專用指令以支持多種應用。提供這些指令的目的就是進一步提高對算法的處理能力,例如維特比算法、Huffman編碼以及許多其他比特操作程序。
zrbj:gt
評論
查看更多