- 片上系統設計思想與源代碼分析
- 陳曦 黃毅
- 225字
- 2018-12-27 17:52:43
第2章 開源嵌入式處理器
本章主要內容
嵌入式處理器種類繁多,但是使用最廣泛的是哈佛架構的RISC處理器。OpenRISC 1000是開放源代碼RISC處理器簇,OR1200是它的一個32位實現,指令集是CPU硬件與軟件的接口。在DemoSoC中,使用了OR1200作為處理器。官方給出的OR1200的性能在同頻率的ARM7和ARM9之間。據作者所知,OR1200是目前唯一一個可以免費商用的開源處理器。本章將講述OpenRISC 1000處理器簇的指令格式、處理器的結構組成,還將闡述OR1200處理器對OpenRISC 1000構架的具體實現、結構組成部分、硬件配置等。不打算更多地了解OR1200 CPU的讀者可以略過本章。
2.1 開源嵌入式處理器介紹
2.1.1 OpenRISC 1000構架的主要特點
OpenRISC 1000是開放源代碼的RISC處理器簇,提供各種價格/性能的應用。它是32/64bit位裝載(Load)和存儲(Store)RISC構架,強調執行效率、簡單、低功耗、可測量性和多樣性。目標是中高執行效率的網絡、嵌入便攜高計算機環境。
OpenRISC 1000執行特征包括全32/64bit構架、向量、DSP和浮點指令、虛擬內存支持、一致的高速緩存、SMP和SMT支持、支持快速上下文切換。它較突出的特征是有幾個指令擴展、提供可配置的通用寄存器、提供可配置的高速緩存和TLB尺寸、支持動態電源管理、有用戶提供指令的空間。
應用OpenRISC 1000構架的RISC的源代碼在http://www.opencores.org可用,并且被GNU軟件開發工具和行為仿真器支持。它們能與http://www.opencores.org上的其他開放源代碼的IP核進行接口。Opencores.org鼓勵第三方設計和在商業上使用OpenRISC 1000構架的RISC。
OpenRISC 1000構架的主要特征如下:
(1)完全自由和開放的構架。
(2)用特定的物理地址空間提供線性的、32bit或64bit邏輯地址空間。
(3)簡單的和長度一致的指令格式,不同的指令集擴展,包括如下指令集。
● 具有32bit寬度指令的OpenRISC基本指令集(ORBIS32/64 OpenRISC Basic Instruction)。它在內存的32bit邊界對齊,并且在32bit和64bit數據上進行操作。
● OpenRISC向量/DSP擴展(ORVDX64 OpenRISC Vector/DSP eXtension),它有32bit位寬指令,可操作8、16、32和64bit數據。
● OpenRISC浮點擴展(ORFPX32/64 OpenRISC Floating-Point eXtension),它有32bit位寬指令,操作32和64bit數據。
(4)兩種簡單內存地址模式,內存地址計算方法如下:
● 寄存器操作數加上一個有符號16bit立即數得到有效地址。
● 寄存器操作數和有符號16bit立即數相加,這個16位立即數被存有計算過的有效地址的寄存器操作數更新。
(5)大多數指令的兩個寄存器操作數(或一個寄存器和一個常量)執行結構放在第三個寄存器中。
(6)單個32條目或窄16條目通用寄存器文件。
(7)保持盡可能全流水線運行的分枝延遲槽。
(8)支持分開的指令和數據高速緩存/MMU(Harvard構架)或統一的指令和數據高速緩存/MMU(標準構架)。
(9)允許某一功能被執行的彈性構架定義。
(10)不同的、分開的例外簡化了例外模型。
(11)在寄存器集、高速緩存和MMU中支持快速上下文切換。
OpenRISC 1000命名規則是:第一個數字“1”表示是OpenRISC 1000構架序列,第二個數字“0”表示具體應用的構架。后兩位數字表示實際應用中的具體配置。
2.1.2 尋址模式
當執行一個內存訪問指令或分支指令或當支取隨后的一個指令時,處理需要計算一個有效地址。如果有效地址和操作數長度的和超過了邏輯地址空間的最大有效地址,內存操作數從最大有效地址循環回到有效地址0。OpenRISC 1000尋址模式有寄存器間接尋址和PC相對尋址。
1.寄存器間接尋址
Load/Store指令使用這種尋址模式將一個有符號的16bit立即數值加到指令指定的通用寄存器所存儲的值上,得到一個有效地址。如圖2-1所示為當使用寄存器間接尋址模式時,一個有效地址是如何計算得到的。

圖2-1 寄存器間接尋址
2.PC(程序計數)相對尋址
分支指令使用這種尋址模式,它存有一個有符號擴展的26bit立即數,并把它加到一個程序計數寄存器存儲的數據上,得到有效地址。在目的地PC執行之前,延遲槽里的指令被執行。如圖2-2所示為當使用PC相對尋址模式時,一個有效地址如何計算得到的。

圖2-2 PC相對尋址
2.1.3 bit位和byte字節次序
字節次序定義了組成半個字、單個字和雙字的字節流在內存中如何排序。為了簡化OpenRISC的使用,構架默認時使用了MSB(Most Significant Byte)字節次序或稱為大端字節序(Big Endian Byte)。但如果構架使用了字節重排序硬件,它也支持LSB(Least Significant Byte)字節次序或稱為小端字節序。重排序使用bit位SR[LEE]激活。
表2-1列出了雙字在大端字節序時字節及bit位在內存中的排序。單個字和半個字的字節及bit位排序使用類似的機制。
表2-1 雙字的字節及bit位次序

對齊和非對齊的訪問方式如下:
如果操作數的地址是操作數長度的整數倍,那么,內存中的操作數是地址對齊的。構架支持非對齊的訪問,但默認的行為是對非對齊操作數的訪問將導致一個對齊例外。OR32指定是4個字節和字對齊的。內存操作數對齊時地址低位的特征如表2-2所示。
表2-2 內存操作數對齊時地址低位的特征

