SystemVerilog Chapter24: Programs

news/2024/5/19 19:50:29 标签: Systemverilog

24.1General概述

本条款描述了以下内容:
        --Programs 声明
        --Programs 调度语义
        --与时钟块结合使用的Programs 
        --匿名Programs 

24.2 Overview

        module是设计的基本构建块。module可以包含其他模块、网络、变量、子例程声明以及always过程和initial过程中的过程语句的层次结构。这种结构对于硬件的描述非常有效。然而,对于测试台来说,重点不在于硬件级别的细节,如布线、结构层次和互连,而在于对验证设计的完整环境进行建模。环境必须正确初始化和同步,避免设计和测试台之间的竞争,自动生成输入激励,并重用现有模型和其他基础设施
程序块有以下三个基本用途:
        --它为测试台的执行提供了一个入口点
        --它创建了一个范围,用于封装程序范围内的数据、任务和函数
        --它提供了一个语法上下文,用于指定reactive区域集中的调度
        program构造充当了设计和测试台之间的清晰分隔符,更重要的是,它在程序中声明的所有元素的reactive区域集中指定了专门的执行语义与clocking块一起,程序结构提供了设计和测试台之间的无竞争交互,并实现了循环和事务级别的抽象
        SystemVerilog的抽象和建模结构简化了测试台的创建和维护。实例化和单独连接每个程序实例的能力使它们能够用作通用模型。

24.3 The program construct

        一个典型的program包含类型和数据声明、子例程、到设计的连接以及一个或多个过程代码流。设计和测试台之间的连接使用用于指定端口连接(包括接口)的相同互连机制。program端口声明语法和语义与模块相同(见23.2.2)。
        程序块的语法如下:

program_nonansi_header ::=                 // from A.1.2
    { attribute_instance } program [ lifetime ] program_identifier
        { package_import_declaration } [ parameter_port_list ] list_of_ports ;
program_ansi_header ::=
    {attribute_instance } program [ lifetime ] program_identifier
        { package_import_declaration }[注释1] [ parameter_port_list ] [ list_of_port_declarations ] ;
program_declaration ::=
    program_nonansi_header [ timeunits_declaration ] { program_item }
        endprogram [ : program_identifier ]
    | program_ansi_header [ timeunits_declaration ] { non_port_program_item }
        endprogram [ : program_identifier ]
    | { attribute_instance } program program_identifier ( .* ) ;
    [ timeunits_declaration ] { program_item }
        endprogram [ : program_identifier ]
    | extern program_nonansi_header
    | extern program_ansi_header
program_item ::=         // from A.1.7
    port_declaration ;
    | non_port_program_item
non_port_program_item ::=
    { attribute_instance } continuous_assign
    | { attribute_instance } module_or_generate_item_declaration
    | { attribute_instance } initial_construct
    | { attribute_instance } final_construct
    | { attribute_instance } concurrent_assertion_item
    | timeunits_declaration[注释3]
    | program_generate_item
program_generate_item[注释5] ::=
    loop_generate_construct
    | conditional_generate_construct
    | generate_region
lifetime ::= static | automatic             // from A.2.1.3
anonymous_program ::= program ; { anonymous_program_item } endprogram // from A.1.11
anonymous_program_item ::=
task_declaration
    | function_declaration
    | class_declaration
    | covergroup_declaration
    | class_constructor_declaration
    | ;

1) package_ansi_header、interface_ansi_head或program_ansi-header中的package_import_declaration后面应跟有参数port_list或list_of_port_declarations,或两者兼有。
3) 只有当时间单位声明在同一时间范围内重复并匹配以前的时间单位声明时,时间单位声明才可以作为non_port_module_item, non_port_interface_item, non_port_program_item, 或 package_item合法项。
5)  program_generate_item在program_generate_item之外的program_declaration中包含任何可能是非法的项目都是非法的。

                Syntax 24-1—Program declaration syntax (excerpt from Annex A)


 program test (input clk, input [16:1] addr, inout [7:0] data);
    initial ...
