您的位置:首页 > 运维架构 > 网站架构

PRET-C:一种用于精确定时架构的编程新语言

2020-02-02 09:50 1586 查看

1.摘要

精确定时架构(PRET)是最近提出的一种设计实时嵌入式系统处理器的方案。这些处理器必须在不牺牲吞吐量的情况下保证应用程序的精确最坏情况反应时间(WCRT),并且必须允许程序的WCRT的计算既简单又有效。本文的目的是提出一种新的基于同步语言的PRET-C,用于编写编译器。PRET-C支持同步并发、抢占和逻辑时间的高级构造。与现有的同步语言相比,PRET-C在并发线程之间提供了基于C的共享内存通信,通过所提议的语义可以保证线程安全。抢占在语义上也更简单。得益于C库,程序员可以通过控制硬件计时器自由地混合逻辑时间(尽管是逻辑节拍的概念)和物理时间。通过WCRT分析器和相关的编译器,可以实现逻辑时间到物理时间的映射。我们还提出了奥克兰反应PRET处理器(ARPRET),它定制了通用处理器(GPP) Xilinx MicroBlaze处理器。PRET-C和ARPRET一起为精确定时嵌入式系统的设计提供了一个简单、可伸缩和高效的解决方案。

典型的嵌入式应用,从复杂的飞机飞行控制器到简单的数码相机,都需要对它们的定时性能做出最坏的保证,因此被称为实时系统。由于推测性很强,所以通用处理器并不适合实现这样的系统。虽然许多研究人员正在研究应用程序需求与处理器技术的匹配,但是具有可预测性的处理器设计,以便直接匹配实时应用程序,仍然是一个开放的研究问题。

不过,支持可预测执行的体系结构并不是一个新概念。多活动上下文系统(mac)架构[9]是在1991年提出的。MACS是一种无缓存的体系结构,它在硬件中跟踪多个任务上下文,在每个循环中使用一个循环调度来从不同的任务上下文发出一条指令。随着精确定时机器(或PRET机器)[11]的概念的出现,可预测架构的思想得到了发展。PRET机器的核心思想是保证精确的定时而不牺牲吞吐量。另一个重要的目的是简化代码执行机器的最坏情况定时分析。自从第一次提议以来,加州大学伯克利分校和哥伦比亚大学集团已经开发了一种基于SPARC的PRET机器[15](以下称为Berkeley-Columbia方法)。其主要思想是引入一个线程交错的管道,它在一个内存轮的支持下执行,这样管道的每个阶段都可以从一个新线程中获取数据。此外,它们使用暂存存储器和适当的静态分配机制[16]消除缓存。最重要的是,他们添加了deadi指令来实现代码段的精确定时:这些指令具有适当的截止日期值,插入到适当的点以确保对共享内存的互斥访问。

虽然berkley-columbia方法是执行C程序的第一个通用PRET机器,但PRET机器也是在奥克兰大学和基尔大学的反应处理器的名义下开发的。在[20]中首次提出的反应型处理器是使用类似于esterel的[4]ISA来开发的,目的是消除现代处理器中中断的不精确的环境交互机制。随后,它们被用于直接高效地执行Esterel代码[18,26]和精确地执行[5]。精确执行是通过使用Esterel程序的最坏情况反应时间分析(WCRT)来确定滴答的长度。然后,处理器的锁周期被固定到这个滴答长度,以实现精确的定时。请注意,Esterel的WCRT分析比C等过程语言的WCET分析要简单得多,并且已经开发了一个简单的 算法[5]。此外,Java的PRET体系结构是由维也纳的一个小组开发的,在[21]中对可预测的体系结构进行了很好的调查。

尽管难以预测地执行,C语言仍然是嵌入式系统编程的首选语言:系统分为相互作用的硬件和软件组件,其中硬件组件在FPGA上合成,软件部分在执行多线程C代码的RTOS上执行。然而,RTOSs增加了不必要的开销,而整个执行仍然是不确定的,因此是不可预测的。本文的目标是对C进行简单的扩展,以确保在通用处理器上执行时不需要任何RTOS。扩展应该是这样的,它们中的大多数都可以作为C宏来实现,这样就不需要复杂的编译器了。此外,该语言的语法和语义应该足够简单,以便于C程序员采用。最后,语言设计应该记住,通用处理器(general purpose processor, gpp)本质上是不可预测的,并且它应该为可预测性提供方便的处理器定制。

考虑到这些目标,我们建议对C进行一组简单的同步扩展。我们使用众所周知的同步语义[2],因为它为可预测性(如决定论和反应性)提供了重要的好处。我们对C语言的扩展如下:ReactiveInput、ReactiveOutput、EOT、PAR和abort when  pre。ReactiveInput和ReactiveOutput语句声明环境的输入和输出。EOT结构结束线程的本地标记。程序的全局标记发生在所有活动线程完成其本地标记之后。因此,EOT为程序员提供了一个管理逻辑时间的非常简单的方案。PAR结构用于创建并发线程,其中所有线程都具有固定的优先级,该优先级基于它们在PAR中的语法顺序。线程使用C共享变量进行通信。由于PAR构造的顺序语义以及读写操作的原子性,线程自动成为线程安全的。预构造时的中止在满足指定条件时抢占线程。

对C的同步扩展不是新的[6,7,13]。ReactiveC[6]与我们的方法最接近,PAR结构与ReactiveC中的PAR相似。相反,我们允许多重读写器在一个瞬间读取这个变量的不同值。另一方面,ReactiveC需要一个更严格的数据一致性概念,即所有的读取器必须读取相同的数据值。我们放宽了这个限制,因此PRET-C程序可以不受限制地访问共享数据,但是由于语言的语义,整个程序仍然是确定性的。这简化了程序员对共享资源的简单管理,而不需要复杂的基于操作系统的同步特性。ECL[13]是一个更接近于Esterel的同步C扩展,它的同步并行结构与Esterel完全相同。ECL中线程之间通信的主要方式是通过信号,就像Esterel中一样。与PRET-C相比,所有这些语言都更加复杂,并且在设计时没有考虑到可预测性。最近,有人提出了一种称为SC[23]的语言来对C语言中的Statecharts进行编码。但是,与PRET-C相比,它更加复杂,因为需要加强Statecharts语义。

关于架构,我们提出了一个PRET架构称为ARPRET(奥克兰反应PRET)通过自定义现有的软核GPP。ARPRET的灵感来自于反应式处理器[20,26,14]和[11]的PRET机器。然而,它增强和扩展了两者。首先,与自定义设计的PRET机器不同,我们建议对软核嵌入式处理器进行简单的硬件扩展。我们的硬件扩展是通过扩展Xilinx[24]的MicroBlaze软核处理器来实现的。但是,这种扩展在任何其他软核处理器上都是可行的。因此,我们的方案通过使用更少的硬件资源来实现PRET,并演示了如何重用软核处理器来实现PRET。