2.1.4 寄存器集
OpenRISC 1000構架的處理器包括幾種類型寄存器,分別為用戶級通用寄存器和特殊寄存器、超級監管者級特殊寄存器和依賴于硬件單元的寄存器。寄存器的詳細說明可參閱《OpenRISC 1000 Architecture Manual》。
用戶級通用和特殊寄存器在用戶模式(user)和超級監管者模式(supervisor)下都可被訪問。超級監管者寄存器僅在超級監管者模式下操作(即SR[SM]=1)時才可被訪問。
依賴于硬件單元的寄存器通常僅在超級監管者模式下可被訪問,但有個別的除外。
1.特殊寄存器
所有單元的特殊寄存器被分成32組,每組中的寄存器使用不同的寄存器地址(編號)區分。一個組中可以放有幾個不同單元或處理器的寄存器。在寄存器地址解碼中,由于一些寄存器僅在超級監管者模式下可被訪問,因此,SR[SM]位也被使用。指令l.mtspr和l.mfspr被用來讀寫特殊寄存器。特殊寄存器的分組說明如表2-3所示。
表2-3 特殊寄存器(SPR Special Purpose Register)的分組

OpenRISC 1000構架處理器需要至少使用第0組特殊寄存器。其他的特殊寄存器是可選的,并且只有單元存在時,單元相應的特殊寄存器組才存在。
16bit的SPR地址由5bit組序號(15~11bit位)和11bit寄存器序號(10~0bit位)組成。表2-4列出了第0組特殊寄存器的說明。其中,帶有R*的SPR表示如果SR[SUMRA]被設置,用戶模式下對SPR的訪問是可讀的。
表2-4 第0組特殊寄存器說明

2.通用寄存器(GPR)
32個通用寄存器被標識為R0~R31,并且在32bit處理器中是32bit位寬,在64bit處理器是64bit位寬。它們存儲浮點數據、向量或內存指針。GPR可被ORBIS、ORVDX和ORFPX指令作為源和目的地寄存器進行訪問。
R0被用作常量0,R0是否實際上硬件連線到0依賴于構架的應用。R0永遠不應該被用做目的地寄存器。
一個構架的應用可能有幾套GPR組,并把它們用做映像(shadow)寄存器,無論何時,一個新的例外發生時,它們之間發生切換。當前使用的一套通過SR[CID]值被鑒別。CID為進程上下文的序號,值為0~15,即可能有16套通用寄存器組,共512個寄存器(32×16=512)。
構架的應用RISC在復位期間不需要初始化GPR到0,必要時復位例外處理句柄負責初始化GPR到0。
3.支持定制GPR數量
程序可能被編譯使用少于32個寄存器,編譯代碼時不用的寄存器被禁止(設置作為固定寄存器)。這些代碼在正常的構架應用RISC中也可執行。如果配置寄存器被使用,CPUCFGR[CGF]指出構架應用RISC是否有完全的32個通用寄存器或少于32個寄存器。
4.超級監管者寄存器
超級監管者寄存器(Supervision Register,SR)是32位特殊寄存器,僅能在超級監管模式下使用l.mtspr/l.mfspr指令訪問。SR值定義了處理器的狀態。
5.例外程序計數寄存器
例外程序計數寄存器(Exception Program Counter Registers)有EPCR0~EPCR15,它們是超級監管者級別的特殊寄存器,使用l.mtspr/l.mfspr指令在超級監管模式下訪問。如果PCMRx[SUMRA]被激活,用戶模式下是可讀的。在一個例外產生后,EPCR被設置到被例外中斷的指令的程序計數器(PC)地址。如果僅一個EPCR出現在構架應用RISC中,在例外識別再次在SR中被激活之前,它必須被例外處理例程存儲。
6.例外有效地址寄存器
例外有效地址寄存器(Exception Effective Address Registers)有EEAR0~EEAR15,它們是的特殊的超級監管者級別的寄存器,使用l.mtspr/l.mfspr指令在超級監管模式下訪問。如果SR[SUMRA]被激活,用戶模式下是可讀的。
在一個例外產生后,EEAR被設置到被例外指令產生的有效地址(EA effective address)。如果僅一個EEAR出現在構架應用RISC中,在例外識別再次在SR中被激活之前,它必須被例外處理例程存儲。
7.例外超級監管者寄存器
例外超級監管者寄存器(Exception Supervision Registers)有ESR0~ESR15,它們是的特殊的超級監管者級別的寄存器,使用l.mtspr/l.mfspr指令在超級監管模式下訪問。
在一個例外產生后,超級監管者寄存器(SR)被復制到ESR。如果僅一個ESR出現在構架應用RISC中,在例外識別再次在SR中被激活之前,它必須被例外處理例程存儲。
8.下一個和前一個程序計數寄存器
下一個和前一個程序計數寄存器(Next and Previous Program Counter)是NPC和PPC。它們代表剛執行完的指令地址或將被執行指令的地址。
這兩個寄存器和GPR寄存器僅被一個外部的調試器因調試目的而映射到SPR空間。應用程序應該使用l.jal指令獲得當前程序計數和使用算術指令獲得GPR寄存器的值。
9.浮點控制狀態寄存器
浮點控制狀態寄存器(FPCSR,Floating Point Control Status Register)是一個32位特殊寄存器,使用l.mtspr/l.mfspr指令在超級監管者模式下進行訪問,如果SR[SUMRA]被激活,用戶模式下是可讀的。
FPCSR控制浮點環形模式、可選地控制浮點例外的產生并提供浮點狀態標識。在每次浮點指令被完成,狀態標識被更新,并且能用來判斷引起浮點例外的原因。
如果浮點例外被激活,那么FPCSR狀態標識必須在浮點例外處理例程中被清除。狀態標識通過寫0到所有的狀態位來被清除。
2.1.5 指令集及指令格式
OpenRISC 1000指令集的主要特征是有簡單和統一長度的指令格式,5個指令子集(即ORBIS32、ORBIS64、ORFPX32、ORFPX64、ORVDX64)。OpenRISC基本指令集ORBIS32/64使用對齊的32bit位寬指令,操作32位和64位數據。OpenRISC向量/DSP擴展ORVDX64使用對齊的32bit位寬指令,操作8位、16位、32位和64位數據。OpenRISC浮點擴展ORFPX32/64使用對齊的32bit位寬指令,操作32位和64位數據。還有保留的操作代碼給定制指令。
每個子集的指令按照重要性還被分成兩個指令類Class I和Class II,分類說明如表2-5所示。
表2-5 OpenRISC 1000指令分類

