Page 137 - 《软件学报》2025年第8期
P. 137

3560                                                       软件学报  2025  年第  36  卷第  8  期


                    (3) 调用结束后更新该变量的值.
                    对于时态运算符之间, 以及时态运算符和普通运算符之间的组合和嵌套的问题, 可以利用                             Lustre 的特性进行
                 解决. 对于  Lustre 中的每个运算符, 在运算后将生成一个新的匿名流. 例如                x+1  将生成一个时钟周期与       x 相同, 而
                 值为  x+1  的新的匿名流. 因此, pre (x+1) 需要存储   x+1  的值; 而  pre pre x 实际上是对  pre x 这个流再做  pre 运算, 即
                 取  pre x 的上一个周期的值. 由此, 不需要考虑存储多个周期前的值的问题.
                    表  3  是时态算子目标码模式, 以      function  结尾的函数为辅助函数, 在编译器内以模板的形式存在, 当一个类型
                 的运算符被调用时, 就生成对应类型的辅助函数. ctx              是上下文   (context) 的缩写, 表示运算符依赖的之前周期的信
                 息, 如算法  1  所示. 其中 result_ctx_type 为程序上下文信息的集合, 其中包含了所有在源程序中需要用到的上下文
                 信息. pre_get_function  表示获取上一周期该<Expression> 的值, 借助变量      ctx (内存空间是运行时申请的). pre_
                 set_function  计算当前周期<Expression> 的值, 并将其赋给   ctx; arrow_function  首先判断当前是否处于初始周期, 若
                 是则返回<Expression1> 表达式的值, 否则, 返回<Expression2> 表达式的值.

                                                  表 3 时态算子目标码模式

                   产生式左部               产生式右部                                目标码模式
                                                                        temp = pre_get_function(ctx);
                                      pre <Expression>
                                                                     pre_set_function(<Expression>, ctx);
                   Expression    <Expression1> → <Expression2>  temp = arrow_function(<Expression1>, <Expression2>, ctx);
                                                            temp = arrow_function(<Expression1>, pre_get_function(ctx), ctx);
                                 <Expression1> fby <Expression2>
                                                                     pre_set_function(<Expression2>, ctx);

                 算法  1. ctx  结构体代码  (目标  C  代码).

                 typedef struct {
                     int _memory;
                 } pre_int_ctx_type;
                 typedef struct {
                     int test;
                     pre_int_ctx_type pre_int_ctx_tab[1];
                 } result_ctx_type;
                    算法  2  为最终生成的    pre 运算符的   ctx  结构体和辅助函数的目标代码. pre_int_ctx_type 是    pre 运算符针对   int
                 型的上下文信息, 因此其_memory       成员保存了     int 型变量. 在辅助函数    pre_int_get 和  pre_int_set 中, 分别对  ctx  中
                 的_memory  进行了存取. 若程序中有不止一个对          int 流取  pre 的操作, 则该辅助函数可以复用.
                 算法  2. 辅助函数代码实例     (目标  C  代码).

                 int pre_int_get(pre_int_ctx_type* ctx){
                     return ctx → _memory;
                 }
                 void pre_int_set(int s1, pre_int_ctx_type* ctx){
                     ctx → _memory = s1;
                 }

                 3.2.2    时钟算子
                    时钟算子    when、current 和  merge 是控制流的时钟的运算符. 其中       when  生成一个非基础周期的流, current 生
                 成一个基础周期的流, merge 将多个非基础周期的流合并为一个基础周期的流. 这里需要指出, Lustre 中的运算符
                 会生成一个新的匿名流, 而非改变输入的流. 例如               A when ck  将生成一个值取决于     A, 而时钟周期取决于      ck  的匿
   132   133   134   135   136   137   138   139   140   141   142