虽然ARPRET是一个响应性处理器[26],但它显著扩展了所有早期的响应性处理器。首先,所有现有的无功处理器都能够只执行纯Esterel而不需要任何C函数调用。其次,早期的反应性处理器依赖于WCRT分析,该分析已被证明是悲观的[5]。最后,所有早期的响应处理器都是自定义处理器。我们演示了通过简单的gpp定制和使用C-宏,我们可以设计使用非常少的硬件定制的PRET机器。

本文的组织结构如下。在第2节中,我们通过一个生产者消费者示例以及一个称为TCCFG的中间格式来展示PRET-C语言。接下来是第3节中的语义。在第4节中,我们将介绍ARPRET体系结构以及PRET-C程序的执行方式。实验结果见第6节,结论见第7节。

2.PRET-C概述

PRET-C的总体设计理念和相关架构可以用以下三个简单的概念来概括:

  • 并发:并发是逻辑的,但执行是顺序的。这是用来确保同步执行和线程安全的内存通信。这是同步编程语言[2]的基本原则。
  • 时间:时间是逻辑的,逻辑时间到物理时间的映射是由编译器和WCRT分析器[19]实现的。
  • 设计方法:ARPRET通过简单的GPPs定制来实现PRET。C语言的扩展是通过C宏实现的。

2.1.PRET-C语言扩展

               状态                                  意义
响应输入 声明I作为来自环境的响应性输入
响应性输出 声明O作为向环境发出的响应性输出
并行执行n个线程Ti,优先级Ti高于Ti+1
标记一个标记的结束(本地或全局,取决于其位置)
[weak] abort P when pre C 当C为真时,立即杀死P

 

PRET-C(精确定时C)是C语言的同步扩展,在本质上类似于ECL和ReactiveC。与早期的同步C扩展不同,它基于最小的扩展集,并且是专门为在ARPRET上执行可预测而设计的。它使用表1中所示的5个构造来扩展C。为了保证可预测的执行,我们对C语言施加了以下四个限制:

  • 不允许指针和动态内存分配,以防止内存分配的不可预测性。
  • 所有的回路必须至少有一个EOT在其体内。这是确保线程组合没有死锁所必需的。对于可以被静态证明为有限的循环,可以放宽这一限制。
  • 所有的函数调用必须是非递归的,以确保函数的执行是可预测的。
  • 通过goto语句的跳转是不允许跨逻辑瞬间的(例如:EOTs)。

我们的5个C扩展被实现为C宏,它们都包含在pret.h文件中,必须在所有PRET-C程序的开头包含该文件。因此,我们只能依赖gcc宏扩展器和编译器来编译PRET-C程序。