指令被分成指令類,僅基本的指令類在OpenRISC 1000構架的RISC中是要求的。5個指令子集說明如下:
(1)ORBIS32包括32位整數指令、基本的DSP指令、32位的Load/Store指令、程序流指令和特殊指令;
(2)ORBIS64包括64位整數指令、64位Load/Store指令;
(3)ORFPX32包括單精度浮點指令;
(4)ORFPX64包括雙精度的浮點指令、64位Load/Store指令;
(5)ORVDX64包括向量指令、DSP指令。
指令按寄存器的使用分為R類型指令、I類型指令和J類型指令,分別說明如下:
1.R類型指令
R類型指令使用寄存器rA和寄存器rB作為源數據寄存器,rD作為目的寄存器,在ALU中rA與rB的數據經運算后放入rD。因此存在著寄存器堆與ALU模塊的A、B、D引腳的連接。
2.I類型指令
I類型指令包括運算指令、Load指令、Store指令、分支指令等的帶操作數的指令。
3.J類型指令
J類型指令指跳轉指令。在跳轉指令的處理過程中,需要把程序計數器PC加4后的高4位和指令字中的跳轉地址合并;然后,把合并的結果作為下一個PC的值,輸出到程序計數器PC中。
CPU的指令按用途可分為Load/Store指令、跳轉指令、ALU和特殊指令幾大類,絕大部分指令在31~26bit定義。
Load/Store指令從存儲器(如數據高速緩存)裝載數據到寄存器堆或從寄存器堆存儲數據到存儲器。
跳轉指令通過改變程序計數器來改變程序執行的順序,在跳轉指令之后緊跟著延遲槽,在延遲槽中的指令為延遲指令。延遲指令在程序流跳轉之前被執行。這種延遲轉移功能是為流水線而設計的。
ALU指令包括算術運算和邏輯運算指令。特殊指令指同步類指令、空操作指令等。
OpenRISC 1000指令尋址方式有寄存器尋址、立即數尋址、基址偏移量尋址、PC相對尋址、偽直接尋址。寄存器尋址是把操作數放在寄存器堆中;立即數尋址是指操作數為一個常數,包含在指令中;基址偏移量尋址指操作數放在寄存器中,存儲器地址由一個寄存器的內容加上指令中的常數得到;PC相對尋址是指轉移指令計算轉移地址,PC的相對值是指令中的一個常數;偽直接尋址指跳轉指令形成轉移地址,指令中的26位目標地址值與PC的高4位拼接而成,形成30位的寄存器“字地址”。
CPU的指令格式與硬件邏輯電路直接相關,簡單較少的格式對應簡單高效的邏輯電路。OpenRISC 1000指令集指令長度為32位,指令的格式只有簡單的幾種,常用指令使用31~26bit進行大類劃分,并將常用的寄存器操作指令類別定義為0x38。另外將比較設置標識指令放在31~21bit位。具體格式說明如下:
1.31~26bit為0x38的指令
31~26bit為0x38的指令都是寄存器之間整數邏輯運算指令,指令字符中含有“l”字符,下面以l.add為例說明這類指令的格式。
指令書寫格式為:l.add rD,rA,rB
指令運算方法如下:
rD[31:0] < - rA[31:0] + rB[31:0] SR[CY] < - carry SR[OV] < - overflow
指令的格式如表2-6所示。D、A、B表示的是通用寄存器編號地址。9~8bit將指令分成小類,每小類由3~0bit組成16條指令。
表2-6 l.add指令格式表

9~8bit將指令分成小類,每小類的指令分別說明如下:
0x38 0x0類指令是常見的加、減、邏輯運算(或、異或等)運算指令,如l.addc、l.and、l.cmov、l.exths、l.extws、l.ff1、l.or、l.sll、l.sub、l.xor等。
0x38 0x01類指令是字節擴展、查找第一次出現“1”的位數等指令,如l.extbs、l.extwz、l.fl1、l.srl等。
0x38 0x02類指令是右移算術指令l.sra。
0x38 0x3類指令主要是乘法與除法指令,如l.div、l.divu、l.extbz、l.mul、l.mulu、l.ror。
2.31~26bit為0x31的指令
31~26bit為0x31的指令有l.mac和l.msb,它們是乘法累加與乘法減,下面以l.mac為例說明指令格式。
指令書寫格式為:l.mac rA,rB
指令的運算方法如下:
temp[31:0] < - rA[31:0]*rB[31:0] MACHI[31:0]MACLO[31:0] < - temp[31:0] +MACHI[31:0]MACLO[31:0]
指令l.mac的運算是將rA×rB的結果裁剪到32bit,并加到特殊寄存器CHI[31:0]MACLO[31:0]上。所有的操作數當做符號整數看待。指令l.mac格式如表2-7所示。
表2-7 指令l.mac格式表

3.31~26bit為0x32的指令
31~26bit為0x32的指令是浮點運算指令,由7~0bit區分具體的命令。浮點運算指令包括加、減、乘、除、大小比較、浮點與整數的轉換等運算。浮點指令又分為單精度和雙精度指令。它們由CPU中的專門浮點運算單元來執行的。在OR1200中沒有浮點運算單元,因些不支持浮點指令。
浮點運算指令用格式“lf.*.d”或“lf.*.s”表示,其中,“lf”表示浮點運算,“d”表示雙精度,“s”表示單精度。下面以lf.add.d為例說明浮點運算指令的格式。
指令書寫格式為:lf.add.d rD,rA,rB
指令的運算方法如下:
rD[63:0] < - rA[63:0] + rB[63:0]
指令lf.add.d是浮點雙精度加法,它的格式如表2-8所示。
表2-8 指令lf.add.d格式表

浮點雙精度指令還有lf.div.d、lf.ftoi.d、lf.itof.d、lf.madd.d、lf.mul.d、lf.rem.d、lf.sfeq.d、lf.sfge.d、lf.sub.d。
浮點單精度指令還有lf.add.s、lf.div.s、lf.ftoi.s、lf.itof.s、lf.madd.s、lf.mul.s、lf.rem.s、lf.sfeq.s、lf.sfge.s、lf.sub.s。
4.31~26bit為0xa的指令
31~26bit為0xa的指令是向量運算指令,7~0bit區分具體的命令。向量運算指令是由向量運算單元完成,是64bit運算的指令。OR1200沒有向量運算單元。向量運算指令的書寫格式是“lv.*.b”或“lv.*.h”,其中,“lv”表示是向量運算指令,“b”表示是字節元素,“h”表示是半字元素。
下面以指令lv.add.b為例說明向量運算指令格式。指令lv.add.b是向量半字元素有符號的加法。
指令書寫格式為:lv.add.b rD,rA,rB
指令的運算方法如下:
rD[7:0] < - rA[7:0] + rB[7:0] rD[15:8] < - rA[15:8] + rB[15:8] rD[23:16] < - rA[23:16] + rB[23:16] rD[31:24] < - rA[31:24] + rB[31:24] rD[39:32] < - rA[39:32] + rB[39:32] rD[47:40] < - rA[47:40] + rB[47:40] rD[55:48] < - rA[55:48] + rB[55:48] rD[63:56] < - rA[63:56] + rB[63:56]
指令lv.add.b格式如表2-9所示。
表2-9 指令lv.add.b格式

5.31~26bit為0x2e的指令
31~26bit為0x2e的指令是帶直接操作數位移動指令,它用7~6bit位區別具體的指令,這4個帶直接操作數位移動指,即l.rori、l.slli、l.srai、l.srli具有同一格式,它們是右旋轉、左移位、右算術移位、右邏輯移位指令。
下面以指令l.rori說明指令的格式。
指令l.rori的作用如下:
6bit立即數指定bit位置序號,rA向右旋轉。結果放入rD。立即數5bit以上被忽略。
指令l.rori的書寫格式為:l.rori rD,rA,L
指令l.rori運算方法如下:
rD[31-L:0] < - rA[31:L] rD[31:32-L] < - rA[L-1:0]
指令l.rori的格式如表2-10所示。
表2-10 指令l.rori的格式

6.31~26bit位的寄存器跳轉指令
l.jalr和l.jr指令都是無條件跳轉指令,跳轉的地址放在rB寄存器中。區別在于l.jalr把延遲槽后的地址被放在鏈接寄存器中。下面l.jalr為例說明指令格式。
指令l.jalr的作用如下:
通用寄存器rB存有跳轉的有效地址,程序在一個指令延遲后無條件跳轉到EA。在延遲槽后的地址被放在鏈接寄存器中。不允許指定鏈接寄存器為rB。
指令書寫格式為:l.jalr rB
指令的運算方法如下:
PC <- rB LR <- DelayInsnAddr + 4
指令l.jalr的格式如表2-11所示。
表2-11 指令l.jalr的格式

7.其他的31~26bit位指令
其他的31~26bit位指令絕大多數是帶直接操作數的指令,由于直接操作數所占的位較多,因此,這些指令大多數因為直接操作數可能較大而沒有用位進行指令分類,而是直接由31~26bit位區分具體的指令。
具體說明如下:
(1)帶直接操作數運算、裝載指令
有同一格式帶直接操作數運算、裝載指令有l.addic、l.andi、l.lbs、l.lbz、l.ld、l.lhs、l.lhz、l.lws、l.lwz、l.mfspr、l.muli、l.ori和l.xori,這些指令的格式一樣,指令中“lb”表示裝載字節,“ld”表示裝載雙字,“lw”表示裝載字,“lh”表示裝載半字。結尾的“s”表示用符號進行位擴展,即32bit中用符號位填充高字節。結尾的“z”表示用“0”進行位擴展。
下面以指令l.addic為例說明指令模式。
指令書寫格式為:l.addi rD,rA,I
指令的運算方法如下:
rD[31:0] <- rA[31:0] + exts (Immediate) SR[CY] <- carry SR[OV] <- overflow
指令l.addic的格式如表2-12所示。
表2-12 指令l.addic的格式

(2)帶直接操作數乘法、存儲指令
有同一格式帶直接操作數乘法、存儲指令有l.maci、l.mtspr(移到通用寄存器的值到特殊寄存器)、l.sb(存儲字節)、l.sd(存儲雙字)、l.sh(存儲半字)、l.sw(存儲字)。
下面以指令l.maci為例說明指令格式。
指令l.maci的作用如下:
通用寄存器rA的值乘以立即數,結果被裁剪到32bit后,加到特殊寄存器MACHI和MACLO上,所有的操作數被當做有符號整數看待。
指令l.maci的書寫格式為:l.maci rA,I
指令l.maci的運算方法如下:
temp[31:0] < - rA[31:0] * exts(Immediate) MACHI[31:0]MACLO[31:0] < - temp[31:0] +MACHI[31:0]MACLO[31:0]
指令l.maci的格式如表2-13所示。
表2-13 指令l.maci的格式

(3)帶直接操作數的跳轉指令
帶直接操作數的跳轉指令有l.bnf、l.cust1(8條用戶定義指令)、l.j、l.jal、l.rfe(從例外中返回)。
下面以指令l.bnf為例說明指令格式。
指令l.bnf的作用如下:
立即值被左移2bit,符號擴展到程序計數器寬度,并接著加到分支指令的地址上,結果是分支的有效地址EA。如果flag被設置,程序分支到EA延遲一個指令周期。
指令l.bnf的書寫格式為:l.bf N
指令l.bnf的運算方法如下:
EA < - exts(Immediate < < 2)+ BranchInsnAddr PC < - EA if SR[F] set
指令l.bnf的格式如表2-14所示。
表2-14 指令l.bnf的格式

(4)31~26bit位為0x6指令
31~26bit位為0x6指令有l.movhi和l.macrc,下面分別對這兩條指令進行說明。
指令l.movhi說明如下:
指令l.movhi的作用如下:
16bit立即數被0擴展,左移16bit,并被放入通用寄存器rD。
指令l.movhi的書寫格式為:l.movhi rD,K
指令l.movhi的運算方法如下:
rD[31:0] < - extz(Immediate)< < 16
指令l.movhi的格式如表2-15所示。
表2-15 指令l.movhi的格式

指令l.macrc說明如下:
指令l.macrc的作用如下:
一旦在MAC流水線中所有指令被完成,MAC的內容被放入通用寄存器rD,同時,MAC累加器被清空。
指令l.macrc的書寫格式為:l.macrc rD
指令l.macrc的運算方法如下:
synchronize-mac rD[31:0] <- MACLO[31:0] MACLO[31:0],MACHI[31:0] <-0
指令l.macrc的格式如表2-16所示。
表2-16 指令l.macrc的格式

