CN108319458A - 一种基于图形化卫式命令演算的多任务编译方法 - Google Patents
一种基于图形化卫式命令演算的多任务编译方法 Download PDFInfo
- Publication number
- CN108319458A CN108319458A CN201810045360.1A CN201810045360A CN108319458A CN 108319458 A CN108319458 A CN 108319458A CN 201810045360 A CN201810045360 A CN 201810045360A CN 108319458 A CN108319458 A CN 108319458A
- Authority
- CN
- China
- Prior art keywords
- thread
- graph
- modules
- gcc
- clock
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/41—Compilation
- G06F8/42—Syntactic analysis
- G06F8/425—Lexical analysis
Abstract
本发明为一种基于图形化卫式命令演算的多任务编译方法,涉及到一个图形化卫式命令演算GCC_graph自动编译生成可执行多任务Ada/C代码方法,对于设计人员输入的GCC_graph程序,该编译器自动将其编译生成相应的可执行多任务Ada/C代码。该编译器的所有功能由函数式程序设计语言CAML编程实现,由于CAML是一种安全的语言,CAML程序在执行之前由自身编译器进行验证。此外,本发明设计的编译器使用模块化结构,一旦程序发生改变,我们只需要修改对应模块的代码。
Description
技术领域
本发明涉及到一种基于图形化卫式命令演算的多任务编译方法,尤其涉及一个图形化 卫式命令演算语言GCC_graph编译生成可执行多任务Ada/C代码方法。
背景技术
同步方法被广泛用于实时嵌入式软件的设计和验证,尤其是安全关键系统(Safety-Critial Systems),因为这类系统对实时性、可靠性和安全性等关键性质要求 非常严格。安全关键嵌入式系统是一类反应式系统(Reactive System),因为它不断对 环境中的输入事件反应,及时的产生结果并输出。反应式系统必须保证自身输入输出 规约的功能正确性和时间约束的时序正确性,而同步方法,基于同步假设理论 (synchronyhypothesis),可以保证程序的确定性和并发性。因此,同步方法广泛被用 于安全关键系统建模。
同步方法,基于数学基础,通过抽象化实时关系来简化系统,使用离散时刻的严格逻辑概念来替代。这种抽象的核心概念称为同步或者同步假设。一般来说,同步假 设将连续的时间划分为没有事件或者计算发生的离散时刻。在这个假设下,设计人员 不需要关注计算的时间开销,只假定计算过程在下一个时刻开始之前完成。只要最终 系统足够快来满足同步假设的假定,这保证系统行为模型平台无关。
随着安全关键嵌入式系统对性能需求的不断增加,使用多核处理器来替代单核成为趋势。然而在安全关键领域应用多核处理器将面临诸多挑战,保证程序运行的时间 可预测性是其中一个主要挑战问题。时间可预测性涉及程序分析和执行平台分析。对 于后者,由于多核处理器中因线程调度、共享Cache和置换算法造成时间可预测难以 分析,学术界提出了设计适合实时分析的时间可预测处理器架构的解决思路,并已实 现PRET-ARM和Java Optimized Processor(JOP)等时间可预测处理器。目前,大多数关 于时间可预测性的已有研究主要关注多核处理器及其上编译的调整和优化,而较少研 究保证时间可预测性质的多任务代码生成方法。
随着多核处理器在航空航天、核电站这类安全关键领域逐渐被广泛应用,如何保证这类系统的实时性、安全性和可靠性成为迫切需要解决的难题。因此出现了相关建 模语言如分析设计与建模语言AADL和同步语言等。
在AADL研究方面。2004年,美国机动工程师协会SAE(Society of AutomotiveEngineers)在MetaH、UML、HOOD的基础上,提出嵌入式实时系统体系结构分析与设 计语言AADL(Architecture Analysis and Design Language),并发布为SAE AS5506标准。 安全关键实时系统是应用软件、运行时环境以及硬件平台深度融合的复杂系统,AADL 语言与之对应地提供了软件体系结构、运行时环境以及硬件体系结构的建模概念。通 过线程(Thread)、线程组(Thread Group)、进程(Process)、数据(Data)、子程序(Subprogram) 等构件以及连接来描述系统的软件体系结构;通过处理器(Processor)、虚拟处理器(Virtual Processor)、存储器(Memory)、外设(Device)、总线(Bus)、虚拟总线(VirtualBus) 等构件以及连接来描述系统的硬件体系结构;通过分发协议(Dispatch)、通信协议(Communication)、调度策略(Scheduling)、模式变换协议(Mode Change)以及分区机制(Partition)等属性来描述系统的运行时环境;最后,通过系统(System)构件进行组合,层次化地建立系统的体系结构模型。另外,行为附件(Behavior Annex)以变迁系统(Transition System)的形式增强了AADL对线程构件和子程序构件控制流行为的详细描述能力。但在嵌入式领域,尤其是航空航天领域中AADL存在大量的数据计算和数据 流行为的描述,目前AADL这方面的表达能力不足。
在同步语言研究方面。根据同步假设的核心原则,多种同步编程语言(LUSTRE、ESTEREL、MRICDF、SIGNAL等)先后被实现并用于设计嵌入式系统。每种同步语 言在规约、编译和预期应用方面都有自己的特点,但它们具有一些共同属性:除了是 事件驱动的反应式系统外,每个语言都是同步的,即每个反应都会启动在相同逻辑时 刻中执行一组操作。一些同步语言(LUSTRE、ESTEREL等)是单时钟同步,执行单 个主时钟。其他(MRICDF、SIGNAL等)则是多态时钟同步,即多个时钟,当组件之 间必须彼此通信时,它们之间才会强制同步。多态同步模式保证了系统规约的高层次 建模的并发能力。随着同步语言的发展,需要解决不同同步语言之间的集成问题。目 前的一个主流做法是选择一种通用的中间语言,将所有同步语言转换为中间语言。例 如Polychrony中使用HCDG、L2C项目中使用S-Lustre*AST、QUARTZ编译器使用 CGA等。
发明内容
为解决现有技术的不足,本发明的目的在于提供一种基于图形化卫式命令演算的多任 务编译方法,用于图形化卫式命令演算语言GCC_graph进行建模并自动编译生成可执行多任务 Ada/C代码方法。GCC_graph主要关注模型的数据流行为,表达软硬件系统建模能力不 足,而AADL存在对数据流行为描述能力不足的问题,因此可采用在AADL中扩展同 步附件的方式,使用图形化卫式命令演算GCC_graph描述同步附件的内容,从而增加 AADL对线程和子程序中数据流行为的表达。
为了实现上述目标,本发明采用如下的技术方案:
一种基于图形化卫式命令演算的多任务编译方法,其特征在于:用于将图形化卫式命令演 算语言GCC_graph编译生成多任务可执行Ada/C代码,编译过程包括如下步骤:
1)定义图形化卫式命令演算GCC_graph语言,包括图形化规约、文本语法和形式语义;
2)使用函数式程序设计语言CAML描述基于GCC_graph的时钟演算;
3)使用函数式程序设计语言CAML描述基于GCC_graph的任务划分,包括划分前进行的 数据依赖分析和依次采用的三种划分方法,所述三种划分方法包括基于拓扑排序的任务 划分、优化拓扑排序划分结果和基于流水线方式的任务划分方法;
4)使用函数式程序设计语言CAML描述基于划分结果的虚拟多线程代码自动生成方法;
5)使用函数式程序设计语言CAML描述虚拟多线程代码转换到可执行多任务Ada/C代码 方法。
前述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤1)中定义 图形化卫式命令演算GCC_graph语言包括:
建立与GCC_graph有关的基本定义:
一个GCC_graph模型是定义在信号变量集合V上的卫式动作集合;
GCC_graph模型的输入输出为一组取值序列,记为信号变量或信号;
在每一个逻辑时刻,信号为两种状态中之一:处于存在状态并携带一个值value或者处于缺 失状态,缺失状态记为⊥;信号s中所有处于存在状态的逻辑时刻集合定义为s对应的抽象时钟, 记为如果两个信号s1和s2的抽象时钟相同,则称s1和s2同步;
a)图形化规约的基本建模元素定义:
卫式动作的基本结构和对应的图形化建模元素包括立即动作、延迟动作、约束动作、输入 动作和输出动作五类,具体如下:
立即动作:接收(m+n)个输入信号,包含m个输入信号用于卫式判断和n个输入信号用 于计算动作,如果卫式G为true,则进行计算f,并返回输出信号k,否则不执行任何操作;其 中,f表达常量、算术运算、逻辑运算以及用户自定义函数;
延迟动作:接收m个用于卫式判断和n个用于动作计算的输入信号,如果卫式G为true, 则执行计算f,并延迟一个逻辑时刻输出结果k,否则不执行任何操作;
约束动作:接收m个用于卫式判断和n个用于约束的输入信号,如果卫式为true,则执行 同步操作,同步n个输入信号,并输出同步结果,否则不执行任何操作;
输入动作:从外部环境中接收输入信号,在每个逻辑时刻,在执行每个GCC_graph中计算 之前,始终检查输入信号;
输出动作:将信号输出到外部环境中;在每个逻辑时刻,在每个GCC_graph中的计算完成 之后判断是否输出信号;
b)GCC_graph文本语法的形式化定义:
GCC_graph的五类基本结构的形式语法和对应语义解释如下所示:
其中,卫式G是定义在信号变量X、信号变量x的逻辑时钟及其初始时钟之上的 布尔条件,x∈X;τ是定义在X上的表达式;σ是定义在X及其逻辑时钟上的布尔表达式;
GCC_graph抽象语法表示为:上述定义中,GCC/x为GCC_graph中的局部信号变量声明;不同的GCC_graph之间组合采用同步组合操作‘||’;表示G和σ可能有这四种表达 方式,τ表示τ可能有x、f(τ,...,τ)这两种表达方式;
c)GCC_graph的形式语义:分为两部分:第一部分为先定义卫式、约束和表达式的时 钟和取值;第二部分为基于踪迹模型定义GCC_graph的指称语义;
第一部分,在给定踪迹S、逻辑时刻i和信号变量X,定义下列函数:
I)的域定义为为真,当且仅当在S上的逻辑时刻i,G中的所有信 号变量都处于存在状态,由于每个时钟都可以在任意逻辑时刻被读取,因此被定义为真:
定义一个偏函数当为真,计算γ的取值为真或假:
II)的域定义为 为真,当且仅当在S上的逻辑时刻i,τ中的所有信号变 量都不缺失:
定义一个偏函数当为真,计算τ的取值真或假:
和分别具有I)中和相同的定义;
第二部分,基于踪迹模型定义GCC_graph的指称语义:
一个GCC_graph系统的踪迹语义定义为踪迹的集合,即,
立即动作:
延迟动作:
约束定义:
输入动作:
输出动作:
GCC_graph的组合语义定义为:
前述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤2)中基于 GCC_graph的时钟演算包括定义时钟关系和构建时钟树;如果时钟树成功被构建,则表示模型 可以生成具有确定性行为的代码,再进行多线程代码生成;具体内容如下:
a)定义卫式动作对应的时钟关系:
其中,表示表达式G中所有信号变量的时钟都为true且G取值为true;表示信 号变量x和表达式τ中变量对应的时钟都为true;→表示时钟蕴含关系;
b)构建时钟树:
通过二元决策图,检查两个时钟之间的时钟蕴含关系,从而构建时钟树;同时,在时钟树 的每个节点中,所有的时钟变量都等价,使用时钟等价类替代对应的时钟变量,优化时钟关系;
时钟树结构可以按如下方式递归定义:一棵时钟树或为Empty,或为一个节点以及节点下方 的多个子时钟树组成;Empty表示空的时钟树,节点由时钟等价类、卫式动作集合组成,子时钟 树也可看做子节点,一棵完整的时钟树的叶子节点全部为Empty;
构建时钟树算法为:
步骤1:从卫式动作集合中选择一个卫式动作act1,如果act1类型为输入动作或输出动作, 则跳转到步骤8;
步骤2:选择act1中动作的等式右侧的变量对应的时钟x_clk,通过二元决策图计算x_clk 的时钟等价类ID_x;
步骤3:如果时钟树为Empty,则新建一个节点Node,其中存储ID_x和act1,并设置Node 的子节点Node’为Empty,跳转到步骤8;
步骤4:如果时钟树中存在节点,记为N,如果N的子节点为Empty,将act1加入到N中, 并且新建N的子节点N’,设置N’的时钟等价类为ID_x,否则跳转到步骤5;
步骤5:如果N有多个子节点,选择其最右侧的子节点Nr,比较Nr的时钟等价类ID_Nr 和ID_x时钟蕴含关系;如果ID_x→ID_Nr,则递归调用,从步骤3开始,将act1和ID_x分别作为步骤1-2的所要计算的数值插入到以Nr为根节点的子时钟树中;
步骤6:如果ID_Nr→ID_x,则将act1加入到N的卫式动作集合中,以及将最右侧的子节 点设置为时钟等价类为ID_x,卫式动作集合为空,其子树为以Nr为根节点的子时钟树,否则跳 转到步骤7;
步骤7:将act1加入到N的卫式动作集合中,新建N的最右侧子节点:时钟等价类为ID_x, 卫式动作集合为空,子树为空;
步骤8:如果卫式动作集合已被遍历,则退出算法并输出clkTree,否则跳转步骤1;
如果clkTree为一棵时钟树,则构建成功,则执行步骤3)中的数据依赖分析;如果clkTree 为多棵时钟树或者非“树”结构,则构建失败,终止编译并报错;
前述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤3)中的具 体内容为:
31)数据依赖分析,通过构建时钟数据依赖图clkdataDG;
步骤1:从卫式动作集合中选择两个不同的卫式动作act1和act2;
步骤2:如果act1和act2都是输入动作或者都是输出动作,则跳转到步骤7;
步骤3:如果act1和act2分别是输入动作和输出动作,则跳转到步骤7;
步骤4:如果act1是输入动作,act2是立即动作或延迟动作,并且act1中信号变量存在于 act2的卫式之中或者动作的表达式之中,则把信息“act1先执行,act2才能执行”的约束条件添 加到clkdataDG中,然后跳转到步骤7;
步骤5:如果act1是输出动作,act2是立即动作或者延迟动作,并且act1中信号变量为act2 的动作中等式右侧的被赋值变量,则把信息“act2先执行,act1才能执行”的约束条件添加到 clkdataDG中,然后跳转到步骤7;
步骤6:如果act1是立即动作或延迟动作,act2是立即动作或延迟动作。则考虑以下情况: 如果act1的动作中等式右侧额被赋值变量存在于act2的卫式之中或者动作的表达式之中,则把 信息“act1先执行,act2才能执行”的约束条件添加到clkdataDG中;
步骤7:如果GCC_graph中任意两个不同的卫式动作都被遍历则退出算法,否则继续遍历 GCC_graph,转到步骤1;
32)基于拓扑排序的划分方法:
步骤1)找出当前clkdataDG中的入度为零的点集合InDegree_ZeroV,InDegree_ZeroV的 类型为列表类型,表示并行执行信息,包括以下子步骤:
步骤1.1:将clkdataDG转换为边对应右侧顶点集合Right_VS和左侧顶点集合Left_VS;
步骤1.2:优化顶点集合;删除冗余的顶点元素;
步骤1.3:计算一个入度为零的边集合ZeroEdges,计算规则为:选取那些只在左侧顶点集 合出现的顶点对应的边;
步骤1.4:计算一个入度为零的顶点集合InDegree_ZeroV;计算规则为:选取ZeroEdges 的左侧顶点元素,并删除冗余顶点,之后加入上一次划分时的孤立点集合;
步骤2)更新clkdataDG,包括以下子步骤:
步骤2.1:将InDegree_ZeroV和ZeroEdges从当前clkdataDG中删除;
步骤2.2:计算一个独立点集合IsolatedVertices,用于下一次划分时加入到InDegree_ZeroV 中,每次计算前清零,计算规则为:找出入度和出度都为零的顶点集合;
步骤2.3:将IsolatedVertices从当前clkdataDG中删除;
步骤3)迭代任务划分,包括以下子步骤:
步骤3.1:将当前InDegree_ZeroV存入partitionResult,partitionResult的类型为二维列表, 第一维保存每次循环得到的InDegree_ZeroV,下标表示串行执行信息;
步骤3.2:把空的InDegree_ZeroV、当前计算得到的IsolatedVertices和更新后的clkdataDG作为参数迭代执行步骤1),当clkdataDG为空时,划分停止,输出划分结 果partitionResult;
33)优化拓扑排序划分结果:
优化分为两部分:消除冗余依赖关系和合并线程;其中,消除冗余依赖关系包括找两个步骤,合并线程方法的主要步骤包括三个步骤,具体如下:
步骤1)找出冗余依赖关系,根据clkdataDG信息,将partitionResult中依赖关系分 类为不可优化的依赖关系和可优化的依赖关系两种,可优化依赖关系即冗余依赖关系,包括以 下子步骤:
步骤1.1:获得卫式动作对应的线程索引值,通过哈希表的方式在卫式动作和线程索引号之间建立映射关系;
步骤1.2:获取不可优化的依赖关系,不可优化表示该依赖关系存在于clkdataDG中,则其余的依赖关系为冗余依赖关系;
步骤2)优化依赖关系,优化步骤1中找出的冗余依赖关系,包括以下子步骤:
步骤2.1:优化线程所依赖的线程数目,根据冗余依赖关系,优化线程所依赖的 多余线程;
步骤2.2:优化线程被依赖的线程数目,根据冗余依赖关系,优化线程被依赖的 多余线程;
步骤3)定义可合并的线程,优化依赖关系之后进行线程合并,从partitionResult中标记可以合并的线程的索引值,标记原则为:如果线程a和b存在依赖关系a→b, 且a被依赖的线程数目和b所依赖的线程数目都为1,则令线程a和b为一组被标记的 索引值;
步骤4)迭代合并线程;
步骤4.1:获取一组被标记的索引值,获取失败表示不存在可合并的线程,进入 步骤5);
步骤4.2:若索引值个数等于2,则只合并索引值对应的两个线程;
步骤4.3:若索引值个数大于2,则选取两个索引值,执行步骤4.2,同时索引值 个数减少1,迭代执行步骤4.2,直到索引值个数为1;
步骤4.4:若索引值个数等于1,则执行步骤4.1;
步骤5)删除线程,合并过后,将除索引值最小的线程之外的其余线程从线程组 中删除,得到优化结果opt_partitionResult,包括以下子步骤:
步骤5.1:将被合并线程从线程组中删除;
步骤5.2:更新合并线程被依赖的线程信息,根据索引值最大的线程被依赖的线程信息更新合并线程的被依赖线程信息;
步骤5.3:更新其他线程所依赖的线程信息,如果其他线程和被合并的线程存在依赖关系,则用合并线程更新其他线程所依赖的线程信息;
34)基于流水线方式的任务划分方法:
步骤1)定义流水线阶段,根据步骤4.3)得到的划分结果opt_partitionResult,确定流水线 阶段,将划分的任务转换为对应的流水线阶段;
步骤2)增加流水线中间变量,在不同的流水线阶段之间增加流水线中间变量,用于记录 不同流水线下的不同流水线阶段生成的中间结果,包括以下子步骤:
步骤2.1:对输入动作进行初始化,基于流水线方式会同时处理多个输入动作,采用数组 方式保存;
步骤2.2:记录流水线中间变量,用于记录存在依赖关系的卫式动作之间用于数据交换的 临时变量;
步骤3)增加通信函数,在同一流水线中不同流水线阶段中增加和流水线中间变量的通信 函数以及不同流水线之间的通信函数,后者是由于延迟动作影响流水线方式,因此需要增加延 迟动作,包括以下子步骤:
步骤3.1:增加并初始化所有流水线对应流水线阶段的延迟动作,增加延迟动作到流水线 阶段的条件为:该流水线阶段的计算中涉及到延迟动作作用的信号;
步骤3.2:增加输入数据传输函数in_exchange,用于水线中间变量和依赖卫式动作进行通 信;
步骤3.3:增加输出数据传输函数out_exchange,用于流水线中间变量和被依赖卫式动作进 行通信;
步骤3.4:增加不同流水线之间通信函数,根据延迟动作找出不同流水线之间的数据通信 关系,进行数据传输。
前述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤4)中虚 拟多线程代码自动生成方法包括如下内容:
a)定义虚拟多线程代码,虚拟多线程的基本元素为:
wait元素:表示时钟数据依赖图中的依赖对象;即依赖关系a→b中a是b的依赖对象;
notify元素:表示时钟数据依赖图中的被依赖对象;即依赖关系a→b中b是a的被依赖 对象;
threadactions元素:表示虚拟多线程中单个线程的计算部分;由GCC_graph的卫式动作转 换得到;
thread元素:表示虚拟多线程的单个线程;线程由串行执行顺序索引值、线程索引值、依 赖对象集合、线程计算部分和被依赖对象集合组成;
b)虚拟多线程代码生成,虚拟多线程分为Init模块、Main模块和线程组模块,对应于转换 程序中的三个转换规则;
首先,将GCC_graph程序转换为虚拟多线程代码VirtualMT,然后分别处理三个模块:线 程组模块、Main模块和Init模块;
其次,从GCC_graph中生成三个不同模块的转换规则分别是:
转换规则1.GCC_graph的初始时钟转换为Init模块,对延迟动作进行初始化, 记为printVirtualInitialzationModule模块;
转换规则2.GCC_graph的卫式动作声明和调用信息转换为Main模块:在Main模 块创建新的线程调用,记为createNewThread模块;
将GCC_graph程序转换为Main模块,包括创建新线程函数、调用Init模块、调用线程组 模块,记为printVirtualMainModule模块;
转换规则3.GCC_graph的卫式动作集合转换为线程组模块,包括
waittoInt、waittoStr子模块:用于获取依赖对象对应的线程索引值;
notifytoInt、notifytoStr子模块:获取被依赖对象对应的线程索引值;
addWaittoThreadBody子模块:给线程增加wait模块,即线程所依赖信息;
addNotifytoThreadBody子模块:给线程增加notify模块,即线程被依赖信息;
handleThreadGroup子模块:将卫式动作集合转换为线程组;给每个线程增加线程索引值, 然后将卫式动作转换为线程的计算部分;
partitionResulttoVirtualMultiThread子模块:根据划分结果partitionResult,对GCC_graph 程序进行划分线程;计算串行执行顺序索引值,然后处理线程组;
前述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤5)中虚 拟多线程代码转换到可执行多线程Ada/C代码方法的具体内容为:
6.1)可执行多任务Ada代码自动生成:
转换规则1.生成头文件:
生成可执行Ada代码中*.ads文件和*.adb文件的库单元,即保留字with和use后面的内容, 记为getAdaHeadFile函数;
转换规则2.Wait/notify生成entry函数和accept函数中函数调用:
getAdaTaskEntry_Call函数:生成Ada中单个task声明中的入口函数entry()和执行函数 accept()中的函数调用;将VirtualMT中任务的输入参数以及流水线方式下的数据传输函数转换为 Ada中的entry()和对应参数;由wait信息中包含任务决定entry()的个数,并将notify转换为accept 函数中的函数调用;
转换规则3.Init模块和线程组模块中的所有变量转换为Ada变量声明,生成Ada中的涉及 到的所有变量声明,并初始化对应变量,将VirtualMT中的变量一一对应转换为procedure和task 等结构中用到的Ada变量,同时,将VirtualMT的Init模块信息赋值到对应Ada变量,记为 getAdaVariables函数;
转换规则4.线程组模块所有线程转换为Ada中对应Task:
getAdaPackage模块:分别在*.ads文件和*.adb文件中生成GCC_graph对应的包声明和包 的主体结构;
getAdaTaskAccept模块:生成Ada中单个taskbody中的执行函数accept()的具体计算,将 VirtualMT中对应任务的计算部分转换accept()中的执行操作;
getExecutableRightBraceIndent模块:生成*.ads文件和*.adb文件中所有的缩进,保证层次 化的结构,提高生成代码可读性;
getAdaTask模块:生成Ada中单个task,包括临时变量声明、入口函数entry()和执行函数 accept()这三部分;
getAdaTasks模块:在Package中生成所有的任务,将VirtualMT的线程组模块转换为Ada 中对应的任务,通过迭代的方式生成所有任务;
getAdaInputFunction模块:生成可执行Ada代码的输入函数,根据GCC_graph的输入动作, 增加读取文件操作,负责从输入文件中读取信号变量,其中,‘’表示信号处于缺失状态;
getAdaOutputFunction模块:生成可执行Ada代码的输出函数,根据GCC_graph的输出动 作,增加写入文件操作,负责往输出文件中写入计算结果;
转换规则5.Main模块转换为主函数procedure:
getAdaCreateTask模块:声明被使用的任务,将VirtualMT中任务转换为Ada代码中的任 务声明,以便于之后被调用;
getAdaProcedure模块:生成可执行Ada代码中的main函数部分,将VirtualMT中main函 数模块转换为procedure,用于创建并调用任务;
6.2)可执行多任务C代码自动生成:
转换规则1.头文件生成:
getExecutableHeadFile模块:生成可执行C代码头文件声明,包括stdio.h和pthread.h;
转换规则2.根据wait/notify定义互斥量函数,包括
getExecutableStructCounter函数:用于生成可执行C代码中的互斥量结构定义;
getExecutableStructWaitNotify函数:用于生成wait/notify机制对应的C代码实现,在目标 C代码中分别是wait()和notify()函数;
转换规则3.声明变量,包括
getExecutableWaitNotify2CounterDeclaration模块:生成互斥量对应的变量声明;
getExecutabledeclaration模块:生成信号变量的可执行C代码声明;
getExecutableClockClassDeclaration模块:生成GAC中时钟对应的变量声明;
转换规则4.变量初始化,包括
printWaitNotifyofExecutableInit模块:初始化互斥量赋值;
printDelayofExecutableInit模块:初始化延迟动作赋值;
printMasterClockofExecutableInit模块:初始化主时钟赋值;
getExecutableInitModule模块:生成Inin模块对应的可执行C代码,包括初始化主时钟、 初始化延迟动作和初始化互斥量;
转换规则5.生成任务组;
getScourceType模块:获取源GAC中的信号变量的类型并转换为目标可执行C代码对应 的类型;基本的数据类型转化为Integer→int、Char→char、Boolean→enumBoolean{FALSE, TRUE}、String→char*;
printExecutableWait模块:处理线程所依赖的线程,将与所依赖线程之间的依赖关系转换 为对应的wait()函数;
printExecutableNotify模块:处理线程被依赖的线程,将与被依赖线程之间的依赖关系转换 为对应的notify()函数;
getExecutableThreadBody模块:处理线程的计算部分,将卫式动作转换为完成计算功能的 可执行C代码;
getExecutableRightBraceIndent模块:处理生成代码的缩进问题,通过使用不同的缩进值, 使得生成的代码层次化明显;
getExecutableSingleThread模块:生成单个可执行C线程,包括处理线程的依赖线程、计 算部分、被依赖线程以及缩进问题;
getExecutableThreadGroupModule模块:生成线程组模块对应的可执行C代码,依次生成 每个可执行C线程;
转换规则6.生成Main函数:
getPthreadCreate模块:线程创建,对应于POSIX中的pthread_create;
getPthreadJoin模块:线程调用,调用需要执行的线程,对应于POSIX中的pthread_join;
getExecutableMainModule模块:生成Main模块对应的可执行C代码,包括初始化调用、 线程创建和线程调用。
本发明所达到的有益效果:本发明定义的GCC_graph具有以下特征:GCC_graph 依赖于同步假设,基于形式化MoC的GCC_graph不仅可以用于功能验证,而且可以 用于静态程序分析来保证应用程序的实时性;GCC_graph采用多任务同步并发模式, 使得任务之间的通信开销为0;在每个逻辑时刻,系统功能行为采用非递归的方式进行 表达,以及通过逻辑时刻的次数表达循环执行次数,因此非常适合设计面向安全关键 领域的时间可预测系统;采用图形化和文本建模两种方式,便于设计人员构建 GCC_graph模型;其次本发明给出了自动编译生成多任务Ada/C代码的方法,包括时 钟演算、数据依赖分析与任务划分、虚拟多线程以及Ada/C代码生成。最后,由于 GCC_graph侧重于模型的数据流行为,因此可采用在AADL中扩展同步附件的方式, 使用图形化卫式命令演算GCC_graph描述同步附件的内容,从而增加AADL对线程和 子程序中数据流行为的表达。同样地,随着多核处理器的广泛使用,多态同步模式得 到更多关注。图形化卫式命令演算GCC_graph同时支持纯同步模式、多态同步模式。 可作为多种同步语言之间进行集成的中间语言,即支持多种同步语言经编译生成统一 的GCC_graph同步模型。
附图说明
图1:模块化GCC_graph编译体系结构;
图2:基于拓扑排序划分示例;
图3:优化任务划分方法示例;
图4:输入输出依赖特例;
图5:基于流水线方式的任务划分示例;
图6:虚拟多线程结构;
图7:虚拟多线程代码生成可执行多线程Ada/C代码;
图8(a)为立即动作的图形化建模元素图,(b)为延迟动作的图形化建模元素图, (c)为约束动作的图形化建模元素图,(d)为输入动作的图形化建模元素图,(e)为输 出动作的图形化建模元素图。
具体实施方式
下面将结合附图对本发明作进一步的说明:
本发明涉及到一个图形化卫式命令演算GCC_graph自动编译生成可执行多任务Ada/C代 码方法,对于设计人员输入的GCC_graph程序,该编译器自动将其编译生成相应的可 执行多任务Ada/C代码。该编译器的所有功能由函数式程序设计语言CAML编程实现, 由于CAML是一种安全的语言,CAML程序在执行之前由自身编译器进行验证。此外, 本发明设计的编译器使用模块化结构,一旦需求发生改变,只需要修改对应模块即可。
本发明定义了图形化卫式命令演算GCC_graph的形式语法和形式语义。该 GCC_graph编译器,基于模块化结构设计技术,将编译过程分为时钟演算、任务划分、 虚拟多线程代码自动生成和可执行多任务Ada/C代码自动生成这四个模块,其中任务划分 包括定义时钟数据依赖图和任务划分方法。我们提供了三种任务划分方法,用于提高 目标Ada/C代码的执行效率。详细见图1。
采用函数式程序设计语言CAML来实现GCC_graph编译器的所有功能,本方法的 实现具体步骤如下:
1)定义GCC_graph语言:
本专利给出一些与GCC_graph有关的基本定义。一个GCC_graph模型是定义在信号变量集 合V上的卫式动作集合。GCC_graph模型的输入输出为一组取值序列,记为信号变量 (或信号)。在每一个逻辑时刻,信号为两种状态中之一:处于存在状态并携带一个值value或 者处于缺失状态(记为⊥)。信号s中所有处于存在状态的逻辑时刻集合定义为s对应的抽象时 钟,记为如果两个信号s1和s2的抽象时钟相同,则称s1和s2同步。
图形化卫式命令演算GCC_graph语言由图形化规约、文本语法和形式语义组成。
图形化规约的基本建模元素定义:
本专利为图形化同步演算建模提供了一套图形化建模元素。卫式动作的基本结构和对应的 图形化建模元素包括立即动作ImA(Immediate Action)、延迟动作DA(DelayAction)、约束 动作AA(Assume Action)、输入动作InA(Input Action)和输出动作OutA(Output Action)五 类,具体如下:
立即动作:接收(m+n)个输入信号,包含m个输入信号用于卫式判断和n个输入信号用 于计算动作,如果卫式为true,则进行计算,并返回输出信号k,否则不执行任何操作。
延迟动作:接收m个用于卫式判断和n个用于动作计算的输入信号,如果卫式为true,则 执行计算,并延迟一个逻辑时刻输出结果k,否则不执行任何操作。
约束动作:接收m个用于卫式判断和n个用于约束的输入信号,如果卫式为true,则执行 同步操作,同步n个输入信号,并输出同步结果,否则不执行任何操作。
输入动作:从外部环境中接收输入信号,在每个逻辑时刻,始终首先检查输入信号。
输出动作:将信号输出到外部环境中。在每个逻辑时刻,在计算完成之后判断是否输出信 号。
GCC_graph文本语法的形式化定义:
GCC_graph的五类基本结构的形式语法和对应语义解释如下所示,
其中,卫式G是定义在信号变量X、信号变量x∈X的逻辑时钟及其初始时钟之 上的布尔条件;τ是定义在X上的表达式;σ则是定义在X及其逻辑时钟上的布尔表达式。
在研究当中,我们仅考虑GCC_graph的基本结构,因为所有的扩展结构都可以通过基本结 构来表示。GCC_graph中基本结构的抽象语法表示如下,
上述定义中,x为GCC_graph中的信号变量,GCC_graph/x为GCC_graph中的局部信号变 量声明,f能够表达常量(如true,false等)、算术运算、逻辑运算以及用户自定义函数。此外, 不同的GCC_graph之间组合采用同步组合操作‘||’,因此GCC_graph能够表达确定性并发行为。
GCC_graph的形式语义:
计算机语言的形式语义主要有操作语义、指称语义、公理语义和代数语义四类。本发明基于踪迹模型定义GCC_graph的指称语义。首先给出卫式、约束和表达式的时钟 定义和取值定义,然后定义GCC_graph的形式语义。
在定义卫式、约束和表达式的时钟和取值部分。给定一个踪迹S、逻辑时刻i和信号变量X, 定义如下函数,
的域定义为 为真,当且仅当在S上的逻辑时刻i,G中的所有信号变 量都处于存在状态。这里需要注意,由于每个时钟都可以在任意逻辑时刻被读取,因此被 定义为真。
定义一个偏函数当为真,计算γ的取值(真或假)。
的域定义为 为真,当且仅当在S上的逻辑时刻i,τ中的所有信号变量 都不缺失。
定义一个偏函数当为真,计算τ的取值(真或假)。
这里和分别具有和相同的定义,是因为卫式和约束具有相同的语 法结构。
在定义GCC_graph的指称语义部分。一个GCC_graph系统的踪迹语义定义为踪迹的集合,
即,我们给出立即动作、延迟动作、约束定
义、输入动作和输出动作的语义规则。
规则1,如果G中包含的所有信号变量都处于存在状态,G取值为真,且x和τ中的所有 变量都处于存在状态,那么x赋值为τ。
规则2,在逻辑时刻i1,如果G中包含的所有信号变量都处于存在状态,G取值为真,且x和τ中的所有变量都处于存在状态,i2为i1的下一个逻辑时刻,在逻辑时刻i2,x处于存在状 态,则i2时刻的x赋值为i1时刻的τ。
规则3,如果G中包含的所有信号变量都处于存在状态,G取值为真,则σ包含的所有信号变量都处于存在状态,且σ的取值为真。
规则4,如果G中包含的所有信号变量都处于存在状态,G取值为真,则x处于存在状态, 且赋值为从环境接收的值r。
规则5,如果G中包含的所有信号变量都处于存在状态,G取值为真,则x处于存在状态, 且赋值给释放到环境的值w。
GCC_graph的组合语义定义为:
2)基于GCC_graph的时钟演算
GCC_graph表达了时钟关系和功能行为。因此针对时钟关系,在编译器生成代码之前必须 先进行时钟演算,从而保证GCC_graph模型是确定可执行的。时钟演算包括定义时钟关系和构 建时钟树。如果时钟树成功被构建,则表示模型可以生成具有确定性行为的代码,再进行多线 程代码生成。
定义卫式动作对应的时钟关系:
其中,表示表达式G中所有信号变量的时钟都为true且G取值为true。表示信 号变量x和表达式τ中变量对应的时钟都为true。→表示时钟蕴含关系,例如意 味着子节点为真,父节点恒为真,从而构建时钟树。
构建时钟树:
通过BDD(Binary Decision Diagram)检查两个时钟之间的时钟蕴含关系,从而构建时钟树。 同时,在时钟树的每个节点中,所有的时钟变量都等价,因此使用时钟等价类替代对应的时钟 变量,从而优化时钟关系。
DefineElement:定义树的节点,包括节点的标记值elm和时钟,elm用于确定生成目标代码 时的时钟等价类的ID;
DefineHierarchy:定义树的结构,树叶为Empty,树枝(或节点)为Relation;
Move:确定插入的位置。通过BDD(Binary Decision Diagram)检查两个当前节点中时钟和 待插入时钟两者之间的时钟蕴含关系。在确定蕴含关系后,如果本节点的子树不为空,执行Move 方法,将时钟插入到某个已有节点上,或者新建的节点上;
InsertClockVariable:将时钟插入到树中,通过Move确定插入位置,执行时钟插入操作;
ConstructHierarchy:将时钟插入到一个空的时钟树中,从而创建一个时钟树。
3)基于GCC_graph的三种任务划分方法
并行代码生成由时钟数据依赖图驱动完成,我们先给出依赖关系定义,基于依赖关系将GCC_graph转换为时钟数据依赖图clkdataDG。进一步地,通过对clkdataDG进 行任务划分抽取源GCC_graph中并行执行信息和串行执行信息,从而生成多任务代码 并保证确定性执行顺序。任务划分是整个并行编译器的核心,为最大限度分析出 GCC_graph程序的并行度以及减少最终可执行代码的运行时间,本专利提出基于拓扑 排序的任务划分、优化任务划分和基于流水线方式的任务划分这三种方法。
构建时钟数据依赖图:
我们先定义依赖关系。对于任意卫式动作a和b存在依赖关系:a执行结束b才可 以执行,记为a→b。
设S(e)为表达式e中所有变量的集合。一个clkdataDG是定义在卫式动作集合A上的依赖关系集合,依赖关系分为三种如下所示。
其中,
双卫式动作依赖:当x1在τ2或γ2中存在,则执行结束才可以执行。表明两个卫式动作之间具有依赖关系;
输入、卫式动作依赖:当x1在τ2中存在,则执行结束才可以执行。输入动作和卫式动作存在依赖关系表示输入的变量被卫式动作用于计算;
输出、卫式动作依赖:当x1和x2相同,执行结束才可以执行。输出动作和卫式动作存在依赖关系表示输出的变量是卫式动作的计算结果。
需要补充的是,两个输入(输出)动作之间不存在依赖关系。在串行代码生成中,因为必须给出确定的执行顺序,所以定义输入(或输出)之间存在依赖关系。而在并行代码 生成中,多个输入(输出)之间的执行顺序没有约束关系,因此不存在依赖关系。而输入 和输出动作的依赖关系通过中间的卫式动作来建立间接的依赖关系。
构建时钟数据依赖图的算法为:
算法1构建时钟数据依赖图clkdataDG
输入:GCC_graph
输出:clkdataDG
步骤1:从卫式动作选择两个不同的卫式动作act1和act2;
步骤2:如果act1和act2都是输入动作或者都是输出动作,则跳转到步骤7;
步骤3:如果act1和act2分别是输入动作和输出动作,则跳转到步骤7;
步骤4:如果act1是输入动作,act2是立即动作或延迟动作,并且act1中信号变 量存在于act2的卫式之中或者动作的表达式之中,则把act1→act2添加到clkdataDG 中,然后跳转到步骤7;
步骤5:如果act1是输出动作,act2是立即动作或者延迟动作,并且act1中信号 变量为act2的动作中等式右侧的被赋值变量,则把act2→act1添加到clkdataDG中, 然后跳转到步骤7;
步骤6:如果act1是立即动作或延迟动作,act2是立即动作或延迟动作。则考虑以下情况:如果act1的动作中等式右侧额被赋值变量存在于act2的卫式之中或者动作的 表达式之中,则把act1→act2添加到clkdataDG中;
步骤7:如果GCC_graph中任意两个不同的卫式动作都被遍历则退出算法,否则继续遍历GCC_graph,转到步骤1;
基于拓扑排序的任务划分:
由于clkdataDG是一个有向无环图。常用的划分方法是使用拓扑排序的思想,对clkdataDG进行任务划分,从而找到并行信息。即将clkdataDG通过划分方法生成partitionResult。划分结果如图2所示,其中串行执行信息为S1到S8顺序执行,并行执行信息为 单个{}内所有节点可以并行执行。
CAML定义构建拓扑排序任务划分方法为:
步骤1.找出当前clkdataDG中的入度为零的点集合InDegree_ZeroV(列表类型,表示并行 执行信息)。包括以下函数:
getOutDegree:将clkdataDG转换为边对应右侧顶点集合Right_VS。通过遍历图中边的右 侧顶点;
getInDegree:将clkdataDG转换为边对应左侧顶点集合Left_VS。通过遍历图中边的左侧 顶点;
deleteDuplicatedElements:优化顶点集合。删除冗余的顶点元素;
getZeroEdges:将clkdataDG转换为入度为零的边集合。选取那些只在左侧顶点集合出现 的顶点对应的边;
getZeroVertices:计算一个入度为零的顶点集合InDegree_ZeroV。计算规则为:选取 getZeroEdges中边的左侧顶点元素,并删除冗余顶点,之后加入上一次划分时的孤立点集合;
步骤2.更新clkdataDG。将InDegree_ZeroV和ZeroEdges从当前clkdataDG中删除;找出独立点集合IsolatedVertices,并将IsolatedVertices从当前clkdataDG中删除。包括以下 函数:
getIsolatedVertices:获取孤立点集合IsolatedVertices。从clkdataDG中删去InDegree_ZeroV对应的边,然后获取入度和出度都为零的顶点集合,用于下一次划分时加入到 InDegree_ZeroV中;
步骤3.迭代任务划分。先将当前计算得到的InDegree_ZeroV存入partitionResult(一 个二维列表类型,第一维保存每次循环得到的InDegree_ZeroV,下标表示串行执行信息)中,然 后把InDegree_ZeroV(为空)、当前循环计算得到的IsolatedVertices和更新后的clkdataDG 作为参数迭代执行步骤1。当clkdataDG为空时,划分停止。主要包括以下函数:
partition_TopologicalSorting:对clkdataDG进行任务划分。使用拓扑排序的思想, 将clkdataDG划分为必须串行执行部分和可以并行执行部分;
getPartitionResult:对GCC_graph进行依赖关系分析和任务划分。先根据分析将GCC_graph 转换为clkdataDG,然后对clkdataDG进行任务划分,得到划分结果partitionResult;
优化任务划分:
得到partitionResult之后,由于基于拓扑排序的任务划分结果会增加一些多余的依赖关系, 这些冗余依赖关系会降低程序划分的并行度,且极大增加生成的代码的执行时间。我们提出解 决方案(如图3所示)对拓扑排序的结果进行优化,消解拓扑排序结果中冗余依赖关系,从而 提高程序的并行度。此外clkdataDG中节点数目决定最终生成的任务数目,因此本发明还提出一 种合并节点(线程)的方法来尝试对任务划分的结果进行进一步的优化。
CAML定义优化任务划分步骤为:
步骤1.找出冗余依赖关系。根据clkdataDG,将partitionResult中依赖关系分类为不 可优化的依赖关系和可优化的依赖关系两种,可优化依赖关系即冗余依赖关系。主要包括以下 函数:
getActionbyId:获得卫式动作对应的线程索引值。通过哈希表的方式在卫式动作和线程索引号之间建立映射关系;
getUniqueElement:获取不可优化的依赖关系。即存在于clkdataDG的依赖关系;
步骤2.优化依赖关系。优化步骤1中找出的冗余依赖关系,包括以下函数:
optimizeWait:优化线程所依赖的线程数目;
optimizeNotify:优化线程被依赖的线程数目;
optimizeWaitNotify:优化线程的依赖关系。根据clkdataDG优化partitionResult中存 在的冗余依赖关系。冗余依赖关系指的是那些包含在partitionResult中而不属于clkdataDG的依 赖关系;
步骤3.定义可合并的线程。优化依赖关系之后进行线程合并,首先需要标记出 哪些线程可以被合并。标记函数为:
getAnnexableThreads:从partitionResult中找出可以合并的依赖关系;
步骤4.迭代合并线程。根据标记函数得到的索引值,通过迭代的方式将所有可 合并线程进行合并。包括以下函数:
getThread:获得线程索引值对应的线程;
mergeTwoThread:合并给定的两个线程。合并原则为:如果线程a和b存在依赖 关系a→b,且a被依赖的线程数目和b所依赖的线程数目都为1,则合并线程a和b;
步骤5.删除线程。合并过后,将除索引值最小的线程之外的其余线程从线程组 中删除,同时包括整个优化步骤的总控函数。主要函数如下:
deleteThreadIdFromWaitlist:删除线程索引值;
deleteRedundantThread:将被合并线程从线程组中删除;
optimizeSortingResult:优化拓扑排序的划分结果。通过合并和删除冗余线程完成 优化,将partitionResult转换为opt_partitionResult;
基于流水线方式的任务划分:
通过上述任务划分,得到clkdataDG中可以并行执行的部分以及必须串行执行的部 分。不过存在两类特殊情况:由于源程序和划分过程的限制,并不能找到并行度更高 的划分结果,或者由于源程序本身并不存在可以并行执行的部分。为解决这类问题,本 文引入计算机流水线技术(Pipeline)的思想,提出一种流水线方式(Pipeline Style)对clkdataDG进行划分。
流水线方式使用的前提是GCC_graph程序中不存在输入输出依赖特例:一个程序的当前逻辑时刻的输出为这个程序下个逻辑时刻的输入。如图4所示,系统的当前逻 辑时刻的Output值被用于下个逻辑时刻的Input_2值,因此会导致多条并行流水线实 际上只能按照一条流水线方式串行执行。
如图5所示,本文的流水线方式分为以下几步:根据划分结果定义流水线阶段; 针对各流水线阶段增加流水线中间变量;在同一流水线中处理不同流水线阶段之间的 通信行为以及在不同流水线中处理GCC_graph的延迟动作的通信行为。
CAML定义基于流水线方式的任务划分方法为:
步骤1.定义流水线阶段。根据划分结果opt_partitionResult,确定流水线阶段。涉及到的函 数为:
pipelineExecutableSingleThread:将划分的任务转换为对应的流水线阶段;
步骤2.增加流水线中间变量。在不同的流水线阶段之间增加流水线中间变量(数组), 用于记录不同流水线下的不同流水线阶段生成的中间结果。包括以下函数:
inputArray:用于对输入动作进行初始化。由于基于流水线方式,会同时处理多个输入动 作,因此采用数组方式保存;
setPipelineVariable:记录流水线中间变量。用于记录存在依赖关系的卫式动作之间用于数 据交换的临时变量;
setExchangeIdofPipelineVariable:记录流水线中间变量对应的索引值;
printDeclarationofPipelineExchange:声明流水线中间变量和对应索引值以及数据传输函数;
步骤3.增加通信函数。在同一流水线中不同流水线阶段中增加和流水线中间变量的通信 函数以及不同流水线之间的通信函数,后者是由于延迟动作影响流水线方式,因此需要增加延 迟动作。包括以下函数:
printDelayofPipelineInit:初始化多个时刻下各自的延迟动作;
addInputExchange:增加输入数据传输函数in_exchange。用于流水线中间变量和依赖卫式 动作进行通信;
addOutputExchange:增加输出数据传输函数out_exchange。用于流水线中间变量和被依赖 卫式动作进行通信;
addPipeLinesCommunication:增加不同流水线之间通信函数。根据延迟动作找出不同流水 线之间的数据通信关系,进行数据传输;
pipelineGuardExp2str:在卫式动作的卫式中加入数据传输函数;
5)虚拟多线程代码自动生成方法
根据partitionResult生成基于Wait/Notify机制的虚拟多线程VirtualMT。目的是提供 支持从编译器后端生成验证代码和仿真代码平台无关的中间表达式的能力,以便未来 使用模型检测工具如UPPAAL对多线程代码的无死锁性等性质进行验证以及在仿真工具如simulink上进行仿真实验。
完整的VirtualMT代码主要分为三个模块:主函数模块、初始化模块和线程组模块, 如图6所示。主函数模块分为两个部分:其一是调用其他模块;其二创建while循环, 每一次循环执行一个逻辑时刻下GCC_graph程序。初始化模块是对GCC_graph程序中 信号变量的第一个逻辑时刻的值进行初始化。线程组模块由多个线程组成,完成对单 个逻辑时刻下的计算行为。
CAML定义的虚拟多线程代码:
wait:表示时钟数据依赖图中的依赖对象。即依赖关系a→b中a是b的依赖对象;
notify:表示时钟数据依赖图中的被依赖对象。即依赖关系a→b中b是a的被依 赖对象;
threadactions:表示虚拟多线程中单个线程的计算部分。由GCC_graph的卫式动作 转换得到;
thread:表示虚拟多线程的单个线程。线程由串行执行顺序索引值、线程索引值、依赖对象集合、线程计算部分和被依赖对象集合组成;
根据任务划分结果,可以抽取源GCC_graph中的并行信息和串行信息,即生成多任务代码并保证确定性执行顺序的信息。因此基于任务划分结果,可以将源GCC_graph 程序转换为虚拟多线程代码。
CAML定义虚拟多线程代码生成方法:
虚拟多线程的Init模块、Main模块和线程组模块分别对应于转换程序中的三个转换规则。 在介绍转换规则之前,定义虚拟多线程代码生成总控程序为:
getVirtualMultiThread:将GCC_graph程序转换为虚拟多线程代码VirtualMT。分别处理三个 模块:线程组模块、Main模块和Init模块;
从GCC_graph中生成三个不同模块的转换规则分别是:
转换规则1.GCC_graph的初始时钟转换为Init模块
printVirtualInitialzationModule:将GCC_graph程序转换为Init模块。主要是对延迟动作进行 初始化;
转换规则2.GCC_graph的卫式动作声明和调用信息转换为Main模块
createNewThread:在Main模块创建新的线程调用;
printVirtualMainModule:将GCC_graph程序转换为Main模块。包括创建新线程函数、调 用Init模块、调用线程组模块;
转换规则3.GCC_graph的卫式动作集合转换为线程组模块
wait2int、wait2str:获取依赖对象对应的线程索引值;
notify2int、notify2str:获取被依赖对象对应的线程索引值;
addWait2ThreadBody:给线程增加wait,即线程所依赖信息;
addNotify2ThreadBody:给线程增加notify,即线程被依赖信息;
handleThreadGroup:将卫式动作集合转换为线程组。给每个线程增加线程索引值,然后将 卫式动作转换为线程的计算部分;
partitionResult2VirtualMultiThread:根据划分结果partitionResult,对GCC_graph程序进行 划分线程。计算串行执行顺序索引值,然后处理线程组的内容;
6)可执行多任务Ada/C代码自动生成方法
虚拟多线程代码是不可执行的,为生成最后的可执行代码,我们接下来给出虚拟多 线程代码到可执行多任务Ada/C代码生成的转换规则。对应转换关系如图7所示,其 中线程组模块转换为Ada中的多个task和C中的多个函数,初始化模块转换为Ada和 C中的初始化函数,main模块分别转换为Ada中的procedure和C中的main函数。
所述虚拟多线程代码转换到可执行多任务Ada/C代码方法包括:
虚拟多线程代码转换到可执行多任务Ada代码方法:
转换规则1.生成头文件。生成基本头文件stdio.h和使用POSIX机制调用的头文件pthread.h。对应的CAML函数为:
getAdaHeadFile:生成可执行Ada代码中*.ads文件和*.adb文件的库单元(library unit), 即保留字with和use后面的内容。例如Ada.Text_IO和Ada.Strings.Unbounded等;
转换规则2.Wait/notify生成entry函数和accept函数中函数调用。根据虚拟多线程代码 中的wait、notify和任务计算部分在Ada代码的对应位置定义函数、函数调用和计算逻 辑。对应的CAML函数为:
getAdaTaskEntry_Call:生成Ada中单个task声明中的入口函数entry()和执行函数accept() 中的函数调用。将VirtualMT中任务的输入参数(以及流水线方式下的数据传输函数)转换为 Ada中的entry()和对应参数。由wait信息中包含任务决定entry()的个数,并将notify转换为accept 函数中的函数调用。
转换规则3.Init模块和线程组模块中所有变量转换为Ada变量声明和初始化。根据源 GCC_graph程序分析变量类型,并转换为对应的Ada类型对变量进行声明。对应的CAML函数为:
getAdaVariables:生成Ada中的涉及到的所有变量声明,并初始化对应变量。将VirtualMT 中的变量(包括时钟变量)一一对应转换为procedure和task等结构中用到的Ada变量。同时, 将VirtualMT的Init模块信息赋值到对应Ada变量。
转换规则4.线程组模块所有线程转换为Ada中对应Task。每个任务生成:任务名、任 务声明、变量声明、入口函数和任务主体。对应的CAML函数包括:
getAdaPackage:分别在*.ads文件和*.adb文件中生成GCC_graph对应的包声明和包的主体 结构;
getAdaTaskbody生成Ada中单个taskbody中的执行函数accept()。将VirtualMT中对应任 务的计算部分转换accept()中的执行操作;
getExecutableRightBraceIndent:生成*.ads文件和*.adb文件中所有的缩进。保证层次化的结 构,提高生成代码可读性;
getAdaTask:生成Ada中单个task。包括临时变量声明、入口函数entry()和执行函数accept() 这三部分;
getAdaTasks:在Package中生成所有的任务。将VirtualMT的线程组模块转换为Ada中对 应的任务,通过迭代的方式生成所有任务;
getAdaInputFunction:生成可执行Ada代码的输入函数。根据GCC_graph的输入动作,增 加读取文件操作,负责从输入文件中读取信号变量。其中,‘’表示信号处于缺失状态;
getAdaOutputFunction:生成可执行Ada代码的输出函数。根据GCC_graph的输出动作, 增加写入文件操作,负责往输出文件中写入计算结果;
转换规则5.Main模块转换为主函数procedure。生成一个Ada中procedure。创建任务 函数,调用任务函数以及处理延迟动作。对应的CAML函数包括:
getAdaCreateTask:声明被使用的任务。将VirtualMT中任务转换为Ada代码中的任务声 明,以便于之后被调用;
getAdaProcedure:生成可执行Ada代码中的main函数部分。将VirtualMT中main函数模 块转换为procedure,用于创建并调用任务;
虚拟多线程代码转换到可执行多任务C代码方法:
转换规则1.头文件生成。生成基本头文件stdio.h和使用POSIX机制调用的头文件pthread.h。对应的CAML函数为:
getExecutableHeadFile:生成可执行C代码头文件声明。包括stdio.h和pthread.h等;
转换规则2.根据wait/notify定义互斥量函数。本文使用POSIX中互斥量的方式来实 现虚拟多线程的Wait/Notify机制,因此需要定义对应函数来完成wait和notify功能。对应的CAML函数包括:
getExecutableStructCounter:生成可执行C代码中的互斥量结构定义;
getExecutableStructWaitNotify:生成wait/notify机制对应的C代码实现。在目标C代码中 分别是wait()和notify()函数;
转换规则3.声明变量。根据源GCC_graph程序分析变量类型,并转换为对应的C 类型对变量进行声明。对应的CAML函数包括:
getExecutableWaitNotify2CounterDeclaration:生成互斥量对应的变量声明;
getExecutabledeclaration:生成信号变量的可执行C代码声明;
getExecutableClockClassDeclaration:生成GCC_graph中时钟对应的变量声明;
转换规则4.变量初始化。对主时钟、虚拟多线程的初始化模块和互斥量进行初始化。对应的CAML函数包括:
printWaitNotifyofExecutableInit:初始化互斥量赋值;
printDelayofExecutableInit:初始化延迟动作赋值;
printMasterClockofExecutableInit:初始化主时钟赋值;
getExecutableInitModule:生成Inin模块对应的可执行C代码。包括初始化主时钟、初始化 延迟动作和初始化互斥量;
转换规则5.生成任务组。每个任务调用各个子函数分别生成:任务名、传入参数、wait机制、卫式、动作和notify机制。对应的CAML函数包括:
getScourceType:获取源GCC_graph中的信号变量的类型并转换为目标可执行C代码对应 的类型。基本的数据类型转化为Integer→int、Char→char、Boolean→enumBoolean{FALSE, TRUE}、String→char*等;
printExecutableWait:处理任务所依赖的任务。将与所依赖任务之间的依赖关系转换为对应 的wait()函数;
printExecutableNotify:处理任务被依赖的任务。将与被依赖任务之间的依赖关系转换为对 应的notify()函数;
getExecutableTaskBody:处理任务的计算部分。将卫式动作转换为完成计算功能的可执行 C代码;
getExecutableRightBraceIndent:处理生成代码的缩进问题。通过使用不同的缩进值,使得 生成的代码层次化明显;
getExecutableSingleTask:生成单个可执行C任务。包括处理任务的依赖任务、计算部分、 被依赖任务以及缩进问题;
getExecutableTaskGroupModule:生成任务组模块对应的可执行C代码。依次生成每个可 执行C任务;
转换规则6.生成Main函数。生成main函数的结构,包括初始化函数,创建任务函数,调用任务函数以及处理延迟动作。对应的CAML函数包括:
getPthreadCreate:任务创建,对应于POSIX中的pthread_create;
getPthreadJoin:任务调用,调用需要执行的任务,对应于POSIX中的pthread_join;
getExecutableMainModule:生成Main模块对应的可执行C代码。包括初始化调用、任务 创建和任务调用。
以上所述仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说, 在不脱离本发明技术原理的前提下,还可以做出若干改进和变形,这些改进和变形也应视为本 发明的保护范围。
Claims (6)
1.一种基于图形化卫式命令演算的多任务编译方法,其特征在于:用于将图形化卫式命令演算语言GCC_graph编译生成多任务可执行Ada/C代码,编译过程包括如下步骤:
1)定义图形化卫式命令演算GCC_graph语言,包括图形化规约、文本语法和形式语义;
2)使用函数式程序设计语言CAML描述基于GCC_graph的时钟演算;
3)使用函数式程序设计语言CAML描述基于GCC_graph的任务划分,包括划分前进行的数据依赖分析和依次采用的三种划分方法,所述三种划分方法包括基于拓扑排序的任务划分、优化拓扑排序划分结果和基于流水线方式的任务划分方法;
4)使用函数式程序设计语言CAML描述基于划分结果的虚拟多线程代码自动生成方法;
5)使用函数式程序设计语言CAML描述虚拟多线程代码转换到可执行多任务Ada/C代码方法。
2.根据权利要求1所述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤1)中定义图形化卫式命令演算GCC_graph语言包括:
建立与GCC_graph有关的基本定义:
一个GCC_graph模型是定义在信号变量集合V上的卫式动作集合;
GCC_graph模型的输入输出为一组取值序列,记为信号变量或信号;
在每一个逻辑时刻,信号为两种状态中之一:处于存在状态并携带一个值value或者处于缺失状态,缺失状态记为⊥;信号s中所有处于存在状态的逻辑时刻集合定义为s对应的抽象时钟,记为如果两个信号s1和s2的抽象时钟相同,则称s1和s2同步;
a)图形化规约的基本建模元素定义:
卫式动作的基本结构和对应的图形化建模元素包括立即动作、延迟动作、约束动作、输入动作和输出动作五类,具体如下:
立即动作:接收(m+n)个输入信号,包含m个输入信号用于卫式判断和n个输入信号用于计算动作,如果卫式G为true,则进行计算f,并返回输出信号k,否则不执行任何操作;其中,f表达常量、算术运算、逻辑运算以及用户自定义函数;
延迟动作:接收m个用于卫式判断和n个用于动作计算的输入信号,如果卫式G为true,则执行计算f,并延迟一个逻辑时刻输出结果k,否则不执行任何操作;
约束动作:接收m个用于卫式判断和n个用于约束的输入信号,如果卫式为true,则执行同步操作,同步n个输入信号,并输出同步结果,否则不执行任何操作;
输入动作:从外部环境中接收输入信号,在每个逻辑时刻,在执行每个GCC_graph中计算之前,始终检查输入信号;
输出动作:将信号输出到外部环境中;在每个逻辑时刻,在每个GCC_graph中的计算完成之后判断是否输出信号;
b)GCC_graph文本语法的形式化定义:
GCC_graph的五类基本结构的形式语法和对应语义解释如下所示:
其中,卫式G是定义在信号变量X、信号变量x的逻辑时钟及其初始时钟之上的布尔条件,x∈X;τ是定义在X上的表达式;σ是定义在X及其逻辑时钟上的布尔表达式;
GCC_graph抽象语法表示为:上述定义中,GCC/x为GCC_graph中的局部信号变量声明;不同的GCC_graph之间组合采用同步组合操作‘||’;表示G和σ可能有x、f(G,...,G)这四种表达方式,τ表示τ可能有x、f(τ,...,τ)这两种表达方式;
c)GCC_graph的形式语义:分为两部分:第一部分为先定义卫式、约束和表达式的时钟和取值;第二部分为基于踪迹模型定义GCC_graph的指称语义;
第一部分,在给定踪迹S、逻辑时刻i和信号变量X,定义下列函数:
I)的域定义为 为真,当且仅当在S上的逻辑时刻i,G中的所有信号变量都处于存在状态,由于每个时钟都可以在任意逻辑时刻被读取,因此被定义为真:
定义一个偏函数当为真,计算γ的取值为真或假:
II)的域定义为 为真,当且仅当在S上的逻辑时刻i,τ中的所有信号变量都不缺失:
定义一个偏函数当为真,计算τ的取值真或假: 和分别具有I)中和相同的定义;
第二部分,基于踪迹模型定义GCC_graph的指称语义:
一个GCC_graph系统的踪迹语义定义为踪迹的集合,即,
立即动作:
延迟动作:
约束定义:
输入动作:
输出动作:
GCC_graph的组合语义定义为:
3.根据权利要求1所述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤2)中基于GCC_graph的时钟演算包括定义时钟关系和构建时钟树;如果时钟树成功被构建,则表示模型可以生成具有确定性行为的代码,再进行多线程代码生成;具体内容如下:
a)定义卫式动作对应的时钟关系:
其中,表示表达式G中所有信号变量的时钟都为true且G取值为true;表示信号变量x和表达式τ中变量对应的时钟都为true;→表示时钟蕴含关系;
b)构建时钟树:
通过二元决策图,检查两个时钟之间的时钟蕴含关系,从而构建时钟树;同时,在时钟树的每个节点中,所有的时钟变量都等价,使用时钟等价类替代对应的时钟变量,优化时钟关系;
时钟树结构可以按如下方式递归定义:一棵时钟树或为Empty,或为一个节点以及节点下方的多个子时钟树组成;Empty表示空的时钟树,节点由时钟等价类、卫式动作集合组成,子时钟树也可看做子节点,一棵完整的时钟树的叶子节点全部为Empty;
构建时钟树算法为:
步骤1:从卫式动作集合中选择一个卫式动作act1,如果act1类型为输入动作或输出动作,则跳转到步骤8;
步骤2:选择act1中动作的等式右侧的变量对应的时钟x_clk,通过二元决策图计算x_clk的时钟等价类ID_x;
步骤3:如果时钟树为Empty,则新建一个节点Node,其中存储ID_x和act1,并设置Node的子节点Node’为Empty,跳转到步骤8;
步骤4:如果时钟树中存在节点,记为N,如果N的子节点为Empty,将act1加入到N中,并且新建N的子节点N’,设置N’的时钟等价类为ID_x,否则跳转到步骤5;
步骤5:如果N有多个子节点,选择其最右侧的子节点Nr,比较Nr的时钟等价类ID_Nr和ID_x时钟蕴含关系;如果ID_x→ID_Nr,则递归调用,从步骤3开始,将act1和ID_x分别作为步骤1-2的所要计算的数值插入到以Nr为根节点的子时钟树中;
步骤6:如果ID_Nr→ID_x,则将act1加入到N的卫式动作集合中,以及将最右侧的子节点设置为时钟等价类为ID_x,卫式动作集合为空,其子树为以Nr为根节点的子时钟树,否则跳转到步骤7;
步骤7:将act1加入到N的卫式动作集合中,新建N的最右侧子节点:时钟等价类为ID_x,卫式动作集合为空,子树为空;
步骤8:如果卫式动作集合已被遍历,则退出算法并输出clkTree,否则跳转步骤1;
如果clkTree为一棵时钟树,则构建成功,则执行步骤3)中的数据依赖分析;如果clkTree为多棵时钟树或者非“树”结构,则构建失败,终止编译并报错。
4.根据权利要求1所述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤3)中的具体内容为:
31)数据依赖分析,通过构建时钟数据依赖图clkdataDG;
步骤1:从卫式动作集合中选择两个不同的卫式动作act1和act2;
步骤2:如果act1和act2都是输入动作或者都是输出动作,则跳转到步骤7;
步骤3:如果act1和act2分别是输入动作和输出动作,则跳转到步骤7;
步骤4:如果act1是输入动作,act2是立即动作或延迟动作,并且act1中信号变量存在于act2的卫式之中或者动作的表达式之中,则把信息“act1先执行,act2才能执行”的约束条件添加到clkdataDG中,然后跳转到步骤7;
步骤5:如果act1是输出动作,act2是立即动作或者延迟动作,并且act1中信号变量为act2的动作中等式右侧的被赋值变量,则把信息“act2先执行,act1才能执行”的约束条件添加到clkdataDG中,然后跳转到步骤7;
步骤6:如果act1是立即动作或延迟动作,act2是立即动作或延迟动作。则考虑以下情况:如果act1的动作中等式右侧额被赋值变量存在于act2的卫式之中或者动作的表达式之中,则把信息“act1先执行,act2才能执行”的约束条件添加到clkdataDG中;
步骤7:如果GCC_graph中任意两个不同的卫式动作都被遍历则退出算法,否则继续遍历GCC_graph,转到步骤1;
32)基于拓扑排序的划分方法:
步骤1)找出当前clkdataDG中的入度为零的点集合InDegree_ZeroV,InDegree_ZeroV的类型为列表类型,表示并行执行信息,包括以下子步骤:
步骤1.1:将clkdataDG转换为边对应右侧顶点集合Right_VS和左侧顶点集合Left_VS;
步骤1.2:优化顶点集合;删除冗余的顶点元素;
步骤1.3:计算一个入度为零的边集合ZeroEdges,计算规则为:选取那些只在左侧顶点集合出现的顶点对应的边;
步骤1.4:计算一个入度为零的顶点集合InDegree_ZeroV;计算规则为:选取ZeroEdges的左侧顶点元素,并删除冗余顶点,之后加入上一次划分时的孤立点集合;
步骤2)更新clkdataDG,包括以下子步骤:
步骤2.1:将InDegree_ZeroV和ZeroEdges从当前clkdataDG中删除;
步骤2.2:计算一个独立点集合IsolatedVertices,用于下一次划分时加入到InDegree_ZeroV中,每次计算前清零,计算规则为:找出入度和出度都为零的顶点集合;
步骤2.3:将IsolatedVertices从当前clkdataDG中删除;
步骤3)迭代任务划分,包括以下子步骤:
步骤3.1:将当前InDegree_ZeroV存入partitionResult,partitionResult的类型为二维列表,第一维保存每次循环得到的InDegree_ZeroV,下标表示串行执行信息;
步骤3.2:把空的InDegree_ZeroV、当前计算得到的IsolatedVertices和更新后的clkdataDG作为参数迭代执行步骤1),当clkdataDG为空时,划分停止,输出划分结果partitionResult;
33)优化拓扑排序划分结果:
优化分为两部分:消除冗余依赖关系和合并线程;其中,消除冗余依赖关系包括找两个步骤,合并线程方法的主要步骤包括三个步骤,具体如下:
步骤1)找出冗余依赖关系,根据clkdataDG信息,将partitionResult中依赖关系分类为不可优化的依赖关系和可优化的依赖关系两种,可优化依赖关系即冗余依赖关系,包括以下子步骤:
步骤1.1:获得卫式动作对应的线程索引值,通过哈希表的方式在卫式动作和线程索引号之间建立映射关系;
步骤1.2:获取不可优化的依赖关系,不可优化表示该依赖关系存在于clkdataDG中,则其余的依赖关系为冗余依赖关系;
步骤2)优化依赖关系,优化步骤1中找出的冗余依赖关系,包括以下子步骤:
步骤2.1:优化线程所依赖的线程数目,根据冗余依赖关系,优化线程所依赖的多余线程;
步骤2.2:优化线程被依赖的线程数目,根据冗余依赖关系,优化线程被依赖的多余线程;
步骤3)定义可合并的线程,优化依赖关系之后进行线程合并,从partitionResult中标记可以合并的线程的索引值,标记原则为:如果线程a和b存在依赖关系a→b,且a被依赖的线程数目和b所依赖的线程数目都为1,则令线程a和b为一组被标记的索引值;
步骤4)迭代合并线程;
步骤4.1:获取一组被标记的索引值,获取失败表示不存在可合并的线程,进入步骤5);
步骤4.2:若索引值个数等于2,则只合并索引值对应的两个线程;
步骤4.3:若索引值个数大于2,则选取两个索引值,执行步骤4.2,同时索引值个数减少1,迭代执行步骤4.2,直到索引值个数为1;
步骤4.4:若索引值个数等于1,则执行步骤4.1;
步骤5)删除线程,合并过后,将除索引值最小的线程之外的其余线程从线程组中删除,得到优化结果opt_partitionResult,包括以下子步骤:
步骤5.1:将被合并线程从线程组中删除;
步骤5.2:更新合并线程被依赖的线程信息,根据索引值最大的线程被依赖的线程信息更新合并线程的被依赖线程信息;
步骤5.2:更新其他线程所依赖的线程信息,如果其他线程和被合并的线程存在依赖关系,则用合并线程更新其他线程所依赖的线程信息;
34)基于流水线方式的任务划分方法:
步骤1)定义流水线阶段,根据步骤4.3)得到的划分结果opt_partitionResult,确定流水线阶段,将划分的任务转换为对应的流水线阶段;
步骤2)增加流水线中间变量,在不同的流水线阶段之间增加流水线中间变量,用于记录不同流水线下的不同流水线阶段生成的中间结果,包括以下子步骤:
步骤2.1:对输入动作进行初始化,基于流水线方式会同时处理多个输入动作,采用数组方式保存;
步骤2.2:记录流水线中间变量,用于记录存在依赖关系的卫式动作之间用于数据交换的临时变量;
步骤3)增加通信函数,在同一流水线中不同流水线阶段中增加和流水线中间变量的通信函数以及不同流水线之间的通信函数,后者是由于延迟动作影响流水线方式,因此需要增加延迟动作,包括以下子步骤:
步骤3.1:增加并初始化所有流水线对应流水线阶段的延迟动作,增加延迟动作到流水线阶段的条件为:该流水线阶段的计算中涉及到延迟动作作用的信号;
步骤3.2:增加输入数据传输函数in_exchange,用于水线中间变量和依赖卫式动作进行通信;
步骤3.3:增加输出数据传输函数out_exchange,用于流水线中间变量和被依赖卫式动作进行通信;
步骤3.4:增加不同流水线之间通信函数,根据延迟动作找出不同流水线之间的数据通信关系,进行数据传输。
5.根据权利要求1所述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤4)中虚拟多线程代码自动生成方法包括如下内容:
a)定义虚拟多线程代码,虚拟多线程的基本元素为:
wait元素:表示时钟数据依赖图中的依赖对象;即依赖关系a→b中a是b的依赖对象;
notify元素:表示时钟数据依赖图中的被依赖对象;即依赖关系a→b中b是a的被依赖对象;
threadactions元素:表示虚拟多线程中单个线程的计算部分;由GCC_graph的卫式动作转换得到;
thread元素:表示虚拟多线程的单个线程;线程由串行执行顺序索引值、线程索引值、依赖对象集合、线程计算部分和被依赖对象集合组成;
b)虚拟多线程代码生成,虚拟多线程分为Init模块、Main模块和线程组模块,对应于转换程序中的三个转换规则;
首先,将GCC_graph程序转换为虚拟多线程代码VirtualMT,然后分别处理三个模块:线程组模块、Main模块和Init模块;
其次,从GCC_graph中生成三个不同模块的转换规则分别是:
转换规则1.GCC_graph的初始时钟转换为Init模块,对延迟动作进行初始化,记为printVirtualInitialzationModule模块;
转换规则2.GCC_graph的卫式动作声明和调用信息转换为Main模块:在Main模块创建新的线程调用,记为createNewThread模块;
将GCC_graph程序转换为Main模块,包括创建新线程函数、调用Init模块、调用线程组模块,记为printVirtualMainModule模块;
转换规则3.GCC_graph的卫式动作集合转换为线程组模块,包括
waittoInt、waittoStr子模块:用于获取依赖对象对应的线程索引值;
notifytoInt、notifytoStr子模块:获取被依赖对象对应的线程索引值;
addWaittoThreadBody子模块:给线程增加wait模块,即线程所依赖信息;
addNotifytoThreadBody子模块:给线程增加notify模块,即线程被依赖信息;
handleThreadGroup子模块:将卫式动作集合转换为线程组;给每个线程增加线程索引值,然后将卫式动作转换为线程的计算部分;
partitionResulttoVirtualMultiThread子模块:根据划分结果partitionResult,对GCC_graph程序进行划分线程;计算串行执行顺序索引值,然后处理线程组。
6.根据权利要求5所述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤5)中虚拟多线程代码转换到可执行多线程Ada/C代码方法的具体内容为:
6.1)可执行多任务Ada代码自动生成:
转换规则1.生成头文件:
生成可执行Ada代码中*.ads文件和*.adb文件的库单元,即保留字with和use后面的内容,记为getAdaHeadFile函数;
转换规则2.Wait/notify生成entry函数和accept函数中函数调用:
getAdaTaskEntry_Call函数:生成Ada中单个task声明中的入口函数entry()和执行函数accept()中的函数调用;将VirtualMT中任务的输入参数以及流水线方式下的数据传输函数转换为Ada中的entry()和对应参数;由wait信息中包含任务决定entry()的个数,并将notify转换为accept函数中的函数调用;
转换规则3.Init模块和线程组模块中的所有变量转换为Ada变量声明,生成Ada中的涉及到的所有变量声明,并初始化对应变量,将VirtualMT中的变量一一对应转换为procedure和task 等结构中用到的Ada变量,同时,将VirtualMT的Init模块信息赋值到对应Ada变量,记为getAdaVariables函数;
转换规则4.线程组模块所有线程转换为Ada中对应Task:
getAdaPackage模块:分别在*.ads文件和*.adb文件中生成GCC_graph对应的包声明和包的主体结构;
getAdaTaskAccept模块:生成Ada中单个task body中的执行函数accept()的具体计算,将VirtualMT中对应任务的计算部分转换accept()中的执行操作;
getExecutableRightBraceIndent模块:生成*.ads文件和*.adb文件中所有的缩进,保证层次化的结构,提高生成代码可读性;
getAdaTask模块:生成Ada中单个task,包括临时变量声明、入口函数entry()和执行函数accept()这三部分;
getAdaTasks模块:在Package中生成所有的任务,将VirtualMT的线程组模块转换为Ada中对应的任务,通过迭代的方式生成所有任务;
getAdaInputFunction模块:生成可执行Ada代码的输入函数,根据GCC_graph的输入动作,增加读取文件操作,负责从输入文件中读取信号变量,其中,‘’表示信号处于缺失状态;
getAdaOutputFunction模块:生成可执行Ada代码的输出函数,根据GCC_graph的输出动作,增加写入文件操作,负责往输出文件中写入计算结果;
转换规则5.Main模块转换为主函数procedure:
getAdaCreateTask模块:声明被使用的任务,将VirtualMT中任务转换为Ada代码中的任务声明,以便于之后被调用;
getAdaProcedure模块:生成可执行Ada代码中的main函数部分,将VirtualMT中main函数模块转换为procedure,用于创建并调用任务;
6.2)可执行多任务C代码自动生成:
转换规则1.头文件生成:
getExecutableHeadFile模块:生成可执行C代码头文件声明,包括stdio.h和pthread.h;
转换规则2.根据wait/notify定义互斥量函数,包括
getExecutableStructCounter函数:用于生成可执行C代码中的互斥量结构定义;
getExecutableStructWaitNotify函数:用于生成wait/notify机制对应的C代码实现,在目标C代码中分别是wait()和notify()函数;
转换规则3.声明变量,包括
getExecutableWaitNotify2CounterDeclaration模块:生成互斥量对应的变量声明;
getExecutabledeclaration模块:生成信号变量的可执行C代码声明;
getExecutableClockClassDeclaration模块:生成GAC中时钟对应的变量声明;
转换规则4.变量初始化,包括
printWaitNotifyofExecutableInit模块:初始化互斥量赋值;
printDelayofExecutableInit模块:初始化延迟动作赋值;
printMasterClockofExecutableInit模块:初始化主时钟赋值;
getExecutableInitModule模块:生成Inin模块对应的可执行C代码,包括初始化主时钟、初始化延迟动作和初始化互斥量;
转换规则5.生成任务组;
getScourceType模块:获取源GAC中的信号变量的类型并转换为目标可执行C代码对应的类型;基本的数据类型转化为Integer→int、Char→char、Boolean→enum Boolean{FALSE,TRUE}、String→char*;
printExecutableWait模块:处理线程所依赖的线程,将与所依赖线程之间的依赖关系转换为对应的wait()函数;
printExecutableNotify模块:处理线程被依赖的线程,将与被依赖线程之间的依赖关系转换为对应的notify()函数;
getExecutableThreadBody模块:处理线程的计算部分,将卫式动作转换为完成计算功能的可执行C代码;
getExecutableRightBraceIndent模块:处理生成代码的缩进问题,通过使用不同的缩进值,使得生成的代码层次化明显;
getExecutableSingleThread模块:生成单个可执行C线程,包括处理线程的依赖线程、计算部分、被依赖线程以及缩进问题;
getExecutableThreadGroupModule模块:生成线程组模块对应的可执行C代码,依次生成每个可执行C线程;
转换规则6.生成Main函数:
getPthreadCreate模块:线程创建,对应于POSIX中的pthread_create;
getPthreadJoin模块:线程调用,调用需要执行的线程,对应于POSIX中的pthread_join;
getExecutableMainModule模块:生成Main模块对应的可执行C代码,包括初始化调用、线程创建和线程调用。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201810045360.1A CN108319458B (zh) | 2018-01-17 | 2018-01-17 | 一种基于图形化卫式命令演算的多任务编译方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201810045360.1A CN108319458B (zh) | 2018-01-17 | 2018-01-17 | 一种基于图形化卫式命令演算的多任务编译方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN108319458A true CN108319458A (zh) | 2018-07-24 |
CN108319458B CN108319458B (zh) | 2021-04-06 |
Family
ID=62894599
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201810045360.1A Active CN108319458B (zh) | 2018-01-17 | 2018-01-17 | 一种基于图形化卫式命令演算的多任务编译方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN108319458B (zh) |
Cited By (6)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN110058940A (zh) * | 2019-03-08 | 2019-07-26 | 苏宁易购集团股份有限公司 | 一种多线程环境下的数据处理方法及装置 |
CN110083337A (zh) * | 2019-04-03 | 2019-08-02 | 江苏梦立渊软件技术有限公司 | 一种软件开发优化方法 |
CN111090464A (zh) * | 2018-10-23 | 2020-05-01 | 华为技术有限公司 | 一种数据流处理方法及相关设备 |
CN112711450A (zh) * | 2020-12-29 | 2021-04-27 | 西安精密机械研究所 | 采用函数指针索引实现软件复杂有限状态机状态迁移的方法 |
CN113806290A (zh) * | 2021-08-27 | 2021-12-17 | 中国航空无线电电子研究所 | 一种用于综合模块化航空电子系统的高完整性片上系统 |
CN116954623A (zh) * | 2023-09-19 | 2023-10-27 | 南京国睿信维软件有限公司 | 一种跨多语言的代码混合调用方法 |
Citations (10)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101329638A (zh) * | 2007-06-18 | 2008-12-24 | 国际商业机器公司 | 程序代码的并行性的分析方法和系统 |
CN101710378A (zh) * | 2009-10-10 | 2010-05-19 | 北京理工大学 | 一种基于序列模式挖掘的软件安全漏洞检测方法 |
CN102566974A (zh) * | 2012-01-14 | 2012-07-11 | 哈尔滨工程大学 | 基于同时多线程的取指控制方法 |
CN103995742A (zh) * | 2014-05-20 | 2014-08-20 | 万向钱潮股份有限公司 | 一种基于mcu的嵌入式实时调度控制装置及方法 |
US20150242747A1 (en) * | 2014-02-26 | 2015-08-27 | Nancy Packes, Inc. | Real estate evaluating platform methods, apparatuses, and media |
US20160299746A1 (en) * | 2015-04-07 | 2016-10-13 | Qualcomm Innovation Center, Inc. | Auto-vectorization in just-in-time compilers for dynamically typed programming languages |
US20160313981A1 (en) * | 2012-05-31 | 2016-10-27 | New York University | Configuration-preserving preprocessor |
CN107341010A (zh) * | 2017-06-26 | 2017-11-10 | 华中科技大学 | 一种C/C++与COStream混合编程方法和可视化编译系统 |
CN107562430A (zh) * | 2017-09-22 | 2018-01-09 | 吉林大学 | 一种针对移动π演算语言的文件处理功能的编译方法 |
CN107577454A (zh) * | 2017-09-25 | 2018-01-12 | 四川长虹电器股份有限公司 | 一种基于python的应用程序多线程运行优化方法 |
-
2018
- 2018-01-17 CN CN201810045360.1A patent/CN108319458B/zh active Active
Patent Citations (11)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101329638A (zh) * | 2007-06-18 | 2008-12-24 | 国际商业机器公司 | 程序代码的并行性的分析方法和系统 |
CN101329638B (zh) * | 2007-06-18 | 2011-11-09 | 国际商业机器公司 | 程序代码的并行性的分析方法和系统 |
CN101710378A (zh) * | 2009-10-10 | 2010-05-19 | 北京理工大学 | 一种基于序列模式挖掘的软件安全漏洞检测方法 |
CN102566974A (zh) * | 2012-01-14 | 2012-07-11 | 哈尔滨工程大学 | 基于同时多线程的取指控制方法 |
US20160313981A1 (en) * | 2012-05-31 | 2016-10-27 | New York University | Configuration-preserving preprocessor |
US20150242747A1 (en) * | 2014-02-26 | 2015-08-27 | Nancy Packes, Inc. | Real estate evaluating platform methods, apparatuses, and media |
CN103995742A (zh) * | 2014-05-20 | 2014-08-20 | 万向钱潮股份有限公司 | 一种基于mcu的嵌入式实时调度控制装置及方法 |
US20160299746A1 (en) * | 2015-04-07 | 2016-10-13 | Qualcomm Innovation Center, Inc. | Auto-vectorization in just-in-time compilers for dynamically typed programming languages |
CN107341010A (zh) * | 2017-06-26 | 2017-11-10 | 华中科技大学 | 一种C/C++与COStream混合编程方法和可视化编译系统 |
CN107562430A (zh) * | 2017-09-22 | 2018-01-09 | 吉林大学 | 一种针对移动π演算语言的文件处理功能的编译方法 |
CN107577454A (zh) * | 2017-09-25 | 2018-01-12 | 四川长虹电器股份有限公司 | 一种基于python的应用程序多线程运行优化方法 |
Non-Patent Citations (2)
Title |
---|
ZHIBIN YANG,JEAN-PAUL BODEVEIX: ""Towards a verified compiler prototype for the synchronous"", 《FRONTIERS OF COMPUTER SCIENCE》 * |
杨志斌等: "同步语言的时间可预测多线程代码生成方法", 《软件学报》 * |
Cited By (12)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN111090464A (zh) * | 2018-10-23 | 2020-05-01 | 华为技术有限公司 | 一种数据流处理方法及相关设备 |
CN111090464B (zh) * | 2018-10-23 | 2023-09-22 | 华为技术有限公司 | 一种数据流处理方法及相关设备 |
US11900113B2 (en) | 2018-10-23 | 2024-02-13 | Huawei Technologies Co., Ltd. | Data flow processing method and related device |
CN110058940A (zh) * | 2019-03-08 | 2019-07-26 | 苏宁易购集团股份有限公司 | 一种多线程环境下的数据处理方法及装置 |
CN110058940B (zh) * | 2019-03-08 | 2022-11-22 | 苏宁易购集团股份有限公司 | 一种多线程环境下的数据处理方法及装置 |
CN110083337A (zh) * | 2019-04-03 | 2019-08-02 | 江苏梦立渊软件技术有限公司 | 一种软件开发优化方法 |
CN110083337B (zh) * | 2019-04-03 | 2023-01-03 | 江苏梦立渊软件技术有限公司 | 一种软件开发优化方法 |
CN112711450A (zh) * | 2020-12-29 | 2021-04-27 | 西安精密机械研究所 | 采用函数指针索引实现软件复杂有限状态机状态迁移的方法 |
CN113806290A (zh) * | 2021-08-27 | 2021-12-17 | 中国航空无线电电子研究所 | 一种用于综合模块化航空电子系统的高完整性片上系统 |
CN113806290B (zh) * | 2021-08-27 | 2023-10-27 | 中国航空无线电电子研究所 | 一种用于综合模块化航空电子系统的高完整性片上系统 |
CN116954623A (zh) * | 2023-09-19 | 2023-10-27 | 南京国睿信维软件有限公司 | 一种跨多语言的代码混合调用方法 |
CN116954623B (zh) * | 2023-09-19 | 2023-12-22 | 南京国睿信维软件有限公司 | 一种跨多语言的代码混合调用方法 |
Also Published As
Publication number | Publication date |
---|---|
CN108319458B (zh) | 2021-04-06 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN108319458A (zh) | 一种基于图形化卫式命令演算的多任务编译方法 | |
Amnell et al. | TIMES: a tool for schedulability analysis and code generation of real-time systems | |
Amnell et al. | UPPAAL-now, next, and future | |
Seawright et al. | Clairvoyant: A synthesis system for production-based specification | |
Baudisch et al. | Multithreaded code from synchronous programs: Extracting independent threads for OpenMP | |
Juan et al. | Compositional verification of concurrent systems using Petri-net-based condensation rules | |
Thiele et al. | Funstate-an internal design representation for codesign | |
Keutzer et al. | Our Pattern Language (OPL): A design pattern language for engineering (parallel) software | |
Tardieu et al. | Curing schizophrenia by program rewriting in Esterel | |
CN103646194B (zh) | 一种基于形式化验证的同步数据流程序的可信排序方法 | |
CN106648813B (zh) | 一种同步数据流程序的形式化编译方法 | |
CN111709138B (zh) | 面向cps时空性质的混成aadl建模与模型转换方法 | |
Potop-Butucaru et al. | Optimizations for faster execution of Esterel programs | |
Simon et al. | Design and analysis of synchronization for real-time closed-loop control in robotics | |
Borrione et al. | A compositional model for the functional verification of high-level synthesis results | |
Dams et al. | Specification and Implementation of Components of a MCRL Toolbox | |
Qi et al. | Formal Codesign and Implementation for Multifunction Vehicle Bus Circuits | |
Toma et al. | Combining several paradigms for circuit validation and verification | |
Bai et al. | A model-based design flow for asynchronous implementations from synchronous specifications | |
Sun et al. | A hierarchical CPN model automatically generating method aiming at multithreading program algorithm error detection | |
Amjad et al. | Verilog code generation scheme from signal language | |
Cai et al. | Introduction of design-oriented profiler of Specfic language | |
Jing et al. | An Automatic Task Partition Method for Multi-core System | |
Edwards et al. | Te FHW Project: High-Level Hardware Synthesis from Haskell Programs | |
Hu et al. | Verification of concurrent code from synchronous specifications |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |