uvm_hw_reset源码解析

发布时间:2026/7/10 9:03:17
uvm_hw_reset源码解析 文件头与类定义systemverilog// 文件头版权与许可证信息声明了代码的版权归属和Apache 2.0许可证[citation:1][citation:4] // ------------------------------------------------------------- // Copyright 2004-2008 Synopsys, Inc. // Copyright 2010 Mentor Graphics Corporation // All Rights Reserved Worldwide // // Licensed under the Apache License, Version 2.0 (the // License); you may not use this file except in // compliance with the License. You may obtain a copy of // the License at // // http://www.apache.org/licenses/LICENSE-2.0 // ------------------------------------------------------------- // 类uvm_reg_hw_reset_seq // 功能测试寄存器的硬件复位值[citation:3][citation:4][citation:6] // 该类继承自 uvm_reg_sequence是一个参数化类[citation:10] class uvm_reg_hw_reset_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item)); // 注册该类到UVM工厂以便可以使用type_id::create()方法创建对象[citation:4] uvm_object_utils(uvm_reg_hw_reset_seq) // 构造函数 function new(string nameuvm_reg_hw_reset_seq); super.new(name); // 调用父类构造函数 endfunction // 变量: model (继承自父类) // 说明: 指向待测试的寄存器块(reg_block)的句柄[citation:3][citation:4] // | uvm_reg_block model; // 任务: body // 说明: 执行硬件复位序列的实际代码。不要直接调用应通过 seq.start() 启动[citation:3][citation:4] virtual task body(); // 1. 检查 model 句柄是否为空 // 如果为空则打印错误信息并退出任务避免空指针操作[citation:4][citation:10] if (model null) begin uvm_error(uvm_reg_hw_reset_seq, Not block or system specified to run sequence on); return; end // 打印序列启动信息[citation:4] uvm_info(STARTING_SEQ,{\n\nStarting ,get_name(), sequence...\n},UVM_LOW) // 2. 调用 reset_blk 任务 // 这是一个空任务作为“钩子”(hook)供用户扩展以执行对DUT的复位操作[citation:3][citation:4][citation:11] this.reset_blk(model); // 3. 调用寄存器模型的 reset() 方法 // 这将重置寄存器模型内部的所有镜像值(mirror values)和期望值(desired values)为复位值[citation:10][citation:11] model.reset(); // 4. 调用 do_block 任务开始对寄存器块执行测试[citation:4][citation:10] do_block(model); endtask: body核心执行任务do_blocksystemverilog// 任务: do_block // 说明: 测试指定寄存器块(block)中的所有寄存器[citation:3][citation:4] // 权限: protected意味着只能由该类或其子类调用 protected virtual task do_block(uvm_reg_block blk); uvm_reg_map maps[$]; // 存储当前block中的所有地址映射(map) uvm_reg_map sub_maps[$]; // 存储子map // 1. 检查当前block是否被排除测试 // 从资源数据库(uvm_resource_db)中查询如果该block被设置了NO_REG_TESTS或NO_REG_HW_RESET_TEST标志 // 则直接返回跳过此block的测试[citation:4][citation:8][citation:10] if (uvm_resource_db#(bit)::get_by_name({REG::,blk.get_full_name()}, NO_REG_TESTS, 0) ! null || uvm_resource_db#(bit)::get_by_name({REG::,blk.get_full_name()}, NO_REG_HW_RESET_TEST, 0) ! null ) begin return; end // 2. 获取当前block的所有地址映射(map) blk.get_maps(maps); // 3. 遍历每一个map // Iterate over all maps defined for the RegModel block [citation:4] foreach (maps[d]) begin uvm_reg regs[$]; // 存储当前map中的所有寄存器 maps[d].get_submaps(sub_maps); // 获取当前map的子map // 如果存在子map则跳过当前map的测试 // 这通常是为了避免对同一个寄存器通过不同map进行重复测试或处理层次化地址映射[citation:4] if(sub_maps.size() !0) begin continue; end // 获取当前map中的所有寄存器 regs.delete(); // 清空之前可能存在的寄存器列表 maps[d].get_registers(regs); // 4. 遍历每一个寄存器 foreach (regs[i]) begin uvm_status_e status; // 用于存储mirror操作的状态 // 检查当前寄存器是否被排除测试 // 查询该寄存器是否设置了NO_REG_TESTS或NO_REG_HW_RESET_TEST标志[citation:4][citation:8] if (uvm_resource_db#(bit)::get_by_name({REG::,regs[i].get_full_name()}, NO_REG_TESTS, 0) ! null || uvm_resource_db#(bit)::get_by_name({REG::,regs[i].get_full_name()}, NO_REG_HW_RESET_TEST, 0) ! null ) continue; // 打印正在验证的寄存器信息[citation:4][citation:10] uvm_info(get_type_name(), $sformatf(Verifying reset value of register %s in map \%s\..., regs[i].get_full_name(), maps[d].get_full_name()), UVM_LOW); // 5. 执行镜像(mirror)操作这是核心验证步骤 // 通过前门(Frontdoor)读取DUT中寄存器的实际值并与模型中的镜像值进行比较[citation:4][citation:10] // UVM_CHECK: 表示执行比较检查 // UVM_FRONTDOOR: 指定使用前门访问即通过总线协议 regs[i].mirror(status, UVM_CHECK, UVM_FRONTDOOR, maps[d], this); // 6. 检查mirror操作的结果状态 // 如果状态不是 UVM_IS_OK表示读取的值与期望的复位值不匹配打印错误信息[citation:4][citation:10] if (status ! UVM_IS_OK) begin uvm_error(get_type_name(), $sformatf(Status was %s when reading reset value of register \%s\ through map \%s\., status.name(), regs[i].get_full_name(), maps[d].get_full_name())); end end // foreach (regs[i]) end // foreach (maps[d]) // 7. 递归处理当前block内部的子block // 获取当前block下的所有子block[citation:4] begin uvm_reg_block blks[$]; blk.get_blocks(blks); // 对每个子block递归调用 do_block 任务实现层次化测试[citation:4] foreach (blks[i]) begin do_block(blks[i]); end end endtask: do_block复位钩子任务reset_blksystemverilog// 任务: reset_blk // 说明: 复位与指定寄存器块对应的DUT[citation:3][citation:4] // 当前实现为空这是一个“钩子”(hook)方法[citation:3][citation:4][citation:11] // 用户应该从这个类派生新类并重写(override)此任务来实现真正的DUT复位逻辑 // 或者在使用该序列之前手动复位DUT。 virtual task reset_blk(uvm_reg_block blk); endtask endclass: uvm_reg_hw_reset_seq关键机制说明排除机制通过uvm_resource_db设置NO_REG_TESTS或NO_REG_HW_RESET_TEST标志来跳过特定block或register的测试。这个标志是全局性的一旦设置在仿真过程中会持续有效。访问方式测试使用的是前门访问 (Frontdoor)即通过总线协议如APB、AHB进行读写操作。model.reset()与DUT复位的关系model.reset()只重置UVM寄存器模型内部的镜像值并不会对DUT硬件施加复位。DUT的复位需要用户通过重写reset_blk任务或外部激励来完成。