endprogram

program test ( interface device_ifc );
    initial ...
endprogram

14.8和14.9中包含了一个更完整的示例。
        program构造可以被认为是具有特殊执行语义的子叶模块一旦声明,程序块就可以在所需的分层位置(通常在顶层)实例化,并且其端口可以以与任何其他模块相同的方式连接。
      
 program块可以嵌套在模块或接口中。这允许多个协作程序共享作用域的本地变量。没有端口的嵌套 program或未显式实例化的顶层 program将隐式实例化一次隐式实例化的 program具有相同的实例和声明名称。
例如:

module test(...);
int shared; // variable shared by programs p1 and p1
    program p1;
        ...
    endprogram
    program p2;
        ...
    endprogram // p1 and p2 are implicitly instantiated once in module test
endmodule

        程序块可以包含一个或多个inital或final过程。它不应包含always过程、primitives、UDP或模块、接口或其他programs的声明或实例
        当program中的所有initial过程都已结束时,该program应立即终止该程序中initial过程的所有子线程。如果在至少一个程序块中至少有一个initial过程,则在所有程序中源自所有initial过程的所有线程及其所有派生线程结束后,整个仿真应立即通过对$finish系统任务的隐式调用终止
        program中的类型和数据声明是program范围的本地声明,并且具有静态生存期。在program范围内声明的变量,包括声明为端口的变量,称为program变量。类似地,在program范围内声明的网络被称为program网络。program变量和网络统称为program信号。
        与program信号相对的是设计信号。在模块、接口、包或$unit中声明的任何net或变量都被认为是设计信号。引用任何program块外部的program信号都是错误的。层次引用从一个program范围扩展到另一个program作用域是合法的。但是,匿名program不应包含对其他program作用域的层次引用。

24.3.1 Scheduling semantics of code in program constructs(program结构中代码的调度语义)

        program块中对设计信号的变化(例如更新事件)敏感的语句和构造被安排在Reactive区域中。考虑一个包含以下语句的program块 @(clk) S1;其中clk是设计信号。信号clk的每一个转变将导致语句S1被调度到Reactive 区域中。连续赋值赋值tclk=clk;也将安排在Reactive 区域。同样,program块中的initial程序也安排在Reactive 区域中。program块中的标准#延迟操作在Reactive 区域中的流程中恢复。
       program代码中的非阻塞赋值在Re-NBA区域中安排其更新。Re-NBA区域在Reactive和Re-Inactive区域清空事件后进行处理。参见4.2。
        program块中允许并发断言。并发断言具有不变的调度语义——无论是存在于程序代码还是设计代码中。断言总是在处理Preponded区域时对可用值进行采样,并且在处理Observed区域时总是对其进行评估。如果断言是由程序对象上的活动计时的(不推荐),则调度器将从图4-1中围绕外循环设置的反应区域,通过评估断言的观察区域进行迭代。
        一旦program进程启动一个执行线程,该线程中的所有后续阻塞语句都会在Reactive区域中进行调度。这包括线程调用的子例程代码,即使子例程代码是在模块、包或接口中声明的。实际上,在design或testbench继承调用它的线程的调度区域。由于程序代码永远不能被模块代码调用,所以program代码总是作为reactive处理的一部分执行。模块、接口或包范围中的代码可以作为Active区域集或reactive集处理的一部分执行。