与任何C程序一样,PRET-C程序以序言部分(#define和#include行)开始,然后是全局声明(响应性输入、响应性输出和经典C全局变量),最后是函数定义(包括主函数)。

PRET-C程序按外部时钟触发的节拍序列周期性地运行。来自环境的输入在每次滴答开始时采样。它们是用ReactiveInput语句声明的。向环境发出的输出用ReactiveOutput语句声明。响应性输入在每次滴答开始时从环境中读取,并且不能在程序内部修改。因此,这些变量的值在瞬间保持不变。当环境没有赋值时,它们有一个默认值。相反,响应性输出可以由程序更新,并且可以在瞬间得到永久值。这些变量的最终值(称为它们的稳态值)被发送到环境中。响应性输出的行为与C语言中的普通变量完全相同,只是它们被发送到环境中,而普通变量用于线程之间的通信,在环境中看不到。

熟悉常用同步语言(如Esterel[4]或其早期基于C的扩展[13])的程序员会注意到与PRET-C的区别。与这些线程通信的主要方式是信号的语言不同,我们使用变量。当信号不纯时,它是一个状态值和一个关联值。出于因果关系的原因,Esterel禁止在线程之间的通信中使用变量。PRET-C允许不受限制的共享变量跨线程访问,线程安全通信是使用静态线程优先级和并行操作符的语义实现的(参见第3节)。

PAR(T1,…,Tn)语句生成n个线程,这些线程在锁步中执行。所有派生的线程都基于相同的环境视图进行演化。但是,与其他同步语言(如Esterel)中常见的||不同,在Esterel中,线程是根据它们的信号依赖关系在每个瞬间调度的,而PRET-C中的线程总是根据固定的静态顺序调度的。这是根据线程使用PAR构造生成的顺序来确定的。例如,PAR(T1,T2)语句为T1分配的优先级高于T2。

并行线程通过共享变量和响应输出进行通信。确保互斥访问的任务是通过确保调度程序在每个瞬间以固定的总顺序执行所有线程来实现的。当多个线程作为同一变量的写入器时,程序的执行语义仍然是确定的。确实,当这些写操作是非原子的时候,RTOSs中会发生竞态条件。如果一个操作可以被中断,另一个线程可以修改同一个变量。然而,只要这些写操作以某种固定的顺序原子地发生,结果的值总是可预测的,竞态条件将被阻止。这是由我们的ARPRET体系结构确保的,这得益于我们提出的多线程执行。在ARPRET上,一旦线程开始执行,它就不能被中断。只有在前一个线程到达它的EOT时才会调度下一个线程。因此,当两个或多个线程可以修改同一个变量时,它们总是以某种固定的顺序进行修改,以确保数据是一致的。

EOT语句标志着一个标记的结束。当在多个并行线程中使用时,它实现了这些线程之间的同步屏障。实际上,每一个EOT都标志着其线程的本地标记的结束。只有当PAR()的所有参与线程到达各自的EOT时,全局标记才会运行。从这个意义上说,EOT类似于Esterel的pause语句。EOT通过确保只有在所有线程都到达它们的EOT时才启动下一个标记,从而加强了并行线程之间的同步。最后,它允许通过计算任意两个连续EOT之间调度的所有计算所需的执行时间来精确地计算程序的WCRT。这个WCRT分析在一个配套的报告[19]中提出。

EOT在本质上类似于[15]的deadi指令(即时截止日期)。但是,与通过关联计时器来管理定时的低级deadi指令不同,EOT是一种高级编程构造。确保线程精确计时的任务不是留给程序员的,而是由WCRT分析派生出来的,是一个编译任务[19]。此外,deadline指令还用于通过时间交错访问共享内存来实现互斥。这是通过为最后期限设置精确的值来实现的。然而,如果手工完成,这个任务可能会非常复杂,即使对于简单的程序也是如此。这主要是由于任意的分支结构和循环。自动化这个任务并不简单,在[15]中还没有解决。另一方面,我们实现对共享内存的互斥访问的解决方案是通过拥有静态线程优先级来确保的,然后在每个瞬间以这个固定的线性顺序调度线程。

当C条件为真时,PRE-C结构体中的”abort P“会立即抢占它的”body P“(如Esterel中的immediate abort)。与Esterel一样,抢占既可以是强的(单独中止),也可以是弱的(使用optional weak关键字时)。在强中止的情况下,抢占发生在瞬间的开始,而弱中止允许它的身体执行,然后在瞬间结束时抢占触发。所有的抢占都是由之前的布尔条件值(因此是pre关键字)触发的,以确保计算是确定性的。这是必要的,因为变量的值可以在瞬间改变。pre的使用确保了抢占总是基于前一时刻的变量的稳定状态值。换句话说,就像在ReactiveC中一样,我们使用了一种限制性的因果关系形式来与Esterel进行比较。

2.2.生产者和消费者的例子

[code]1.#include <pretc.h>
2.#define N 1000
3.ReactiveInput (int ,reset , 0);
4.ReactiveInput (float ,sensor , 0.0);
5.int cnt=0;
6.float buffer 
;
7.void sampler() {
8.    int i=0;
9.    while(1) {
10.        EOT;
11.        while (cnt==N) EOT;
12.        buffer[i]=sensor;
13.        EOT;
14.        i=(i+1)%N;
15.        cnt=cnt+1;
16.    }
17.}

18.void display() {
19.    int i=0;
20.    float out;
21.    initLCD ();
22.    while(1) {
23.        while (cnt==0) EOT;
24.        out=buffer[i];
25.        EOT;
26.        i=(i+1)%N;
27.        cnt=cnt−1;
28.        EOT;
29.        WriteLCD(out);
30.}

31.void main() {
32.    while{1}{
33.        abort
34.            PAR(sampler, display);
35.            when pre(reset);
36.            cnt=0;
37.            flush(buffer);
38.            EOT;
39.    }
40.}

                                                                                       清单1

我们提出了一个生产者-消费者改编自[22]来激励PRET-C。如清单1所示。程序首先包含pretc.h文件(第1行),然后声明响应性输入(第3行和第4行),然后是常规的全局C变量(第5行和第6行),最后定义所有C函数(第7行到第41行)。主要功能包括一个主线程,产生两个线程(35)行:一个采样线程从传感器响应输入读取一些数据并将这些数据存储在一个全局循环缓冲区中,另一个显示线程从缓冲区读取存储的数据并将这些数据显示在屏幕上,这要感谢用户定义的函数WriteLCD(第29行)。采样器和显示线程使用共享变量cnt和buffer进行通信。此外,程序员给采样线程分配了一个比显示线程更高的优先级。

在它的第一个局部滴答期间,采样器线程什么也不做。在它的第二个本地标记期间,它检查它的数据缓冲区是否满了(第11行):只要缓冲区满了,它就一直等待,直到显示线程读取了一些数据,这样缓冲区中就有了空的空间。当它退出这个while循环时,它将传感器输入的当前瞬时值写入缓冲区的下一个可用位置(第12行),并结束它的本地标记(第13行)。在它的最后一个局部标记中,缓冲区的i索引和缓冲区中的数据cnt总数增加(第14行和第15行),因为这是一个循环缓冲区。然后重新启动采样循环。

在它的第一个本地标记期间,显示线程检查是否有任何数据可以从缓冲区读取(第23行)。如果没有可用的数据,那么它将结束本地标记并继续等待,直到生产者存储了一些数据。当这种情况发生时,它从buffer中读取下一个数据(第24行),并结束本地标记(第25行)。在它的下一个局部标记中,缓冲区的i索引递增(第26行),缓冲区中的数据cnt总数递减(第27行)。在最后一次本地校验期间,它将从缓冲区读取的数据发送到显示设备(第29行)。

主线程(主函数)对PAR构造有一个封闭的中止。只要在前一时刻按下了外部重置按钮,就会执行此抢占操作(第36行)。在我们的例子中,当一个强抢占发生时,两个线程被中止,程序刷新缓冲区(第38行),初始化cnt变量(第37行),并暂停片刻,然后重新启动两个线程。

在任何带有RTOS的GPP上执行此代码以模拟并发将导致竞争条件。程序员的职责是确保使用诸如信号量之类的操作系统原语正确地实现关键部分。这是因为对共享变量cnt的非独占访问。但是,在ARPRET上,执行总是确定的。假设cnt=cnt+1和cnt=cnt-1发生在同一时刻。由于采样器的优先级高于显示,cnt将首先递增1,一旦采样器到达EOT, ARPRET调度器(参见第4节)将选择显示, 显示将cnt递减1。因此,cnt的值将是一致的,而不需要强制采样器和显示线程之间的互斥。

2.3.TCCFG中间格式

                                                        生产者和消费者的关系

我们提出了一种新的PRET-C程序中间格式,称为定时并发控制流图(TCCFG)。TCCFG是一个类似于[12]的CCFG的控制流图。但是,它比早期的中间格式要简单得多,因为我们的语言更简单。与清单1的示例对应的TCCFG如图1所示。

PRET-C程序首先被转换成ARPRET汇编代码,然后自动从该汇编代码中提取TCCFG。我们从汇编代码(而不是从源代码)中生成中间格式,以便为每一次滴答得到ARPRET时钟周期的精确值。此外,通过处理汇编代码,编译器优化不需要关闭。我们使用TCCFG对PRET-C进行WCRT分析,该分析在配套的报告[19]中提出。

TCCFG编码线程的显式控制流以及线程的分叉和连接信息。节点类型如下:

  • 开始/结束节点:每个TCCFG都有一个惟一的开始节点,该节点是控件开始的地方,如果程序可以终止,则可能有一个结束节点。它们都是同心圆。
  • Fork/Join节点:它们标记控制并发线程的开始和结束位置。它们被画成三角形。
  • 操作节点:它们用于任何C函数调用或数据计算。我们用矩形来画它们。
  • EOT节点:它们表示局部标记或全局标记的结束,并被绘制为填充矩形。
  • 控制流节点:我们有两种类型的控制流节点:实现条件分支的条件节点(用条件标记的菱形绘制)和映射无条件分支的跳转节点(用箭头形的五边形绘制),这是无限循环所需要的。
  • 中止节点:我们有中止开始和中止结束节点来标记中止的范围。它们被标记为菱形,用' s '或' w '表示强中止或弱中止。
  • Checkabort节点:这些是实现中止语义的特殊节点。它们被绘制为细菱形,标记为“cs”或“cw”,以表示强或弱的checkaborts。

根据中止的类型,我们使用以下结构转换规则在精确的点插入checkabort节点。如图2所示:

  • 对于程序中的每个强中止,将在每个EOT节点之后插入一个checkabort节点,以在每次循环开始时检查抢占条件。此外,checkabort节点被插入到该abort的封闭线程体的开头,以便在不执行该体的情况下立即触发抢占(根据PRET-C中强抢占的语义)。PRET-C的强中止对应于Esterel的强直接抢占。
  • 对于程序中的每个弱中止,我们在每个EOT节点之前插入一个checkabort节点。PRET-C的弱中止对应于Esterel的弱直接抢占。

3.PRET-C语义

在本节中,我们将使用结构操作风格[17]来展示PRET-C的语义。我们的语义类似于早期同步语言的语义,如Esterel[3]和SL语言[8]。与早期同步语义的主要区别在于,将并行编码为基于线程优先级的固定序列。我们使用它来确保具有任意数据依赖关系的所有PRET-C程序的确定性。另一个关键的区别是我们处理抢占的方式。与以前的方法不同,以前的方法依赖于将中止转换为trap,然后基于trap定义语义,而我们直接定义中止的语义。由于将中止转换为陷阱,所以使用陷阱体中额外的并发线程对弱中止进行编码。为了处理强中止,需要额外的暂停。与此不同,我们建议使用名为checkabort的内核语句。然后,我们提供一个结构转换,在代码中的适当位置插入checkabort项(与2.3节中描述的checkabort节点的插入完全相同)。因此,我们可以在语义上处理中止,而不需要在转换期间引入额外的线程。我们首先介绍一组用于插入checkabort语句的结构转换规则。

3.1.抢先占有的结构翻译规则

为了能够处理抢占,除了抢占语句本身之外,还需要一个名为checkabort的内核语句。需要使用checkabort语句来检查是否满足抢占条件。此外,这种检查必须在代码中的特定点进行,以保留PRET-C中强抢占和弱抢占的语义。

语义中的第一步是在结构上转换中止体,以便在中止体中插入适当的checkabort语句。插入这些语句的规则如下(与在TCCFG中插入checkabort节点的规则相同,见第2.3节)。

  • 对于每个强中止,在每个EOT之后插入checkabort语句,以在每个瞬间开始时检查抢占条件。另外,在正文的开头插入checkabort语句,以立即触发抢占,而不执行正文(根据PRET-C中强抢占的语义,其行为类似于Esterel中的强立即抢占)。
  • 对于每个弱中止,我们在每个EOT之前插入checkabort语句。弱中止相当于弱立即中止。
  • 在嵌套abort语句时,它显式地捕获优先级。与Esterel一样,外部中止语句比内部中止语句具有更高的优先级。同样,为了正确地捕获强中止和弱中止的行为,需要从外部到内部检查强中止,而从内部到外部检查弱中止。我们插入checkabort语句,以便在从最外层到最内层的每个实例开始时检查强中止。对于弱中止,我们在每个实例的末尾从最内层到最外层进行检查(以处理嵌套的弱中止体的链接)。

清单 中的示例代码和清单 中插入的 语句解释了这种结构化转换方法。根据结构转换规则插入 语句。优先级是通过 语句嵌套显式编码的。例如,在第 行和第 行,我们首先检查最外层的强中止(条件 ),然后检查内部的强中止(条件 )。类似地,在第 行和第 行,我们首先检查内部弱中止(条件 ),然后检查外部弱中止(条件 )。

                                                                               清单3.1:嵌套中止及其结构转换

3.2.内核语言和操作规则

我们首先介绍内核语言,如表2所示。我们不使用这个内核来编译,只是为了表达语言的语义。重要的一点是,在PRET-C程序中,EOT标记线程在PAR范围内的本地标记的结束,否则标记全局标记的结束。

状态 意义
nop 立即终止,不做任何事
EOT 标记当到达所有局部滴答时完成一个反应(全局滴答)
t;u 顺序执行t,然后是u
PAR(t,u) t和u的逻辑并行执行,t的优先级更高
v=f(...) 计算f,然后将结果赋给变量v
if (c) {t} else {u} 条件语句
while(1) {t} 无限循环,其中t必须有至少一个EOT
while(c) {t} 可能是有限循环,其中t必须有至少一个EOT
checkabort(cond,label) 当抢占条件cond为真时,返回label的值
[weak] abort P when pre c 当条件为真时,P的弱或强抢占

                                                                                        表2:PRET-C的内核语句

然后,任何程序转换都由形式 规则表示,其中:t表示由任意内核语句组成的术语。

  • 表示由任意的内核语句组成的术语。
  • 表示经过跃迁后的项的余项。
  • 表示一组响应性输入。
  • 表示一组变量(包括全局变量和局部变量)的状态或估值。
  • 表示在进行转换之后,同一组变量的状态。
  • 表示转换完成后的完成代码。可以使用代码0完成转换,以表示已经执行了nop语句,1代表已经执行一个测试结束,标签代表抢占条件为真。⊥代表:上述以外的任何转换被执行。只有当完成⊥规则的代码环境 才会改变一些 。这些是正确执行 语句所需要的。我们在补全码上使用偏序 ,因此 声明 是一个标签。具体来说,标签是执行抢占后的延续地址。这种完成码的编码是由Esterel语义中的trap编码激发的(虽然更简单)。

声明:该声明在不修改变量的情况下立即终止:

                                                                                                                                                    

声明: 声明的执行完成了程序的本地标记,这是由一个完成代码 捕获的:

                                                                                                                                                  

序列操作符:右分支 在左分支 之后依次执行:

如果 是除 之外的任何声明,而且t不触发抢占。则此规则规定,由于在 中执行语句而使术语 变为 之后,术语 将与状态 保持顺序。由于执行了当前的微步步骤,这些变量将从 更改为 。因为当前步骤执行,既不是测试结束,也不是nop的一份声明中,所以使用⊥来完成代码。

                                                                                                                                            

此规则断言当 暂停(通过执行 )时,序列也暂停:

                                                                                                                                             

此规则捕获 终止时的情况。然后控制权立即传递给 :

                                                                                                                                                        

此规则捕获触发封闭抢占的 的执行。在此事件中,序列终止时的完成代码等于 返回的值。

                                                                                                                                

赋值语句:一个变量可以赋值给一个函数,也可以赋值给一个表达式的计算结果(表达式也可以封装为一个函数)。该规则规定,当这样的语句是执行后,变量v的值由变量E中的函数的返回值更新。

                                                               

条件语句:当条件语句的保护条件分别为真和假时,有两条规则对应。

当保护条件为 时,该规则声明接下来执行 分支(术语 )。

                                                                                                     

当保护条件为 时,该规则声明接下来执行 分支(术语 )。

                                                                                                     

无限循环:无限循环被重写为一个序列,该序列由循环体和循环本身组成。在我们的语义中,我们进一步要求 至少对每个输入在 上执行,以避免将循环重写为无限的未完成转换序列。

                                                                                                               

有限循环:根据保护条件是真还是假,有两种情况。我们要求循环体 必须至少有一个 来防止死锁(由于循环条件与其他线程的依赖)。

当保护条件为真时, 的主体将执行一次。完成代码将是基于主体的完成代码的值 ,由于主体只执行一次,变量的状态将从 更新到 。如果条件 达到 ,则 终止时完成代码为1。如果主体完成,则术语 完成时的完成代码为0,然后再次计算序列中的 条件。

                                                                    

当保护条件为 时,语句将终止。

                                                                                                       

语句:并行执行术语 ,其中 的优先级高于 ,首先执行 的所有语句,直到到达 的本地标记( 语句)。规则 (减少 直到 )和规则 (暂停 直到到达 )分别捕捉到这一点。

                                                                                                                   

                                                                                                                    

当两个线程都达到它们的 时, 暂停,完成代码为 (规则 )。或者,如果 位于 ,而 终止,则 也终止,完成代码为 (规则 )。在这两种情况下, 已经走完了滴答时间;这是全局标记还是局部标记取决于 的嵌套。

                                                                                                                   

                                                                                                                

终止时, 变成 ,就像序列的规则 (规则 )。规则 (当 终止时)和规则 (当 终止时)之间的不对称性是由于 优先于

    

                                                                                                                                        

接下来的两个派生规则用于处理由于任何封闭的抢占语句而导致的 抢占。当第一个线程到达 语句时,需要使用规则18,以便该语句的执行将返回一个完成代码 。在这种情况下,第一个线程暂停,第二个线程开始执行。然后继续执行第二个线程,直到匹配的 为止。

                                                                                                          

当两个线程使用相同的完成代码退出时, 退出并完成 。当两个线程通过执行各自的 语句来响应一个封闭的抢占时,就会发生这种情况。这是下面第19条规定的。

                                                                                                         

规则 和规则 中关于优先级的行为与规则 和规则 中关于 的行为相似。

3.3.处理抢占

语句:当抢占条件为 时, 返回一个与连续地址 相等的完成代码。注意,抢占条件是在前一个实例( )中的变量状态上定义的。

如果优先抢占条件为 时,则 状态将被重写为 。并且返回一个大于1的值。

                                                                                                     

如果抢占条件为 时,另一方面, 语句将不做任何操作而终止。

                                                                                                     

中止和弱中止语句:强和弱抢占的规则是一样的。两者行为之间的实际区别是通过前面介绍的结构翻译规则实现的。

当主体执行一系列瞬时转换或达到一个 而不满足抢占条件时,则分别适用规则 。在这些情况下,主体只是简单地替换为结果项。这可以通过以下两条规则来实现。

                                                            

                                                              

主体可以执行 语句,以便终止代码是大于 的。在这种情况下,我们必须区分规则 所示的两种情况。规则 捕获这样一个事实,即由返回标签 项检查的 条件与 语句的条件相匹配。在本例中,中止被简单地重写为 。自中止发生后,中止语句返回

规则 捕获的第二种情况是,当 对应于封闭的 时,需要将内部中止重写为 ,以指示中止没有执行。与规则 不同,规则 返回到其封闭上下文。

                                                                

[code]abort
abort
EOT;
checkabort(c2,A2);
checkabort(c1,A1);
t;u;
when pre c1;
A1;
when pre c2;
A2;

                                                                               Figure 4: 优先级实例

                                                            

为了说明这两种情况,我们考虑图 所示的程序。在抢占时,最外层的 将返回标签 的地址作为其完成代码。如果最外层的 返回 ,则最内层的 不需要执行,因此规则将其重写为 。此外,这个 语句将把 返回到它的环境(即:封闭中止)。另一方面,如果最外层的 返回 ,最内层的 返回A1,那么使用 ,内部的 将触发并将控制权转移到

最后一种情况发生在主体正常终止时。在这个事件中, 语句被 替换。

                                                                                                          

请注意,到异常中止主体外部的实际分支是由异常中止语句执行的,而不是由 执行的。这对于正确处理并行 的执行是必要的:即使在多个子线程中触发抢占,我们也只希望执行一次跳转。特别是,我们不能用条件跳转替换

3.4.例证

考虑以下PRET-C程序,其中 是没有任何 术语的术语:

[code]weak abort
PAR(// first thread
PAR(t1,t2);
PAR(t3;EOT,t4;EOT);
EOT;t7,
//second thread
t5;EOT;t6;EOT;t8;EOT
)
when pre I;
END: t9

这个程序的线程之间的调度和同步由TCCFG解释,如图 所示。在下面,我们将使用符号PAR-i来表示第i个PAR。我们将考虑以下两个执行场景。

                            

                                                                       Figure5:用于说明语义的TCCFG示例

  • 在前一时刻没有出现:然后PAR-1将启动,并将立即启动PAR-2。规则 下的PAR-2将启动 并执行,最终成为 。然后,根据规则 ,PAR-2变成 ,最终在 终止时终止。然后,开始执行PAR-3,根据规则 执行 ,直到执行 。当发生这种情况时,由于规则 的原因, 暂停并启动 的执行。最后,PAR-3返回一个 的完成代码,在 也达到 时使用规则 。现在,PAR-1使用规则 启动第二个线程 的执行。最后,当 到达 时,全局滴答时间按规则 发生。线程的执行将以类似的方式继续,按以下顺序执行这些块: ,最后是
  • 出现在前一时刻:考虑到满足抢占条件,执行将会不同。与前一种情况一样,在开始执行PAR-3之前,执行都是类似的。这里,条件 将完成,然后 项的执行将返回一个值 。然后,根据规则 ,第一个线程的左分支的执行将暂停,直到右分支中的术语 的执行完成为止。这之后将在右分支中执行 语句。这个 还将返回一个与左分支返回的值相同的值 。因此,根据规则   PAR-3也将返回相同的值。现在,根据规则 ,线程 的执行将暂停,线程 的执行将继续,直到匹配的 语句为止。现在,PAR-1将以两个线程返回的值 结束。当这种情况发生时,封闭的弱异常终止语句将根据规则 将执行转移到术语

定义1:一个程序在瞬间的反应将被表示成: 。如果存在一个转换序列,其将被表示为:

我们现在使用以下两个定理来描述PRET-C程序。我们首先以标准的方式定义反应性和决定论[25]。

定义2:如果对于任何语句 和数据集 ,对于输入集 至少存在一个反应,则PRET-C程序是反应性的。即:程序不死锁在任何状态下给一些有效的输入。

定义3:如果对于任何语句 和数据集 ,对于输入集 最多存在一个反应,则程序是确定的。

定理1:所有有效的PRET-C程序都是反应性的。即:对于任意的 。存在 ,使得

定理2:所有有效的PRET-C程序都是确定性的。即:对于任意的 。使得 成立。则:

, ,

4.ARPRET架构

本节介绍GPP MicroBlaze (MB)[24]的硬件扩展,以实现时间可预测性。我们设计了PRET-C语言,以便通过简单的GPPs定制来实现PRET机器的设计。执行PRET-C所需的更改涉及对并发和抢占的支持。如果并发完全在软件中实现,那么调度的开销将与并行线程的数量成比例。实际上,在每个EOT中,调度器必须根据线程的状态和抢占上下文选择下一个线程。在软件中这样做将消耗大量的时钟周期(与硬件实现相比),从而降低总体吞吐量。因此,我们使用定制的可预测功能单元(PFU)在硬件中进行调度。图6显示了由连接到PFU的MB软核处理器组成的ARPRET平台的基本设置。

MB是一个可定制的基于RISC的软核处理器,针对Xilinx FPGA的实现进行了优化。为了保证可预测性,它禁用了指令和数据缓存的推测性功能。没有使用来自内存管理单元的任何特性,也没有使用并行移位器或浮点单元。我们在流水线中使用了五个阶段,并禁用了分支延迟槽特性。

PFU存储多个线程上下文并调度线程。对于每个线程,线程表将其程序计数器(PC)存储为一个32位的值、其状态(死或活,称为TDA)、其暂停状态(TSP)、其本地标记状态(TLT)和其优先级(TP)。根据三个线程的状态,调度程序在请求时发出下一个程序计数器。中止上下文也保存在中止表中,用于处理抢占。

MB通过启动线程创建、终止和挂起(这与Esterel挂起不同;在PRET-C中,生成子线程的任何线程都是挂起的)。PFU将每个线程的上下文存储在thread表中,并在MB上执行时监视线程的进程。当给定线程在MB上完成EOT指令时,它使用FIFO1向TCB发送适当的控制信息。作为对此的响应,PFU将这个线程的本地滴答位(LTL)设置为1,然后调用调度器。然后,调度器通过从线程表中检索PC值并使用FIFO2将其发送到MB来选择下一个最高优先级的线程执行。此外,当所有参与的线程都完成了它们的本地节拍时,PFU将等待节拍长度过期。每当它完成一个本地标记,MB块等待下一个从PFU过来的PC值。当所有的滴答完成了它们的本地滴答,但是全局滴答没有发生时,它也会等待。滴答的长度是由PRET-C程序的静态WCRT分析决定的,详见报告[19]。接下来,我们将详细介绍如何在ARPRET中创建MB和PFU之间的紧密耦合连接。

MB和PFU之间的通信是通过使用Xilinx提供的快速单工链路(FSL)接口[24]来完成的。这种通信是通过使用硬件FIFOs来完成的。FSL使用两个FIFOs(分别称为FIFO1和FIFO2)将MB与PFU紧密地连接起来,以提供确定性和可预测的通信。与FIFOs通信需要交换一些常见的控制信号,如时钟、复位、缓冲区状态(满/空)、读、写,以及PC值等数据。

Function(ID) Number of reads Number of wirtes
SPAWN(10) 1 0
EOT(12) 1 1
SUSPEND(14) 1 1

                                                                       Table 3:PFU使用简单的查找表来解码FIFO1中的数据

                                                                                   

当MB执行PAR(T1、T2)和EOT等指令时,将触发MB(主)和PFU(从)之间的通信。PFU包含一个控制器逻辑,它引用表 中所示的查找表(LUT)来解码FIFO1中的数据。例如,为了生成一个线程,MB将一个值10后跟线程的起始地址写入FIFO1。控制器逻辑将10解码为衍生。然后,通过引用表3中的读取次数,它从FIFO1中再获取一个数据元素,并将其存储为新线程的PC。另外,作为对这个衍生的响应,其他状态位(如线程状态和挂起的位)也被适当地更改。

而且,TLT位设置为0,表示线程的本地标记尚未到达。

5.Esterel与Reactive C的对比

本节试图通过一组示例来说明该语言,并将其与Esterel[4]、ReactiveC[6](表示RC)和Reactive Shared Variables[7]进行比较。我们不与ECL语言[13]进行比较,因为它在语义上几乎与Esterel相同。我们首先对表4所示的语言进行定性比较。

Criteria Esterel RC PRET-C
Commutativity of || yes no no
Communication signals yes/no no
Instantaneous Broadcast yes multiple multiple
Signals/Shared-variable values in an instant single multiple multiple
Types of aborts 4 4 4
Types of suspend 4 4 0
Traps yes yes no
Non-Causal Programs possible possible possible
Dynamic Processes no yes no
Compilation complex complex macro-expansion

                                                                                Table 4:与Esterel和RC进行定性比较                              

我们现在根据4中列出的标准来比较这三种语言。

1.并行的本质:在Esterel中,一个并行程序在编译过程中被转换成一个连续的程序。编译器交错执行线程,这样所有信号的产生者都被安排在消费者之前。因此,可以执行相同的线程不同的执行订单在不同的瞬间,以尊重生产者消费者依赖的信号(见图8)。与这个不同,在RC和PRET-C所有线程都执行基于一个固定的静态秩序重复在每一个瞬间。因此,Esterel并行算子是可交换的,而RC和PRET-C中的可交换算子不是。虽然RC和PRET-C实现并行运算符的方法相似,但是由于线程通信方式的不同,RC和PRET-C程序的行为有很大的不同。下文对此进行了阐述。

2.通信:在Esterel和RC中,线程之间通信的主要方式是通过一组信号。在Esterel,一个信号不是每时每刻都存在(真)就是不存在(假)。一个信号可以携带一个附加的值。此外,每个信号在任何时刻都只能有一个单一的值(因此在任何时刻都不可能有一个以上的发射器)。为了允许同一信号的多个发射器,在必须使用交换和联合运算符组合多个发射器的情况下,支持组合值信号。RC放宽了这些限制,允许同一个信号的多个值的释放(没有合并操作符),其中最后一个释放的值覆盖了之前的释放(RC也支持组合值信号)。它还允许使用reset语句在瞬间重置发出的信号。这在Esterel是不可能的。RC的一个问题是,信号检查是动态进行的,一旦信号被读取,如果将来发生发射,则会引发运行时异常。这种方法可能导致不可预测的运行时行为,这对于编写PRET机器是不可取的。

[code]1    [
2        emit A(0);
3        pause;
4        emit A(?B+1)
5    ||
6        emit B(?A)
7        pause;
8        emit B(7)
9    ]
[code]1    PAR(T1,T2)
2    ...
3    void T1(){
4        A=0;
5        EOT;
6        A=B+1;
7    }
8
9    void T2(){
10        B=A;
11        EOT;
12        B=7;
13   }
Esterel A 0 8
B 0 7
PRET-C A 0 1
B 0 7

                                                                 Figure 8: Esterel和PRET-C的并行 

与Esterel和RC相比,线程之间的所有通信都是通过变量进行的(反应性的和内部的)。反应性输入变量的行为与Esterel的输入信号完全相同。这些数据是在瞬间开始时从环境中读取的,它们的值在整个瞬间不会改变。无功输出变量和所有其他内部共享变量的行为与Esterel和RC信号有很大的不同。由于多个写入器写入该变量,所以一个无功输出变量可以在瞬间具有多个值。只有最后的值被发送到环境中(这类似于RC方法,允许多个写入器写入信号)。与Esterel和RC不同,所有线程都可以不受限制地访问所有共享变量(参见图9)。由于所有线程都以固定的顺序执行,并且所有读和写都是原子性的,所以程序仍然是确定性的。RC还允许对共享变量的受限访问,在这种情况下,需要程序员强制执行数据一致性要求。RC的一个变种称为基于响应共享变量的系统[7],它只使用共享变量进行线程通信,如PRET-C。然而,这种语言的决定论观点更为严格。它要求所有的读取器必须读取相同的值,以便数据具有一致性。因此,它在每个瞬间都引入了两个阶段。在第一阶段,所有的数据写入器都被调度,在第二阶段允许读取器读取。由于我们对确定性的输入-输出行为感兴趣(参见第3节中决定论的定义),所以我们对数据一致性的限制较少,只要整个程序行为保持确定性,就允许读者读取同一变量的不同值。

[code]1    PAR(T1,T2);
2    ...
3    void T1(){
4        while(1){
5            x=I+1;
6            if (x>MAX)    x=MAX;
7            EOT;
8            x=I-1;
9            if (x<MIN)    x=MIN;
10       }
11   }

11    void T2(){
12        abort
13            while(1){
14                x=2*x;
15            }
16        when pre(DONE);
17        x=x/2;
18    }

                                                            Figure 9: PRET-C中对共享变量的多次读写

3.瞬时广播:在Esterel中,线程之间的通信是通过同步广播进行的。因此,一旦发出一个信号,所有其他线程都可以立即测试这个值。这在RC中是不可能的,因为并行操作符被映射到一个固定的序列。RC引入了挂起操作符,通过插入挂起来模拟同步广播行为。在PRET-C中,我们不能支持即时广播的概念。

[code]1    [
2        emit A;
3    ||
4        present A then emit B end
5    ||
6        abort
7            halt
8        when not A
9    ]
[code]1    PAR(T1,T2,T3);
2    ...
3    void T1(){
4        a=1;
5    }
6
7    void T2(){
8        if (a==1) b=1;
9    }
10
11   void T3(){
12       abort
13           while(1){EOT}
14       when (pre(a==1))
15   }

                                                            Figure 10: 在Esterel和PRET-C的瞬时广播

4.抢占支持:在Esterel和RC中,有四种类型的中止(强中止、弱中止、强中止和弱中止)是可能的。此外,四种类型的暂停是可能的。在PRET-C中,我们只支持与RC/Esterel中的强立即中止和弱立即中止对应的两种中止类型。我们采用这种观点是为了简化语言,避免需要区分程序的表面(第一个瞬间的行为)和深度(所有后续瞬间的行为)。另一个区别是,所有的先占行为都是基于对前一时刻情况的评估。这是必要的,因为变量值可以在瞬间发生变化,并且通过引用之前的瞬间抢占总是基于稳态值发生。参见图10中的示例。

[code]1    [
2        present A then emit B end
3    ||
4        present B then emit A end
5    ]
[code]1    PAR(T1,T2);
2    ...
3    void T1(){
4        if (a==1) b==1;
5    }
6
7    void T2(){
8        if (b==1) a==1;
9    }

                 Figure 11:Esterel的因果循环。在PRET-C中,T2和T1之间没有信息流。

5.因果关系:由于反馈循环,Esterel/RC可以有非因果的[2]线程组成。这些必须被编译器拒绝,并且相关的分析会导致大量的编译器开销。由于我们的并行运算符的语义,PRET-C程序由结构决定因果关系。因此,PRET-C程序的编译要简单得多(仅基于宏展开)。图11显示了从T2到T1的信息流是如何缺乏的。

6.动态流程支持:RC是允许动态创建流程的最通用语言,这在Esterel和PRET-C中是不可能的。

总之,PRET-C与Esterel的不同之处在于它的并行操作符的性质,而且所有线程都可以不受限制地访问共享变量。另一个关键的区别是,我们没有表面和深度行为的概念,没有traps和延时。此外,PRET-C程序是因果关系的结构。由于缺乏同步广播通信,因此不需要调度线程。因此,可以通过简单的宏展开从PRET-C生成代码。

与RC相比,PRET-C继承了并行操作符的语义相似性。但是,由于数据一致性要求的不同,PRET-C允许不受限制地访问共享变量,这与RC不同。这使得PRET-C中的编程任务更简单。一般来说,PRET-C是一种简单的语言,与RC和Esterel相比,表达能力较差。例如,它不能直接表达同步广播。此外,瞬时对话框[6],可能在Esterel可行,在PRET-C中不可行。

PRET-C与早期同步语言之间的关键区别之一是我们的时间观。在Esterel和RC中,程序中所表示的时间是完全合乎逻辑的。在PRET-C中,程序员可以自由地混合逻辑时间和物理时间。使用我们的工具WCRT analyzer[19],程序员可以自动查看逻辑时间到物理时间的映射。所提出的分析是基于模型检验的,并返回给定程序的紧WCRT值。因此,这种方法对于PRET实现来说是一个很好的选择,因为吞吐量不会因为高估了节拍的WCRT值而浪费。实际上,我们的映射与Esterel的硬件编译器是相同的。关于PRET-C程序的WCRT分析的更多细节可以在[19]中找到。

6.总结和展望

精确定时(PRET)架构是最近尝试设计的一种处理器,它可以保证在不牺牲吞吐量的情况下执行可预测的代码。来自伯克利和哥伦比亚的研究人员提出了一种定制的处理器,它具有线程交错的流水线和一个低级指令,可以在C代码[15]中引入精确的定时。与此相反,本文提出了嵌入式软核处理器的定制来设计最小硬件需求的PRET架构。我们还提出了一种新的PRET机器编程语言,称为PRET-C,通过对C语言进行简单的同步扩展。PRET-C具有表示逻辑时间、抢占和并发的构造。并发线程使用共享内存模型(常规C变量)进行通信,并且通过构造实现线程安全的通信。我们设计了一个新的PRET机器,称为ARPRET,通过定制MicroBlaze软核处理器。我们通过比较PRET-C在ARPRET上的执行情况和Esterel在其投机性对应物(MicroBlaze)上的执行情况,对提出的设计进行了基准测试。基准测试结果表明,该方法在不牺牲吞吐量的情况下实现了可预测的执行。

在未来,我们将扩展我们的设计,使其能够处理内存分层问题,以便ARPRET能够预测并有效地执行大型嵌入式应用程序。我们还将开发能够静态地向程序员强调代码定时行为的工具。这将允许程序员根据应用程序需求定制代码。另一个要研究的领域是PRET-C在多核架构上的执行。一种可能的扩展是一种基于gales的语言,它可以支持多核执行。

7.参考文献

[1] G. Andrews. Concurrent Programming: Principles and Practice. Benjamin/Cummings, 1991.

[2] A. Benveniste, P. Caspi, S. Edwards, N. Halbwachs, P. Le Guernic, and R. de Simone. The synchronous languages 12 years later. Proceedings of the IEEE, 91(1):64–83, Jan 2003. 

[3] G. Berry. Constructive semantics of Esterel: From theory to practice (abstract). In AMAST ’96: Proceedings of the 5th International Conference on Algebraic Methodology and Software Technology, page225,London, UK, 1996. Springer-Verlag. 

[4] G.BerryandG.Gonthier.The Esterel synchronous programming language: design, semantics and implementation. Science of Computer Programming, 19(2):87–152, 1992. 

[5] M. Boldt, C. Traulsen, and R. von Hanxleden. Worst case reaction time analysis of concurrent reactive programs. Electronic Notes in Theoretical Computer Science, 203(4):65–79, June 2008.

[6] F. Boussinot. Reactive C: An extension of C to program reactive systems. Software Practice and Experience, 21(4):401–428, April 1991. 

[7] F. Boussinot. Reactive shared variables based systems. Technical Report 1849, INRIA, 1993. 

[8] F. Boussinot and R. de Simone. The SL synchronous language. IEEE Trans. Softw. Eng., 22(4):256–266, 1996.

[9] B. Cogswell and Z. Segall. MACS: A predictable architecture for real time systems. In Real-Time Systems Symposium. IEEE CS Press, 1991. 

[10] S. Edwards. Estbench Esterel benchmark suite. http://www1.cs.columbia.edu/ sedwards/software/estbench-1.0.tar.gz. 

[11] S. A. Edwardsand E.A. Lee. The casefor the precisiontimed (PRET)machine. In Proceedings of the 44th annual conference on Design automation, pages 264–265. SESSION: Wild and crazy ideas (WACI), June 2007. 

[12] S. A. Edwards and J. Zeng. Code generation in the Columbia Esterel Compiler. EURASIP Journal on Embedded Systems, 2007. Article ID 52651. 

[13] L.Lavagno and E.Sentovich. ECL:A specification environment for system-level design. In Proceedings of Design Automation Conference (DAC), New Orleans, USA, June 1999. 

[14] X. Li, M. Boldt, and R. von Hanxleden. Mapping Esterel onto a multi-threaded embedded processor. SIGARCH Comput. Archit. News, 34(5):303–314, 2006. 

[15] B. Lickly, I. Liu, S. Kim, H. D. Patel, S. A. Edwards, and E. A. Lee. Predictable programming on a precision timed architecture. In In Proceedings of International Conference on Compilers, Architecture, and Synthesis from Embedded Systems, October 2008.
        [16] H. D. Patel, B. Lickly, B. Burgers, and E. A. Lee. A timing requirements-aware scratchpad memory allocation scheme for a precision timed architecture. Technical Report UCB/EECS-2008-115, University of California, Berkeley, Sept. 2008. 

[17] G. Plotkin. A Structural Approach to Operational Semantics. Technical Report DAIMI FN-19, University of Aarhus, 1981. 

[18] P. Roop, Z. Salcic, and M. Dayaratne. Towards direct execution of Esterel programs on reactive processors. In 4th ACM International Conference on Embedded Software (EMSOFT 04), 2004. 

[19] P. S. Roop, S. Andalam, R. von Hanxleden, S. Yuan, and C. Traulsen. Tight WCRT analysis of synchronous C programs. Technical Report 0912, Christian-Albrechts-Universit¨at Kiel, Department of Computer Science, May 2009. www.ece.auckland.ac.nz/∼roop/pub/2009/roop-report09.pdf. 

[20] Z. Salcic, P. Roop, M. Biglari-Abhari, and A. Bigdeli. Reflix: A processor core for reactive embedded applications. In 12th International Conference on Filed Programmable Logic and Applications (FPL-02), 2002. 

[21] M. Schoeberl. Time-predictable computer architecture. EURASIP Journal on Embedded Systems, 2009. Article ID 758480. 

[22] F. Vahid and T. Givargis. Embedded System Design. John Wiley and Sons, 2002. 

[23] R. von Hanxleden. SyncCharts in C. Technical Report 0910, ChristianAlbrechts-Universit¨at Kiel, Department of Computer Science, May 2008. 

[24] Xilinx. MicroBlaze Processor Reference Guide, 2008. 

[25] L.-H. Yoong, P. S. Roop, V. Vyatkin, and Z. Salcic. A synchronous approach for IEC-61499 function block implementation. IEEE Transactions on Computers, 2009 (to appear). 

[26] S. Yuan, S. Andalam, L.-H. Yoong, P. S. Roop, and Z. Salcic. STARPro: A new multithreaded direct execution platform for Esterel. In Model-driven High-level Programming of Embedded Systems (SLA++P’08), 2008.
 

  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
s_nan 发布了14 篇原创文章 · 获赞 6 · 访问量 1100 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: