什么是專用處理器?
先說一般的處理器概念,wiki定義是“ In computing, a processor is an electronic circuit which performs operations on some external data source, usually memory or some other data stream ”。專用處理器就是針對特定應(yīng)用或者領(lǐng)域的處理器,類似于是我們經(jīng)常說的Domain Specific Architecture的概念。
最為通用的處理器當(dāng)然是CPU(比如intel的桌面CPU,ARM的嵌入式CPU),可以運行任何程序,處理各種數(shù)據(jù)。但問題是CPU對某些應(yīng)用效率太低(處理能力不夠,無法實時處理,或者是能耗太大)。比如,處理graphic不行,于是出現(xiàn)了GPU;信號處理不行,于是出現(xiàn)了DSP。GPU可以做圖像處理,也可以做DNN的training和inference,但是在處理某些DNN應(yīng)用的時候效率不高,于是有了專用針對這些應(yīng)用處理器,也就是我最近討論的AI/ML/DL處理器。所以說,專用處理器也是個相對概念,相對CPU而言,別的類型處理器都可以認(rèn)為是專用處理器。而我在本文里主要討論的是相對GPU/DSP而言更為“ 專用 ”的處理器。
專用處理器的覆蓋范圍也很廣,有的能夠運行標(biāo)準(zhǔn)的C程序,比如很多ASIP處理器(Application Specific ISA Processor);有的只有很簡單的可編程性,比如一些可配置的硬件加速器(Configurable Hardware Accelerators),極端的例子就是“只運行一條fft指令的“FFT硬件加速器。當(dāng)然具體的硬件設(shè)計里可能并沒有指令的概念,只有配置的概念。我討論的重點是至少具有一定可編程能力,可以(并需要)運行程序的專用處理器。
指令集設(shè)計
這里先簡單說一下指令集的概念。指令集就是一個處理器的硬件可以支持的基本操作(符號化的抽象描述)的集合。(wiki:“ An instruction set, with its instruction set architecture (ISA), is the interface between a computer's software and its hardware, and thereby enables the independent development of these two computing realms; it defines the valid instructions that a machine may execute. ”)。借用Patterson老爺子最近講演里了一張圖,ISA就是傳統(tǒng)上軟件和硬件的分界線。
通常,處理器的指令集架構(gòu)(ISA:Instruction Set Architecture)決定了處理器的功能(編程模型)。最著名的x86就是intel CPU的指令集。一個通用處理器,為了適應(yīng)所有的應(yīng)用,其指令集必須考慮最大的靈活性。這種靈活性主要表現(xiàn)在指令功能是不是完備和粒度是不是足夠細。
舉個例子,大家都知道FFT運算是由蝶形運算組成的;而蝶形運算是由復(fù)數(shù)乘法和加法組成;復(fù)數(shù)的乘法和加法又是由普通的乘法和加法組成。如果你設(shè)計一個可以處理FFT的處理器,可以有幾種方法設(shè)計指令集。最簡單的就是用一個通用指令集,指令集里有最基本的乘法和加法就沒問題。FFT的處理分解為這些基本運算,一步一步完成。這樣,你的處理器具有最高的靈活性,如果這個處理器不做FFT,還可以做其它的運算。還有一種方法,指令集里只設(shè)計一條指令,fft指令,執(zhí)行這條指令就可以完成所有操作。當(dāng)然,這樣顯然沒什么靈活性。即使是要做一個“1+1”的操作,你的處理器也干不了。這個例子比較極端,實際設(shè)計中一般是折中的處理。但是后者就是我想討論的專用處理器的一個重要特點,一條指令完成更多的處理。
由于專用處理器這個名稱可以用在很多地方,我想再明確一下本文說的專用處理器設(shè)計的范圍:1. 我們主要討論IP級的設(shè)計,也就是說專用處理器設(shè)計最終作為一個SoC(System-on-Chip)芯片中的IP出現(xiàn)。它需要和其它模塊合作完成整個芯片要實現(xiàn)的功能(下圖為一個簡化模型)。2. 我們主要討論的專用處理器是要運行程序的,有自己的指令集(可能很簡單,比如Google第一代TPU,主要指令不超過10條),需要有存儲程序的空間和讀取指令,執(zhí)行指令的機制。
專用處理器雖然強調(diào)專用二字,但實際上還是一個處理器。因此,設(shè)計一個專用處理器,和設(shè)計通用處理器的內(nèi)容和過程類似。簡單來說,這一過程覆蓋指令集(ISA),微結(jié)構(gòu)(硬件)和工具鏈(軟件)的設(shè)計和實現(xiàn)。下面先討論一下指令集的問題。
對專用處理器來說,指令集的設(shè)計直接反映了對應(yīng)用需求的理解。比如,第一篇中介紹的例子,如果我們的專用處理器只是為了加速256點的FFT用的,那么指令集里只有FFT指令就夠用了??紤]到數(shù)據(jù)搬移的需求,再加上幾條數(shù)據(jù)搬移的指令,比如讀取數(shù)據(jù),寫回數(shù)據(jù)。于是可以得到一個有三條指令的指令集(fft,load,store)。這個處理器執(zhí)行的匯編(Assembly)程序大概就是這樣的。
當(dāng)然,這里做了很多簡化,但看起來這個指令集已經(jīng)可以work了。同時,這也是一個“高效”的設(shè)計,沒有多余的東西。如果你要循環(huán)做8次fft,那么可能需要增加一條loop(循環(huán))指令,要不然你就得把上面的代碼copy八次。加了loop指令,匯編代碼可能是下面這樣。
設(shè)計指令集除了確定每條指令的功能和操作數(shù)(比如上面的例子里的寄存器的名字,循環(huán)次數(shù)等等),還有一個重要工作就是設(shè)計指令編碼。像“l(fā)oad”這樣的指令名稱只是個抽象的描述,而處理器的硬件看到的實際上是二進制的指令編碼。還是上面這個例子,由于我們的指令集有4條指令,則需要2個比特來區(qū)分,比如,00:fft;01:load:10;store;11:loop。再具體看load指令,還需要幾個bit來說明目標(biāo)寄存器,假設(shè)一共有8個寄存器(R0-R7),區(qū)分他們又需要3個bit;另外需要一個bit來說明數(shù)據(jù)的來源:是一個立即數(shù)還是來自內(nèi)存;如果來源是內(nèi)存,還需要幾個bit表示內(nèi)存地址,或者指示存放內(nèi)存地址的寄存器編號,等等。你會發(fā)現(xiàn),可能對于一個load指令,一共需要32個bit的指令編碼。上面的匯編程序第三行對應(yīng)的機器碼可能是這樣的。
最后,把所有的情況列出來,就形成一個指令和指令編碼的列表。這就是一個完整的指令集架構(gòu)(ISA)了。實際上的ISA當(dāng)然比這個復(fù)雜很多,但不管多復(fù)雜,主要也就是這幾大類功能:第一是執(zhí)行運算或處理功能的,比如算數(shù)運算;第二類是控制程序流的,比如循環(huán),分支和跳轉(zhuǎn);第三類實現(xiàn)數(shù)據(jù)搬移的,比如內(nèi)存到寄存器,寄存器之間;最后還有一些輔助功能,比如debug,中斷,cache之類的指令。這里就不展開講了,有興趣的同學(xué)可以自己研究一下現(xiàn)在很火的開源指令集RISC-V。個人感覺,仔細看明白一個好的指令集的設(shè)計思想,比看教科書收獲要多得多。
以上算是指令集的背景知識吧,回到設(shè)計專用處理器的問題。當(dāng)我們有了一個應(yīng)用需求,怎么來設(shè)計和優(yōu)化一套專用的指令集呢?我想這個問題可能很難有個統(tǒng)一的答案,這里就說說我的個人經(jīng)驗吧。
1. 確定評價標(biāo)準(zhǔn)
我們設(shè)計專用處理器都是有明確目的性的,先把目標(biāo)弄清楚至關(guān)重要。評價一般的通用處理器有一些成熟的benchmark。還有一些benchmark更面向?qū)S妙I(lǐng)域,比如多媒體,DSP,或者針對特殊結(jié)構(gòu)的,比如cache。
那么評價專用處理器的標(biāo)準(zhǔn)是什么呢?很簡單,目標(biāo)應(yīng)用。 所以,最好在開始設(shè)計之前,就把目標(biāo)應(yīng)用定量化。如果目標(biāo)應(yīng)用已經(jīng)有程序代碼,就可以直接用這些程序代碼做benchmark,來評價你的設(shè)計。如果還沒有完整的應(yīng)用程序代碼,最好也要把關(guān)鍵算法部分寫出來。當(dāng)然,這一條不只是針對指令集,而是針對完整的專用處理器,包括工具鏈的設(shè)計(后續(xù)再介紹)。對于專用處理器設(shè)計來說,評價標(biāo)準(zhǔn)一般是有限而明確,是正是它能夠在一個領(lǐng)域做的比通用處理器效率高的最重要因素。
2. 選擇一個參考指令集作為基礎(chǔ)
從零開始做專用處理器相當(dāng)于“重新發(fā)明輪子”,存在很大的風(fēng)險。那么我們能否把問題變成“優(yōu)化輪子設(shè)計”呢(是不是看起來要簡單了很多)?在多數(shù)情況下都是可以,而且有效的。對于大部分應(yīng)用來說,其合理的指令集都需要一些基本的指令,比如基本的算術(shù)指令和跳轉(zhuǎn)控制指令等,這一部分完全可以參考已有的設(shè)計。這樣可以大大降低設(shè)計的風(fēng)險。
比如,我們現(xiàn)在有一個應(yīng)用,在通用處理以外需要大量的FFT操作。一種方法是自己設(shè)計一套指令集,即包括通用指令,又包括特殊指令,比如專門的蝶形運算(butterfly)操作。另一種方法是參考一個成熟的指令集,在它的基礎(chǔ)上做優(yōu)化工作,增加butterfly指令,并減少一些不常用的指令。相比第一種方法,這樣顯然風(fēng)險要小的多。還有一個好處,我們 可以重用參考處理器的工具鏈 ,或者只要少量改動,進一步降低的工作量。
結(jié)合第1點,一般我們可以先把目標(biāo)應(yīng)用的程序在參考的處理器上跑一下,做一些評估,找到瓶頸。針對瓶頸問題設(shè)計或改進指令集,以及后面要介紹的微結(jié)構(gòu)和工具鏈。這也說明在開始的時候就有一個明確的評價標(biāo)準(zhǔn)的好處。
3. 充分利用工具
實際上,不管是指令集還是微結(jié)構(gòu),設(shè)計和優(yōu)化過程就是一個在優(yōu)化目標(biāo)指導(dǎo)下的設(shè)計空間探索問題。如果你足夠厲害,你當(dāng)然可以采用“pencil & paper”的方法。但對于我們大部分設(shè)計者來說,人肉探索這個設(shè)計空間幾乎是不可能的。能不能充分利用工具幫忙,往往決定我們是不是能夠盡快得出一個比較好的設(shè)計。在第2點里,我們先把應(yīng)用在一個現(xiàn)有的處理器上跑一下,然后根據(jù)profiling結(jié)果做優(yōu)化設(shè)計,實際就是借助工具幫助我們分析問題。
如果你有足夠的資金,還可以借助一些商用的工具。比如,有的DSP IP支持一些擴展和定制的功能和工具,你可以在一個基礎(chǔ)設(shè)計上針對你的應(yīng)用設(shè)計你自己的專用處理器;還有專門設(shè)計ASIP(專用指令處理器)的工具,你甚至可以用一些高層次的語言來描述處理器,工具自動生成工具鏈和硬件設(shè)計(RTL代碼),并且評估設(shè)計的好壞,幫忙進行優(yōu)化。當(dāng)然,這些IP或者工具一般價格昂貴,也有一定的技術(shù)門檻。以后有機會在詳細介紹吧。
微結(jié)構(gòu)
下面我們來看看上述指令集的硬件實現(xiàn),微結(jié)構(gòu)(microarchitecture)。wiki對微結(jié)構(gòu)的定義如下:
“In electronics engineering and computer engineering, microarchitecture, also called computer organization and sometimes abbreviated as μarch or uarch, is the way a given instruction set architecture (ISA) is implemented in a particular processor. A given ISA may be implemented with different microarchitectures; implementations may vary due to different goals of a given design or due to shifts in technology.”
如果說指令集是一個處理器的功能規(guī)范,那么微結(jié)構(gòu)可以認(rèn)為是實現(xiàn)ISA的硬件架構(gòu)。對于不同的優(yōu)化目標(biāo),相同的一個ISA可能用不同的微結(jié)構(gòu)來實現(xiàn)。換句話說,微結(jié)構(gòu)是最終實現(xiàn)性能指標(biāo)要求的途徑。當(dāng)然,一個優(yōu)秀合理的ISA的在設(shè)計的時候肯定也考慮了微結(jié)構(gòu)實現(xiàn)的問題。在我們設(shè)計一個專用處理器的時候,ISA和微結(jié)構(gòu)的設(shè)計和優(yōu)化往往是一個交織進行的過程。先設(shè)計一個ISA,然后在做微結(jié)構(gòu)實現(xiàn)的過程中再修改ISA也是很常見的。
微結(jié)構(gòu)的設(shè)計和優(yōu)化又是一個巨大的話題,也涉及很多知識。我還是先通過FFT專用處理器的例子來說明一下基本概念。為了實現(xiàn)上一部分設(shè)計的ISA,我們可以設(shè)計這樣一個處理器微結(jié)構(gòu)。
如果讀者您一看就明白了這個圖的意思,請?zhí)^下面這段簡要說明,直接看微結(jié)構(gòu)優(yōu)化的討論。
首先,我們要執(zhí)行的關(guān)鍵指令是fft指令,這里假設(shè)fft指令就是做一次蝶形運算(buffterfly)。所以我們要有一個做蝶形運算的硬件單元(圖中的4)。而這個功能單元FU(Functional Unit)需要輸入和輸出數(shù)據(jù)。數(shù)據(jù)了來源可能是通用寄存器堆RF(Register File,圖中的3),也可能是memory或者流水線寄存器。同樣,數(shù)據(jù)的輸出也有很多可能。因此,需要一些MUX來進行選擇。簡單說,圖中的3和4就構(gòu)成了處理器中的數(shù)據(jù)通道(datapath),也就是處理數(shù)據(jù)的通路。另外,為了把數(shù)據(jù)從數(shù)據(jù)存儲器(data memory)中讀進來進行處理(load),或者將處理的結(jié)果再寫回到存儲器,還需要一個“l(fā)oad store單元”(圖中的5)。
但是,數(shù)據(jù)通道要正確運行,需要很多控制信息。比如,在寄存器堆中倒底哪個存放的是輸入數(shù)據(jù);哪個應(yīng)該存放運算結(jié)果?FU的數(shù)據(jù)來源倒底來自RF還是memory;結(jié)果要寫回哪里?等等。而這些信息實際上就包含在程序指令里。我們假想?yún)R編程序,每行指令都包含對datapath的控制信息。因此,在一個處理器里還需要有一條控制通路(control path),根據(jù)程序指令實現(xiàn)對datapath的設(shè)置和控制。
我們先要把指令從程序存儲器(PM:program memory)讀進來。這需要一個取指令的功能模塊(fetch);取指模塊的功能是向PM發(fā)出地址,執(zhí)行“讀”操作。這個地址是根據(jù)一個特殊的寄存器:程序計數(shù)器(PC:program counter)產(chǎn)生的。PC也可以看作是指向程序存儲空間的一個指針,它實際控制著程序執(zhí)行的流程。如果程序按正常順序執(zhí)行,則PC = PC + 1。如果需要改變程序流,比如跳轉(zhuǎn),則需要改變PC的值,指向要跳轉(zhuǎn)的新地址,PC = PC + offset。這樣取指模塊讀出的就是跳轉(zhuǎn)目標(biāo)位置的指令。
上篇文章已經(jīng)介紹了,指令經(jīng)過編碼以后形成一個二進制的機器碼。取指模塊讀進來的正是這個機器碼。要確定這條指令要執(zhí)行的具體操作,就需要進行譯碼(decode)。比如,在咱們的例子中,根據(jù)機器碼的頭兩個bit就可以判斷倒底是那一條指令。
分辨出具體是什么指令,就可以執(zhí)行該指令的操作了。通常這個過程稱為指令發(fā)射(issue)或者執(zhí)行(execution)。其結(jié)果包括,對數(shù)據(jù)通路的控制,比如“fft”指令;對PC的修改,比如指令“l(fā)oop”和對訪的控制“l(fā)oad和store”指令,等等。
到此為止,我們已經(jīng)有了一個workable的硬件架構(gòu)了,在這個硬件上可以運行前面說的匯編程序并且輸出結(jié)果。但實際上,這是一個“極簡”微結(jié)構(gòu),忽略了很多重要內(nèi)容。為了后面討論的方便,下面介紹幾個和微結(jié)構(gòu)相關(guān)的名詞。
指令周期(Instruction cycle):
一條指令一般會經(jīng)歷“取指”,“譯碼”,“發(fā)射/執(zhí)行”和“寫回”這些操作。處理器執(zhí)行程序的過程就是不斷重復(fù)這幾個操作。
指令流水線(Instruction pipeline):
當(dāng)一條指令,完成了“取指”操作,開始進行“譯碼”的時候,取指模塊就可以取下一條指令了,這樣可以讓這些模塊不至于閑著沒用。wiki對指令流水線的示例如下(IF:取指;ID:指令譯碼;EX:執(zhí)行;MEM:訪存;WB:寫回):
指令并行(Instruction-level parallelism):
同時執(zhí)行多條指令。比如,一邊從memory讀數(shù)據(jù),一邊進行fft處理。我們經(jīng)常聽到的超標(biāo)量(Superscalar),超長指令字(VLIW),亂序執(zhí)行( Out-of-order execution)等等技術(shù)都是發(fā)掘指令級并行的技術(shù)。
數(shù)據(jù)并行(Data parallelism):
同時處理多個數(shù)據(jù)。我們常聽到的向量處理器(vector procesor),張量處理器(Tensor processor)多數(shù)都是利用了SIMD(一條指令可以處理多個數(shù)據(jù),比如一個向量乘法)技術(shù)。
存儲層次(memory hierarchy):
處理器相關(guān)的存儲實際是由多種類型的存儲器組成。一般訪問速度越快(離datapath的“距離”越近),成本越高;相應(yīng)的容量也越小。按從快到慢的順序,包括芯片內(nèi)的存儲器:寄存器(Register),TCM(Tightly Coupled Memory),L1 cache,L2 cache和芯片外的存儲器,DDR,硬盤等等。
實際上,對處理器微結(jié)構(gòu)的研究到今天為止已經(jīng)非常非常成熟,想有很大的創(chuàng)新幾乎不太可能了。做一個專用處理器無非是怎么針對應(yīng)用的特點,利用好這些經(jīng)驗的問題。當(dāng)然,這也是一種創(chuàng)新。下面談一些做專用處理器的個人感受吧。
1. 通用處理器的背景知識
既然專用處理器只是一種特殊的處理器,那么處理器的一般性知識還是非常重要的。如果你對處理器設(shè)計的常用技術(shù)和技巧都非常熟悉,那么你設(shè)計專用處理器肯定也是游刃有余。比如指令級并行和數(shù)據(jù)并行是微結(jié)構(gòu)設(shè)計的兩個重要方向,你是否能準(zhǔn)確的了解每一種并行技術(shù)的優(yōu)勢,劣勢和代價呢?最好你能夠在腦子里就有一個對比的表格,隨時可以拿出來和目標(biāo)應(yīng)用放在一起做評估。另外,還是要跟蹤這個領(lǐng)域的最新進展,也許能給你帶來很大的啟發(fā)。
2. 突破通用處理器的思維
雖然做專用處理器要以處理器的一般知識為基礎(chǔ)。但也要敢于做出突破。實際上,我們看到的處理器設(shè)計經(jīng)典知識往往針對通用處理器。畢竟它的應(yīng)用范圍廣,討論的也比較多。而面向某個領(lǐng)域的專用處理器通常都是by design的優(yōu)化,可能就只有你自己或者很少的人做,討論的也比較少。這種時候就要相信自己對應(yīng)用的理解,敢于做出一些“奇怪”的設(shè)計。當(dāng)然,前提是我們有嚴(yán)謹(jǐn)?shù)亩糠治鲎鲋?。這一點我會在后續(xù)介紹方法學(xué)和工具鏈的文章里進一步說明。
3. 發(fā)掘歷史的寶藏
從最近兩年AI硬件熱潮中我們發(fā)現(xiàn),很多在歷史上曇花一現(xiàn)的架構(gòu)重新獲得了成功,或者至少獲得了新的關(guān)注,Google TPU中使用的脈動陣列架構(gòu)就是最好的例子。在歷史上有過體系結(jié)構(gòu)百花齊放的年代,當(dāng)時很多有趣的設(shè)計只是由于生不逢時而被遺忘了。對于專用處理器來說,重點是高效解決特定問題,因此歷史上很多當(dāng)時看起來”非主流“的設(shè)計可能反而是最合適的。所以我們不妨經(jīng)常做做“考古”工作,能發(fā)現(xiàn)金礦也說不定。
設(shè)計方法和工具
前面我們分別討論了專用處理器的指令集和微結(jié)構(gòu)的問題。其實,在指令集和微結(jié)構(gòu)方面,專用處理器用的技術(shù)基本上都是在通用處理器發(fā)展過程中探索過的東西。要說專用處理器設(shè)計最為特殊的地方,我個人認(rèn)為應(yīng)該是設(shè)計方法(方法學(xué))和工具。專用處理器設(shè)計成功與否完全由目標(biāo)應(yīng)用來檢驗,而應(yīng)用的多樣性也決定了專用處理器的多樣性。這種多樣性不僅反映在軟硬件設(shè)計本身,也反映在設(shè)計方法和工具上。
上面這副圖展示的domain-specific computing的概念既包括了專用處理器(圖中的ASP,Application Specific Processor)設(shè)計和也包括了相應(yīng)的工具開發(fā)。下面我們就結(jié)合這副圖,把DNN作為一個domain,討論一下專用處理器的設(shè)計方法和各種工具。
Domain Modeling
首先是對特定領(lǐng)域(domain,比我們說的目標(biāo)應(yīng)用的概念要更廣泛一下)進行建模,把需求模型化和量化,作為后續(xù)工作的評價標(biāo)準(zhǔn)。建模可能會使用特殊的語言擴展或者數(shù)據(jù)流圖的形式,比如在DNN領(lǐng)域經(jīng)常使用的Tensorflow就是典型的例子。
Domain Model是后續(xù)開發(fā)的基礎(chǔ),據(jù)此可以得到兩個重要的中間描述:一個是用于硬件架構(gòu)設(shè)計的Domain Characteristics;另一個是用于生成C/C++應(yīng)用代碼(當(dāng)然也可能是其它語言)的Application Model。這里的具體名稱并不太重要,重要的是一個domain model需要經(jīng)過處理,分離出指導(dǎo)硬件設(shè)計和生成應(yīng)用軟件代碼的兩部分信息。
HW Architecture design和Architecture Model
硬件架構(gòu)設(shè)計的主要工作是設(shè)計專用的計算引擎(Customized Computing Engine)和互連機制(Customized Interconnection)。比如在CNN加速器中比較常見的由PE(Processing Engine)組成的2D mesh網(wǎng)絡(luò),PE就是專用的計算引擎,2D網(wǎng)絡(luò)就是適應(yīng)CNN 2D卷積特征的互連機制。
硬件架構(gòu)設(shè)計還要輸出一個架構(gòu)模型。而這個硬件架構(gòu)模型也是整個設(shè)計方法中重要的一環(huán)。一方面,這個架構(gòu)模型可以生成虛擬原型系統(tǒng)(Virtual Prototyping);另一方面,它也是程序代碼映射工具(Source-to-source mapper)的輸入,而代碼映射功能用于將一些特殊的模型轉(zhuǎn)換為C/C++這類傳統(tǒng)的編程語言(這類語言有很好的工具進行處理),同時輸出Analysis Annotations,用于指導(dǎo)硬件設(shè)計和軟件工具鏈的前端設(shè)計。
虛擬原型(Virtual Prototyping)
我們通常說的Prototyping一般指基于FPGA或者測試芯片(testchip)系統(tǒng)原型,即用于驗證硬件設(shè)計,又可以debug固件,操作系統(tǒng)和應(yīng)用程序。但是開發(fā)硬件原型系統(tǒng)本身也是一項費時的工作,并且要等等所有硬件設(shè)計完成了才能實現(xiàn)。虛擬原型則是個純軟件的仿真器。最常見的方式是使用SystemC這樣語言(抽象層次更高)來對硬件進行建模,而不是直接使用RTL級的硬件模型。建模的抽象層次提高雖然會損失一些細節(jié),但好處是開發(fā)便捷(C++編程),仿真速度快。和硬件的原型系統(tǒng)相比,虛擬原型可以在項目開始階段就開發(fā)完成,提供給軟件開發(fā)人員,而不需要等到硬件準(zhǔn)備好。最后,虛擬原型是純軟件仿真,很容易debug,也很容易部署。虛擬原型是個有趣的話題,以后有機會可以專門講一下。
計算引擎硬件實現(xiàn)
這里把計算引擎分為三種:專用處理器(ASP),硬件加速器(HW Accelerators)和可編程陣列(Programing fabric)。前兩種我們都介紹過,第三種的硬件結(jié)果類似于FPGA,差別是這里的邏輯電路陣列也是根據(jù)應(yīng)用定制的。實現(xiàn)這三類計算引擎可以靠工程師完成,也可以借助專門的工具,比如,High-level Synthesizer(高層次綜合工具,也有叫行為級綜合的)可以把C,systemC甚至Matlab代碼(當(dāng)然有一定的約束)自動綜合成硬件設(shè)計(RTL代碼)。也有一些工具可以根據(jù)特殊的處理器描述語言,如Synopsys的LISA,NML和RISC-V處理器用的Bluespec等,自動生成RTL代碼。
這里插一句,自動生成RTL代碼看起來高大上,實際也沒那么難。記得10年前在SiliconHive(也是一個做專用處理器和工具的公司,后來被Intel收購了)實習(xí)做NoC的時候,RTL代碼就是從XML描述里自動生成的。其實就是大家平時形成的好習(xí)慣:RTL代碼盡量用腳本生成,積累起來也就成了自己的自動化工具。
這之后的工作主要就是將計算引擎和互連機制集成在一起,并且實現(xiàn)硬件的原型系統(tǒng)。互連機制的設(shè)計也有很多內(nèi)容,這里就暫不深入了。
軟件開發(fā)工具鏈
圖的右半部分就是軟件開發(fā)的工具鏈,這個和我們傳統(tǒng)上說的工具鏈基本是類似的,即從C/C++的源代碼,經(jīng)過一系列的工具,生成運行在最終硬件上的機器代碼(可以有很多形式)。工具鏈主要包括,前端(front end)后端(back end)和runtime。這里和通用CPU的工具鏈的主要差別在于back end和runtime,因為這兩部分和硬件架構(gòu)(指令集和微結(jié)構(gòu))關(guān)系密切。對應(yīng)專用處理器的硬件,主要體現(xiàn)在customized和adaptive這種特征。不過這里還有一些輔助性的工具,比較典型的比如debuger,就不細說了。
小結(jié)一下:
1.專用處理器雖然特殊,但設(shè)計方法和工具是有普遍性的,這也是研究方法學(xué)的價值所在。2. 設(shè)計方法往大說是方法學(xué),但在實際的工程中體現(xiàn)為任務(wù),流程和工具,設(shè)計專用處理器的過程也是優(yōu)化方法學(xué)的過程。3. 專用處理器設(shè)計面向應(yīng)用,往往有比較高的Time to Market要求,因此從架構(gòu)探索到RTL生成到原型驗證,都要盡量利用自動化工具提高設(shè)計的效率,自己設(shè)計小工具并且不斷積累是很好的實踐;4. 采用專用處理器的系統(tǒng)往往是軟硬件緊密協(xié)同的系統(tǒng),設(shè)計方法上最重要的理念是軟硬件的聯(lián)合優(yōu)化:在設(shè)計硬件的時候充分利用對應(yīng)用軟件的分析;而在設(shè)計軟件工具鏈的時候也要充分結(jié)合硬件架構(gòu)的特點;Architecture Model和Analysis Annotations就是軟硬件設(shè)計和工具間的橋梁。
“自己動手”設(shè)計專用處理器
最后實戰(zhàn)一下專用處理器的設(shè)計項目吧。我們先從結(jié)果說起,也就是這項任務(wù)的最終交付物。這里不妨參考ARM處理器核的deliverables。當(dāng)然,如果只是一個自己用的專用處理器,不一定要有這么完整的交付物。
硬件 :主要是處理器相關(guān)的RTL代碼,驗證環(huán)境,EDA工具的腳本,文檔等等。
工具軟件 :主要包括編譯工具(compiler),調(diào)試工具(debugger),仿真工具(simulator)和性能分析工具(profiler)。下圖是ARM的編譯工具的例子,主要包括armclang(C編譯器),armasm(匯編器),armlink(鏈接器)和fromelf(image工具)。
source: arm.com
仿真工具一般至少包括一個指令仿真器 instruction set simulator (ISS)。
模型 :此外,現(xiàn)在一般的處理器IP還會提供一些處理器的模型來支持系統(tǒng)級設(shè)計,比如用于前面介紹的虛擬原型的處理器模型(類似于ARM的Fast Model)。專用的處理器模型是虛擬平臺的重要組成部分,和總線模型以及其它IP模型一起模擬系統(tǒng)的功能。
看到這一大堆工作,如果你沒有膽怯,而是覺得很有意思。那么我也很愿意給你點幫助,看看是不是可以把你的想法變成現(xiàn)實。其實方法也很簡單 -- 自己做不了就“找別人幫忙唄”。具體來說,根據(jù)你的預(yù)算情況,可以分為“ 窮 ”和“ 富 ”兩種玩法。
我先說說有錢的玩法吧。其實,不止你一個人想做專用處理器,很多大公司也有這樣的需求。所以,就有人為這種需求專門提供了解決方案,比如Synopsys的ASIP-designer工具就是為了滿足定制處理器的需求而設(shè)計的。ASIP designer支持從零開始設(shè)計和實現(xiàn)一個專用處理器。你可以非常自由的設(shè)計指令集和微結(jié)構(gòu),覆蓋從Extensible processor,到Application-specific uP/DSP,到Programmable datapath這樣一個更大的架構(gòu)空間,如下圖所示。這里也可以看出,這個工具的目標(biāo)并不是設(shè)計通用處理器。
source:synopsys.com
下圖是該工具完整的方法學(xué)。
source: synopsys.com
它的輸入就是兩個,算法(C/C++代碼)和處理器模型(Processor Model),輸出則是一個處理器相關(guān)的所有設(shè)計和工具鏈。從輸入到輸出的過程同樣是自動化完成的。當(dāng)然,這個過程并不像看起來那么簡單,處理器建模的門檻不低。而且,工具賦予你的靈活性越高,掌握這種工具的門檻也越高。ASIP designer的處理器建模需要使用一種專門的語言,即nML,對處理器的指令集和架構(gòu)進行高層次建模;此外還需要很多和編譯器相關(guān)的設(shè)計。所以,即使你能買得起,要玩好這套工具,還得具備兩個條件:第一,是你必須熟悉處理器架構(gòu)和編譯方面知識;第二,是要學(xué)習(xí)這套建模語言和工具。
總的來說,如果你有專用處理器設(shè)計的需求,足夠的資金和學(xué)習(xí)的耐心,可以考慮引入這類輔助設(shè)計工具。在經(jīng)歷過一定的學(xué)習(xí)周期后,你不僅可以完成一個設(shè)計,還能獲得快速、高效設(shè)計處理器的能力。
下面再看看“ 窮玩法 ”。如果你沒有足夠的資金來購買上述工具,或者是你的目標(biāo)收益還不值得做出這樣的投資。這種情況下,我建議你從開源免費的處理器(或者指令集)開始做你自己的專用處理器。其實這也算是廢話吧。
假設(shè)你想在RSIC-V的基礎(chǔ)上做定制處理器吧。RSIC-V是現(xiàn)在一個相對成熟的開源處理器指令集,也有開源的處理器實現(xiàn)和非?;钴S的社區(qū)。相信大家都聽說過,就不科普了。這里得說明一下,我并沒有對RISC-V進行過深入的研究和嘗試,以下的說法基本上是紙上談兵,不對的地方請大家批評指正。
首先,你要好好學(xué)習(xí)一下RISC-V指令集手冊中的“Chapter 10 Extending RISC-V”,這里明確介紹了給RISC-V指令集擴展指令的規(guī)則。包括標(biāo)準(zhǔn)的擴展和非標(biāo)準(zhǔn)擴展兩個方面。
第二,在現(xiàn)有的RISC-V的硬件實現(xiàn)基礎(chǔ)上,增加新指令對應(yīng)的硬件??赡苄枰黾訉S玫募拇嫫鳎\算單元,pipeline寄存器,控制信號等等?;蛘撸憧梢园凑招碌闹噶罴僭O(shè)叫“RISC-V++ ISA”)自己做完整的硬件實現(xiàn)。其實我覺得第二種方法還更靠譜一點。很多時候,修改別人的東西,要比自己做困難的多。
第三,在RISC-V原有的工具鏈(比如GNU或者LLVM的編譯器)基礎(chǔ)上做出修改,支持新的指令。相對來說,這項工作是有比較完善的規(guī)則的,只要按照編譯工具的規(guī)則就可以把新增的指令加進去。當(dāng)然,如果你增加的指令比較特殊,比如是向量操作,那么工具鏈的設(shè)計會困難很多。這種情況下的一個選擇是在高級程序語言的編譯器中不增加對新指令的支持,這些新的指令以匯編或者intrinsic的方法實現(xiàn)。
最后,這套方法是不是也能支持在前面提到的快速design space exploration呢?基本的思路也是差不多的。你可以先用基本指令集來仿真你的算法;根據(jù)profiling的結(jié)果(比如性能指標(biāo),指令效率,code size等)考慮對指令集進行的修改;然后更新相應(yīng)的微架構(gòu)設(shè)計,硬件實現(xiàn)和工具鏈,再編譯和測試你的算法,并不斷迭代。如果這個過程沒有自動化工具的幫忙,可能需要比較長的時間才能完成,特別是需要對功耗面積進行詳細優(yōu)化的情況。
這種方法看起來行的通,不過中間的坑可能非常多,要求你對基礎(chǔ)處理器(比如RISC-V)非常熟悉。適合那些已經(jīng)完整的做過RISC-V實現(xiàn)的玩家嘗試。否則,也許有的坑你根本過不去。
設(shè)計專用處理器常見的”坑“
做專用處理器是個復(fù)雜工程,坑很多,以下僅舉幾例。
我們并不真的了解目標(biāo)應(yīng)用
在我們做一個面向特定應(yīng)用的專用處理器的時候,也許沒有想象中那么了解這個應(yīng)用。我傾向于用這樣問題來判斷:“1.你是否已經(jīng)有了全部目標(biāo)應(yīng)用或者算法的軟件(程序)?2. 你是否有定量的約束條件?”。如果有,那么你就可以保證對你的設(shè)計進行客觀和定量的評價(驗證)。如果在對設(shè)計進行評估的時候,能夠覆蓋目標(biāo)應(yīng)用的軟件程序還不到80%,或者具體的約束條件還不明確,那么就有很大風(fēng)險。一種可能是,你為不確定性做出一些over design;另一種可能是你的優(yōu)化目標(biāo)和實際情況并不相符。不管是那一種情況,實際上都沒有能夠很好的發(fā)揮專用處理器的優(yōu)勢。
不知道什么不應(yīng)該做
如果我們不具備自己做專用處理器的能力,往往覺得它很神秘,會夸大設(shè)計的難度和風(fēng)險。而當(dāng)我們具備了這種能力,一個可能的傾向是夸大專用處理器的優(yōu)勢,什么地方都想用專用處理器來搞定。實際上,掌握了設(shè)計專用處理器的能力,相當(dāng)于一個團隊有了一件強有力的武器。至于是否使用和怎樣使用則是一種更強的能力。一個好的SoC架構(gòu),往往是各種類型的處理器和硬件加速器配合工作的。能夠得到這樣的架構(gòu),或者是通過了多次迭代和優(yōu)化,或者是以定量分析和仿真為基礎(chǔ)(再次強調(diào)這一點)。
忽視工具鏈的開發(fā)
設(shè)計一個專用處理器,要經(jīng)歷需求分析,架構(gòu)設(shè)計,硬件實現(xiàn)和工具鏈開發(fā)等多項工作。一個比較常見的問題是忽視工具鏈的開發(fā)。但正如我在對方法和工具的討論中指出的,工具鏈(包括處理器開發(fā)工具和應(yīng)用開發(fā)工具)對于專用處理器開發(fā)和使用是至關(guān)重要的。即使你的架構(gòu)設(shè)計和硬件實現(xiàn)做的再好,如果沒有一個完善的工具鏈,這些硬件就沒法發(fā)揮最大的效能。從另一個角度來說,如果沒有好的開發(fā)工具,架構(gòu)設(shè)計和硬件實現(xiàn)也很難做好。個人認(rèn)為,比較好的實踐是在項目開始的時候就能夠?qū)ぞ哝溤O(shè)計做出規(guī)劃并配置專職的人員。
評論