加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 15.3  高速緩沖存儲(chǔ)器Cache
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

ARM存儲(chǔ)器之:高速緩沖存儲(chǔ)器Cache

2013/09/30
3
閱讀需 46 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

?

15.3??高速緩沖存儲(chǔ)器Cache

當(dāng)?shù)谝淮鶵ISC微處理器剛出現(xiàn)時(shí),標(biāo)準(zhǔn)存儲(chǔ)器元件的速度比當(dāng)時(shí)微處理器的速度快。很快,半導(dǎo)體工藝技術(shù)的進(jìn)展被用來(lái)提高微處理器的速度。標(biāo)準(zhǔn)DRAM部件雖然也快了一些,但其發(fā)展的主要精力則放在提高存儲(chǔ)容量上。

1980年,典型DRAM部件的容量為4KB。1981年和1982年開(kāi)發(fā)出了16KB芯片。這些部件的隨機(jī)訪問(wèn)速率為3MHz或4MHz,局部訪問(wèn)(頁(yè)模式)時(shí)速率大約快1倍。當(dāng)時(shí)的微處理器每秒需要訪問(wèn)存儲(chǔ)器2M次。

到2000年,DRAM部件每片的容量到達(dá)256Mbit,隨機(jī)訪問(wèn)速率在30MHz左右。微處理器每秒需要訪問(wèn)存儲(chǔ)器幾百兆次。如果處理器速率遠(yuǎn)高于存儲(chǔ)器,那么只能借助Cache才能滿足其全部性能。

Cache存儲(chǔ)器是一個(gè)容量小但存取速度非??斓拇鎯?chǔ)器,它保存最近用到的存儲(chǔ)器數(shù)據(jù)拷貝。對(duì)于程序員來(lái)說(shuō),Cache是透明的。它自動(dòng)決定保存哪些數(shù)據(jù)、覆蓋哪些數(shù)據(jù)?,F(xiàn)在Cache通常與處理器在同一芯片上實(shí)現(xiàn)。Cache能夠發(fā)揮作用是因?yàn)槌绦蚓哂芯植啃蕴匦?。所謂局部性就是指,在任何特定的時(shí)間,微處理器趨于對(duì)相同區(qū)域的數(shù)據(jù)(如堆棧)多次執(zhí)行相同的指令(如循環(huán))。

Cache經(jīng)常與寫緩存器(write?buffer)一起使用。寫緩存器是一個(gè)非常小的先進(jìn)先出(FIFO)存儲(chǔ)器,位于處理器核與主存之間。使用寫緩存的目的是,將處理器核和Cache從較慢的主存寫操作中解脫出來(lái)。當(dāng)CPU主存儲(chǔ)器做寫入操作時(shí),它先將數(shù)據(jù)寫入到寫緩存區(qū)中,由于寫緩存器的速度很高,這種寫入操作的速度也將很高。寫緩存區(qū)在CPU空閑時(shí),以較低的速度將數(shù)據(jù)寫入到主存儲(chǔ)器中相應(yīng)的位置。

通過(guò)引入Cache和寫緩存區(qū),存儲(chǔ)系統(tǒng)的性能得到了很大的提高,但同時(shí)也帶來(lái)了一些問(wèn)題。比如,由于數(shù)據(jù)將存在于系統(tǒng)中的不同的物理位置,可能造成數(shù)據(jù)的不一致性;由于寫緩存區(qū)的優(yōu)化作用,可能有些寫操作的執(zhí)行順序不是用戶期望的順序,從而造成操作錯(cuò)誤。

15.3.1??Cache的分類

Cache有多種構(gòu)造方法。在最高層次,微處理器可以采用下面兩種組織中的一組。

(1)統(tǒng)一Cache。指令和數(shù)據(jù)用同一個(gè)Cache。結(jié)構(gòu)如圖15.8所示。

圖15.8??統(tǒng)一的指令Cache和數(shù)據(jù)Cache

(2)指令和數(shù)據(jù)分開(kāi)的Cache。有時(shí)這種組織方式也被稱為改進(jìn)的哈佛結(jié)構(gòu)。

圖15.9顯示了這種組織方式。

這兩種組織方式各有優(yōu)缺點(diǎn)。統(tǒng)一Cache能夠根據(jù)當(dāng)前程序的需要自動(dòng)調(diào)整指令在Cache存儲(chǔ)器的比例,比固定劃分的有更好的性能。另一方面,分開(kāi)的Cache使Load/Store指令能夠單周期執(zhí)行。

15.3.2??Cache性能的衡量

只有當(dāng)所需要的Cache存儲(chǔ)器內(nèi)容已經(jīng)在Cache時(shí),微處理器才能以高時(shí)鐘速率工作。因此,系統(tǒng)的總體性能就可以用存儲(chǔ)器訪問(wèn)中命中Cache的比例來(lái)衡量。當(dāng)要訪問(wèn)的內(nèi)容在Cache時(shí)稱為命中(hit),而要訪問(wèn)的內(nèi)容不在Cache時(shí)稱為未命中(miss)。在給定時(shí)間間隔內(nèi),Cache命中的次數(shù)與總的存儲(chǔ)器請(qǐng)求次數(shù)的比值被稱為命中率。

圖15.9??指令Cache和數(shù)據(jù)分開(kāi)的Cache

命中率用下面的公式進(jìn)行計(jì)算:

命中率=(Cache命中次數(shù)÷存儲(chǔ)器請(qǐng)求次數(shù))×100%

未命中率與命中率形式相似,即在給定時(shí)間間隔內(nèi),Cache未命中的總次數(shù)除以總的存儲(chǔ)器請(qǐng)求次數(shù)所得的百分比。未命中率與命中率之和等于100。

目前設(shè)計(jì)良好的處理器,Cache的未命中率只有百分之幾。未命中率依賴多個(gè)Cache參數(shù),包括Cache大小和組織。

?

15.3.3??Cache工作原理

Cache的基本存儲(chǔ)單元為Cache行(Cache?line)。存儲(chǔ)系統(tǒng)把Cache和主存儲(chǔ)器都劃分為相同大小的行。Cache與主存儲(chǔ)器交換數(shù)據(jù)是以行為基本單位進(jìn)行的。每一個(gè)Cache行都對(duì)應(yīng)于主存中的一個(gè)存儲(chǔ)塊(memory?block)。

Cache行的大小通常是2L字節(jié)。通常情況下是16字節(jié)(4個(gè)字)和32字節(jié)(8個(gè)字)。如果Cache行的大小為2L字節(jié),那么對(duì)主存的訪問(wèn)通常是2L字節(jié)對(duì)齊的。所以對(duì)于一個(gè)虛擬地址來(lái)說(shuō),它的bit[31∶L]位,是Cache行的一個(gè)標(biāo)識(shí)。當(dāng)CPU發(fā)出的虛擬地址的bit[31∶L]和Cache中的某行bit[31∶L]相同,那么Cache中包含CPU要訪問(wèn)的數(shù)據(jù),即成為一次Cache命中。

為了加快Cache訪問(wèn)的速度,又將多個(gè)Cache行劃分成一個(gè)Cache組(Cache?Set)。Cache組中包含的Cache行的個(gè)數(shù)通常也為2的N次方的倍數(shù)。為了方便起見(jiàn),取N=S。這樣,一個(gè)Cache組中就包含2S個(gè)Cache行。這時(shí),虛擬地址中的bit[L+S-1∶L]為Cache組的標(biāo)識(shí)。虛擬地址中余下的位bit[31∶L+S]成為一個(gè)Cache標(biāo)(Cache-tag)。它標(biāo)識(shí)了Cache行中的內(nèi)容和主存間的對(duì)應(yīng)關(guān)系。

圖15.10顯示了Cache的訪問(wèn)過(guò)程。

圖15.10??Cache訪問(wèn)過(guò)程

15.3.4??Cache與主存的關(guān)系

在Cache中采用地址映射將主存中的內(nèi)容映射到Cache地址空間。具體的說(shuō),就是把存放在主存中的程序按照某種規(guī)則裝入到Cache中,并建立主存地址到Cache地址之間的對(duì)應(yīng)關(guān)系。而地址變換是指當(dāng)程序已經(jīng)裝入到Cache后,在實(shí)際運(yùn)行過(guò)程中,把主存地址變換成Cache地址。

地址的映射和變換是密切相關(guān)的。采用什么樣的地址映射方法,就必然有與之對(duì)應(yīng)的地址變換。

常用的地址映射和變換方式包括直接映射和變換方式、組相聯(lián)映射和變換方式以及全相聯(lián)和變換方式。

(1)直接(direct-mapped)映射方式

直接映射是一種最簡(jiǎn)單,也是最直接的映射方式。主存中的每個(gè)地址都對(duì)應(yīng)Cache存儲(chǔ)器中惟一的一行。由于主存的容量遠(yuǎn)遠(yuǎn)大于Cache存儲(chǔ)器,所以在主存中很多地址被映射到同一個(gè)Cache行。

圖15.11顯示了主存與Cache的直接映射關(guān)系。

圖15.11??主存和Cache的直接映射

直接映射Cache是一種簡(jiǎn)單的解決方法,但這種設(shè)計(jì)使得每個(gè)主存塊在Cache中只有一個(gè)特定的行可以存放。如果程序同時(shí)用到對(duì)應(yīng)于Cache同一行的兩個(gè)主存塊,那么就會(huì)發(fā)生沖突,沖突的結(jié)果是導(dǎo)致Cache行的頻繁變換。這種由直接映射導(dǎo)致的Cache存儲(chǔ)器中的軟件沖突稱為顛簸(thrashing)問(wèn)題。

(2)組相聯(lián)映射方式

為了減少顛簸問(wèn)題,有些Cache使用了組相聯(lián)的映射策略。在組相聯(lián)的地址映射和變換中,把主存和Cache按同樣大小劃分成組(set),每個(gè)組都由相同的行數(shù)組成。

由于主存的容量比Cache容量大得多,因此,主存的組數(shù)要比Cache的組數(shù)多。從主存的組到Cache的組之間采用直接映射方式。主存中的一組與Cache中的一組之間建立了之間映射方式后,在兩個(gè)對(duì)應(yīng)的組內(nèi)部采用全相聯(lián)映射方式。

在ARM中采用的是組相聯(lián)的地址映射和變換方式。如果Cache的行大小為2L,則同一行中各地址的bit[31∶L]是相同的。如果Cache中組的大?。拷M中包含的行數(shù))為2S,則虛地址位bit[L+S∶L]用于選擇Cache中的某個(gè)組。

圖15.12顯示了一個(gè)Cache與主存儲(chǔ)器的組相聯(lián)映射

圖15.12??Cache與主存儲(chǔ)器組相聯(lián)映射

擁有相同組索引的Cache行稱為組相聯(lián)的(set?associative)。主存中的程序或代碼段可以在不影響程序執(zhí)行的情況下被分配到Cache中的某一組中。也就是說(shuō),將數(shù)據(jù)或代碼存入Cache行中的操作不會(huì)影響程序的執(zhí)行。

(3)全相聯(lián)映射方式

隨著Cache控制器的相聯(lián)度的提高,沖突的可能性減少了。理想的目標(biāo)是,盡量提高組相聯(lián)程度,使主存地址能夠映射到任意Cache行。這樣的Cache被稱為全相聯(lián)Cache。然而,隨著相聯(lián)度的提高,與之相匹配的硬件的復(fù)雜度也在提高。硬件設(shè)計(jì)者提高Cache相聯(lián)度的一種方法就是使用內(nèi)容尋址寄存器CAM(Content?Addressable?Memory)。

CAM使用一組比較器,以比較輸入的標(biāo)簽地址和存儲(chǔ)在每一個(gè)有效Cache行中的標(biāo)簽位。CAM采取了與RAM相反的工作方式;RAM在得到一個(gè)地址后再給出數(shù)據(jù);而CAM則是在檢測(cè)到給定的數(shù)據(jù)值在存儲(chǔ)器中后,再給出該數(shù)據(jù)的地址。使用CAM允許同時(shí)比較更多的地址中的標(biāo)簽位,從而增加了可以包含在一個(gè)組中的Cache行數(shù)。

在ARM920T和ARM940T存儲(chǔ)器核中,ARM使用了CAM來(lái)定位地址中的標(biāo)簽域。ARM920T和ARM940T中的Cache是64組組相聯(lián)的。圖15.13所示為ARM940T的Cache結(jié)構(gòu)圖。Cache控制器把地址標(biāo)簽域作為CAM的輸入,它的輸出選擇了包含有效Cache行的組。

