吳 昊,章 博,陳香蘭,王 超,李 曦
中國科學技術大學 計算機科學與技術學院,合肥230026
在實時系統中,如一個汽車、機器人系統,系統的正確性同時取決于邏輯和時間的正確性。系統行為的定時、及時發生需要在軟件中明確指定,并在實時平臺上正確執行。然而,現有的編程語言缺乏顯示表達系統時間屬性的語法結構,為此實時系統領域逐漸衍生出了各種實時語言來顯示表達系統的時間屬性。
嵌入式實時系統編程模型根據其發展歷程和應用場景的需求主要可以分為三類:有界執行時間模型(bounded execution time,BET)[1]、零執行時間模型(zero execution time,ZET)[2]以及邏輯執行時間模型(logical execution time,LET)[3]。目前的實時編程語言便基于這三種編程模型。
有界執行時間模型又叫作異步模型,模型通過優先級決定任務的執行順序,要求任務在既定的截止時間之前完成執行。異步模型的代表性編程語言為Ada[4]。Ada通過調用時間控制函數來指定任務的時間屬性與時間行為,其運行時系統是基于線程模型實現的執行環境,在執行環境里多個并發的Ada 任務異步交錯執行。但在異步模型中,由于運行時系統缺乏對任務時序行為的約束,可搶占線程在并發情況下的執行過程具有不確定性,導致系統實際執行的時序語義很難與模型層保持一致性,系統行為具有不可預測性。
零執行時間模型又叫作同步模型,模型基于同步假設,即在邏輯上任務的執行時間為零。同步模型抽象層次高,具有數學抽象能力,可采用形式化工具證明其行為正確性。同步模型主要刻畫任務的因果關系,通過邏輯時間表達任務的時間行為?;谕侥P偷木幊陶Z言有Esterel[5]、PRET-C[6]、Lustre[7]以及Signal[8]等。然而,在實際的物理平臺中,無法實現無限快的運算速度,系統實際運行過程中不可能按照ZET的時序假設運行。
邏輯執行時間模型介于異步模型和同步模型之間,模型為每個任務指定了一段邏輯執行時間,任務只能在該時間段的開始和結束時刻分別執行輸入和輸出過程,即進行任務間的同步,而計算過程異步進行,且計算結果必須在輸出時刻之前有效。LET 模型約束了決定任務時序行為的關鍵過程(輸入和輸出),能直接有效地刻畫任務的時間行為。
Giotto[9]、HTL[10]、TDL[11]等現有的基于LET 模型的編程語言,其語言只描述了系統的時間約束,而具體的功能代碼則通過C、Java 等常見的高級語言來實現;語言通過特定編譯器編譯為中間代碼E-code[12],在執行時,虛擬機E-machine[12]根據E-code 描述的時間行為驅動功能代碼的執行,虛擬機本身則是運行在實時操作系統之上。這種將時間控制程序和功能代碼分開的方式并不方便設計,希望通過擴展一種高級語言的方式來實現一種實時編程語言。
本文提出一種基于C 擴展的實時編程語言TBC。TBC基于LET編程模型,在語言層次上,從設計的時間需求出發,引入可觀測事件的概念,來簡化系統內部的時間約束,降低系統響應延遲,并通過擴展的語法結構來表達系統中的各種時間屬性。在編譯器層次,本文提出了一種針對實時編程語言的編譯技術,通過在編譯器前端增加相應的數據結構來表示語法結構中的時間屬性,同時對中間語言LLVM IR進行時間指令擴展,使其可以表示系統的時間行為。在之前的工作中作者提出了包含時間語義的指令集TTI[13],將其作為編譯器的目標指令。
除了編程模型外,實時語言的區別主要在于其實現方式和編譯方式,本文針對這兩點提出一種實時語言設計框架,基于此架構來設計實時語言TBC。如圖1所示,整個語言框架分為高級語言、中間語言和匯編語言三個層次。

圖1 語言設計整體架構Fig.1 Overall architecture of language design
高級語言指實時語言本身,在本文中通過基于C擴展語法結構的方式來實現語言時間語義的擴展。在這里語法結構是指如if、for 一樣的語言結構,通過編譯器來進行分析處理,相對于Ada、RTOS通過API來指定時間屬性的方式,軟件程序更加簡單,不需要大量的代碼來設置定時器,處理不同的時間格式。同時如果程序使用某個平臺依賴的API,則該程序的運行不再靈活,時間操作必須是平臺依賴的,更重要的是,語法結構可以通過形式化的方式表示其語法和語義,并能對語義進行驗證。在高級語言層次,通過擴展的語法結構來表達多個任務并發執行的時間語義。
現有的許多編程框架[14-15]或實時語言基于RTOS來實現。如文獻[16]將實時語言Timed-C編譯成RTOS代碼,而本文將具有時間語義的指令集作為編譯器的目標代碼,這使得目標平臺不需要支持功能復雜的RTOS,只需要增加相應定時器來支持時間語義指令的實現。
具體的,編譯器基于LLVM[17]編譯器框架,分為前端和后端,并將LLVM IR 作為編譯器的中間語言。擴展的語法結構在編譯器前端經過分析處理轉換為中間語言中的時間指令,此時語法結構所表示的任務并發的執行行為轉換為時間指令所表示的串行執行行為。最后中間語言通過編譯器后端轉換成具體的匯編語言,即中間語言中的時間指令映射到匯編語言中的時間指令。
高級語言中的語法結構和中間語言及匯編語言中的時間指令都是為了約束各個層次中系統的時間行為,但為了便于系統設計者進行編程,語法結構應表示更高層次的時間約束,如任務級的任務周期、任務優先關系等;而時間指令應該更注重平臺實現,表示時間操作更具體,如延遲操作delay等。
另外,本文注重時間的本身,即各層次語言都應該明確語言中時間的連續離散與否、時間粒度等時間屬性。本文采用文獻[18]中時間域的概念來描述時間。時間域指時間所基于的一個數域(如R、N等),系統中的時間可取范圍為數域的值域。如圖1所示,各層次的時間隨著語言的轉換也進行相應的轉換。
本文將數域N 作為語言TBC 的時間域,即在TBC中,時間為離散的,并且時間域上的時間粒度為一段實時間,如1 ms、1 μs等,系統中的動作發生在基于離散時間域的某個時間點上,多個動作可以發生在同一個時刻。
CCSL(clock constraint specification language)[19]是嵌入式實時系統的標準描述語言(UML)[20]中描述時鐘約束的規范語言,可以用來表示各種連續和離散的時鐘。本文通過CCSL來形式化地定義TBC的離散時間域,在TBC默認時間粒度為1 ms,時間域通過CCSL定義為:

其中IdealClk在CCSL中表示一個連續時鐘,其單位為“s”,通過對該時鐘離散化可以得到一個離散時鐘。TBC的離散時間域std 通過一個以1 ms為tick間隔的離散時鐘來表示。
在TBC 中,引入可觀測事件的概念。將系統中的事件根據外界環境是否可以觀測到,分為可觀測事件和不可觀測事件兩種??捎^測事件主要指獲取外部傳感器的信號、更新執行器的值等動作,這些事件都和外部環境有直接的關聯。不可觀測事件主要指系統內部各個任務之間的數據通訊等,這些事件不被外界環境可見,其時間行為對外界環境也沒有直接的影響。
從設計需求的角度來看,構建實時系統時,所需的時間約束需求便是可觀測事件的時間約束,因此,主要關注可觀測事件的時間約束。本文以三元組(E,type,P)來表示可觀測事件的時間約束。其中E表示一個可觀測事件的標識符;type為事件的種類,分為輸入事件I和輸出事件O;P表示事件發生的周期,為一段實時間,取時間粒度的整數倍。如:(E1,I,10)表示周期為10 ms的輸入事件E1。本文以一個事件集合的形式作為系統設計的時間約束需求。
在TBC中,系統包括多個并發的周期性任務,每個任務分為相對獨立的I、C、O三部分。任務的輸入(輸出)可能包括一個或者多個事件來與外界或其他任務進行交互,可以根據任務的輸入(輸出)是否包含可觀測事件,即是否與外界環境進行通訊,將包含可觀測事件的輸入(輸出)叫作外部輸入(輸出),將包含不可觀測事件的輸入(輸出)叫作內部輸入(輸出)。
本文主要關注外部輸入(輸出)的時間約束。外部輸入(輸出)本身蘊含了兩種時間語義:外部輸入(輸出)首先作為LET編程模型的輸入(輸出),應在邏輯執行時間的開始(結束)時刻執行;同時因為外部輸入(輸出)包含了可觀測事件,所以應該滿足可觀測事件的時間約束。在TBC中,任務的邏輯執行時間等于任務周期,因此在構建任務時,通常將可觀測事件的周期作為其所在任務的任務周期。
內部輸入(輸出)適用于任務之間的數據通訊,從外部環境無法觀測,其時間行為并不直接影響系統與外界環境的通訊,因此不專門考慮內部輸入(輸出)的時間行為。從編程模型的角度來看,TBC實際上基于一種放松的LET模型。
在單個任務內部,擁有可觀測事件的外部輸入(輸出)基于時間觸發,每到任務邏輯執行時間的開始時刻(結束時刻)便會觸發任務的外部輸入(外部輸出)的執行。如圖2 所示,周期為T的任務T1 的外部輸入輸出分別在0時刻和T時刻進行觸發執行。

圖2 外部輸入輸出的時間行為Fig.2 Time behavior on external inputs and outputs
任務的內部輸入輸出用于兩個數據相關任務的數據同步,兩個任務會在邏輯執行時間的某個時間點進行同步。如圖3 所示,兩個周期都為T的任務T1 和T2,兩任務數據相關,T2 依賴于T1 的計算結果;在0時刻,T2 讀取外界傳感器傳來的數據,并在對數據進行計算后,在t1 時刻便通過內部輸出和任務T2 的內部輸入對計算結果進行同步,任務T2 在t1 時刻得到T1 的計算結果后,再經過自己的計算過程,在T時刻通過外部輸出向外輸出計算結果;t1 為基于離散時域的某個時刻,不過本文并不關注t1 時刻的具體數值,t1 時刻只需要處于T2 的計算過程完成之后以及T3 的計算過程開始之前。

圖3 內部輸入輸出的時間行為Fig.3 Time behavior on internal inputs and outputs
TBC放松了LET編程模型的時間約束,允許任務存在內部同步點,任務可在其邏輯執行時間段內進行通信,消除了邏輯執行時間模型中周期延遲問題,提升了系統響應能力。如圖4所示,對于圖3中的兩個任務T1和T2,在一般的LET模型中,系統在0時刻獲取傳感器的數據,在2T時刻才會產生相應的輸出;而在TBC中,如圖5所示,由于系統可以通過T1 的內部輸出和T2 的內部輸入在t1 時刻提前進行同步,在T時刻便可向外產生同樣的輸出,提升了系統的響應能力。TBC語言模型在保障系統與外界交互的時間行為不變的情況下,將系統的內部同步提前,來降低系統的響應延遲。

圖4 LET模型系統響應延遲Fig.4 System response delay of LET model

圖5 TBC系統響應延遲Fig.5 System response delay of TBC
當系統出現欠采樣和過采樣的情況時,需要指定系統的時間行為來保障輸入與輸出關系的確定性,本文規定系統在短周期任務的第一個周期內進行同步。
如圖6所示,周期和諧的兩個任務T1 和T2,T1 周期為T2 的兩倍,在0 時刻T1 讀取傳感器數據,在T和2T時刻T2 向外界輸出結果,本文規定這種欠采樣情況下同步點t1 位于任務T2 的第一個周期內,這樣保障T時刻和2T時刻的輸出結果對應于0 時刻的輸入,輸入和輸出之間可以相互確定。