8.31~21bit位寄存器比較設置標識指令
31~21bit位寄存器比較設置標識指令是比較寄存器rA和rB,并將比較結果設置寄存器SR的F位,即設置SR[F],用來表示比較等式是否成立。
31~21bit位寄存器比較設置標識指令有l.sfges、l.sfgeu、l.sfgts、l.sfgtu、l.sfles、l.sfleu、l.sflts、l.sfltu、l.sfne。指令中字符的含義為“sf”表示Set Flag,“ge”表示Great and Equal(大于或等于),“gt”表示Great(等于),“le”表示Little and Equal,“ne”表示Not Equal,“u”表示unsigned(無符號的),“s”表示Signed(有符號的)。
下面以指令l.sfeq為例說明指令格式。
指令l.sfeq的作用如下:
如果rA與rB相等,比較標識被設置,否則被清除。
指令l.sfeq的書寫格式為:l.sfeq rA,rB
指令l.sfeq的運算方法如下:
SR[F] < - rA[31:0] == rB[31:0]
指令l.sfeq的格式如表2-17所示。
表2-17 指令l.sfeq的格式

9.31~21bit位立即操作數比較設置標識指令
31~21bit位立即操作數比較設置標識指令是比較寄存器rA和立即操作數,并將比較結果設置寄存器SR的F位,即設置SR[F],用來表示比較等式是否成立。
31~21bit位立即操作數比較設置標識指令有l.sfgesi、l.sfgeui、l.sfgtsi、l.sfgtui、l.sflesi、l.sfleui、l.sfltsi、l.sfltui、l.sfnei。指令中的字符i表示立即操作數Immediate。
下面以指令l.sfeq為例說明指令格式。
指令l.sfeqi的作用如下:
如果相等,設置比較標識。
指令l.sfeqi的書寫格式為:l.sfeqi rA,I
指令l.sfeqi的運算方法如下:
SR[F] < - rA[31:0] == exts(Immediate)
指令l.sfeqi的格式如表2-18所示。
表2-18 指令l.sfeqi的格式

10.31~0bit位同步指令
31~0bit位同步指令是不需要參數的特殊指令,同步指令有l.csync、l.msync(內存同步)、l.psync(流水線同步)。
下面以指令l.csync為例說明指令格式。
指令l.csync的作用如下:
上下文同步指令的執行導致在處理器內所有操作的完成和指令流水線的刷新。當所有的操作完成時,RISC核心假定有一個空的指令流水線,并刷新在所有單元(如MMU)的上下文。
指令l.csync的書寫格式為:l.csync
指令l.csync的運算方法為:context syncronization()
指令l.csync的格式如表2-19所示。
表2-19 指令l.csync的格式

11.31~16bit位系統調用或陷阱指令
31~16bit位系統調用或陷阱指令有l.sys和l.trap(陷阱)。如果在SR寄存器中指定的位被設置時,l.trap指令的執行導致陷阱例外。陷阱例外是對操作系統的請求,或者請求調試設置執行某一調試服務。立即數被用來選擇SR寄存器的哪個bit位被l.trap指令測試。
下面以指令l.sys為例說明指令格式。
指令l.sys的作用如下:
系統調用指令的執行導致系統調用例外。系統調用例外是一個對操作系統提供系統服務的請求。立即值用來指定哪種服務被請求。可替代地,被ABI定義的GPR(通用寄存器)能被用來指令系統服務。
指令l.sys的書寫格式為:l.sys K。
指令l.sys的運算方法如下:
system-call-exception(K)
指令l.sys的格式如表2-20所示。
表2-20 指令l.sys的格式

12.31~24bit位空操作指令
31~24bit位空操作指令l.nop說明如下:
指令l.nop的作用如下:
這條指令除了至少花費一個時鐘周期外不做任何操作。它常被用來填充延遲槽間隙。立即數能被用做仿真目的。
指令l.nop的書寫格式為:l.nop K。
指令l.nop的運算方法為:無。
指令l.nop的格式如表2-21所示。
表2-21 指令l.nop的格式

2.1.6 例外模型
例外(Exception)機制允許處理器由于在指令的執行過程中外部信號、錯誤或不常用條件的觸發導致切換到超級監管者狀態。當例外發生時,有關處理器的狀態信息被存儲到某些寄存器,并且處理器開始在預定地址為每個例外運行。例外的處理以超級監管者模式開始。
OpenRISC 1000構架對快速例外處理有特殊的支持,也稱快速上下文切換支持。這允許非常快速的中斷處理。這種快速通過通用寄存器和特殊寄存器的映像獲得。構架要求所有例外按嚴格指令流相應的次序被處理。當一個指令引起的例外被識別到,任何出現在這個指令之前沒有執行的指令被取消。
當一個例外處理例程正在執行時例外能發生,并且多個例外可能變成嵌套的。快速例外的支持允許例外的快速嵌套,直到所有的映像的寄存器被使用。如果上下文切換沒被使用,嵌套的例外應該沒有發生。
1.例外分類
所有的例外能被描述成有精度的或沒有精度的,以及同步的或異步的。同步的例外由指令引起,異步的例外由外部對處理器的事件引起的。例外分類如表2-22所示。
表2-22 例外分類

無論何時一個例外發生,當前PC被存到當前的EPCR,并且新PC按照表2-23所示的向量地址被設置。
表2-23 例外類型和引起的條件

2.例外處理
當一個例外發生時,當前/下一個PC被存儲到當前的EPCR,除了如果當前的指令在延遲槽中。如果PC指向延遲槽指令,PC-4被存儲到當前的EPCR,并且SR[DSX]被設置。表2-24定義了當前/下一個PC和有效的地址。
表2-24 在例外之后EPCR和EEAR的值。

