當(dāng)前位置:首頁 > 模擬 > 模擬
[導(dǎo)讀]現(xiàn)代處理器為了更好的支持高級編程語言的高效編譯,通常處理器所擁有的通用寄存器的數(shù)目都有16個(gè)甚至32個(gè)之多,如此多的寄存器在比較復(fù)雜的應(yīng)用程序上實(shí)現(xiàn)深度嵌套調(diào)用的時(shí)候,為了保證程序的正確執(zhí)行,寄存器要頻繁

現(xiàn)代處理器為了更好的支持高級編程語言的高效編譯,通常處理器所擁有的通用寄存器的數(shù)目都有16個(gè)甚至32個(gè)之多,如此多的寄存器在比較復(fù)雜的應(yīng)用程序上實(shí)現(xiàn)深度嵌套調(diào)用的時(shí)候,為了保證程序的正確執(zhí)行,寄存器要頻繁的進(jìn)行入棧和出棧操作,這樣頻繁的堆棧存儲(chǔ)器訪問將明顯降低應(yīng)用程序的性能,為有效解決這一問題,tensilica的Xtensa架構(gòu)設(shè)計(jì)了一種Windows旋轉(zhuǎn)方式的寄存器管理機(jī)制,將邏輯寄存器和物理寄存器分開,在函數(shù)調(diào)用的時(shí)候通過windows滑動(dòng)切換邏輯寄存器,從而避免寄存器覆蓋,減少壓棧和出棧的操作,更大限度的提高性能。

  以一個(gè)MP3解碼器為例(如表1),假設(shè)外部存儲(chǔ)器的訪問的R/W等待cycles分別為100和20,可以看到采用Call8的windows旋轉(zhuǎn)大幅減少M(fèi)CPS到9%之多。

表1:MP3解碼器。

  那么Windows寄存器機(jī)制是如何工作的,它又有那些典型應(yīng)用呢? 本文將詳細(xì)闡述這一主題。

  寄存器Windows函數(shù)調(diào)用機(jī)制原理

  1.AR物理寄存器環(huán)形Buffer

  該方法的基本實(shí)現(xiàn)原理是用更多的物理AR寄存器組成一個(gè)環(huán)形的buffer,這些物理寄存器每4個(gè)為一組(pane),用一個(gè)WindowStart的每個(gè)比特依次表示是否該組作為邏輯寄存器窗口的起始位置或者占用,當(dāng)前的邏輯寄存器的起始位置則用WindowBase狀態(tài)寄存器來表示。如圖1,在發(fā)生函數(shù)調(diào)用的時(shí)候則通過修改WindowBase寄存器,滑動(dòng)邏輯寄存器窗口,設(shè)置相應(yīng)的WindowStart比特標(biāo)識當(dāng)前邏輯窗口在環(huán)形物理AR寄存器buffer中的位置。這樣父子函數(shù)看到的是不同的物理寄存器,避免了寄存器的壓棧和出棧。要說明的是,如果AR物理寄存器的數(shù)目為NAREG,則WindowStart的比特?cái)?shù)則為NAREG/4,而WindowBase的比特位數(shù)則為log(NAREG/4),如圖1所示,物理寄存器數(shù)為32,則WindowStart比特?cái)?shù)為8,WindowBase比特?cái)?shù)則為3.

圖1:Windows AR寄存器環(huán)形buffer.

  2.Windows ABI函數(shù)調(diào)用規(guī)范

  以每4個(gè)寄存器(pane)為單位,函數(shù)調(diào)用的時(shí)候窗口可以滑動(dòng)4個(gè)、8個(gè)、或者12個(gè)物理寄存器,分別可以用call4、call8、call12指令來實(shí)現(xiàn),而最典型的應(yīng)用則為call8,在c語言層面,編譯器通過XPG的core配置,可以為函數(shù)調(diào)用分別產(chǎn)生非windows機(jī)制的call0和call8,那么call8的Windows ABI函數(shù)調(diào)用規(guī)范是怎樣的呢? 參考圖2,左上角說明的是子函數(shù)調(diào)用約用規(guī)范,a0被用來保存返回地址,a1則為sp堆棧指針,a2~a7則用來傳遞函數(shù)入?yún)?,參?shù)超過6個(gè)的時(shí)候則需要使用堆棧了,以對調(diào)用者函數(shù)和被調(diào)用函數(shù)來說,a0~a7為獨(dú)立的寄存器,可以自由使用,而a8~a15則為scratch寄存器,隨時(shí)會(huì)被子函數(shù)使用,調(diào)用者函數(shù)如果要使用,則在調(diào)用子函數(shù)前要壓棧保存。

圖2:Window ABI調(diào)用規(guī)范。

  為方便寄存器正常的保存與恢復(fù),以及調(diào)用棧的高效回溯,有必要對函數(shù)的Frame??臻g做統(tǒng)一的安排,在call8的Windows ABI規(guī)范下,Tensilica進(jìn)行了如下設(shè)計(jì)(如圖3)。

圖3:Windows ABI堆棧布局。

  每級函數(shù)FrAME下包含有Base Area用于存儲(chǔ)其父函數(shù)的基本寄存器a0~a3,可能的extra area保存其子函數(shù)的擴(kuò)展寄存器a4~a7(call8),或者a4~a11(call12),函數(shù)局部變量(非寄存器變量)和alloc分配空間,及用于傳子函數(shù)所需要的??臻g等等。

  當(dāng)較新的深度函數(shù)Fun(i)的寄存器窗口覆蓋到過去的函數(shù)Fun(p)時(shí),基本寄存器a0~a3保存到Fun(p+1)的basic area,額外的寄存器則存入Fun(p)的extra area,當(dāng)函數(shù)Fun(p+1)返回時(shí),如果檢測到underflow則相應(yīng)地將base area和extra area的寄存器恢復(fù)到Fun(p)的活動(dòng)窗口,讀者可以參考Tensilica的代碼體會(huì)一下,這樣的布局在壓棧和恢復(fù)的時(shí)候代碼是最高效和節(jié)省空間的。

