CN108319458B - 一种基于图形化卫式命令演算的多任务编译方法 - Google Patents
一种基于图形化卫式命令演算的多任务编译方法 Download PDFInfo
- Publication number
- CN108319458B CN108319458B CN201810045360.1A CN201810045360A CN108319458B CN 108319458 B CN108319458 B CN 108319458B CN 201810045360 A CN201810045360 A CN 201810045360A CN 108319458 B CN108319458 B CN 108319458B
- Authority
- CN
- China
- Prior art keywords
- action
- module
- thread
- graph
- gcc
- 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.)
- Active
Links
- 238000000034 method Methods 0.000 title claims abstract description 115
- 238000004364 calculation method Methods 0.000 title claims abstract description 79
- 230000006870 function Effects 0.000 claims abstract description 152
- 102100025594 Guided entry of tail-anchored proteins factor CAMLG Human genes 0.000 claims abstract description 31
- 101000932902 Homo sapiens Guided entry of tail-anchored proteins factor CAMLG Proteins 0.000 claims abstract description 29
- 230000009471 action Effects 0.000 claims description 224
- 101150103244 ACT1 gene Proteins 0.000 claims description 48
- 102100031102 C-C motif chemokine 4 Human genes 0.000 claims description 36
- 101150078046 act2 gene Proteins 0.000 claims description 34
- 238000006243 chemical reaction Methods 0.000 claims description 33
- 230000014509 gene expression Effects 0.000 claims description 29
- 230000001360 synchronised effect Effects 0.000 claims description 27
- 230000001419 dependent effect Effects 0.000 claims description 25
- 238000004891 communication Methods 0.000 claims description 24
- 238000012545 processing Methods 0.000 claims description 20
- 230000009474 immediate action Effects 0.000 claims description 19
- 230000006399 behavior Effects 0.000 claims description 18
- 238000000638 solvent extraction Methods 0.000 claims description 13
- 238000004458 analytical method Methods 0.000 claims description 11
- 230000009466 transformation Effects 0.000 claims description 11
- 238000004422 calculation algorithm Methods 0.000 claims description 10
- 230000007246 mechanism Effects 0.000 claims description 10
- 238000005457 optimization Methods 0.000 claims description 10
- 238000007373 indentation Methods 0.000 claims description 9
- 230000008569 process Effects 0.000 claims description 7
- 230000005540 biological transmission Effects 0.000 claims description 6
- 238000010586 diagram Methods 0.000 claims description 6
- 238000010276 construction Methods 0.000 claims description 5
- 230000003111 delayed effect Effects 0.000 claims description 5
- 238000012546 transfer Methods 0.000 claims description 5
- 230000009191 jumping Effects 0.000 claims description 4
- 239000000126 substance Substances 0.000 claims description 4
- 238000012905 input function Methods 0.000 claims description 3
- 238000013507 mapping Methods 0.000 claims description 3
- 101100054773 Caenorhabditis elegans act-2 gene Proteins 0.000 claims description 2
- 238000013461 design Methods 0.000 description 4
- 238000005192 partition Methods 0.000 description 4
- 238000003780 insertion Methods 0.000 description 3
- 230000037431 insertion Effects 0.000 description 3
- 230000010354 integration Effects 0.000 description 3
- 238000011160 research Methods 0.000 description 3
- 238000004088 simulation Methods 0.000 description 3
- 238000012795 verification Methods 0.000 description 3
- 238000013459 approach Methods 0.000 description 2
- VQLYBLABXAHUDN-UHFFFAOYSA-N bis(4-fluorophenyl)-methyl-(1,2,4-triazol-1-ylmethyl)silane;methyl n-(1h-benzimidazol-2-yl)carbamate Chemical compound C1=CC=C2NC(NC(=O)OC)=NC2=C1.C=1C=C(F)C=CC=1[Si](C=1C=CC(F)=CC=1)(C)CN1C=NC=N1 VQLYBLABXAHUDN-UHFFFAOYSA-N 0.000 description 2
- 230000008859 change Effects 0.000 description 2
- 238000005516 engineering process Methods 0.000 description 2
- 238000004519 manufacturing process Methods 0.000 description 2
- 238000012986 modification Methods 0.000 description 2
- 230000004048 modification Effects 0.000 description 2
- 230000007704 transition Effects 0.000 description 2
- 238000003491 array Methods 0.000 description 1
- 230000009286 beneficial effect Effects 0.000 description 1
- 238000005094 computer simulation Methods 0.000 description 1
- 230000007547 defect Effects 0.000 description 1
- 238000001514 detection method Methods 0.000 description 1
- 238000011161 development Methods 0.000 description 1
- 238000009826 distribution Methods 0.000 description 1
- 230000007717 exclusion Effects 0.000 description 1
- 238000000605 extraction Methods 0.000 description 1
- 238000003384 imaging method Methods 0.000 description 1
- 238000002372 labelling Methods 0.000 description 1
- 230000002093 peripheral effect Effects 0.000 description 1
- 239000010453 quartz Substances 0.000 description 1
- 238000010223 real-time analysis Methods 0.000 description 1
- 238000012163 sequencing technique Methods 0.000 description 1
- VYPSYNLAJGMNEJ-UHFFFAOYSA-N silicon dioxide Inorganic materials O=[Si]=O VYPSYNLAJGMNEJ-UHFFFAOYSA-N 0.000 description 1
- 230000003068 static effect Effects 0.000 description 1
- 230000002123 temporal effect Effects 0.000 description 1
Images
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
Landscapes
- Engineering & Computer Science (AREA)
- General Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Devices For Executing Special Programs (AREA)
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和JavaOptimized 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)、虚拟处理器(VirtualProcessor)、存储器(Memory)、外设(Device)、总线(Bus)、虚拟总线(Virtual Bus)等构件以及连接来描述系统的硬件体系结构;通过分发协议(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模型的输入输出为一组取值序列,记为信号变量或信号;
在每一个逻辑时刻,信号为两种状态中之一:处于存在状态并携带一个值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的五类基本结构的形式语法和对应语义解释如下所示:
GCC_graph抽象语法表示为:上述定义中,GCC/x为GCC_graph中的局部信号变量声明;不同的GCC_graph之间组合采用同步组合操作‘||’;表示G和σ可能有x、f(G,...,G)这四种表达方式,τ表示τ可能有x、f(τ,...,τ)这两种表达方式;
c)GCC_graph的形式语义:分为两部分:第一部分为先定义卫式、约束和表达式的时钟和取值;第二部分为基于踪迹模型定义GCC_graph的指称语义;
第一部分,在给定踪迹S、逻辑时刻i和信号变量X,定义下列函数:
第二部分,基于踪迹模型定义GCC_graph的指称语义:
一个GCC_graph系统的踪迹语义定义为踪迹的集合,即,
延迟动作:
输入动作:
输出动作:
前述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤2)中基于GCC_graph的时钟演算包括定义时钟关系和构建时钟树;如果时钟树成功被构建,则表示模型可以生成具有确定性行为的代码,再进行多线程代码生成;具体内容如下:
a)定义卫式动作对应的时钟关系:
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中生成三个不同模块的转换规则分别是:
转换规则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中单个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代码,包括初始化调用、线程创建和线程调用。
本发明所达到的有益效果:本发明定义的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)五类,图8(a)为立即动作的图形化建模元素图,(b)为延迟动作的图形化建模元素图,(c)为约束动作的图形化建模元素图,(d)为输入动作的图形化建模元素图,(e)为输出动作的图形化建模元素图,具体如下:
立即动作:接收(m+n)个输入信号,包含m个输入信号用于卫式判断和n个输入信号用于计算动作,如果卫式为true,则进行计算,并返回输出信号k,否则不执行任何操作。
延迟动作:接收m个用于卫式判断和n个用于动作计算的输入信号,如果卫式为true,则执行计算,并延迟一个逻辑时刻输出结果k,否则不执行任何操作。
约束动作:接收m个用于卫式判断和n个用于约束的输入信号,如果卫式为true,则执行同步操作,同步n个输入信号,并输出同步结果,否则不执行任何操作。
输入动作:从外部环境中接收输入信号,在每个逻辑时刻,始终首先检查输入信号。
输出动作:将信号输出到外部环境中。在每个逻辑时刻,在计算完成之后判断是否输出信号。
GCC_graph文本语法的形式化定义:
GCC_graph的五类基本结构的形式语法和对应语义解释如下所示,
在研究当中,我们仅考虑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,定义如下函数,
在定义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。
2)基于GCC_graph的时钟演算
GCC_graph表达了时钟关系和功能行为。因此针对时钟关系,在编译器生成代码之前必须先进行时钟演算,从而保证GCC_graph模型是确定可执行的。时钟演算包括定义时钟关系和构建时钟树。如果时钟树成功被构建,则表示模型可以生成具有确定性行为的代码,再进行多线程代码生成。
定义卫式动作对应的时钟关系:
构建时钟树:
通过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上的依赖关系集合,依赖关系分为三种如下所示。
其中,
需要补充的是,两个输入(输出)动作之间不存在依赖关系。在串行代码生成中,因为必须给出确定的执行顺序,所以定义输入(或输出)之间存在依赖关系。而在并行代码生成中,多个输入(输出)之间的执行顺序没有约束关系,因此不存在依赖关系。而输入和输出动作的依赖关系通过中间的卫式动作来建立间接的依赖关系。
构建时钟数据依赖图的算法为:
算法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中生成三个不同模块的转换规则分别是:
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 (5)
1.一种基于图形化卫式命令演算的多任务编译方法,其特征在于:用于将图形化卫式命令演算语言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模型的输入输出为一组取值序列,记为信号变量或信号;
在每一个逻辑时刻,信号为两种状态中之一:处于存在状态并携带一个值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的五类基本结构的形式语法和对应语义解释如下所示:
GCC_graph抽象语法表示为:上述定义中,GCC/x为GCC_graph中的局部信号变量声明;不同的GCC_graph之间组合采用同步组合操作‘||’;表示G和σ可能有x、f(G,...,G)这四种表达方式,τ表示τ可能有x、f(τ,...,τ)这两种表达方式;
c)GCC_graph的形式语义:分为两部分:第一部分为先定义卫式、约束和表达式的时钟和取值;第二部分为基于踪迹模型定义GCC_graph的指称语义;
第一部分,在给定踪迹S、逻辑时刻i和信号变量X,定义下列函数:
第二部分,基于踪迹模型定义GCC_graph的指称语义:
延迟动作:
输入动作:
输出动作:
2.根据权利要求1所述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤2)中基于GCC_graph的时钟演算包括定义时钟关系和构建时钟树;如果时钟树成功被构建,则表示模型可以生成具有确定性行为的代码,再进行多线程代码生成;具体内容如下:
a)定义卫式动作对应的时钟关系:
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.根据权利要求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:增加不同流水线之间通信函数,根据延迟动作找出不同流水线之间的数据通信关系,进行数据传输。
4.根据权利要求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中生成三个不同模块的转换规则分别是:
转换规则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.根据权利要求4所述的一种基于图形化卫式命令演算的多任务编译方法,其特征在于:所述步骤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代码,包括初始化调用、线程创建和线程调用。
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 CN108319458A (zh) | 2018-07-24 |
CN108319458B true 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) |
Families Citing this family (8)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN111090464B (zh) | 2018-10-23 | 2023-09-22 | 华为技术有限公司 | 一种数据流处理方法及相关设备 |
CN110058940B (zh) * | 2019-03-08 | 2022-11-22 | 苏宁易购集团股份有限公司 | 一种多线程环境下的数据处理方法及装置 |
CN110083337B (zh) * | 2019-04-03 | 2023-01-03 | 江苏梦立渊软件技术有限公司 | 一种软件开发优化方法 |
CN112711478B (zh) * | 2019-10-24 | 2024-05-28 | 珠海零边界集成电路有限公司 | 基于神经网络的任务处理方法、装置、服务器和存储介质 |
CN112711450A (zh) * | 2020-12-29 | 2021-04-27 | 西安精密机械研究所 | 采用函数指针索引实现软件复杂有限状态机状态迁移的方法 |
CN113806290B (zh) * | 2021-08-27 | 2023-10-27 | 中国航空无线电电子研究所 | 一种用于综合模块化航空电子系统的高完整性片上系统 |
CN116954623B (zh) * | 2023-09-19 | 2023-12-22 | 南京国睿信维软件有限公司 | 一种跨多语言的代码混合调用方法 |
CN117950866B (zh) * | 2024-01-29 | 2024-07-05 | 维能(深圳)大数据技术有限公司 | 一种基于人工智能的算力运营管理系统及方法 |
Citations (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101329638B (zh) * | 2007-06-18 | 2011-11-09 | 国际商业机器公司 | 程序代码的并行性的分析方法和系统 |
CN102566974A (zh) * | 2012-01-14 | 2012-07-11 | 哈尔滨工程大学 | 基于同时多线程的取指控制方法 |
CN103995742A (zh) * | 2014-05-20 | 2014-08-20 | 万向钱潮股份有限公司 | 一种基于mcu的嵌入式实时调度控制装置及方法 |
Family Cites Families (7)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101710378B (zh) * | 2009-10-10 | 2011-04-06 | 北京理工大学 | 一种基于序列模式挖掘的软件安全漏洞检测方法 |
US8806456B2 (en) * | 2012-05-31 | 2014-08-12 | New York University | Configuration-preserving preprocessor and configuration-preserving parser |
WO2015130928A1 (en) * | 2014-02-26 | 2015-09-03 | Nancy Packes, Inc. | Real estate evaluating platform methods, apparatuses, and media |
US9690551B2 (en) * | 2015-04-07 | 2017-06-27 | Qualcomm Innovation Center, Inc. | Auto-vectorization in just-in-time compilers for dynamically typed programming languages |
CN107341010B (zh) * | 2017-06-26 | 2019-12-13 | 华中科技大学 | 一种C/C++与COStream混合编程方法和可视化编译系统 |
CN107562430B (zh) * | 2017-09-22 | 2020-07-28 | 吉林大学 | 一种针对移动π演算语言的文件处理功能的编译方法 |
CN107577454A (zh) * | 2017-09-25 | 2018-01-12 | 四川长虹电器股份有限公司 | 一种基于python的应用程序多线程运行优化方法 |
-
2018
- 2018-01-17 CN CN201810045360.1A patent/CN108319458B/zh active Active
Patent Citations (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101329638B (zh) * | 2007-06-18 | 2011-11-09 | 国际商业机器公司 | 程序代码的并行性的分析方法和系统 |
CN102566974A (zh) * | 2012-01-14 | 2012-07-11 | 哈尔滨工程大学 | 基于同时多线程的取指控制方法 |
CN103995742A (zh) * | 2014-05-20 | 2014-08-20 | 万向钱潮股份有限公司 | 一种基于mcu的嵌入式实时调度控制装置及方法 |
Also Published As
Publication number | Publication date |
---|---|
CN108319458A (zh) | 2018-07-24 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN108319458B (zh) | 一种基于图形化卫式命令演算的多任务编译方法 | |
Bourke et al. | A formally verified compiler for Lustre | |
Amnell et al. | UPPAAL-now, next, and future | |
Li et al. | Aggressive pipelining of irregular applications on reconfigurable hardware | |
Thiele et al. | Funstate-an internal design representation for codesign | |
Bhaduri et al. | Model checking of statechart models: Survey and research directions | |
Hobor et al. | Barriers in concurrent separation logic: now with tool support! | |
Huang et al. | A framework for reliability-aware embedded system design on multiprocessor platforms | |
Keutzer et al. | Our Pattern Language (OPL): A design pattern language for engineering (parallel) software | |
Yip et al. | The ForeC synchronous deterministic parallel programming language for multicores | |
Tardieu et al. | Curing schizophrenia by program rewriting in Esterel | |
CN106648813B (zh) | 一种同步数据流程序的形式化编译方法 | |
Puschner | Transforming execution-time boundable code into temporally predictable code | |
Potop-Butucaru et al. | Optimizations for faster execution of Esterel programs | |
Hu et al. | Multi-threaded code generation from Signal program to OpenMP | |
Bezati | High-level synthesis of dataflow programs for heterogeneous platforms: design flow tools and design space exploration | |
Durand et al. | A tool to support Bluespec SystemVerilog coding based on UML diagrams | |
Castrillon et al. | Dataflow Models of computation for programming heterogeneous multicores | |
Sun et al. | A hierarchical CPN model automatically generating method aiming at multithreading program algorithm error detection | |
EP3970003B1 (en) | Compilation and execution of source code as services | |
Nanjundappa et al. | A new multi-threaded code synthesis methodology and tool for correct-by-construction synthesis from polychronous specifications | |
Sinha et al. | Competitors or Cousins? Studying the parallels between distributed programming languages SystemJ and IEC61499 | |
Talpin et al. | A compositional behavioral modeling framework for embedded system design and conformance checking | |
Hu et al. | Verification of concurrent code from synchronous specifications | |
Arató et al. | A data flow graph generation method starting from C description by handling loop nest hierarchy |
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 |