圖6 系統欠采樣的時間行為Fig.6 Time behavior of system under-sampling
同理,對于系統發生過采樣的情況,如圖7所示,周期和諧的兩個任務T1 和T2,T2 周期為T1 的兩倍,在0時刻和T時刻T1 讀取傳感器數據,在2T時刻T2 向外界輸出結果,本文規定兩任務的同步點t1 位于任務T1 的第一個周期內,保障2T時刻的輸出結果對應于0時刻的輸入,輸入和輸出之間關系可以確定。

圖7 系統過采樣的時間行為Fig.7 Time behavior of system over-sampling
任務中的輸入輸出過程,在邏輯層次被認為是在觸發時刻瞬時執行,在具體的物理執行平臺上,輸入輸出過程勢必要花費一段時間來執行(即使時間很短),執行過程處于一個時間執行區間上。如圖8所示,對于外部輸入過程,邏輯層次在0時刻執行,到物理層次上,其執行在一個時間區間[0,t1]上,其中t1 為輸入的執行時間長度;同理,對于外部輸出過程,邏輯層次在T時刻執行,到物理層次上,其執行在一個時間區間[t2,T]上。

圖8 時間映射Fig.8 Time mapping
對于內部輸入輸出過程,在邏輯層次上,由于其并非在某確定時間點定時觸發,只需要滿足進行同步的兩個輸入輸出,輸出過程在輸入過程之前執行。
本文用組件來統一表示任務中的I、C、O 過程。組件一共有五種:內部輸入組件、外部輸入組件、計算組件、外部輸出組件、內部輸出組件。每個組件會被分配一個執行區間(slot),組件在執行區間執行時不可搶占,組件若提前執行完成,可主動放棄處理器資源;對于任務的輸入輸出組件來說,執行區間即為從邏輯層次映射到物理層次的時間區間。組件的執行區間通常設置為大于或等于其最壞情況執行時間(worst-case execution time,WCET)的值,避免組件執行出現超時的情況。為了便于分析計算,執行區間的長度以離散時域的時間粒度(ms)為單位,取整數值。
如表1所示,TBC擴展了7種時間語法結構,來表示系統中的任務、各種組件及其時間屬性。

表1 擴展的語法結構Table 1 Extended syntax structure
Task語法結構用于定義一個并發的LET任務,語法結構顯示聲明了任務的兩個參數:任務的唯一標識符以及任務周期。如Task(T1,50){…}表示一個周期為50 ms的LET 任務,Task 語法結構大括號內的部分為任務體,任務體由三個組件構成,即一個輸入組件(內部輸入組件或者外部輸入組件)、一個輸出組件(內部輸出組件或者外部輸出組件)以及一個計算組件。
E_I 語法結構和I 語法結構分別代表外部輸入組件和內部輸入組件,兩個語法結構顯示聲明了任務輸入的兩個參數:輸入組件的標識符以及組件的執行區間長度;E_O語法結構和O語法結構分別代表外部輸出組件或者內部輸出組件,兩個語法結構顯示聲明了輸出組件的標識符以及組件的執行區間長度;與PRET-C和文獻[21]中的語言相同,TBC 采用全局變量作為任務間通訊方式。C語法結構代表任務的計算組件,顯示聲明了組件標識符和計算過程的執行區間長度。
Pre 語法結構規定了任務之間的數據依賴關系,包括兩個參數,分別表示屬于不同任務的內部輸出組件和內部輸入組件,任務通過這兩個組件會進行數據同步。如對于兩個任務T1、T2,T2 數據依賴于T1,T2 擁有一個內部輸入P2,T1 擁有一個內部輸出P1,則可通過Pre(P1,P2)表示兩個任務之間的數據依賴關系。
本文通過擴展的巴科斯范式(extended Backus-Naur form,EBNF)來形式化描述TBC的語法規則。EBNF是巴科斯范式(Backus-Naur form,BNF)的一種擴展,通常作為計算機編程語言和形式語言的形式化語法表示方法。TBC 的EBNF 表示如下所示,其中"c_code"表示常規的C語言代碼。


本章將介紹TBC特有的編譯技術。編譯器通過對TBC程序中的時間語法結構進行分析處理,最終將其轉換為特定的匯編指令。
如圖9 所示,TBC 編譯器基于LLVM 編譯器框架,主要包括編譯器前端、IR和編譯器后端三部分。

圖9 編譯器總體架構Fig.9 Compiler general architecture
TBC前端分為詞法分析、語法分析、分析調度、中間代碼生成四個過程。詞法分析和語法分析分別通過Flex 和Bison 工具來實現。與常規的編譯器不同,TBC程序經過詞法分析和語法分析后除了生成抽象語法樹(abstract syntax tree,AST)以外,還會生成TBC 特有的中間表示DAG(directed acyclic graph)和TAST(timed AST)。DAG和TAST分別用于表示TBC程序中的時序關系和時間值信息。兩種中間表示接下來作為分析調度器的輸入,經過靜態分析、調度后會生成系統全局的靜態調度表。在中間代碼生成階段,抽象語法樹會結合靜態調度表的調度信息生成LLVM的中間語言IR。
在TBC 編譯器中,本文基于IR 擴展了具有時間操作的指令,使得IR擁有定時觸發的語義,這里將擴展了時間指令的LLVM IR 叫作TIR(timed LLVM IR)。在編譯器的后端,將基于RISCV的時間語義指令集TTI作為后端的目標指令集。
如圖10 所示,TBC 程序經過編譯器各個步驟進行了多次轉換,最終映射到匯編指令。在高級語言層次,TBC通過擴展的語法結構來表示程序中的時間語義;表示時間語義的語法結構在編譯器前端轉換為中間表示TAST和DAG,分別表示程序中的時序關系和時間值信息;經過分析調度后,程序中的時序關系和時間值信息再轉換為調度表所表示的串行時間行為;中間語言TIR通過擴展時間操作指令,根據調度表中的調度信息以定時觸發的方式驅動系統運行;最后經過編譯器后端的指令映射,TIR中的時間指令最終轉換為具有時間語義的匯編指令TTI。

圖10 程序轉換流程Fig.10 Program translation flow
在編譯器前端,程序的功能部分和時間控制部分被分開處理。TBC 對于功能部分的處理和普通編譯器相同,通過詞法分析和語法分析得到AST,并對AST 進行相應的的語義分析。為了使得編譯器能夠更好地分析處理時間,TBC編譯器將程序中所有與時間有關的信息分為時序關系和時間值信息兩部分,并分別用兩種中間數據結構DAG圖和TAST表示。
DAG 圖用于表示組件之間的時序關系,時序關系分為兩種。DAG 圖如圖11 所示,圖中實線表示不同任務組件之間的時序關系,即程序中Pre 語法結構所聲明的任務之間的數據依賴關系;圖中虛線表示LET任務內固有的時序關系,即任務的計算組件要在輸入組件和輸出組件之間執行。

圖11 DAG圖Fig.11 DAG figure
TAST 主要有兩個作用:一是用于表示系統的結構層次,二是充當一個特殊符號表。如圖12 所示,TAST展現了系統的整體結構,根節點TBC 中每個分支代表了一個并發的LET任務,而每個任務則包含多個不同類型的組件節點。同時作為一個符號表,樹儲存著系統的時間值信息:每個任務節點儲存任務的周期值,每個組件節點儲存著組件的執行區間長度。

圖12 TAST內部結構Fig.12 Internal structure of TAST
本文采用靜態調度的方式,在編譯器前端生成靜態調度表,調度表中指定了組件執行的順序和具體時刻。
4.3.1 必要性分析
在得到TAST 后,編譯器便可以檢查系統可調度的必要條件,即任務利用率和系統利用率都是否小于等于1。具體的,將任務各組件執行區間長度之和除以任務周期,作為任務的利用率,所有任務的利用率都必須要小于等于1,否則終止編譯,并給出錯誤信息。將一個超周期內,系統執行所有組件用時總和除以系統的超周期,作為系統的利用率,系統利用率必須小于1,否則同樣終止編譯,并給出錯誤信息。用P表示任務的周期,TT表示系統的超周期,其中TT為所有任務的最小公倍數,Ti(Mj)表示任務i的第j個組件,slot表示組件的執行區間長度。必要性分析形式化表示如下,其中N表示系統任務數量,Ni表示第i個任務組件的數量。

4.3.2 調度表
在初步檢查滿足系統可調度的必要條件后,通過DAG 圖和TAST 中的信息進行靜態調度。本文通過對多個周期任務進行循環展開,來集成一個周期為超周期的大循環塊,靜態調度表中的每一個表項用于表示組件一次執行的具體時間行為,可以通過三元組(M,t1,t2)來形式化表示,其中M表示組件的標識符,t1 表示組件在循環塊中的開始執行時間,t2 表示組件的執行區間長度。
4.3.3 調度規則
對于系統復雜的情況,靜態調度有可能是個NP-hard問題,常通過啟發式算法等來解決。本文不涉及具體的調度算法,而是規定調度中所要遵循的調度規則,調度規則主要指靜態調度需要遵循的優先關系,主要包括以下兩部分:
(1)靜態調度需要滿足DAG圖中指定的時序關系:同一任務的計算組件要在輸入組件和輸出組件之間執行;進行數據同步的兩個組件,輸入組件要在輸出組件之后執行。
(2)對于一個實際的系統,會出現多個任務的外部輸入(輸出)同時定時觸發的情況,如兩個任務的外部輸入同時在0時刻觸發執行,需要指定多個任務同時輸入(輸出)的優先順序:首先根據RM 調度規則,即任務的周期越短,其輸入(輸出)越優先執行;若兩個任務的周期相同,則按照任務的標識符的大小,如兩個周期相同的任務T1 和T2,T1 的輸入(輸出)優先于T2 的輸入(輸出)。
4.3.4 調度表處理
調度表中兩個相鄰表項之間會出現存在空閑時間段的情況,如兩個相鄰的表項(M1,t1,t2),(M2,t3,t4),如果t1+t2 在IR層次,本文擴展了具有時間操作的指令,使得IR可以表示調度表中組件串行執行的時間行為。本文中將具有時間指令的LLVM IR叫作TIR。 在TIR 中,采用時間觸發的系統執行模式[22],根據調度表中預先安排的組件時序行為,來定時驅動組件的執行,且一次只需要處理一個組件,時間觸發的方式不但可以提高系統的可預測性,更便于對系統功能和時序的正確性進行驗證。 TIR和TBC基于同樣的離散時間域,以1 ms為時間粒度,TIR 的時間觸發方式通過點時間來展現:對于調度表中的一個表項(M1,t1,t2),代表了系統會在點時間t1 觸發組件M的開始執行,與TBC的并發執行語義不同,在TIR中,組件根據調度表中的信息串行執行,執行時間為組件的執行區間長度。 TIR 擴展了絕對延時指令delay_until 指令,其語義表示從當前時間開始延遲到某個時間點,如delay_until i32 10表示延遲到系統時間點10 ms。 同時TIR 擴展了兩條時間初始化指令timeinit 和timegran。timegran 用于設置系統的時間粒度,時間粒度為μs的整數倍,如timegran i32 2表示設置時間粒度為2 μs。timeinit指令用于設置當前系統時間。 TIR 程序的整體結構為一個大的循環,TIR 程序結構如圖13所示,程序最開始時設置系統時間粒度為1 ms(與TBC 保持一致),每個循環開始時重置系統時間為0,每次循環系統按調度表中的調度信息定時執行組件。 圖13 TIR程序結構Fig.13 TIR program structure 對于調度表中的表項,將其映射到的TIR 指令如圖13所示,如果表項是一個組件表項,組件功能代碼的轉換和普通基于LLVM 架構的編譯器相同。圖13 中,(M1,tstart1,tinterval1)是調度表中的第一個表項,組件M1從時刻tstart1=0 開始執行,通過絕對延時指令delay_until保證M1 占用系統時間到tstart2=tstart1+tinterval1 時刻,因設置的執行區間長度tinterval1 大于組件的WCET,不會出現超時的情況。 TIR通過定時觸發的方式來驅動系統執行,因此作為編譯器后端的目標指令集需要支持TIR 的定時觸發語義。本文使用時間指令集TTI 作為TBC 編譯器的目標指令集,TTI指令集是本實驗室提出的具有時間語義的指令集,TTI 基于RISC-V 指令集進行時間語義擴展。RISC-V是一個典型的三操作數、加載-存儲形式的RISC 指令集架構,其擴展指令分為標準擴展和非標準擴展兩類,其中非標準擴展作為一個高度特殊化的擴展,由用戶根據功能需求自定義完成,TTI 指令集基于RISC-V非標準擴展進行定義。 在TTI 中,時間采用時間點的形式來表示,對于段時間,通過段時間的開始時間點和結束時間點來表示。 TTI擴展了多個時間語義的指令,用來表示時間觸發的語義,擴展的指令如下: (1)時間管理指令:setti/getti 指令用于設置/獲取系統當前時間點;settg 指令用于設置系統當前時間粒度,為了和TIR的時間粒度統一,將TTI的時間粒度默認設為1 ms。 (2)實時操作指令:delay指令用于將時間延遲到一個絕對時間點。 LLVM 的后端通??梢苑譃橥ㄓ么a生成器和后端移植接口兩部分,而增加一個LLVM新后端主要指增加相關的后端移植接口。后端移植接口主要包括全局描述實現、寄存器描述實現、指令集描述實現、匯編輸出描述實現等。一般后端信息主要采用LLVM 架構中的Tablegen 語言進行后端的描述。TableGen 是LLVM 中用來專門描述目標后端的語言,主要用于描述子目標平臺、寄存器文件、調用慣例和指令集等目標平臺相關信息。 TBC編譯器后端基于開源項目LLVM-RISCV進行擴展,擴展主要包括TTI時間指令的擴展和TIR時間指令與TTI時間指令之間的映射兩部分。本文通過Tablegen來描述指令的擴展和指令的映射。 TIR與TTI的映射關系如表2所示,本文通過Tablegen中的DAG匿名匹配模式來實現指令的映射。 表2 指令映射Table 2 Instruction mapping 本文通過一個遙控車控制實例來展示如何用TBC構建實時系統。遙控車控制系統如下:遙控車每隔50 ms接受手柄的控制信號,根據控制信號,計算得到小車當前的速度、加速度等狀態信息,以及控制小車電機轉動的PWM 波;小車每隔100 ms 將狀態信息通過zigbee 通訊模塊傳送給PC 端,使得小車的狀態信息可以被實時獲取;同時小車每隔50 ms 將PWM 波傳送給電機,電機驅動車輪轉動。以上信息可以規約為一個外部事件的集合:(E1,I,50),(E2,O,50),(E3,O,100) ;事件E1 表示接受手柄信號,E2 表示將PWM波傳送給電機,E3 表示將狀態信息傳送給PC端,該集合作為系統設計的時間需求。由此基于TBC模型構建遙控車控制系統如表3 所示。遙控車控制系統包括三個并發的任務,其中任務T1 包含輸入事件E1,任務T2 和T3 的分別包含輸出事件E2 和E3。 表3 遙控車控制系統任務集Table 3 Task set of remote control vehicle system 遙控車控制系統如偽代碼1所示,其中com1到com5表示任務中的計算函數。任務T1 通過計算得到小車的狀態信息和PWM 波,通過內部輸出P2 將這些數據傳送給其他任務,任務T2 和T3 分別通過內部輸入P3和P5 獲得T1 的輸出數據。偽代碼1 中的第24、25 行“Pre(P2,P3)”“Pre(P2,P5)”用來表示三個任務之間的數據依賴關系。 偽代碼1遙控車控制系統TBC程序偽代碼 TBC程序經過前端的分析調度后執行序列如圖14所示。對于外部輸入輸出組件P1、P4 和P6,其執行位于周期開始或結束的時刻,其余組件遵照調度規則中的優先關系執行。 圖14 組件執行序列Fig.14 Component execution sequence 具體的調度表信息如下:(P1,0,1),(C1,1,10),(P2,11,1),(P3,12,1),(C2,13,5),(P5,18,1),(C3,19,10),(D,29,20),(P4,49,1),(P1,50,1),(C1,51,10),(P2,61,1),(P3,62,1),(C2,63,5),(D,68,30),(P4,98,1)(P6,99,1)。其中(D,29,20)和(D,68,30)表示系統空閑狀態,對應圖14 中的空白部分。 程序經過前端的分析調度以及后端的指令映射后,最后轉換為TTI 匯編代碼,匯編程序代碼如偽代碼2 所示,這里主要展示TTI程序的時間行為。 偽代碼2遙控車系統TTI程序偽代碼 其中第1行到第2行表示系統時間粒度的設置,第4行表示每次循環系統時間的重置,第5 行到第7 行則對應三元組表項(P1,0,1),用來控制組件P1 的時間行為。 本文使用實驗室開發的專門支持TTI指令的RISCV仿真器來測試TBC 各方面性能,仿真器可精確模擬各TTI指令在流水線各段的行為,以此獲得系統運行的具體時間行為(精確到時鐘cycle 級別),仿真器的頻率設置為1 MHz。 除了通過TBC 來實現上述遙控車控制系統外,本文還通過傳統的LET模型,基于PSPM[15]編程框架來實現,PSPM運行在stm32F407開發板上,開發板采用基于RAM架構的CortexM4芯片,芯片具有168 MHz的時鐘頻率。 兩種實現方式的系統輸入輸出抖動如表4 所示。這里系統輸入輸出抖動是指系統實際I/O開始時間和系統設計時間的差值。基于傳統LET 模型的PSPM 編程框架,其底層通過FreeRTOS實時操作系統來實現,輸入輸出抖動由系統內核開銷、時間調度器開銷導致,高達幾百個時鐘cycle;相比之下,TBC使用時間指令來保障系統行為的定時觸發,輸入輸出抖動由delay指令引起,其導致系統實際輸入輸出的時間比預期時間延遲一個時鐘cycle,遠小于前者,具有更強的時間可預測性。 表4 系統輸入輸出抖動Table 4 System input and output jitter 表5為兩種實現方式的系統平均端到端延遲,其中端到端延遲1為從接收到遙控信號到輸出PWM波的時間,端到端延遲2為從接收到遙控信號到輸出狀態信息的時間。在傳統的LET模型中,任務之間只能在邏輯執行時間的開始和結束時刻進行交互,導致整個系統的端到端延遲時間較長;而TBC 的LET 模型與傳統的LET模型相比,增加了外部、內部事件,允許任務在邏輯執行時間內與其他任務進行交互,使得系統端到端延遲降低了大約50%。綜上,TBC采用了放松的LET模型,在提高了時間可預測性的同時,相對于傳統的LET模型降低了系統的端到端延遲。 表5 系統端到端延遲Table 5 System end-to-end latency 本文提出了一種基于LET 的時間語義編程語言TBC以及相應的編譯技術。主要包含以下工作: (1)提出一種實時語言設計和編譯的通用模型,基于此模型可以方便條理地設計一種實時語言。 (2)基于通用語言C,擴展了具有時間語義的語法結構,來實現實時語言TBC;同時基于LET模型,增加了可觀測事件的概念,旨在保證系統中與外界環境相關聯事件的時間行為,同時降低了系統的響應延遲。 (3)提出了一種實時語言的編譯技術,通過在編譯器前端增加中間表示DAG 和TAST 來表示語法結構中的時間屬性。同時通過對中間語言IR進行時間指令擴展,使得其可以定時觸發系統中的行為,并可以映射到特定的時間語義指令集。 未來的主要工作集中于TBC語言設計的完善。目前TIR中的時間和操作相對分離,并不能很好體現定時觸發的語義,計劃添加定時觸發指令TT,其語義為某操作在某時刻定時觸發執行;TBC 中的任務皆為周期任務,對于系統中存在的非安全關鍵的非周期任務,可將其插入到空閑塊(D,t1,t2)中執行,使其對周期任務的時間行為不產生影響。4.4 中間語言

4.5 編譯器后端

5 實驗設計與分析
5.1 基于TBC構建遙控車控制系統





5.2 實驗對比分析


6 結束語