3.Windows寄存器覆蓋問題

  物理AR寄存器的數(shù)目是有限的,典型情況下,32個(gè)物理寄存器發(fā)生深度為3次,64個(gè)AR發(fā)生7次的函數(shù)調(diào)用后將會(huì)覆蓋到原來的函數(shù)寄存器窗,那么如何有效檢測和處理寄存器overflow問題呢?

  寄存器的覆蓋檢測只發(fā)生在如下兩種情況:

  函數(shù)調(diào)用時(shí),參考如下硬件semanTIcs:

  CALLn/CALLXn

  PS.CALLINC ← n32

  AR[n||2'b00] ← n || (PC + 3)290

  ENTRY s,imm12

  WindowCheck (00,PS.CALLINC,00)

  if as > 3 | PS.WOE = 0 | PS.EXCM = 1 then

  -- undefined operatiON

  -- may raise illegal instruction exception

  else

  AR[PS.CALLINC||s10] ← AR[s]- (017||imm12||03)

  WindowBase ← WindowBase + (02||PS.CALLINC)

  WindowStartWindowBase ← 1

  endif

  在發(fā)生函數(shù)調(diào)用,執(zhí)行call指令的時(shí)候,窗遞增值(call4、call8、call12分別對應(yīng)1、2、3)存入PS處理器狀態(tài)寄存器的CALLINC域,在進(jìn)入函數(shù)的入口處ENTRY指令將首先進(jìn)行Window重疊檢測,條件滿足的時(shí)候?qū)⒂|發(fā)相應(yīng)的windows overflow異常,引導(dǎo)程序進(jìn)行覆蓋寄存器的入棧保護(hù)。

  正常模式下函數(shù)內(nèi)部指令的寄存器引用,如xxx ar,as,at,處理器在非異常模式下將進(jìn)行正常的window檢測,否則產(chǎn)生非法指令異常。

  4.Windows寄存器檢測方法

  寄存器覆蓋檢測通過如下硬件semantic實(shí)現(xiàn):

  WindowCheck

  n ← if (wr ≠ 2'b00 or ws ≠ 2'b00 or wt ≠ 2'b00) and WindowStartWindowBase+1 then 2'b01

  else if (wr1 or ws1 or wt1) and WindowStartWindowBase+2 then 2'b10

  else if (wr = 2'b11 or ws = 2'b11 or wt = 2'b11) and WindowStartWindowBase+3 then 2'b11

  else 2'b00

  if CWOE = 1 and n ≠ 2'b00 then

  PS.OWB ← WindowBase

  m ← WindowBase + (2'b00||n)

  PS.EXCM ← 1

  EPC[1] ← PC

  nextPC ← if WindowStartm+1 then WindowOverflow4

  else if WindowStartm+2 then WindowOverflow8

  else WindowOverflow12

  WindowBase ← m(注:和Overflow跳轉(zhuǎn)并行)

  endif

  通過深入解析如上原語,有如下注意要點(diǎn):任何地方引用a0~a3不會(huì)產(chǎn)生windows異常,因此在用戶的c或者匯編代碼里可以任意使用,為什么呢? 因?yàn)樵赼0~a3引用的任意環(huán)境里,當(dāng)前函數(shù)的邏輯窗里的物理寄存器,要么是無覆蓋安全到達(dá),要么是經(jīng)過了函數(shù)調(diào)用entry指令觸發(fā)windows overflow異常,在異常里,a0~a3的所在物理AR寄存器已經(jīng)安全地壓棧保存了。

  a15~a4之間的高位寄存器(比如a15)引用會(huì)觸發(fā)低位寄存器(如a4)的寄存器覆蓋檢測,哪怕沒有指令顯式的應(yīng)用低位寄存器,觸發(fā)的順序?qū)⑹窍冗M(jìn)行overflow4,overflow8,至overflow12,從而最有效和最安全地保存活動(dòng)寄存器。通過了解以上兩點(diǎn),讀者可以深入理解Tensilica提供的高效XTOS代碼,透徹體會(huì)相關(guān)代碼的精妙之處。

  5. Windows寄存器下溢(underflow)問題

  當(dāng)子函數(shù)返回時(shí),RETW或者RETW.N指令執(zhí)行,此時(shí)也僅此時(shí)處理器將進(jìn)行上溢檢查。如果當(dāng)Windowbase所在位置的前3個(gè)window pane(4 registers組)的WindowStart比特都為零,則意味著返回后的父函數(shù)發(fā)生過 WindowOverflow,父函數(shù)的窗口寄存器曾經(jīng)被壓入棧,要先行通過相應(yīng)的underflow彈出。

  如果不是全為零,則應(yīng)該不為零的點(diǎn)和正常window返回的點(diǎn)對應(yīng),要正常返回,如果不同,則說明發(fā)生了不正常的調(diào)用,a0被破壞掉,要產(chǎn)生非法指令錯(cuò)誤。關(guān)于這個(gè)方面的具體硬件原語,讀者可以參考Xtensa的ISA手冊,這里不再贅述。

Alloca異常問題

  C語言中函數(shù)中經(jīng)常會(huì)發(fā)生從堆棧中分配臨時(shí)空間的情況,在正常的不發(fā)生窗寄存器溢出的時(shí)候沒有任何問題。但是,如果該函數(shù)的下級函數(shù)的嵌套調(diào)用曾導(dǎo)致過寄存器溢出,由于該函數(shù)的堆棧Frame底部存有溢出的basic area的寄存器,如果簡單的偏移堆棧指針來分配臨時(shí)空間,則這些保存過basic寄存器會(huì)被完全破壞掉。為有效解決這一問題,Xtensa架構(gòu)引入一個(gè)特殊的Alloca異常來管理basic area寄存器的搬移和臨時(shí)空間的分配。

  當(dāng)函數(shù)內(nèi)部進(jìn)行局部stack的內(nèi)存分配時(shí),Xtensa編譯器會(huì)生成一個(gè)MOVSP at,as指令,異常的檢測通過這一指令來完成,該指令有如下原語:

  if WindowStartWindowBase-0011WindowBase-0001 = 03 then

  Exception (AllocaCause)

  elseAR[t] ← AR[s]

  endif

  類似于underflow,如果當(dāng)前寄存器窗口前3個(gè)register pane的占用狀態(tài)全為0(全部為自由使用狀態(tài)),則說明其上一級函數(shù)一定發(fā)生過窗口溢出,當(dāng)前函數(shù)棧下方一定保存有溢出的寄存器,簡單的修改SP指針不再安全,需要觸發(fā)Alloca異常來進(jìn)行正確處理。需要說明的是,發(fā)生alloc異常的時(shí)候,過去的寄存器窗口調(diào)用已經(jīng)循環(huán)一周,且發(fā)生溢出,溢出的充分必要條件必然是當(dāng)前寄存器窗口的前3個(gè)register pane占用狀態(tài)全為0(WindowStartWindowBase-0011WindowBase-0001 = 000),其次當(dāng)前函數(shù)不可能是調(diào)用樹的葉子節(jié)點(diǎn),當(dāng)前函數(shù)的前半部分曾經(jīng)進(jìn)入過,且過去進(jìn)入的路徑上發(fā)生過溢出,否則就沒有產(chǎn)生異常的必要。alloca異常是為解決sp覆蓋而引入的硬件機(jī)制。

  這里解釋了alloc異常產(chǎn)生的基本原理,那么,什么樣的代碼會(huì)產(chǎn)生MOVsp指令,從而可能觸發(fā)alloc異常呢? 有如下幾種情況:

  調(diào)用alloc函數(shù),如

  void foo(int array_size) {

  char * bar = alloca(array_size);

  …

  使用變長數(shù)組(GNU C 擴(kuò)展語言),如

  void foo(int array_size) {

  char bar[array_size];

  …

  使用嵌套函數(shù)定義(GNU C 擴(kuò)展語言),如

  void afunction(void) {

  …

  int anotherfunction(void) {

  }

  使用特別長的局部數(shù)組,如

  void foo(void) {

  int an_array[8192]; // 32,768 bytes

  int another_array[100]; // 400 bytes

  …

  精確的size限制是32,760,包含16~48字節(jié)的Frame開銷。

  當(dāng)然,這里列出的不是全部的可能情況,僅僅列出幾個(gè)常見用例,讀者不能認(rèn)為自己的代碼沒有以上情況,編譯器就不會(huì)產(chǎn)生movsp指令,從而不會(huì)產(chǎn)生alloc異常。

  由于alloc是一種不容易避免的正常的異常,應(yīng)用軟件需要積極的處理。處理的思路有兩種,其一是用異常或者中斷棧作為臨時(shí)儲(chǔ)存來搬移,這里要介紹另外一種比較巧妙的方法,如下述代碼:

  rsr a2,PS

  rsr a4,WINDOWBASE

  extui a3,a2,XCHAL_PS_OWB_SHIFT,XCHAL_PS_OWB_BITS

  xor a3,a3,a4

  slli a3,a3,XCHAL_PS_OWB_SHIFT

  xor a2,a2,a3

  wsr a2,PS

  l32i a4,a1,A4_SAVE

  l32i a3,a1,A3_SAVE

  l32i a2,a1,A2_SAVE

  addi a1,a1,USER_EXCEPTION_FRAME_SIZE

  rsync

  // Now branch on the call increment

  // We could branch earlier rotw instructions prior to the handler

  // which would avoid executing two rotw instructions in the underflow

  // eight case. However,the underflow 8 handler is right at a

  // cache-line,so that would likely involve an extra cache miss better

  // to just take the single cycle penalty here.

  rotw -1

  // what was a0 (that had the return address) is now a4

  _bbci.l a4,31,_WindowUnderflow4

  rotw -1

  // what was a0 (that had the return address) is now a8

  _bbci.l a8,30,_WindowUnderflow8

  j _setup_WindowUnderflow12

  這段代碼的巧妙之處在于首先通過將當(dāng)前的Windowbase保存到PS的OWB域中,然后通過反向旋轉(zhuǎn)窗,根據(jù)a0的高端2bit表示的調(diào)用類型,跳轉(zhuǎn)到相應(yīng)的下溢exception的位置進(jìn)行出?;謴?fù)save area的寄存器,當(dāng)sp指針正確偏移后,利用寄存器的引用觸發(fā)overflow異常自動(dòng)進(jìn)行再次入棧,從而實(shí)現(xiàn)搬移。

  Context Switch下的寄存器保存與恢復(fù)

  在windows窗口寄存器機(jī)制下,多任務(wù)RTOS的上下文環(huán)境切換問題變得非常有趣。 那么該如何保存這些通用寄存器呢,是不是所有的物理寄存器都要保存與恢復(fù)呢? 答案是否定的,除了當(dāng)前窗口的邏輯寄存器要保存外,只需要保存當(dāng)前任務(wù)進(jìn)程里的live寄存器(置1的寄存器pane),而恢復(fù)則只需要恢復(fù)邏輯寄存器。

  對于任務(wù)軟件來說,寄存器的實(shí)現(xiàn)機(jī)制是透明的,因此特別要說明的是WindowsStart和WindowsBase寄存器則完全不需要保存與恢復(fù)。參考如下進(jìn)程切換的環(huán)境保護(hù)核心代碼:

  .Lspill_loop:

  // Top of save loop.

  // Find the size of this call and branch to the appropriate save routine.

  beqz a2,.Ldone // if no start bit remaining,we're done

  bbsi.l a2,0,.Lspill4 // if next start bit is set,it's a call4

  bbsi.l a2,1,.Lspill8 // if 2nd next bit set,it's a call8

  bbsi.l a2,2,.Lspill12 // if 3rd next bit set,it's a call12

  j .Linvalid_window // else it's an invalid window!

  // SAVE A CALL4

  .Lspill4:

  addi a3,a9,-16 // a3 gets call[i+1]'s sp - 16

  s32i a4,a3,0 // store call[i]'s a0

  s32i a5,a3,4 // store call[i]'s a1

  s32i a6,a3,8 // store call[i]'s a2

  s32i a7,a3,12 // store call[i]'s a3

  srli a6,a2,1 // move and shift the start bits

  rotw 1 // rotate the window

  j .Lspill_loop

  // SAVE A CALL8

  .Lspill8:

  ……

  該代碼的基本思路是通過處理WindowStart寄存器,解析各live窗口的相對偏移,基于調(diào)用棧布局規(guī)范進(jìn)行入棧處理。 當(dāng)任務(wù)切換到其他的進(jìn)程后,這些live窗口可能會(huì)被破壞(相應(yīng)的WindowStart比特清零),這沒有關(guān)系, 當(dāng)進(jìn)程重新切換回來時(shí),如果這些live窗口已經(jīng)在切換過的進(jìn)程恢復(fù)(WindowStart比特置1),則切換回來后無需出棧,程序可正常繼續(xù)執(zhí)行,如果沒有恢復(fù)(相應(yīng)的WindowStart比特繼續(xù)為零),那么該進(jìn)程就可以根據(jù)這個(gè)清零的狀態(tài)位將原先入棧的live寄存器正確恢復(fù)。

  本文小結(jié)

  Xtensa處理器寄存器窗口旋轉(zhuǎn)函數(shù)調(diào)用是一種非常巧妙的實(shí)現(xiàn)機(jī)制,通過這一機(jī)制嵌入式軟件可明顯提高性能,并且其alloc異常,多任務(wù)上下文切換等等衍生和應(yīng)用問題也可高效而經(jīng)濟(jì)的解決,其和TIE(Tensilica Instruction Extension),其他諸多可配置選項(xiàng)等等正充分說明了Xtensa架構(gòu)經(jīng)久不衰,廣泛應(yīng)用,煥發(fā)持久生命力的原因所在。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