圖15.13??ARM940T64路組相聯(lián)Cache

訪問(wèn)地址的標(biāo)簽部分被作為4個(gè)CAM的輸入,輸入標(biāo)簽的同時(shí)與存儲(chǔ)在64組中的所有Cache標(biāo)簽比較。如果有一個(gè)匹配,那么數(shù)據(jù)就由Cache寄存器提供;如果沒(méi)有匹配,存儲(chǔ)器就會(huì)產(chǎn)生一個(gè)失效(misss)信號(hào)。

控制器使用組索引位(set?index)在4個(gè)CAM中選擇一個(gè)。被選中的CAM會(huì)在Cache存儲(chǔ)器中選擇一個(gè)Cache行,該地址的數(shù)據(jù)索引部分(data?index)在該Cache行中選擇出所需的字、半字或者字節(jié)。

15.3.5??Cache的寫策略

當(dāng)CPU更新了Cache內(nèi)容時(shí),要將結(jié)果寫回到主存中,通常有兩種方法:

·??直寫法(write-through);

·??回寫法(write-back)。

直寫法是指,當(dāng)CPU在執(zhí)行寫操作時(shí),必須把數(shù)據(jù)同時(shí)寫入Cache和主存,以確保Cache和主存數(shù)據(jù)一致。在這種寫策略下,處理器在每次寫Cache時(shí)也要寫相應(yīng)的主存單元。由于要訪問(wèn)主存,直寫法的速度比回寫法要慢一些。

回寫法是指,當(dāng)處理器和寫Cache命中時(shí),只向Cache存儲(chǔ)器寫數(shù)據(jù),而不立即寫入主存。這樣,主存儲(chǔ)器與相應(yīng)的Cache行數(shù)據(jù)有可能不一致。Cache中的數(shù)據(jù)是新的,而主存中的數(shù)據(jù)可能是較早的、沒(méi)有被更新過(guò)的。

配置成回寫法的Cache要使用Cache行的狀態(tài)信息塊中的一個(gè)或多個(gè)臟位(dirty?bit)。當(dāng)回寫Cache控制器向Cache存儲(chǔ)器中的某一行寫入數(shù)據(jù)時(shí),它會(huì)將臟位設(shè)置為1。如果控制器內(nèi)核此后訪問(wèn)該Cache行,那么通過(guò)臟位的狀態(tài)就可以知道該Cache行中含有主存儲(chǔ)器中沒(méi)有的數(shù)據(jù)。如果Cache控制器要將一個(gè)臟位被設(shè)置的Cache行替換出Cache存儲(chǔ)器,那么該Cache行數(shù)據(jù)會(huì)自動(dòng)被寫入主存單元中??刂破魍ㄟ^(guò)這種方法來(lái)防止只存在于Cache中而主存中沒(méi)有的重要信息的丟失。

表15.12比較了直寫法和回寫法的優(yōu)缺點(diǎn)。

表15.12 直寫法與回寫法

寫??策??略

直??寫??法

回??寫??法

可靠性

與主存的通信

控制的復(fù)雜性

簡(jiǎn)單

復(fù)雜

硬件實(shí)現(xiàn)代價(jià)

下面分析產(chǎn)生這些性能差異的原因。

·??可靠性。直寫法要優(yōu)于回寫法。這是因?yàn)橹睂懛ㄊ冀K保證Cache是主存的正確副本。當(dāng)Cache發(fā)生錯(cuò)誤時(shí),可以從主存中糾正。

·??與主存的通信量。一般情況下,回寫法少于直寫法。這是因?yàn)椋环矫?,Cache的命中率很高,對(duì)于回寫法來(lái)說(shuō),CPU絕大多數(shù)操作只需要寫Cache,不必寫主存。另一方面,當(dāng)Cache失效時(shí),要將Cache中的行替換到主存,而直寫法每次只寫一個(gè)字到主存。總的來(lái)說(shuō),由于直寫法在每次寫Cache時(shí),同時(shí)寫主存,從而增加了寫操作的開(kāi)銷。而回寫法是把與主存的數(shù)據(jù)交換集中到一次主存操作,可能要一次性的進(jìn)行多個(gè)字的操作。

·??控制的復(fù)雜性。直寫法必回寫法簡(jiǎn)單。直寫法在Cache的行狀態(tài)表中不需要修改位。同時(shí),直寫法的糾錯(cuò)技術(shù)相對(duì)簡(jiǎn)單。

·??硬件代價(jià)?;貙懛ū戎睂懛ê谩R?yàn)橹睂懛ㄖ?,每次寫操作都要寫主存,因此為了?jié)省寫主存所花費(fèi)的時(shí)間,通常要采用一個(gè)高速小容量的緩存存儲(chǔ)器,把要寫的數(shù)據(jù)和地址寫到這個(gè)緩存中。在每次讀主存時(shí),也要首先判斷所讀的數(shù)據(jù)是否在這個(gè)緩存中。而回寫法不需要上述操作,相對(duì)硬件代價(jià)要小。

?

15.3.6??Cache的替換策略

在Cache訪問(wèn)過(guò)程中,發(fā)現(xiàn)查找的Cache行已經(jīng)失效,則需要從主存中調(diào)入新的行到Cache中。在采用組相聯(lián)的Cache中,一個(gè)來(lái)自主存的行可以放入多個(gè)Cache組中。當(dāng)所有組中的對(duì)應(yīng)行都已經(jīng)裝滿時(shí),就要使用Cache替換算法,從這些組中找出一個(gè)Cache,把它調(diào)回到主存中原來(lái)存放它的地方,騰出新行來(lái)存放新調(diào)入的行。被選中替換的Cache行被稱為丟棄者(victim)。如果丟棄者中包含有效的臟數(shù)據(jù),那么在該行被寫入新數(shù)據(jù)之前,控制器必須把該行中的數(shù)據(jù)寫到主存。選擇和替換丟棄Cache行的過(guò)程被稱為淘汰(eviction)。

Cache控制器選擇下一個(gè)丟棄Cache行的策略被稱為替換策略。在ARM常用的替換算法有兩種:輪轉(zhuǎn)算法和隨機(jī)替換算法。