24.3.2 Operation of program port connections in the absence of clocking blocks(在没有时钟块的情况下程序端口连接的操作)

        第14章节描述了clocking 块与程序端口的相互作用。clocking 块是在设计和测试台之间建立无竞争行为的重要组成部分。然而,可以构造一个不包含clocking 块的程序。这样的程序在与设计代码交互时更容易发生竞争。本小节定义了在没有时钟块的情况下程序端口与设计代码的交互。
        程序端口是程序范围对象。它们总是连接到设计对象(网络和变量),因为程序只能在设计范围内实例化。程序中声明的顺序代码总是在reactive区域集中执行。因此,程序端口连接的另一侧的变量在 reactive区域集中被更新。类似地,程序端口连接另一侧的网络的驱动和解析也发生在 reactive区域集中。这种驱动和解析在事件导致程序网络上的驱动程序改变之后立即发生。对那些跨区域变量和网络敏感的设计过程被安排在active区域集中唤醒。
        考虑以下设计示例,其中包含设计构造和程序构造:

module m;
    logic r;
    wire dw1, dw2;
    initial begin
        r = 0;
        #10 r = 1;
    end
assign dw1 = r;

p p_i(dw2, dw1);

always @(dw2)
    $display("dw2 is %b", dw2);
endmodule

program p(output pw2, input pw1);
    assign pw2 = pw1;
endprogram

        在这种设计中,数据流起源于logic r,并终止于always过程的执行。由于程序p的存在,仿真器有必要在图4-1中的整个循环中执行多次迭代。这是因为程序p中的assign语句在Reactive区域之前不得执行。当它执行并触发模块m中的always过程上的活动时,该always过程直到整个调度循环的下一次迭代中的活动区域才被执行。

24.4 Eliminating testbench races

        SystemVerilog中存在两个主要的不确定性来源。第一种是以任意顺序处理active事件。第二个问题是,行为块中没有时间控制结构的语句不会作为一个事件执行。然而,从测试台的角度来看,这些影响都是不重要的细节。测试台的主要任务是为被测设计生成有效的输入激励,并验证设备是否正确运行。此外,使用循环抽象的测试台只关心系统的稳定或稳定状态,用于检查当前输出和计算下一个循环的激励。形式工具也以这种方式工作。由于程序在reactive区集合中调度事件因此时钟块结构对于自动采样先前时间步长或时钟周期的稳态值非常有用
        仅通过时钟为设计信号的时钟块读取设计值的程序对读写竞争不敏感。重要的是要理解,简单地对输入信号进行采样(或在时钟块输入上设置非零倾斜)并不能消除竞争的可能性正确的输入采样只针对单个时钟块。对于多个时钟,处理重叠或同时时钟的任意顺序仍然是竞争的潜在来源。在处理完所有设计事件(包括由非阻塞分配驱动的时钟)后,程序结构通过在Reactive区调度其执行来解决这个问题

24.5 Blocking tasks in cycle/event mode

        从设计模块内调用程序子程序是非法的,会导致错误。这是因为设计人员不应该知道测试台。允许程序调用其他程序或设计模块中的子例程。设计模块中的函数可以从程序中调用,不需要特殊处理。当从程序调用设计模块中的任务时,它应使用为其调度活动设置的reactive区域。参见24.3.1。

module ...
    task T;
        S1: a = b; // executes in reactive region set if called from a program
        #5;
        S2: b <= 1'b1; // executes in reactive region set if called from a program
    endtask
endmodule

        如果从模块内调用上述任务T,则在通过非阻塞分配更新变量b之前,语句S1可以在处理活动区域时立即执行。如果从程序中调用相同的任务,则在处理Reactive区域时应执行语句S1。语句S2也应在Reactive区域中执行,变量b的更新应安排在Re-NBA区域中。

24.6 Programwide space and anonymous programs

        一组程序定义和实例定义了一个只有程序才能访问的程序范围内的数据、任务和函数空间。匿名程序可以在包(见第26条)或编译单元作用域(见3.12.1)中使用,以声明属于程序范围空间的项,而无需声明新的作用域。匿名程序中声明的项与声明它们的包或编译单元作用域共享相同的名称空间
        注意——尽管在匿名程序内声明的标识符不能在任何程序块外引用,但试图在匿名程序块外声明另一个同名标识符将产生错误。这是因为标识符在周围包或编译单元的范围内共享相同的名称空间

