ARTICLE DETAIL

资讯详情

深耕网站SEO优化与搜索引擎排名提升的一线实战洞察。

【UVM实战】第三章 UVM基础

【UVM实战】第三章 UVM基础 一. uvm_component 与 uvm_object1. 诞生由来UVM 所有类顶层基类为uvm_void派生uvm_object为区分平台骨架组件和传输数据对象从 uvm_object 拆分出子类uvm_component形成 UVM 二元类结构解决两类对象能力差异化需求单纯数据包 / 序列不需要层级、生命周期平台 driver、env、test 等组件需要树形挂载、phase 自动调度因此新增 uvm_component。2. 标准定义uvm_objectUVM 最顶层通用基类无层级、无自动 phase 调度仅提供拷贝 / 打印 / 打包基础能力是所有非组件类父类。uvm_component直接继承 uvm_object新增两大独有核心能力new 函数携带parent参数自动构建 UVM 树形层级内置全套 phase 生命周期仿真时框架自动按顺序执行各个阶段。3. 核心作用3.1. 派生自 uvm_object 的类数据载体仅负责传输、存储激励 / 配置无树形节点资格仿真中可动态创建销毁uvm_sequence_item、uvm_sequence生成、传输总线事务数据包config 配置类存储平台可调参数通过 config_db 下发寄存器模型全套类uvm_reg/uvm_reg_block 等uvm_phasephase 调度控制对象。 通俗理解uvm_object 如同 “血液、规则卡片”在组件之间流转传递信息。3.2 派生自 uvm_component 的类平台骨架节点可挂载进 UVM 树全程驻留仿真拥有完整 phase 生命周期uvm_test验证顶层用例树最顶层uvm_env环境容器统一管理 agent、scoreboard、参考模型uvm_agent封装 drivermonitor区分主动 / 被动模式uvm_driver接收 sequence 数据驱动 DUT 引脚uvm_monitor采集 DUT 引脚信号封装事务送出uvm_scoreboard接收 DUT 输出与参考模型数据做比对uvm_sequencersequence 与 driver 中间桥梁uvm_rootUVM 树全局根节点uvm_top。4. 关键重点二元结构分工明确component 搭平台骨架object 传递数据component new 函数固定双参数new(string name, uvm_component parent)object 仅单参数new(string name)component 实例只能在 build_phase 创建仿真全程不可销毁object 可任意时刻 new/deletecomponent 默认不支持 copy、compare必须搭配 field automation 宏才能使用。5. 标准使用方式 示例逐行解析示例 1uvm_objectsequence_item 事务class my_trans extends uvm_sequence_item;//继承事务基类本质 uvm_object rand bit[31:0] data;//随机激励字段 uvm_object_utils(my_trans) // object注册宏无parent, 工厂注册支持 create、clone function new(string name my_trans); super.new(name); // new 仅传name无parent, 无法挂载 UVM 树 endfunction endclass示例 2uvm_componentdriver 组件class my_driver extends uvm_driver;//属于 component可挂载树形 uvm_component_utils(my_driver) // component专属注册宏, 注册后工厂create 会自动传入 parent function new(string name my_driver, uvm_component parent null); super.new(name, parent); // 必须传递nameparent构建树形,携带两个参数框架自动记录父子关系生成完整层次路径 endfunction endclass6. 注意事项1. 不要用 uvm_component 存储临时数据包会大幅浪费仿真内存2. component new 函数是 function不能写 #延时、时序等待3. 不能直接 clone component仅 uvm_object 支持 clone4. 所有 test、env、agent 必须派生 component否则无法使用 config_db、phase 机制。二. UVM 树形层次结构1. 诞生由来大量 component 分层搭建平台后需要统一标识每个组件、跨层级传递配置config_db 依赖路径匹配、遍历所有子组件因此 UVM 基于 parent 参数构建全局唯一树形结构每个组件拥有独一无二完整路径字符串。2. 标准定义树根uvm_root全局单例句柄别名uvm_top顶层 test 实例名字固定为uvm_test_top所有组件全部挂载在 test 下方层次路径规则父子组件名称用.拼接格式uvm_test_top.env.i_agt.drv父子关系子组件 new 时传入父组件 this自动绑定 parent 指针。3. 核心作用生成唯一层次路径作为 config_db 匹配 key提供全套层次遍历 API批量操作子组件统一设置冗余度、递归打印配置区分相对路径、绝对路径灵活读写 config_db 参数。4. 关键重点uvm_topuvm_root不会出现在打印路径中路径从uvm_test_top开始组件实例化名字直接决定路径字符串变量名与实例名不一致会造成路径混乱所有层次操作函数仅 uvm_component 可用uvm_object 无层次 API。5. 标准层次操作函数 示例解析5.1. get_full_name()作用返回当前组件完整绝对路径字符串function void my_driver::build_phase(); super.build_phase(phase); uvm_info(PATH,$sformat(当前完整路径%s,get_full_name()),UVM_MEDIUM) endfunction打印结果uvm_test_top.env.i_agt.drv5.2. get_parent()作用获取当前组件父组件句柄无参数uvm_component p this.get_parent();5.3. get_child(string name)作用根据子组件实例名获取对应子组件句柄必须传入实例名字符串5.4. get_first_child(ref string name) / get_next_child(ref string name)作用遍历当前组件所有子节点name 为 ref 参数无需手动赋值string child_name; uvm_component child; if(this.get_first_child(child_name)) begin do begin child this.get_child(child_name); child.print(); end while(this.get_next_child(child_name)); end5.5. get_num_children()作用返回当前组件直接子组件总数量返回 int 整型6. 注意事项实例化组件时变量名与 create 传入 name 保持一致避免路径拼写错误遍历子组件仅能获取直接子节点不会递归获取孙子节点绝对路径以uvm_test_top开头相对路径基于当前 this 组件拼接parent 为 null 的组件只有顶层 test。三. field automation 域自动化机制1. 诞生由来早期 uvm_object 无法自动完成 print、copy、compare、pack/unpack每个字段需要手写重复逻辑UVM 推出 field 自动化宏一键注册类内字段框架自动生成全套数据操作函数同时支持 config_db 自动读取参数。2. 标准定义一套uvm_field_*系列注册宏包裹在utils_begin/utils_end之间标记类内成员变量注册后自动内置 print、copy、compare、pack_bytes/unpack、clone、自动 get 配置六大能力。3. 核心作用自动打印对象全部成员tr.print () 无需手动拼接字符串完整对象拷贝 tr2 tr.clone ()、tr2.copy (tr)两个 transaction 一键比对 tr1.compare (tr2)支持打包 bit/byte/int 流适配总线数据包传输满足特定条件时省略 config_db 手动 get 代码。4. 关键重点宏分基础类型、数组、队列、关联数组、枚举五大类第二个参数为功能掩码控制是否开启 print/copy/pack 等功能支持if条件包裹宏实现 VLAN 帧这类可选字段动态注册仅 uvm_object/uvm_sequence_item 推荐大量使用component 按需使用。5. 分类宏标准使用 逐行示例5.1. 基础字段宏int/string/enum/objecttypedef enum{IDLE,WR,RD} op_e; class my_trans extends uvm_sequence_item; rand op_e op_flag; rand bit[31:0] addr; string dev_name; uvm_object_utils_begin(my_trans)//开启域自动化注册 uvm_field_enum(op_e,op_flag,UVM_ALL_ON) //枚举三参数宏,枚举类型必须先写枚举名再写变量第三参数功能掩码 uvm_field_int(addr,UVM_ALL_ON) // 整型,同时开启 print/copy/compare/pack 全部功能 uvm_field_string(dev_name,UVM_ALL_ON) // 字符串 uvm_object_utils_end//结束注册 function new(string name); super.new(name); endfunction endclass5.2. 数组 / 队列 / 关联数组宏静态数组uvm_field_sarray_int动态数组uvm_field_array_int队列无专属宏嵌套动态数组宏实现关联数组uvm_field_aa_索引类型_存储类型如uvm_field_aa_int_string索引 int存 string5.3. 内置自动化函数clone()完整深拷贝对象返回 uvm_objectcopy(rhs)将 rhs 对象数据拷贝至当前实例compare(rhs)逐字段比对匹配返回 1不匹配返回 0pack/unpack打包 / 解包 bit 流pack_bytes/unpack_bytes打包字节流适配硬件总线pack_ints/unpack_ints打包 int 数据流。5.4. 功能掩码标志位详解UVM_ALL_ON全开功能UVM_NOCOPY关闭拷贝功能UVM_NOCOMPARE关闭比对UVM_NOPRINT关闭打印UVM_NOPACK关闭打包多掩码用|拼接UVM_ALL_ON | UVM_NOPACK5.5. 宏与 if 结合VLAN 帧可选字段案例rand bit is_vlan; // 标记是否为VLAN帧 rand bit[11:0] vlan_id; uvm_object_utils_begin(my_trans) uvm_field_int(dmac,UVM_ALL_ON) if(is_vlan) begin // 仅VLAN帧才注册vlan字段 uvm_field_int(vlan_id,UVM_ALL_ON) end uvm_object_utils_end使用随机化时约束tr.randomize() with {is_vlan 1;}自动启用 vlan 字段打包 / 打印。6. 注意事项注册变量名必须和 config_db set 的 field_name 完全一致才能自动省略 get掩码按需关闭不需要的功能减少仿真运算开销component 使用uvm_component_utils_beginobject 使用uvm_object_utils_begin不可混用条件 if 仅支持编译期宏 / 类内 rand 标记运行时动态判断不生效。四. UVM 打印信息全维度控制1. 诞生由来仿真日志量庞大需要分层过滤打印、区分报错等级、超限自动退出、日志分类存储UVM 内置全套 report 日志控制 API统一管控uvm_info/uvm_warning/uvm_error/uvm_fatal输出行为。2. 标准定义UVM 报告系统基于 report_server 全局日志服务器支持 7 大类控制能力冗余度过滤、严重性重载、ERROR 计数退出、自定义日志行为、断点暂停、日志分流文件、ID 单独管控。3. 核心作用过滤无关低等级日志提升仿真可读性。动态调整警告 / 错误等级灵活调试。限制最大 ERROR 数量避免无效长时间仿真。按 ID / 严重性拆分日志文件便于后期定位 bug。触发 ERROR 时自动暂停仿真进入交互调试。4. 分模块详细讲解4.1 设置打印冗余度阈值4.1.1 定义4 个冗余等级从小到大UVM_NONE UVM_LOW UVM_MEDIUM UVM_HIGH UVM_FULL仅信息冗余等级≤阈值才会打印。4.1.2 使用方式1. 单个组件设置virtual function void connect_phase(uvm_phase phase); super.connect_phase(phase); // 当前driver冗余阈值设为UVM_HIGH仅高等级日志打印 env.i_agt.drv.set_report_verbosity_level(UVM_HIGH); endfunction2. 递归设置当前组件及所有子组件env.i_agt.set_report_verbosity_level_hier(UVM_MEDIUM);3. 按日志 ID 单独设置过滤env.i_agt.drv.set_report_id_verbosity(DRV_TX,UVM_LOW);4. 命令行全局设置无需改代码simv UVM_VERBOSITYHIGH4.2 重载打印信息严重性1. 定义动态将某一类日志等级强制转换例如把 WARNING 升级为 ERROR。2. 示例// 将driver内所有UVM_WARNING强制输出为UVM_ERROR env.i_agt.drv.set_report_severity_override(UVM_WARNING,UVM_ERROR); // 仅指定ID的WARNING升级ERROR env.i_agt.drv.set_report_severity_id_override(UVM_WARNING,DRV_TX,UVM_ERROR);4.3 UVM_ERROR 达到指定数量结束仿真1. 定义设置最大允许 ERROR 计数达到阈值自动终止仿真避免无效运行。2. 示例function void base_test::build_phase(uvm_phase phase); super.build_phase(phase); set_report_max_quit_count(5); // 出现5个ERROR直接退出 endfunction命令行参数simv UVM_MAX_QUIT_COUNT64.4 设置计数目标1. 定义默认仅 UVM_ERROR 计入退出计数可把 WARNING/INFO 加入计数统计。2. 核心函数set_report_severity_action行为掩码UVM_DISPLAY终端打印UVM_COUNT计入错误统计UVM_LOG写入日志文件UVM_STOP触发断点UVM_EXIT直接退出仿真。// 当前agent下所有WARNING计入统计 env.i_agt.set_report_severity_action_hier(UVM_WARNING,UVM_DISPLAY|UVM_COUNT);4.5 UVM 断点功能1. 定义日志触发时暂停仿真进入交互调试模式替换仿真器原生断点。2. 示例// WARNING日志触发时停止仿真 env.i_agt.drv.set_report_severity_action(UVM_WARNING,UVM_DISPLAY|UVM_STOP);命令行统一开启simv uvm_set_action*,*,UVM_WARNING,UVM_STOP4.6 日志输出重定向到文件1. 定义按严重性 / 日志 ID 拆分独立日志文件区分 info、warning、error 日志。2. 示例UVM_FILE error_log; virtual function void connect_phase(uvm_phase phase); super.connect_phase(phase); error_log $fopen(error.log,w); // driver所有ERROR写入error.log env.i_agt.drv.set_report_severity_file(UVM_ERROR,error_log); env.i_agt.drv.set_report_severity_action(UVM_ERROR,UVM_DISPLAY|UVM_LOG|UVM_COUNT); endfunction5. 通用注意事项冗余度、严重性设置建议写在 connect_phasebuild 阶段组件未完全实例化无法跨层次引用递归函数_hier批量操作子组件适合统一环境日志管控仿真回归测试关闭 UVM_FULL 冗余减少日志拖慢仿真速度日志分流仅用于后期 bug 复盘常规调试保持终端输出。五. uvm_config_db 全局配置数据库※1. 诞生由来早期逐层 new 传参耦合度极高全局变量多用例冲突UVM 设计全局静态哈希数据库uvm_config_db#(T)依靠层次路径 字段名键值对跨层级传参实现组件解耦同时支持虚接口、对象、整型、字符串全类型传递。2. 标准定义uvm_config_db#(T)是模板静态类底层继承uvm_resource_db全局唯一资源仓库 两大核心静态函数set()写入配置存数据get()读取配置取数据 匹配唯一 key 组件完整层次路径 field_name 配置名。3. 核心作用test 顶层向下 env/agent/driver 远距离下发参数传递 DUT virtual interface 虚接口平台与 DUT 唯一连接方式配置 agent is_active 主动 / 被动模式设置 sequencer default_sequence 自动启动序列传递全局配置 config 对象、寄存器模型句柄。4. set/get 参数完整拆解 逐行示例4.1 set 函数原型static function void set(uvm_component cntxt, string inst_name, string field_name, T value);示例test 顶层写入 driver 参数uvm_config_db#(int)::set(this,env.i_agt.drv,pre_num,100);逐行逐参数解释#(int)模板 T指定存储数据类型int/string/virtual interface/uvm_object 一一对应第一参数this上下文参考组件作为路径起点填 null 代表使用完整绝对路径第二参数env.i_agt.drv相对 this 的组件路径拼接生成完整 key 路径第三参数pre_num配置标记名set/get 必须完全一致区分大小写第四参数100需要存储的实际数值。4.2 get 函数原型static function bit get(uvm_component cntxt, string inst_name, string field_name, ref T value);示例driver 内部读取参数int pre_num; if(!uvm_config_db#(int)::get(this,,pre_num,pre_num)) begin uvm_warning(GET_ERR,未读取到pre_num配置使用默认值) pre_num 10; end逐参数解释this当前 driver 组件读取自身配置inst_name 填空字符串返回 bit1 读取成功0 匹配失败必须判断返回值否则静默失效无告警最后参数为 ref 引用读取成功自动赋值5. 省略 get 语句field 自动化联动5.1 生效三大硬性前提类内变量使用uvm_field_*宏注册build_phase 中必须执行super.build_phase(phase)set 的 field_name 与变量名字完全相同。5.2 效果无需手动调用uvm_config_db::get父类 super.build 自动读取配置赋值变量set 语句无法省略。6. 跨层次多重设置优先级规则1. 层级优先级高于时间优先级越靠近 uvm_test_top 顶层的 set优先级越高2. 同一层级多次 set后执行 set 覆盖先写入的值 示例test、env 同时给 driver 设置 pre_num最终取 test 设置的值。7. 非直线设置 通配符非直线 setset 上下文与目标组件非父子直链推荐用uvm_root::get()作为全局起点避免 build 时序错乱通配符*批量匹配组件路径// env下所有agent统一配置参数 uvm_config_db#(int)::set(this,env.*,cfg_en,1);注意通配符可读性差大型项目尽量少用路径排查困难。8. 调试工具check_config_usage()打印所有执行 set、但从未 get 读取的闲置配置快速定位路径拼写错误print_config(1)递归打印当前组件 全部子组件所有已存入配置命令行全局追踪simv UVM_CONFIG_DB_TRACE实时打印每一次 set/get 完整日志。9. 旧版废弃 API set_config_intOVM 遗留接口功能等价uvm_config_db#(int)UVM1.2 标记废弃新项目禁止使用仅兼容老代码阅读set_config_int(env.i_agt.drv,pre_num,100); get_config_int(,pre_num,pre_num);10. 重点 通用注意事项set 与 get 的路径、配置名字符必须一字不差区分大小写拼写错误无自动报错set 必须在 get 所属 phase 之前执行标准规范顶层 build 执行 set子组件 build 执行 get模板 T 类型必须完全匹配int 与 bit 不可混用数据库全局静态同路径同名称多次 set后值覆盖前值set 写入不存在的组件路径不会报错只会静默存入仅 get 时发现读取失败传递 uvm_object 仅存储句柄外部修改原对象会同步变更数据库内数据如需独立配置使用 clone 深拷贝。六. 整体总结UVM 二元结构uvm_object 承载数据uvm_component 搭建树形验证平台二者能力完全区分。树形层次依靠 parent 指针构建完整路径是 config_db 匹配的核心索引。field 自动化宏一键实现打印、拷贝、打包还可省略 config_db 手动 get。report 日志系统全维度管控仿真输出过滤日志、限制报错数量、断点调试大幅提升开发效率。uvm_config_db 是平台解耦核心依靠路径 名称传参重点把控执行时序、字符串匹配、三大调试工具排查读取失败问题。
返回列表