輪轉(zhuǎn)算法又叫循環(huán)法,這種算法維護(hù)一個(gè)邏輯計(jì)數(shù)器,每進(jìn)行一次替換,計(jì)算器加1,當(dāng)計(jì)算器達(dá)到最大值時(shí),就被復(fù)位成預(yù)先定義好的一個(gè)基值。這種算法容易預(yù)測(cè)最壞情況下的Cache性能。但它一個(gè)明顯缺點(diǎn)就是,在程序發(fā)生很小變化時(shí),可能造成Cache性能急劇下降。

隨機(jī)算法從特定的位置上隨機(jī)地選出一行替換出去。它通過(guò)一個(gè)隨機(jī)發(fā)生器來(lái)完成上述操作。當(dāng)每次需要替換Cache行時(shí),隨機(jī)發(fā)生器將產(chǎn)生一個(gè)隨機(jī)數(shù),用新行將編號(hào)為該隨機(jī)數(shù)的行替換出去。這種算法與輪轉(zhuǎn)算法最大的區(qū)別在于它在每次產(chǎn)生替換行時(shí),增加的是一個(gè)非連續(xù)值,這個(gè)值是由控制器隨機(jī)產(chǎn)生的。同樣,當(dāng)丟棄計(jì)算器達(dá)到最大值時(shí),會(huì)被復(fù)位成預(yù)先定義好的一個(gè)基值。

相比之下,隨機(jī)算法沒(méi)有考慮到程序的局部性特點(diǎn),因而效果有時(shí)不盡人意,同時(shí)這種算法不易預(yù)測(cè)最壞情況下Cache性能。而輪轉(zhuǎn)法就有更好的可預(yù)測(cè)性,容易預(yù)測(cè)最壞情況下Cache性能,在一些實(shí)時(shí)系統(tǒng)中,十分重視這一點(diǎn)。但是,輪轉(zhuǎn)法替換策略在存儲(chǔ)器訪問(wèn)發(fā)生很小變化時(shí),可能造成Cache性能有較大變化。

表15.13顯示了目前比較流行的ARM核所使用的策略。

表15.13 常見(jiàn)ARM核使用的替換策略

內(nèi)????核

寫??策??略

替?換?策?略

ARM720T

直寫法

隨機(jī)

ARM740T

直寫法

隨機(jī)

ARM920T

直寫法、回寫法

隨機(jī)、輪轉(zhuǎn)

ARM940T

直寫法、回寫法

隨機(jī)

ARM926EJ-S

直寫法、回寫法

隨機(jī)、輪轉(zhuǎn)

ARM946E

直寫法、回寫法

隨機(jī)、輪轉(zhuǎn)

ARM1020E

直寫法、回寫法

隨機(jī)、輪轉(zhuǎn)

ARM1026EJS

直寫法、回寫法

隨機(jī)、輪轉(zhuǎn)

Intel?Strong?ARM

回寫法

輪轉(zhuǎn)

Intel?Xscale

直寫法

輪轉(zhuǎn)

?

15.3.7??與Cache相關(guān)的編程接口

與Cache編程相關(guān)的CP15的寄存器共有3個(gè),它們分別為c1、c7及c9。

(1)寄存器c1中與Cache相關(guān)的位

c1寄存器在前面CP15寄存器一節(jié)中已經(jīng)介紹過(guò),下面對(duì)Cache的控制位進(jìn)行詳細(xì)介紹。

表15.14顯示了c1中與Cache有關(guān)位的作用。

表15.14 c1中與Cache相關(guān)的位

相??關(guān)??位

作????用

C(bit[2])

當(dāng)數(shù)據(jù)Cache和指令Cache分開(kāi)時(shí),本控制位禁止/使能數(shù)據(jù)Cache

當(dāng)數(shù)據(jù)Cache和指令Cache統(tǒng)一時(shí),本控制位禁止/使能整個(gè)Cache

0:禁止Cache

1:使能Cache

如果系統(tǒng)中不含Cache,讀取時(shí)該位返回0,寫入時(shí)忽略該位

當(dāng)系統(tǒng)中Cache不能禁止時(shí),讀取返回1,寫入時(shí)忽略該位

續(xù)表

相??關(guān)??位

作????用

I(bit[12])

當(dāng)數(shù)據(jù)Cache和指令Cache是分開(kāi)的,本控制位禁止/使能指令Cache

0:禁止指令Cache

1:使能指令Cache

如果系統(tǒng)中使用統(tǒng)一的指令Cache和數(shù)據(jù)Cache或者系統(tǒng)中不含Cache,讀取該位時(shí)返回0,寫入時(shí)忽略該位

當(dāng)系統(tǒng)中的指令Cache不能禁止時(shí),讀取該位返回1,寫入時(shí)忽略該位

RR(bit[14])

如果系統(tǒng)中Cache的淘汰算法可以選擇的話,本控制位選擇淘汰算法

0:選擇常規(guī)的淘汰算法,如隨機(jī)淘汰算法

1:選擇預(yù)測(cè)性的淘汰算法,如輪轉(zhuǎn)(round-robin)淘汰算法

如果系統(tǒng)中淘汰算法不可選擇,寫入該位時(shí)被忽略,讀取該位時(shí),根據(jù)其淘汰算法可以簡(jiǎn)單地預(yù)測(cè)最壞情況,并返回1或者0

?

(2)寄存器c7

CP15中的寄存器c7主要用于控制Cache和寫緩存。

注意

c7有時(shí)也用于其他相似的功能,如果系統(tǒng)中存在預(yù)測(cè)緩存(prefetch?buffers)和分支目標(biāo)(branch?target)Cache,c7也將負(fù)責(zé)對(duì)它們進(jìn)行控制。

c7是一個(gè)只寫存儲(chǔ)器,可以使用協(xié)處理器指令MCR對(duì)其進(jìn)行操作。如果程序中包含讀c7的操作,那么指令的結(jié)果不可預(yù)知。

使用MCR指令寫該寄存器的命令格式如下所示。

MCR??P15,0,<Rd>,<c7>,<CRm>,<opcode2>

其中,CRm和opcode2的不同組合,決定指令執(zhí)行的不同操作。具體組合與操作的對(duì)應(yīng)關(guān)系見(jiàn)表15.15。

表15.15 CRm與opcode2不同組合與操作的應(yīng)用關(guān)系

CRm

Opcode2

含????義

數(shù)????據(jù)

c0

4

等待中斷

0(SBZ,should?be?zero)

c5

0

使整個(gè)指令Cache無(wú)效

0

c5

1

使指令Cache中某行無(wú)效

虛擬地址

c5

2

使指令Cache中某行無(wú)效

組號(hào)/索引

c5

4

清空預(yù)取緩存區(qū)

0

c5

6

清空整個(gè)分支目標(biāo)Cache

0

c5

7

清空分支目標(biāo)Cache中的某入口項(xiàng)

生產(chǎn)商定義

c6

0

使整個(gè)數(shù)據(jù)Cache無(wú)效

0

續(xù)表

CRm

Opcode2

含????義

數(shù)????據(jù)

c6

1

使數(shù)據(jù)Cache中的某行無(wú)效

虛擬地址

c6

2

使數(shù)據(jù)Cache中的某行無(wú)效

組號(hào)/索引

c7

0

使整個(gè)統(tǒng)一Cache無(wú)效

哈佛結(jié)構(gòu)中,使整個(gè)數(shù)據(jù)Cache和指令Cache無(wú)效

0

c7

1

使統(tǒng)一Cache中某行無(wú)效

虛擬地址

c7

2

使統(tǒng)一Cache中某行無(wú)效

組號(hào)/索引

c8

2

等待中斷

0

c10

1

清理數(shù)據(jù)Cache行

虛擬地址

c10

2

清理數(shù)據(jù)Cache行

組號(hào)/索引

c10

4

清除寫緩存區(qū)

0

c11

1

清理統(tǒng)一Cache行

虛擬地址

c11

2

清理統(tǒng)一Cache行

組號(hào)/索引

c13

1

預(yù)取指令Cache中的某行

虛擬地址

c14

1

清理并使數(shù)據(jù)Cache中的某行無(wú)效

虛擬地址

c14

2

清理并使數(shù)據(jù)Cache中的某行無(wú)效

組號(hào)/索引

c15

1

清理并使統(tǒng)一Cache中的某行無(wú)效

虛擬地址

c15

2

清理并使統(tǒng)一Cache中的某行無(wú)效

組號(hào)/索引

(3)寄存器c9

將Cache進(jìn)入存儲(chǔ)系統(tǒng)的注意目的是要提高系統(tǒng)的平均訪問(wèn)速度。但Cache是一把雙刃劍,在某些情況下,可能使系統(tǒng)的性能更遭。下面列出了3種使Cache性能明顯下降的原因。

①?Cache訪問(wèn)未命中,處理器轉(zhuǎn)向主存尋址數(shù)據(jù),這期間的延時(shí)對(duì)系統(tǒng)性能影響很大。

②?在回寫型Cache中,如果Cache中的數(shù)據(jù)所在地址被存儲(chǔ)管理單元重新定位(即Cache中存儲(chǔ)的為虛地址數(shù)據(jù)),那么數(shù)據(jù)回寫的操作延時(shí)很大。

③?當(dāng)處理器需要一個(gè)字節(jié)數(shù)據(jù),而此數(shù)據(jù)恰好不在Cache中,那么Cache的替換策略就會(huì)將整個(gè)Cache行換進(jìn),增加了系統(tǒng)不必要的開(kāi)銷。

?

以上3點(diǎn)對(duì)實(shí)時(shí)系統(tǒng)來(lái)說(shuō),影響更為明顯。

為了減少這種不利的影響,在ARM系統(tǒng)中引入了Cache內(nèi)容鎖定技術(shù)。這種技術(shù)允許編程人員人為地將一些關(guān)鍵代碼或數(shù)據(jù)預(yù)取到Cache中后,通過(guò)寄存器操作對(duì)其設(shè)定一定的屬性,這樣當(dāng)有Cache未命中發(fā)生,需要進(jìn)行Cache替換時(shí),將這些數(shù)據(jù)保護(hù)起來(lái),使這些關(guān)鍵代碼或數(shù)據(jù)不會(huì)被換出。

這種策略在很大程度上保證了處理器對(duì)關(guān)鍵代碼或數(shù)據(jù)訪問(wèn)時(shí)的性能。

Cache的鎖定操作是分組塊(block)為單位進(jìn)行的,它的分塊方法如下。

為了敘述方便,作下述假設(shè)。

L(Length?of?the?Line):Cache的基本存儲(chǔ)單元行的大小。

A(Associativity):表示每個(gè)Cache組中的行數(shù)。

N(Number?of?Sets):Cache中的組數(shù)。

M表示Cache中的鎖定塊。

每個(gè)鎖定塊(lockdown?block)包括Cache每組中的一行。這樣Cache中共有A個(gè)鎖定塊,其編號(hào)為從0到A-1。其中編號(hào)為0的鎖定塊中包含Cache組0中的0#行,組1中的0#行,直到組A-1中的0#行。依此類推,鎖定塊1包含Cache組0中的1#行,組1中的1#行,直到組A-1中的1#行。這樣每個(gè)鎖定塊中包含了N個(gè)Cache行。

當(dāng)編號(hào)為0~M的鎖定塊被鎖定在Cache中,編號(hào)為M+1~A的鎖定塊可以用于正常的Cache替換操作。

注意

編程中不能將全部Cache鎖定,至少要留出一個(gè)未鎖定的塊來(lái)支持存儲(chǔ)器的正常操作。

每一個(gè)鎖定塊都包含有N個(gè)不同組中的Cache行。建議程序在使用Cache鎖定時(shí),使每個(gè)Cache塊中的N個(gè)Cache行映射的為存儲(chǔ)器中的連續(xù)地址。也就是說(shuō),存儲(chǔ)器中N×L大小的聯(lián)系區(qū)域被映射到Cache中鎖定,這塊區(qū)域是Cache行邊界對(duì)齊的(如果一個(gè)Cache行包含4字節(jié),那么被鎖定的區(qū)域要是4字節(jié)對(duì)齊的,如果一個(gè)Cache行包含8字節(jié),那么被鎖定的Cache行就是8字節(jié)對(duì)齊的)。

在ARM的存儲(chǔ)管理體系中,主要依靠系統(tǒng)協(xié)處理器和協(xié)處理器的寄存器c9來(lái)實(shí)現(xiàn)和管理Cache鎖定。如果系統(tǒng)中使用的是數(shù)據(jù)和指令分離的Cache,那么就依靠協(xié)處理器指令MCR和MRC中的<opcode>2來(lái)區(qū)分:

·??<opcode>=0使用數(shù)據(jù)Cache鎖定寄存器;

·??<opcode>=1使用指令Cache鎖定寄存器。

如果系統(tǒng)使用的是數(shù)據(jù)和指令統(tǒng)一的Cache,那么<opcode2>要設(shè)置成0。

另外,無(wú)論是MCR指令還是MCR指令,指令中的<CRm>通常設(shè)為c0。

寄存器c9有兩種主要的格式:格式A和格式B。

格式A的編碼如圖15.14所示。

圖15.14??格式A編碼

?

程序員通過(guò)指令對(duì)寄存器中的Cache組內(nèi)行號(hào)進(jìn)行操作。讀取格式A的寄存器c9,將返回最后一次寫入寄存器c9的值。將數(shù)據(jù)index寫入寄存器c9,就是對(duì)要鎖定的Cache行進(jìn)行設(shè)置。當(dāng)用MCR指令向寄存器寫入數(shù)據(jù)時(shí),執(zhí)行以下操作。

①?當(dāng)下一次發(fā)生Cache未命中時(shí),將預(yù)取的存儲(chǔ)器行存入Cache中與該行相對(duì)應(yīng)的組中編號(hào)為index的Cache行中。

②?這時(shí)被鎖定的Cache塊包括序號(hào)為0~index-1的鎖定塊。當(dāng)發(fā)生Cache替換時(shí),從編號(hào)為index到A-1的塊中選擇被替換的塊。

格式B的編碼如圖15.15所示。

程序員通過(guò)指令對(duì)寄存器中的Cache組內(nèi)行號(hào)進(jìn)行操作。讀取格式B的寄存器c9,將返回最后一次寫入寄存器c9的值。將數(shù)據(jù)index寫入寄存器c9,就是對(duì)要鎖定的Cache行進(jìn)行設(shè)置。當(dāng)用MCR指令向寄存器寫入數(shù)據(jù)時(shí),執(zhí)行以下操作。

圖15.15??格式B編碼

①?當(dāng)L=0時(shí),如果方式Cache未命中,將預(yù)取的存儲(chǔ)行存入Cache中與該行對(duì)應(yīng)的組中序號(hào)為index的Cache行中。

②?當(dāng)L=1時(shí),如果本次寫操作之前L=0,并且index值小于本次寫入的index,本次寫操作執(zhí)行的結(jié)果不可預(yù)知;否則,這時(shí)被鎖定的Cache塊包括序號(hào)為0~index-1的塊。當(dāng)發(fā)生Cache替換時(shí),從序號(hào)為index~A-1的塊中選擇被替換的塊。

下面以鎖定塊N來(lái)說(shuō)明要鎖定一個(gè)Cache塊的步驟。

①?首先確保在下面的整個(gè)Cache鎖定過(guò)程不會(huì)被中斷打斷。如果程序要求中斷不能關(guān)閉,那么必須確保被打開(kāi)的中斷相關(guān)代碼和數(shù)據(jù)位于非緩存(uncachable)的存儲(chǔ)區(qū)域。

關(guān)中斷的典型做法如下所示。

MRS??r2,CPSR????????????????????????;讀出當(dāng)前程序狀態(tài)字?CPSR

ORR??r2,r2,#?0x000000C0???????????;關(guān)中斷

MSR??CPSR_cxsf,r2??????????????????;設(shè)置當(dāng)前程序狀態(tài)字

②?如果鎖定是指令Cache或者統(tǒng)一Cache,必須保證鎖定過(guò)程所執(zhí)行的代碼位于非緩存的存儲(chǔ)域。

③?如果鎖定的是數(shù)據(jù)Cache或者統(tǒng)一的Cache,必須保證鎖定過(guò)程所執(zhí)行的數(shù)據(jù)位于非緩存的存儲(chǔ)域。

④?保證要鎖定的代碼和數(shù)據(jù)位于緩存的存儲(chǔ)區(qū)域中。

⑤?如果要鎖定的代碼和數(shù)據(jù)不在Cache中,使用Cache清除或清理指令,將其置換到Cache中。

⑥?N次循環(huán)執(zhí)行下面的操作。

·??index=I寫入寄存器c9,當(dāng)使用B格式的鎖定寄存器時(shí),令L=0。

·??如果鎖定的是數(shù)據(jù)Cache或數(shù)據(jù)和指令統(tǒng)一Cache,使用LDR指令將數(shù)據(jù)從內(nèi)存讀出,這個(gè)讀操作將使要鎖定的內(nèi)容存在于Cache行中。

·??如果鎖定的是指令Cache,那么要借助c7寄存器,相關(guān)指令詳細(xì)內(nèi)容,參見(jiàn)c7寄存器一節(jié)。

⑦??將index=N寫入寄存器c9,當(dāng)使用B格式的鎖定寄存器時(shí),令L=0。

如果要解除對(duì)N鎖定塊的鎖定,執(zhí)行以下操作。

·??將index=0寫入寄存器c9。

·??當(dāng)使用格式B的鎖定寄存器時(shí),令L=0。

15.3.8??內(nèi)存一致性

當(dāng)一個(gè)系統(tǒng)中同時(shí)使用了Cache、寫緩存時(shí),同一地址的數(shù)據(jù)可能同時(shí)出現(xiàn)在包括系統(tǒng)內(nèi)存在內(nèi)的多個(gè)不同的物理位置中。如果Cache引入了哈佛架構(gòu),使用數(shù)據(jù)和指令分類的Cache,那情況將更復(fù)雜。

由于上述存儲(chǔ)系統(tǒng)的多樣性特點(diǎn),當(dāng)從內(nèi)存中讀取數(shù)據(jù)時(shí),不能保證讀取的是數(shù)據(jù)的最新值(即有可能出現(xiàn)下述情況:寫操作將數(shù)據(jù)寫入到Cache中,但更新數(shù)據(jù)還沒(méi)有被回寫到內(nèi)存)。

ARM存儲(chǔ)系統(tǒng)中,數(shù)據(jù)不一致問(wèn)題一方面可以通過(guò)存儲(chǔ)系統(tǒng)自動(dòng)保證解決,另一方面編寫程序時(shí)要遵循一定的規(guī)則,防止數(shù)據(jù)不一致性發(fā)生。

下面就幾個(gè)常出現(xiàn)數(shù)據(jù)不一致的地方進(jìn)行討論。

·??地址映射發(fā)生變化時(shí)

·??指令和數(shù)據(jù)分離的Cache

·??系統(tǒng)執(zhí)行DMA(Direct?Memory?Access)操作

(1)地址映射發(fā)生的變換

當(dāng)系統(tǒng)中使用MMU時(shí),Cache行對(duì)應(yīng)的地址可能是:

①?內(nèi)存中的實(shí)際地址;

②?經(jīng)過(guò)地址轉(zhuǎn)換后的虛擬地址。

如果查詢Cache時(shí)相聯(lián)地址比較使用的是虛擬地址,則當(dāng)系統(tǒng)地址到物理地址的映射發(fā)生變換時(shí),可能造成Cache中數(shù)據(jù)與主存中的不一致。

同時(shí),當(dāng)系統(tǒng)中使用了寫緩存,處理器對(duì)寫緩存中的數(shù)據(jù)處理也是按虛擬地址進(jìn)行的,所以同樣會(huì)發(fā)生數(shù)據(jù)不統(tǒng)一的問(wèn)題。比如,當(dāng)前處理器使用虛擬地址向某個(gè)內(nèi)存單元寫數(shù)據(jù),該寫操作已經(jīng)將虛擬地址和數(shù)據(jù)寫入到寫緩存區(qū)中,此時(shí),虛擬地址到物理地址的映射關(guān)系發(fā)生變換,使先前要寫入數(shù)據(jù)的虛擬地址發(fā)生了變化,當(dāng)寫緩存將上面被延時(shí)的寫操作寫到主存時(shí),使用的是變換后的地址,從而寫操作執(zhí)行失敗。

為了避免發(fā)生這種數(shù)據(jù)不統(tǒng)一的情況,在系統(tǒng)虛擬地址到物理地址的映射關(guān)系發(fā)生變換前,根據(jù)系統(tǒng)的具體情況,執(zhí)行下面的操作序列中的一種或幾種。

·??如果數(shù)據(jù)Cache為寫回型Cache,清空該數(shù)據(jù)Cache。

·??使數(shù)據(jù)Cache中相應(yīng)的行無(wú)效。

·??使指令Cache中相應(yīng)的行無(wú)效。

·??將寫緩存區(qū)中被延時(shí)的操作全部執(zhí)行。

·??有些情況可能還要求相關(guān)的存儲(chǔ)區(qū)域被置換成非緩存的。

?

(2)指令Cache

當(dāng)系統(tǒng)中采用分離的數(shù)據(jù)Cache和指令Cache時(shí),下面的幾種情況可能造成指令不一致情況的發(fā)生。

①?地址為A1的指令被預(yù)取,該指令的數(shù)據(jù)行被取到Cache中。

②?和A1同在一個(gè)數(shù)據(jù)行的地址為A2的數(shù)據(jù)被一條存儲(chǔ)器寫操作修改。這個(gè)數(shù)據(jù)寫操作可能影響數(shù)據(jù)Cache中、寫緩存中和主存的地址為A2的存儲(chǔ)單元內(nèi)容,但不影響指令Cache中地址為A2的存儲(chǔ)單元中的內(nèi)容。

③?如果地址A2存放的是指令,當(dāng)該指令執(zhí)行時(shí),就可能發(fā)生指令不一致問(wèn)題。如果地址A2所在的行還在指令Cache中,系統(tǒng)將執(zhí)行修改前的指令;如果地址A2所在的行不在指令Cache中,地址將執(zhí)行修改后的指令。

為了避免這種指令不一致的情況發(fā)生,要在地址A2的數(shù)據(jù)被修改前執(zhí)行一些防護(hù)性的操作。也就是說(shuō),在步驟①和②之間插入下面必要的操作。

·??如果系統(tǒng)中使用的數(shù)據(jù)、指令統(tǒng)一的Cache,程序跳到步驟②繼續(xù)執(zhí)行。

·??對(duì)于使用數(shù)據(jù)和指令分離Cache的系統(tǒng),使指令Cache的內(nèi)容無(wú)效。

·??對(duì)于使用數(shù)據(jù)和指令分離Cache的系統(tǒng),如果數(shù)據(jù)Cache是寫回類型的,清空數(shù)據(jù)Cache。

上述操作系列可作為一種標(biāo)準(zhǔn),應(yīng)用于一些典型的場(chǎng)合。

注意

當(dāng)可執(zhí)行文件加載到主存中后,在程序跳轉(zhuǎn)到入口點(diǎn)處開(kāi)始執(zhí)行之前,先執(zhí)行上述操作序列,以保證新加載的可執(zhí)行代碼正確執(zhí)行。

(3)DMA造成的數(shù)據(jù)不一致

DMA操作直接訪問(wèn)內(nèi)存,不更新Cache和寫緩存區(qū)中相應(yīng)內(nèi)容,這樣就很可能造成數(shù)據(jù)不一致。

為了避免DMA造成的數(shù)據(jù)不統(tǒng)一,根據(jù)系統(tǒng)情況,執(zhí)行下面操作的一種和幾種。

·??將DMA訪問(wèn)的存儲(chǔ)器設(shè)置成非緩存的

·??將DMA訪問(wèn)的存儲(chǔ)區(qū)所涉及的數(shù)據(jù)Cache中的行設(shè)置成無(wú)效,或者清空數(shù)據(jù)Cache。

·??清空寫緩存區(qū)(將寫緩存區(qū)中延時(shí)操作全部執(zhí)行)。

·??在DMA訪問(wèn)期間限制存儲(chǔ)器訪問(wèn)DMA所訪問(wèn)的存儲(chǔ)區(qū)域。

15.3.9??Cache初始化子程序示例

下面給出了一段例子代碼,此代碼以ARM740T芯片為參考,顯示了Cache初始化的標(biāo)準(zhǔn)過(guò)程。

;下面代碼必須運(yùn)行于處理器的特權(quán)模式下。

????????AREA???INIT740,?CODE,?READONLY ;設(shè)置段屬性

????????ENTRY

????????EXPORT?Cache_Init ;以便作為子程序被其他程序使用

Cache_Init

;禁止MMU/MPU

;清理數(shù)據(jù)Cache

;

;

???????MRC?????p15,?0,?r0,?c1,?c0,?0 ;讀CP15寄存器c1到r0

???????BIC?????r0,?r0,?#0x1 ;清除bit[0]?

???????MCR?????p15,?0,?r0,?c1,?c0,?0 ;將設(shè)置的新值寫回

???????MOV?????r0,#0 ;準(zhǔn)備禁止其他域

???????MCR?????p15,?0,?r0,?c6,?c1,?0

???????MCR?????p15,?0,?r0,?c6,?c2,?0

???????MCR?????p15,?0,?r0,?c6,?c3,?0

???????MCR?????p15,?0,?r0,?c6,?c4,?0

;???????MCR?????p15,?0,?r0,?c6,?c5,?0

;???????MCR?????p15,?0,?r0,?c6,?c6,?0

;???????MCR?????p15,?0,?r0,?c6,?c7,?0??

;

;?區(qū)域0:背景區(qū):從0x0地址開(kāi)始的4GB存儲(chǔ)空間

;?區(qū)域1:SRAM區(qū):從0x0地址開(kāi)始的0x4000字節(jié)存儲(chǔ)空間

;?區(qū)域2:FLASH:從0x24000000開(kāi)始的0x02000000字節(jié)存儲(chǔ)空間

;?區(qū)域3:外設(shè)區(qū):從0x10000000地址開(kāi)始的0x10000000字節(jié)存儲(chǔ)空間

;開(kāi)啟?region?0?

?????????MOV?????r0,#2_111111

?????????MCR?????p15,?0,?r0,?c6,?c0,?0 ;?region?0區(qū)域0

;?開(kāi)啟region?1

?????????MOV?????r0,#2_100011

?????????MCR?????p15,?0,?r0,?c6,?c1,?0 ;?region?1區(qū)域1

;?開(kāi)啟region?2

?????????LDR?????r0,=2_110001+0x24000000

?????????MCR?????p15,?0,?r0,?c6,?c2,?0 ;?region?2區(qū)域2

;?開(kāi)啟region?3

?????????LDR?????r0,=2_110111?+?0x10000000

?????????MCR?????p15,?0,?r0,?c6,?c3,?0 ;?region?3區(qū)域3

;?開(kāi)啟Cache/寫緩存?

?????????MOV?????r0,?#2_0110

?????????MCR?????p15,?0,?r0,?c2,?c0,?0 ;Cache

?????????MCR?????p15,?0,?r0,?c3,?c0,?0 ;寫緩存

;?開(kāi)啟access?允許

?????????MOV?????r0,?#2_11111100

?????????MCR?????p15,?0,?r0,?c5,?c0,?0 ;允許訪問(wèn)

;

;?設(shè)置全局配置?

;

?????????MRC?????p15,?0,?r0,?c1,?c0,?0 ;讀CP15寄存器到r0

?????????ORR?????r0,?r0,?#(0x1?<<2)? ;開(kāi)啟Cache????????

?????????ORR?????r0,?r0,?#0x1 ;開(kāi)啟MPU

?

;

;增加的配置選項(xiàng)

;????????

;????????ORR?????r0,?r0,?#(0x1?<<13)? ;開(kāi)啟Hi?Vectors

;????????ORR?????r0,?r0,?#(0x1?<<7)? ;開(kāi)啟大端模式

?????????MCR?????p15,?0,?r0,?c1,?c0,?0 ;寫CP15寄存器c1

?????????MOV?????pc,lr ;返回

?????????END

上述程序端可作為參考,可以在程序中直接使用,也可以作為子程序被其他程序調(diào)用。如果作為子程序調(diào)用,下面兩種調(diào)用方式作為參考。

①?在匯編程序中調(diào)用。

????IMPORT?Cache_Init

????BL?Cache_Init

②?在C語(yǔ)言中調(diào)用。

extern?void?Cache_Init(void);

Cache_Init();

Arm

Arm

ARM公司是一家知識(shí)產(chǎn)權(quán)(IP)供應(yīng)商,主要為國(guó)際上其他的電子公司提供高性能RISC處理器、外設(shè)和系統(tǒng)芯片技術(shù)授權(quán)。目前,ARM公司的處理器內(nèi)核已經(jīng)成為便攜通訊、手持計(jì)算設(shè)備、多媒體數(shù)字消費(fèi)品等方案的RISC標(biāo)準(zhǔn)。公司1990年11月由Acorn、Apple和VLSI合并而成。

ARM公司是一家知識(shí)產(chǎn)權(quán)(IP)供應(yīng)商,主要為國(guó)際上其他的電子公司提供高性能RISC處理器、外設(shè)和系統(tǒng)芯片技術(shù)授權(quán)。目前,ARM公司的處理器內(nèi)核已經(jīng)成為便攜通訊、手持計(jì)算設(shè)備、多媒體數(shù)字消費(fèi)品等方案的RISC標(biāo)準(zhǔn)。公司1990年11月由Acorn、Apple和VLSI合并而成。收起

查看更多

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

華清遠(yuǎn)見(jiàn)(www.farsight.com.cn)是國(guó)內(nèi)領(lǐng)先嵌入師培訓(xùn)機(jī)構(gòu),2004年注冊(cè)于中國(guó)北京海淀高科技園區(qū),除北京總部外,上海、深圳、成都、南京、武漢、西安、廣州均有直營(yíng)分公司。華清遠(yuǎn)見(jiàn)除提供嵌入式相關(guān)的長(zhǎng)期就業(yè)培訓(xùn)、短期高端培訓(xùn)、師資培訓(xùn)及企業(yè)員工內(nèi)訓(xùn)等業(yè)務(wù)外,其下屬研發(fā)中心還負(fù)責(zé)嵌入式、Android及物聯(lián)網(wǎng)方向的教學(xué)實(shí)驗(yàn)平臺(tái)的研發(fā)及培訓(xùn)教材的出版,截止目前為止已公開(kāi)出版70余本嵌入式/移動(dòng)開(kāi)發(fā)/物聯(lián)網(wǎng)相關(guān)圖書。企業(yè)理念:專業(yè)始于專注 卓識(shí)源于遠(yuǎn)見(jiàn)。企業(yè)價(jià)值觀:做良心教育、做專業(yè)教育,更要做受人尊敬的職業(yè)教育。