24.7 Program control tasks

        除了正常的仿真控制任务($stop和$finish)外,程序还可以使用$exit控制任务。程序块可以通过调用$exit系统任务来显式终止其所有initial过程的线程及其所有子线程。$exit系统任务的语法如下:

$exit();

        从程序块initial过程中产生的线程或其派生线程调用$exit将终止该程序块内的所有initial过程及其派生线程。从不是源于程序中initial过程的线程或其派生线程调用$exit将被忽略,并且可能会发出警告,表明对$exit的调用已被忽略
 


 


http://www.niftyadmin.cn/n/4973881.html

相关文章

什么是回调函数(callback function)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 回调函数&#xff08;Callback Function&#xff09;⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这…

MySQL高级篇——MySQL架构篇3(用户与权限管理)

目录 1 用户管理1.1 登录MySQL服务器1.2 创建用户1.3 修改用户1.4 删除用户1.5 设置当前用户密码1.6 修改其它用户密码1.7 MySQL8密码管理(了解) 2 权限管理2.1 权限列表2.2 授予权限的原则2.3 授予权限2.4 查看权限2.5 收回权限 3 权限表3.1 user表3.2 db表3.3 tables_priv表和…

[GDOUCTF 2023]EZ WEB

进入环境有一个点击标签&#xff0c;点击 后触发提示&#xff0c;flag就在附近 习惯性查看源码&#xff0c;得到路径提示 访问后&#xff0c;得到源码&#xff0c;源码中存在三个路由&#xff0c;前两个都是GET方式&#xff0c;已经访问过了&#xff0c;最后一个PUT是什么请求…

Ngnix配置Minio动态代理:访问桶列表报错解决方案:

多台服务器间免密登录|免密拷贝 Cenos7 搭建Minio集群部署服务器(一) Cenos7 搭建Minio集群Nginx统一访问入口|反向动态代理(二) Spring Boot 与Minio整合实现文件上传与下载(三) CentOS7的journalctl日志查看方法 MySQL8.xx一主两从复制安装与配置 Ngnix配置Minio动态…

LeetCode 刷题第四轮 Offer I + 类型题

目录 剑指 Offer 04. 二维数组中的查找 剑指 Offer 29. 顺时针打印矩阵 剑指 Offer 09. 用两个栈实现队列 剑指 Offer 30. 包含min函数的栈 剑指 Offer 10- I. 斐波那契数列 [类型&#xff1a;记忆优化 递归 / 动态规划] 剑指 Offer 10- II. 青蛙跳台阶问题 [类型&am…

代码随想录第五十三天

代码随想录第五十三天 Leetcode 1143. 最长公共子序列Leetcode 1035. 不相交的线Leetcode 53. 最大子数组和 Leetcode 1143. 最长公共子序列 题目链接: 最长公共子序列 自己的思路:没想出来&#xff01;&#xff01;&#xff01; 正确思路:首先这道题由于是涉及到了两个数组&…

mysql profiling profiles profile

要想优化一条 Query&#xff0c;我们就需要清楚的知道这条 Query 的性能瓶颈到底在哪里&#xff0c;是消耗的 CPU计算太多&#xff0c;还是需要的的 IO 操作太多&#xff1f;要想能够清楚的了解这些信息&#xff0c;在 MySQL 5.0 和 MySQL 5.1正式版中已经可以非常容易做到了&a…

[LitCTF 2023]Flag点击就送!

进入环境后是一个输入框&#xff0c;可以提交名字 然后就可以点击获取flag&#xff0c;结果回显提示&#xff0c;需要获取管理员 可以尝试将名字改为admin 触发报错&#xff0c;说明可能存在其他的验证是否为管理员的方式 通过抓包后&#xff0c;在cookie字段发现了 特殊的东西…