SR被存儲到當前的ESR。當前的EPCR/ESR由SR[CID]鑒別。如果快速上下文切換沒有被使用,那么當前的EPCR/ESR總是EPCR0/ESR0。
如果總線錯誤、IMMU頁錯誤、DMMU頁錯誤、I-TLB失靶和D-TLB miss失靶這些例外之一發生時,當前的EEAR被用有效的地址設置。
如果使用了快速上下文切換,SR[CID]與新例外一起使用,這將導致使用一套新的映像寄存器。如果SR[CID]與當前的例外一起溢出,range(范圍)例外被觸發。
然后,如果沒設置SR[CE],快速上下文切換將失效。這時,必須首先存儲所有被例外處理例程修改的寄存器。所有的例外設置一個新SR,在這個新SR里,禁止了MMU(禁止了地址翻譯),打開了超級監管者模式,并且禁止了Tick定時器例外和中斷。即SR[DME]=0,SR[IME]=0,SR[SM]=1,SR[IEE]=0和SR[TEE]=0。
當例外處理例程存儲了足夠機器狀態信息時,SR[TTE]和SR[IEE]再次激活,從而不阻塞Tick定時器和外部中斷。
當l.rfe指令從一個例外處理例程返回時,SR和PC被恢復。如果SR[CE]設置時,CID將自動遞減,并且恢復以前的機器狀態。另外,必須恢復以前被例外處理例程存儲的通用寄存器。
3.快速上下文切換(可選的)
快速上下文切換是在例外發生時降低寄存器存儲到堆棧的時間的一種技術。快速上下文切換僅能處理一種類型的例外,這樣它依賴于軟件指出引起例外的原因。使用軟件能快速處理中斷處理函數的調用和線程切換。硬件應該有在一個時鐘周期內切換上下文的能力。
上下文也能在一個例外期間切換,或者通過以超級監管者模式使用寄存器CXR(上下文寄存器Context Register)。對所有上下文來說,CXR是一樣的。
(1)在超級監管者模式改變上下文
讀/寫寄存器CXR由兩個部分組成,其中低16位代表當前上下文寄存器集,高16位代表當前的CID。不能在用戶模式訪問CCID;寫CCID將引起一個立即上下文改變;讀CCID將返回運行(當前的)上下文ID。在CID=0的上下文也稱為主上下文。上下文寄存器如表2-25所示。
表2-25 上下文寄存器(CXR)

CCRS有如下兩個功能。
■ 當例外發生時,它持有前一個CID;
■ 它被用來訪問其他上下文的寄存器。
(2)例外引起的上下文切換
當一個例外發生并且激活了快速切換時,CCID被復制到CCRS,并接著被設置到0,這樣切換到了主上下文。
主上下文的功能如下:
■ 在線程之間切換;
■ 處理例外;
■ 準備、存儲CID到CID表或從CID表裝載、釋放CID。
CXR應該盡可能快地存儲到一個通用寄存器,以便允許更多的例外嵌套。
表2-26顯示了一個樣例,說明怎樣使用CID表。通常,空閑的例外上下文不必相等的。
表2-26 多個上下文切換

表2-26中,裝載了4個線程上下文,并且軟件能以超級監管者模式使用主上下文在它們之間自由切換。當一個例發生時,首先需要判斷引起例外的原因,并切換到下一個空閑例外上下文。因為例外可能被嵌套,因此需要有更多的空閑上下文。這樣為了切換一個新的例外,一些上下文需要被存儲到內存。
在主上下文里處理上下文存儲/恢復和切換的算法應盡可能簡單。它還應該足夠的寄存器來存儲信息,這些信息包括當前運行的CID、下一個例外。線程周期信息、內存中上下文表的指針、CXR的復制。
如果中斷號是重要的,可使用一些延遲中斷調用機制。主上下文算法應該存儲中斷剛剛傳遞的I/O信息,以便后面運行時使用,并且盡可能快地從主上下文返回。
(3)訪問其他上下文的寄存器
這種操作僅在超級監管者模式下進行。在基本指令集中,使用l.mtspr和l.mfspr指令訪問映像寄存器。
2.1.7 內存管理
1.內存模型
OpenRISC 1000使用弱次序內存模型,以獲得較高的內存效率,訪問次序由軟件來嚴格控制。頁設計為弱次序內存(Weakly-Ordered-Memory)頁,能使用預取來亂序訪問指令和數據。內存以字節單位用地址索引,以2字節邊界對齊、半字形式進行訪問,單個字以4字節邊界對齊、雙字以8字節邊界對齊訪問。
內存同步指令l.msync允許程序控制Load和Store操作執行的次序,它確保程序發取的內存訪問在下一個指令執行前完成。
軟件信號量需要原子地訪問內存,OpenRISC 1000構架提供了兩個指令執行讀-修改-寫操作,這兩個指令列出如下:
l.lwa rD,I(rA) l.swa I(rA),rB
指令l.lwa從內存裝載單個字,并為一個后繼符合條件的存儲操作創建一個內存位置的保留,一個編程不可見的特殊寄存器用來保存這個內存位置的地址,用于原子地讀-修改-寫操作。
如果另外一個讀操作讀同一內存位置,或者另一個l.lwa執行或軟件清除保留寄存器,將取消為隨后的l.swa指令保留的內存位置。
如果在相應的l.swa執行時,內存保留還有效,l.swa存儲通用寄存器rB到內存,如果保留被取消,l.swa不執行操作。
2.內存管理
內存管理涉及頁表結構、MMU各種例外、MMU寄存器等,MMU組織和TLB大小等內存硬件的設置不包括在體系結構定義中,對OpenRISC 1000編程模型不可見。
OpenRISC 1000內存管理單元(Memory Management Unit,MMU)主要特征有支持32位和64位有效地址、支持35位物理地址空間大小、三種不同的頁尺寸(32G、16M、8K字節)、使用1~3級而表進行地址翻譯、頁保護、支持并發多線程(simultaneous multi-threading,SMT)。
32GB的頁需要在64位地址下使用BD/I區域翻譯緩存(Area Translation Buffer,ATB)翻譯,16MB的頁需要使用D/I ATB翻譯,8KB頁需要使用D/I TLB(Translation Lookaside Buffer)。
MMU的主要功能是翻譯有效地址到物理地址,還提供基于頁的各種級別的訪問保護。OpenRISC 1000處理器需要取指令單元和數據訪問單元的地址翻譯,通常根據頁表將有效地址映射到物理地址。
TLB保存了最近使用的頁地址翻譯,ATB可以翻譯16MB和32GB的頁,如果TLB和ATB同時匹配同一個虛擬地址,將使用TLB。
32位有效地址(EA)的內存分為Level 1和Level 2頁,基于二級頁表進行翻譯。對于不需要最小8KB頁的虛擬內存匹配可以使用一級頁表。32位有效地址的二級頁表映射如圖2-3所示。

圖2-3 內存分為L1和L2頁
64位有效地址的內存被分為Level 0、Level 1和Level 2頁,基于三級頁表進行翻譯。64位有效地址的三級頁表映射如圖2-4所示。

圖2-4 內存分成L0、L1和L2頁
TLB完成了有效地址到物理地址的翻譯,如果翻譯失敗將引發MMU例外。TLB失靶例外僅發生在用軟件進行TLB重載的OpenRISC 1000處理器上。頁出錯例外可能由頁表中的PTE或頁訪問保護引發。
MMU與例外處理機制一起給操作系統提供了使用以頁為單位的虛擬內存環境。
2.1.8 高速緩存模型和高速緩存一致性
高速緩存管理寄存器的功能依賴于具體高速緩存的實現和內存/高速緩存訪問屬性的設置。對于一個在OpenRISC 1000處理器應用上運行的程序來說,軟件應該假定是Harvard高速緩存模型。在沒有高速緩存的處理器中,構架應保證對高速緩存寄存的寫不會停止軟件的執行。例如,一個沒有高速緩存的處理器應該簡單忽略對高速緩存管理寄存器的寫入。一個帶有Stanford高速緩存模型的處理器應該簡單地忽略對指令高速緩存管理寄存器的寫入。
由高速緩存管理引起的內存訪問不會留下記錄(不像Load/Store指令),并且不會引起例外。指令高速緩存不需要與內存或其他處理器的高速緩存保持一致。軟件必須保證指令高速緩存中的指令與內存中修改過的指令一致。典型方法有數據高速緩存阻塞回寫(內存的更新)、使用l.csync指令等待更新完成、設置指令高速緩存塊無效(清除指令高速緩存阻塞)和刷新流水線。
1.數據高速緩存管理
(1)數據高速緩存塊預取(可選的)
數據高速緩存塊預支取寄存器(DCBPR)可以控制將內存的數據塊預取到高速緩存,內存訪問不被記錄(不像Load/Store指令),不能引起任何例外。數據高速緩存塊預取可提高執行效率。
(2)數據高速緩存塊刷新
數據高速緩存塊刷新寄存器(DCBFR)可以控制數據高速緩存塊的刷新,對于有內存一致性要求的處理方法如下:
■ 未被修改的數據高速緩存塊在所有的處理器無效。
■ 被修改的數據高速緩存塊被寫回到內存,并且數據高速緩存塊在所有的處理器無效。
■ 在本地處理器上失靶的數據高速緩存塊,引起在其他處理器的被修改高速緩存數據塊寫回到內存,并設置緩存塊為無效。如果其他處理器存在沒有修改的數據高速緩存塊,則緩存塊僅在所有的處理器被置為無效。
不要求內存一致性的處理方法如下:
■ 未被修改的數據高速緩存塊在本地的處理器上被置為無效。
■ 修改過的數據高速緩存塊被寫回到內存,并在本地的處理器上置為無效。
■ 在本地的處理器上失靶的高速緩存塊不引起任何動作。
(3)數據高速緩存塊無效
數據高速緩存塊無效寄存器(DCBIR)用來控制數據高速緩存塊無效的處理方法,要求內存一致性的處理方法如下:
■ 未被修改的數據高速緩存塊在所有的處理器無效。
■ 被修改的數據高速緩存塊在所有的處理器無效。
■ 在本地的處理器上失靶的數據高速緩存塊,引起其他處理器上的數據高速緩存塊失效。
不要求內存一致性的處理方法如下:
■ 未被修改的數據高速緩存塊在所有的處理器無效。
■ 被修改的數據高速緩存塊無效。
■ 在本地的處理器上失靶的高速緩存塊不引起任何動作。
(4)數據高速緩存塊回寫
數據高速緩存塊回寫寄存器(DCBWBR)控制數據高速緩存塊的回寫操作,如果要求內存一致性,那么在任何處理器中修改過的數據高速緩存塊應被寫回到內存。如果不要求內存一致性,那么本地處理器中修改過的數據高速緩存被寫回到內存。
(5)數據高速緩存塊鎖存(可選的)
數據高速緩存塊鎖寄存器(DCBLR)是用來鎖住本地處理器上的數據高速緩存塊,如果所有的高速緩存通道上同一設置的所有塊被鎖住,那么,高速緩存重填充可以自動解鎖最近最少使用的塊。
2.指令高速緩存管理
(1)指令高速緩存塊預取(可選的)
指令高速緩存塊預取寄存器(ICBPR)控制指令的預取操作,將內存的指令塊預取到指令高速緩存,提高了CPU執行效率。
(2)指令高速緩存塊無效
指令高速緩存塊無效寄存器(ICBIR)是控制指令高速緩存塊無效時的操作,如果要求內存一致性,那么所有處理器中相應的指令高速緩存塊被置為無效。如果不要求內存一致性,那么本地處理器中相應的指令高速緩存塊被置為無效。
(3)指令高速緩存塊鎖存(可選的)
指令高速緩存塊鎖寄存器(ICBLR)用來鎖住本地處理器上的相應的指令高速緩存塊。如果所有的高速緩存通道上同一設置的塊被鎖住,那么,高速緩存重填充可以自動解鎖最近最少使用的塊。本地處理器上高速緩存塊的失靶不引起任何動作。
3.高速緩存/內存一致性
高速緩存一致性系統的主要角色是與其他高速緩存及與內存同步高速緩存,并提供同一內存的映像給使用這個內存的設備。
構架提供了幾個特征使用高速緩存一致性。在不提供與PTE屬性(如沒有使用內存管理單元)進行高速緩存一致性的系統中,高速緩存一致性可通過外在明確的高速緩存管理來提供。
系統中通過PTE(Page Table Entry,頁表條目)的屬性設置在頁到頁基礎上提供高速緩存與虛擬內存的一致性。這些屬性具體如下:
■ 是否高速緩存一致性(CC屬性位Cache Coherent Attribute)
■ 是否繼承的高速緩存(CI屬性位Caching-Inhibited Attribute)
■ 是否回寫高速緩存(WBC屬性位Write-Back Cache Attribute)
當內存/高速緩存屬性被改變,高速緩存應該反映新的屬性設置,這通常意味著高速緩存塊應該被刷新或置為無效的。
(1)指定作高速緩存一致性的頁
在硬件執行高速緩存一致性相對慢的系統里,這個屬性可改進系統的執行性。不需要高速緩存一致性的頁設置CC=0,需要高速緩存一致性的頁設置CC=1。當一個對共享資源的訪問發生時,本地處理器將聲明一些高速緩存一致性信號,并且如果其他處理器的高速緩存中有目標位置的復制時,它們將做出反應。
為了改進單處理器系統的執行性能,內存頁不應該指定為CC=1。
(2)指定作為高速緩存繼承的頁
指定CI=1的內存頁在內存訪問時總是直接進入主內存,而忽略所有的高速緩存;指定CI=1的頁不裝進高速緩存,并且目標內容在高速緩存中應該永不可用。為了阻止在高速緩存中目標位置的任何意外復制,無論何時操作系統設置一個內存頁為高速緩存繼承,它應該刷新相應的高速緩存塊。
除了單個訪問被l.msync或l.csync或l.psync分開外,多個訪問可以被融合成聯合的訪問。
(3)指定作回寫高速緩存頁的頁
指定WBC=0的內存頁在Store操作時,Store操作在數據高速緩存和內存中同時執行。如果一個系統使用了多級高速緩存,Store操作必須至少在其他處理器或設備感知到的內存體系中進行。
除了單個Store操作被l.msync或l.csync或l.psync分開外,多個Store操作可以融合成聯合的Store操作。一個Store操作可能引起高速緩存塊任何部分寫回到主內存。
指定WBC=1的內存頁在Store訪問操作時僅對本地數據高速緩存進行。當要求進行復制回(copy-back)操作時,來自本地的數據高速緩存的數據能被復制到其他的高速緩存和主存。WBC=1改進了系統執行性能,然而,它要求在數據高速緩存控制器中,高速緩存支持偵聽硬件,以保證高速緩存的一致性。
2.1.9 調試單元
調試單元協助軟件開發者調試他們的系統。它提供了Watchpoints、Breakpoints和程序流控制寄存器。Watchpoint和Breakpoint是程序或數據流匹配被編程在調試寄存器里的條件觸發的事件。
Watchpoints除了當引起一個Breakpoint影響程序執行外,不干預程序流的執行。Watchpoints能被執行計數單元(Performance Counters Unit)計數。
Breakpoint不像Watchpoint,它還掛起當前程序流的執行,并開始陷阱例外處理。Breakpoint是Watchpoints的可選結果。
OpenRISC 1000構架定義了8套調試寄存器集。附加的調試寄存器集能被構架應用的RISC本身所定義。調試單元是可選的,并且調試單元的出現是由寄存器UPR[DUP]位來指明的。調試單元的特征列出如下:
● 可選的構架應用。
● 8個構架定義的調試值/比較寄存器集。
● 在指令支取EA、Load/Store EA和Load/Store數據上匹配有符號/無符號的條件。
● 為復雜的Watchpoints組合匹配條件。
● Watchpoints能被執行計數單元計數。
● Watchpoints能產生斷點(陷阱例外)。
● 給附加的Watchpoint產生計數Watchpoints。
DVR/DCR寄存器用來將支取或LoadStore EA和Load/Store數據指令與存儲在DVR中的值進行比較。Watchpoints能作為Breakpoint計數和報告。
2.1.10 執行計數單元
執行計數器能被用來給諸如L1指令或數據高速緩存失靶、分支指令、流水線停止這樣的預定義事件計數。來自執行計數器單元的數據能用做下面的目的。
● 通過開發較好的應用程序級算法、優化操作系統例程改進執行性能,并改進這些系統的硬件結構(如內存子系統)。
● 改進將來OpenRISC 1000,并增加將來的增強到OpenRISC構架。
● 幫助系統開發者調試和測試他們的系統。
OpenRISC 1000構架定義了8個執行計數器,還可定義補充的執行計數器。
2.1.11 電源管理
OpenRISC 1000構架定義5種特征減少電源消耗,列出如下:
● 減速(slow down)特征
● 小睡(doze)模式
● 睡眠(sleep)模式
● 掛起(suspend)模式
● 動態時鐘調速(dynamic clock gating)特征
slow down特征在外部時鐘產生電路降低頻率,從而降低電源消耗。通常在操作系統空閑時設置。
當軟件激活了doze模式,則軟件進程被掛起,處理器內部單元的時鐘被關閉,除了內部的Tick定時器和可編程中斷外。然而,處理器以外的片上模塊繼續正常工作。當一個中斷發生時,處理器應從doze模式進入正常模式。
在睡眠狀態,所有的處理器內部單元被關閉,時鐘減速,還可降低處理器電壓。當一個中斷發生時,處理器從睡眠狀態進入正常狀態。
在suspend模式,所有的處理器內部單元被關閉,時鐘減速,還可降低處理器電壓。當處理器復位時,處理器從suspend狀態進入正常狀態。軟件可使用復位例外處理函數更新系統內存,并用suspend之前的狀態更新RISC。
如果激活了時鐘調速特征,則自動關閉處理器內部單元的時鐘子樹,如PU/VU、IC、DC、IMMU和DMMU單元。
2.1.12 可編程中斷控制器
OpenRISC 1000構架定義了一個可支持32個中斷輸入的中斷控制器,它通過掩碼寄存器(PIC Mask Register,PICMR)和狀態寄存器(PIC Status Register,PICSR)來控制可掩碼的32個中斷輸入。如圖2-5所示為可編程中斷控制器的功能框圖,32位中斷輸出后,經PICMR的掩碼操作,決定哪些中斷是可用的,并傳送到處理器觸發中斷例外,同時,中斷的狀態保存在寄存器PICSR中。

圖2-5 可編程中斷控制器框圖
2.1.13 Tick定時器
Tick定時器用來作為調度操作系統和用戶任務的時間基或高精度時間參考,每個時鐘周期定時計數寄存器(Tick Timer Count Register,TTCR)加1,當計數值達到模式寄存器(Tick Timer Mode Register,TTMR)設定值,觸發中斷。Tick定時器框圖如圖2-6所示。

圖2-6 Tick定時器框圖
Tick定時器最大定時為2^32個時鐘,中斷之間最大時間周期為2^28個時鐘,時鐘可以掩碼,可提供單個運行、可重啟動計數器或連接計數器。
- Vue.js 3.x快速入門
- 圖解Java數據結構與算法(微課視頻版)
- Java Web程序設計
- 批調度與網絡問題的組合算法
- RabbitMQ Essentials
- PLC應用技術(三菱FX2N系列)
- Spring Boot+Vue全棧開發實戰
- Mastering Akka
- Python項目實戰從入門到精通
- IDA Pro權威指南(第2版)
- 從零開始學Android開發
- SignalR:Real-time Application Development(Second Edition)
- 創新工場講AI課:從知識到實踐
- MySQL數據庫教程(視頻指導版)
- Manage Your SAP Projects with SAP Activate