Easier UVM Coding Guidelines / 便捷UVM 编码指南
简介,原则和目标
easier UVM是一组编码指南,附带一个代码生成器,可以创建符合本指南的UVM代码。创建easier UVM是为了帮助个人和项目团队学习,然后尽快使用UVM提高工作效率,并减轻在公司或组织内支持UVM代码的负担。
拥有各种编码风格会增加维护和支持UVM代码库的负担。easier UVM专门用于通过推荐一种方法来解决这个问题。
Easier UVM可以更轻松地创建可维护和可重用的UVM代码的代码库。 easier UVM根据工业项目的经验总结了最佳实践。 在某些情况下,Easier UVM已被证明可以在项目开始时保存6周的编码工作(取决于项目的细节),以帮助避免陷阱,使代码更可重用,并帮助统一UVM的方式,用于整个公司。
UVM是一种在SystemVerilog中构建基于类的验证环境的方法,利用面向对象的编程技术来帮助代码重用。重用是UVM的核心:如果您不打算从一开始就重用验证码,那么您可能已经错过了UVM的重点。
通用代码结构
☐使用条件编译保护措施避免多次编译同一个包含文件。
例:
`ifndef BUS_PKG_SV
`define BUS_PKG_SV
...
`endif // BUS_PKG_SV
☐每个接口使用一个agent,带有passive monitor和可选的sequence和driver,其存在性由类uvm_agent的get_is_active方法的值决定。由于DUT通常具有多个接口,这意味着将多个UVM agent组织为并行结构。
☐agent不应实例化除一个sequencer,一个driver和一个monitor的规范agent结构之外的组件。agent可以在应用程序要求的情况下实例化其他组件,但这通常应该避免。 每个agent通常都有一个关联的配置对象,但该对象应该由封闭的env实例化,而不是由agent本身实例化(请参阅配置)。
☐使用虚拟sequence协调多个并行agent的激励生成活动。避免用“default_sequence”配置参数作为启动sequence的方法。通常,您应该通过调用其start方法来启动sequence。如果要在阶段开始时启动sequence,uvm-1.2建议使用类uvm_sequence_library。
☐通常,使用analysis port和export连接agent,检查器,记分板和coverage收集器。
☐使用factory覆盖和/或配置数据库,使重新调整的UVM组件的行为适应新验证环境的需要。避免修改重新使用的代码本身。
Clocks,Timing,Synchronization,and Interfaces
☐在SystemVerilog的module中生成时钟和复位,而从不在基于UVM class的验证环境中,也从不在SystemVerilog program中生成。
☐优先使用SystemVerilog module,而不是SystemVerilog program。program扮演着将验证环境从DUT中SV schedule问题中隔离出来的角色,但是这同样能在clocking block中完成。使用program更方便的情况是处理异步断言。
☐使用SystemVerilog接口内的clocking block来检测和驱动一个同步DUT接口。
SV clocking block能够很好地隔离开验证环境和门级timing以及SV scheduler中的不确定性。如果使用过程语句可以充分同步DUT引脚的驱动和采样,特别是如果使用简单的RTL代码建模DUT,并且始终从SystemVerilog模块而不是程序生成激励,则不使用时钟模块可能是合理的。另注意,访问异步引脚时必须绕过时钟模块。
☐如果一个driver在驱动DUT接口时需要在transaction之间或者transaction内插入可变延迟,那么这个可变延迟应当存储在transaction中传递给driver。将延迟存储在transaction中可以使得sequence在生成back2back时能够控制timing。
☐driver应使用非阻塞try_ *方法从sequencer中获取transaction,以便在作者无法知道sequence是否会阻塞driver执行的情况下最大限度地提高可重用性。
假如一个运行在sequencer上的sequence阻塞了发送给driver的transaction flow(比如sequence在等待环境中的其他事件),从driver调用阻塞性的get / get_next_item可能会导致driver错过接口上的关键信号。
class my_driver extends uvm_driver #(my_transaction); `uvm_component_utils(my_driver) virtual dut_if vif; ... task run_phase(uvm_phase phase); forever begin my_transaction tx =my_transaction::type_id::create("tx"); seq_item_port.try_next_item(req); if (req != null) begin // Wiggle pins seq_item_port.item_done(); @(posedge vif.clock); vif.en <= 1; vif.cmd <= req.m_cmd; vif.addr <= req.m_addr; vif.data <= req.m_data; end else begin
// Insert an idle cycle @(posedge vif.clock); vif.en <= 0; vif.cmd <= 0; vif.addr <= 0; vif.data <= 0; end end endtask
endclass: my_driver
☐driver只应在需要时从sequencer中提取transaction。driver一次仅获取一个transaction而不是获取很多个transaction,这样可以使得sequence能够根据验证环境实时控制transaction的随机化生成策略。
☐使用uvm_event或uvm_barrier在sequence和/或analysis组件(如记分板)之间进行临时同步。当对分布在多个UVM组件上的并行进程,sequence或transaction stream进行同步时,UVM的events或barriers有时可能是比port和export更方便的通信机制。比如,将被发送到一个DUT接口的transaction正在等待被另外一个DUT接口检测的一个特定场景。另一个例子是几个sequence在锁定步骤中彼此运行但在不同的agent上运行。
☐monitor不应在SystemVerilog接口中为变量或wire赋值。monitor应总是作为一个passive组件,负责检测接口数据和生成transaction并传递transaction到其他组件。monitor的执行不能被其他组件或sequence阻塞。
☐在接口中使用并发断言和cover property,以进行协议检查和相关的覆盖率收集。
Transactions
☐通过扩展类uvm_sequence_item来创建用户定义的transaction类。
☐尽量减少不同transaction类的数量。在一个agent的driver和monitor中使用一个transaction类,这样易于维护。
☐在现在或将来可能需要随机化的类成员变量前面使用rand限定符。
☐在成员变量之后,定义一个构造函数,该构造函数包含一个字符串名称参数,其默认值可为空字符串,并调用super.new。
☐推荐重写convert2string,do_copy,do_compare,do_print和do_record等方法(可使用相关宏`uvm_record_attribute和`uvm_record_field等)。
☐推荐重写do_pack和do_unpack 方法(可使用相关宏`uvm_pack_int等)。
☐使用factory实例化transaction对象。
var_name = transaction_type::type_id::create("var_name");
Sequence
☐与sequence执行相关的任何housekeeping代码,例如提出和撤销objection,都应放在sequence的pre_start和post_start方法中。sequence的body方法应该只执行sequence的原始功能行为。pre_start和post_start被称为用户可定义的回调。
☐在body任务中使用如下通用模板:
req = tx_type::type_id::create("req");
start_item(req);
assert( req.randomize() with {…;} ) else `uvm_error( ... );
finish_item(req);
☐不要使用`uvm_do系列宏。`uvm_do系列宏隐藏了很多功能,如无必要,推荐使用上述的通用模板。
☐推荐在sequence中使用内建的transaction变量req和rsp。
☐通过调用start方法在启动sequence。避免使用“default_sequence”配置参数作为启动sequence的方法。如果要在phase开始时启动sequence,uvm-1.2建议使用类uvm_sequence_library,这是在sequencer上启动background traffic的有效方式,但调用start方法应该用作启动sequence的主要方法。
Stimulus and Phasing
☐使用virtual sequence协调多个agent的行为。不要过度约束virtual sequence。 虚拟sequence应该用于协调多个并行agent的活动,但不要过度约束这些agent的活动。
☐sequence不应是phase-aware的,Sequence应该在所有run-time phase中都能够被启动,这样有利于重用。
Objections
☐在任何class中都可以通过提起和撤销objection来控制验证平台的起始与结束。
通常,driver从sequencer中获取transaction时都应该提起objection,在处理完该transaction后撤销objection。Monitor在检测到新的transaction时应该提起objection,在通过analysis port发生出该transaction后应该撤销objection。当Scoreboard需要等待多个item时,应该提起objection。
☐考虑在内部循环中提起和撤销objection的对仿真速度影响,例如:各个transaction。如果仿真速度损失很大,则从内部循环中删除objection。在删除objection时,应该保证有其他的objection覆盖到此objection,否则可能引起验证环境停止。
☐如果sequence要提出和撤销objection,则应在其pre_start方法中调用raise_objection,在其post_start方法中调用drop_objection。尽管可以在sequence的body任务中提出并删除objection,但是将对objection限制在pre / post_start方法中更具有一致性。
☐在sequence中调用raise_objection与drop_objection方法时,将其置于if (starting_phase != null)条件中。
在uvm-1.2之前,starting_phase是类uvm_sequence_base的成员。从uvm-1.2开始,不推荐使用starting_phase变量,而必须使用get_starting_phase方法访问它。
task pre_start;uvm_phase starting_phase = get_starting_phase(); // uvm-1.2if (starting_phase != null)starting_phase.raise_objection(this, "Sequence started");
endtask
☐在启动sequence之前,如果要提起objection,则需要先设置starting_phase成员变量。从uvm-1.2开始,不推荐使用starting_phase变量,必须使用set_starting_phase方法设置:
task run_phase(uvm_phase phase);my_sequence seq;seq = my_sequence::type_id::create("seq");if ( !seq.randomize() )`uvm_error( ... )seq.set_starting_phase(phase); // uvm-1.2seq.start( ... );
endtask
☐调用raise_objection或drop_objection时,总是传递一个字符串作为第二个参数来描述objection以帮助调试。命令行参数+ UVM_OBJECTION_TRACE打开objection跟踪,打印出每个被调用的objection的description参数。
☐如果调用sequence的kill方法并且sequence可以提出objection,请确保覆盖sequence的do_kill方法以能够撤销objection。
否则,objection可能永远不会被撤销,这将阻止phase结束。如果sequence由于phase跳转而过早结束,则所有objection计数都会自动清除,因此不需要明确撤销objection。在phase跳转时也不会自动调用kill。例如:
function void do_kill;if (starting_phase != null)starting_phase.drop_objection(this, "Sequence ended prematurely");
endfunction
Components
☐通过扩展uvm_component的相应子类来创建用户定义的组件类,以实现需要的功能。
☐在类中的第一行使用宏`uvm_component_utils在factory中注册组件类。
☐构造函数应包含string name 和无默认值的parent参数,需要调用super.new。除了调用super.new之外,构造函数应该是空的,除非它需要实例化covergroup或初始化常量:
function new (string name, uvm_component parent);super.new(name, parent);
endfunction
☐在build_phase中实例化组件类,而不应该在其他phase或者构造函数中实例化组件类。
☐总是使用factory实例化组件:
var_name = component_type::type_id::create("var_name", this);
一个component的写法模板如下:
class my_component extends uvm_env;`uvm_component_utils(my_component)// Transaction-level ports and exportsuvm_analysis_port #(my_tx) a_port;// Virtual interfacesvirtual dut_if vif;// Internal data members (variables)my_agent m_agent;// Constructorfunction new (string name, uvm_component parent);super.new(name, parent);endfunction// Standard phase methodsfunction void build_phase(uvm_phase phase);a_port = new("a_port", this);m_agent = my_agent::type_id::create("m_agent", this);endfunctionfunction void connect_phase(uvm_phase phase);...endfunctiontask run_phase(uvm_phase phase);...endfunction
endclass
Connection to the DUT
☐在UVM验证环境使用虚拟接口访问SystemVerilog接口实例。
☐agent应检查其虚拟接口是否已被set。agent应从其配置对象获取虚拟接口,并在其driver和monitor中分配虚拟接口变量。如果虚拟接口为空,则agent应报告fatal_error,因为仿真没有必要继续。
bus_config m_config;
function void bus_agent::build_phase(uvm_phase phase);
if (!uvm_config_db #(bus_config)::get(this, "", "config", m_config))`uvm_error(get_type_name(), "bus config not found"
if (m_config.vif == null)`uvm_fatal(get_type_name(), "bus virtual interface not set")...
endfunction
TLM Connections
☐在connect_phase中建立TLM port/export连接,分配虚拟接口。
☐使用port和export在UVM组件之间进行通信,包括analysis ports和相应的exports。
通常,首选ports和exports用于组件之间的通信,而不是使用点对点共享对象或其他UVM通信机制。在需要点对点共享对象进行同步的情况下,使用uvm_event或uvm_barrier来同步组件。 (请参阅时钟,时序,同步和接口)。
☐当UVM组件之间需要实现一对多的连接时,使用analysis ports和analysis exports(或者是uvm_subscriber的对象)。
在许多情况下,analysis ports和analysis exports优于常规的ports和export,因为analysis ports支持向多个组件(所谓的uvm_subscriber)广播transaction,并允许ports可以是未连接状态。当然,使用常规ports和export实施一对一连接,有时也可能是您想要的。analysis ports通常是将transaction传递出agent,并将transaction传递到scoreboard,checker和覆盖率收集器组件或在组件之间传递的最佳选择。
☐在组件之间建立对等(peer-to-peer)连接时,将ports(或analysis ports)直接连接到exports(或analysis exports),而无需任何中间FIFO。ports和export直接连接应被视为UVM中的标准,只在需要时才插入FIFO。当需要FIFO时,它们应该插入组件内部而不是组件之间。
☐与agent进行通信的两种方式:将agent的analysis ports连接到uvm_subscriber,或从外部的使用直接对象引用(direct object reference)来访问agent中的sequencer。
由于agent具有已知的内部结构,因此允许使用层次对象引用直接从外部访问内部对象。建议将monitor的analysis ports连接到agent的analysis ports,当然也可以直接从外部访问monitor的analysis ports。
Configurations
☐使用配置数据库uvm_config_db而不是资源数据库uvm_resource_db。使用uvm_resource_db的唯一情况是,在多次设置相同item(即同名和相同范围)时,它们具有不同的规则。但是,不必学习两组规则,单独使用uvm_config_db就可以完成所需的一切。
☐将给定组件的配置参数分组到配置对象中,并将该配置对象设置到配置数据库中。
☐顶层配置对象应包含对所有低层配置对象的引用。顶层配置对象应该实例化自顶层模块,而低级配置对象应该从顶层配置对象的构造函数(new)中实例化。较低级别的配置对象通常与agent关联。此方法的好处是无需在顶层配置对象和较低级别配置对象之间复制或复制信息,顶层配置对象可以包含对较低级别配置对象中变量的约束。可以从顶层模块或test类以及顶层env类对较低级别配置对象的变量赋值(见示例)。
☐通过扩展类uvm_object来创建用户定义的配置类。扩展uvm_object为配置对象提供层次名称,并启用UVM种子以获得更好的随机稳定性。虽然配置对象不是transaction和组件,但随机化仍然有用。
☐不要使用factory注册用户定义的配置类。因此,配置类可以具有带有任意数量的用户自定义参数的构造函数。将配置对象视为一组参数值,而不是激励。
☐组件在build_phase中get和set配置参数(通常是配置的对象)。
☐始终检查uvm_config_db#(T):: get的返回值(bit),以确保配置数据库中存在这个配置参数。
☐如果uvm_config_db#(T):: get返回0(即get失败),则应选择合理的默认值。在未正确配置其配置参数的情况下,验证组件应具有合理的默认行为。
☐每个组件都应该是仅仅get自己实例对应的配置对象,而不应该get到其他组件实例的配置对象。也就是说,应该如下方式使用get:
uvm_config_db#(T)::get(this, "", ...);
The Factory
☐总是使用factory实例化transaction,sequence,以及组件的对象。
不要简单使用new函数来实例化对象,而是应该使用如下方式:
实例化transaction,sequence等object对象:
var_name = type_name::type_id::create("var_name");
实例化组件的对象:
var_name = type_name::type_id::create("var_name", this);
这里的var_name是对象名称, type_name是类名。以这种方式一致地使用UVM factory是能够在UVM中利用OOP的关键之一,因为它允许在运行时而不是在编译时确定对象的类型,因此可以在不需要修改源代码的情况下进行override(调用create)。
☐使用factory将transaction,sequence,以及组件对象替换为其类的扩展类的另一个对象时,factory覆盖应采用以下形式之一:
old_type_name::type_id::set_type_override(new_type_name::get_type());
old_type_name::type_id::set_inst_override(new_type_name::get_type() ... );
这与直接调用类uvm_factory的方法形成对比,只是为了保持一致性,并不鼓励这样做。
☐当您需要访问factory时,请调用静态方法uvm_factory :: get( )。
不要使用全局变量factory来访问某个factory(全局变量factory在uvm_1.2中被丢弃)。一个调用factory中的print方法例子:
uvm_factory factory = uvm_factory::get(); // 利用get函数得到
factory.print();
Tests
☐不要直接从测试中生成激励,而是使用测试来设置配置参数和factory覆盖。通常最好从env而不是从测试中启动sequence,并将测试限制为参数化或重配置环境。环境应该知道如何激励DUT(见 Stimulus.)。
☐设置验证环境的默认配置,并在env类中生成默认激励,而不是测试类,以便即使使用空测试也能运行env。env应该独立运行,并且应该使用有效激励来运行DUT,即使是空的测试。在经典受约束随机验证适用的应用中,可以通过使用的不同种子重复测试以增加覆盖率。 (参见覆盖率驱动的验证方法。)
☐在适当的情况下,使用text_base类来定义一组测试中常见的结构和行为,并通过扩展这些base类来创建各个测试。将公共代码移动到base类中是良好的面向对象编程实践的一个例子,但重要的是规划重用的原则。请记住每个标准phase方法都应该先调用super.<phase_name>_phase方法(请参阅组件)。
☐为了重复使用,请避免根据验证环境的具体细节进行测试。例如,避免引入深入验证环境的层次对象引用。在引用env中的组件时,使用uvm_top.find(“*.path”)来定位验证环境中的组件,而不是使用完整的“硬连线”对象引用(即层次化引用),但请注意,find方法在CPU时间方面可能很昂贵(所以不要从内部循环调用它)。
☐使用命令行参数修改测试行为,无需重新编译。例如,使用+ UVM_TESTNAME命令行参数选择testcase,并通过调用不带参数的run_test来启动测试:uvm_top.run_test();您还可以使用命令行参数设置factory覆盖,设置配置数据库中的值以及设置打印阈值级别,所有这些都无需重新编译SystemVerilog源代码。
Messaging
☐要报告消息,请始终使用八个标准报告宏之一`uvm_info,`uvm_info_context等,而不是$display及类似语句。打印消息需要消耗一定的计算机仿真时间,因此,使用UVM的报告功能(例如消息详细程度)来控制生成的消息数非常重要。
☐将消息ID设置为静态 string 或get_type_name( )。消息id是报告宏的第一个参数,例如`uvm_info,`uvm_warning等等。如果该字符串与当前VIP中的所有报告相同,则将其设置为静态字符串,从而有助于将报告标识为源自该VIP。否则将其设置为get_type_name(),它返回表示当前类类型的字符串。请注意,get_type_name( )在VIP的原始开发和调试期间可能很有用,但在要广泛应用的VIP中可能不太合适。如果没有其他明显更优的选择,get_type_name( )在任何情况下都是一个很好的fallback。
☐在整个代码中仔细,有条理地和一致地设置消息详细级别,以避免日志文件中不必要的数据,并区分在验证环境开发调试期间使用的消息和在运行testcase时使用的消息。
☐默认情况下,将各个报告宏的详细级别设置为较大的数字,以便不太可能报告message。
建议使用以下详细级别:
UVM_HIGH和UVM_DEBUG 用于调试验证环境或测试本身的消息,通常在验证环境或测试能够成功到达运行阶段的开始时应被抑制。
UVM_MEDIUM - 与sequence执行或DUT引脚级行为相关的消息,通常在run phase生成,用于帮助诊断DUT中的错误。
UVM_NONE - 消息不会被消息详细程度机制抑制,因此仅用于不经常用,或非常重要的信息,例如测试执行期间的主要阶段或状态更改
使用命令行参数+ UVM_VERBOSITY从命令行设置特定testcase的消息详细级别非常有用。
☐仔细设置消息严重性级别,以区分纯信息性消息,可能代表错误的消息和肯定是错误的消息。
建议使用以下严重性级别:
UVM_INFO - 消息仅供参考,并不表示错误。
UVM_WARNING - 该消息指示需要进一步调查的潜在错误
UVM_ERROR - 该消息指示实际错误,但允许进行继续仿真。通过允许仿真持续一段时间,可以在有可能收集有关错误来源的更多信息时使用。默认情况下,UVM_ERROR与退出计数关联,退出计数在达到最大错误计数时中止。
UVM_FATAL - 该消息指示严重性错误,不允许继续进行仿真。
Register Layer
☐顶层UVM环境应使用factory实例化寄存器块,并应调用寄存器模型的build方法。factor方法调用type_id :: create,并且应该在环境的build_phase中调用build。
☐对于子环境使用寄存器模型的层次结构UVM环境,应该有一个顶层寄存器块,用于实例化与子环境关联的寄存器块,依此类推。
☐任何使用寄存器模型的UVM env都应该有一个名为regmodel的变量,该变量存储对该特定环境的寄存器块的引用。
☐具有寄存器模型的UVM env应设置所有子组件的regmodel变量,如果子组件也使用了寄存器模型到其寄存器块的相应子块。子组件的regmodel变量应在env的build_phase中被设置。
☐如果env的regmodel变量的值为null,则UVM环境应仅实例化一个寄存器块。对于顶层环境,regmodel的值将为null,因此env应实例化寄存器块并设置regmodel的值。对于较低层次的env,regmodel的值不应为null,因为它应该由更高层次的env设置。此机制允许将相同的env实例化为顶层env(具有寄存器模型)或作为较低层次的env(没有自己的寄存器模型)。
Functional Coverage
☐使用SystemVerilog covergroup结构在UVM验证环境中收集功能覆盖率。处理或转换来自DUT的值以创建为实际采样覆盖点的派生值,有时这是必要的或更方便的。例如,您可以计算在总线上连续出现的两个地址之间的差异,并将结果值用作覆盖点。
☐在适当的情况下,使用cover property在interface中收集功能覆盖信息。使用cover property语句的基于property的coverage是收集接口协议中时间sequence的功能覆盖信息的好方法(与使用covergroup语句的基于样本的覆盖相反),但请注意,cover property语句不能在类中使用。 (参见并发断言)
☐Covergroups应该在UVM组件类中实例化,而不是在sequence或transaction中。coverage应该从在整个仿真过程中持续存在的准静态对象中收集,而不是从随时间动态变化的对象中收集。
☐Covergroups应在UVM subscribers或scoreboards中实例化,并且scoreboard是在UVM env类中实例化并连接到monitor/agent的analysis port。使用monitor以通过其analysis port发送的transaction形式收集和组合信息,但不要将covergroup放在monitor中。monitor的数据收集和scoreboards的数据分析之间的这种分离对于重用是重要的。
☐如果coverage收集跨越多个DUT接口,因此需要从多个agent接收analysis transaction,请使用`uvm_analysis_imp_decl宏在coverage collector类中提供多个analysis exports。uvm_subscriber类仅仅只有一个analysis export,`uvm_analysis_imp_decl宏提供了接受多个传入transaction流的最方便的方法,每个传入transaction流都有自己独立的write方法。例:
`uvm_analysis_imp_decl(_expected)
`uvm_analysis_imp_decl(_actual)
class my_cov_collector extends uvm_scoreboard;`uvm_component_utils(my_cov_collector)uvm_analysis_imp_expected #(tx_t, my_cov_collector) expected_export;uvm_analysis_imp_actual #(tx_t, my_cov_collector) actual_export;...function void build_phase(uvm_phase phase);expected_export = new("expected_export", this);actual_export = new("actual_export", this);endfunction...function void write_expected(tx_t t);...endfunctionfunction void write_actual(tx_t t);...endfunction
☐将覆盖点分为多个覆盖组,以便将的specification features的coverage与implementation features的coverage分开。这将有助于重新使用coverage模型。
☐在coverage收集器的配置对象中使用变量coverage_enable来启用或禁用coverage收集。coverage收集会产生性能和内存消耗,而某些用例可能不需要收集coverage。“UVM用户指南”建议使用名为coverage_enable的变量来实现此目的。
☐通过调用sample方法而不是为covergroup指定时钟事件来对进行采样。这可以是内建sample方法或带有参数列表的sample方法,如covergroup IDENTIFIER with function sample(...)。调用sample方法允许仅在transaction从DUT到达coverage collector组件时才对值进行采样。
☐不要频繁地过度对覆盖组进行采样。考虑对每个覆盖点使用条件表达式iff( ...)来降低采样频率。过于频繁的采样会不必要地增加需要存储和分析的覆盖数据量。每次对covergroup进行采样时,对每个覆盖点进行采样可能没有必要或没有意义。任何条件表达式都应该保持简单:复杂的iff条件很难调试。
☐在DUT端口或者DUT内部进行采样,不要在激励上面进行采样。在采样DUT的寄存器的值时,应该等到DUT寄存器值发生变化后才采样,而不是在激励发生变化时就进行采样。
☐考虑将每个覆盖组和覆盖点的option.at_least设置为默认值1以外的某个值。option.at_least的默认值仅确保每个状态被命中一次,这通常不足以测试状态是否已经锁定。
☐不要设置覆盖组和覆盖点的option.weight或option.goal。首先,给某些状态赋予更大或更小权重的方法可能会扭曲覆盖率报告,其次,这些选项在不同的仿真工具上可能有不同实现方式。
☐仔细设计coverprint bin,以确保涵盖功能重要的case。由于100%覆盖是不现实的,因此仔细设计coverage bin对于验证质量至关重要。一种解决方案的是为典型值,特殊值和边界条件创建单独的bin。bin的选择应与验证计划有关。
☐设计覆盖点时,请指定非法值或不需要覆盖的值为ignore_bins。不要使用illegal_bins。Covergroups应限于收集功能覆盖率信息,而不是直接与错误报告相关联。应使用断言或使用UVM报告处理程序来捕获非法值。
原文链接:
Easier UVM Code Generatorwww.doulos.com/knowhow/sysverilog/uvm/easier_uvm_generator/
Easier UVM Coding Guidelines / 便捷UVM 编码指南相关推荐
- 【android 插件】alibaba的编码规范Java Coding Guidelines
参考 Java Coding Guidelines
- IDEA插件 阿里巴Java编码指南插件支持
IDEA里面搜索插件 Alibaba Java Coding Guidelines 并安装 Alibaba Java Coding Guidelines plugin support. Java编码指 ...
- Python Coding Guidelines
Python Coding Guidelines 12/14/07 Written by Rob Knight for the Cogent project Table of Contents Why ...
- 如何确定autosar的版本_AUTOSAR编码指南(中文版)
在汽车应用领域,软件开发变得越来越重要.随着安全.环境以及便利性需求的增长,车辆中应用电子系统的数量也在急速增长.其中有90%的创新应用都是基于软件驱动的电子组件.而这些组件的研发成本占车辆开发成本的 ...
- IDEA安装“Alibaba Java Coding Guidelines”插件
Alibaba Java Coding Guidelines 中文名为"阿里巴巴Java代码规约扫描" 第一步:根据"File - Settings - Plugins ...
- IDEA/Eclipse安装 Alibaba Java Coding Guidelines 插件
为了让开发者更加方便.并且达到快速规范代码格式的目的并实行起来,阿里巴巴基于<阿里巴巴Java开发规约>手册内容,研发了一套自动化的IDE检测插件(IDEA.Eclipse).它就是Ali ...
- 阿里巴巴Java开发手册 (Alibaba Java Coding Guidelines)
参考资料: 阿里巴巴Java开发手册 https://www.cntofu.com/book/78/index.html 一.编程规约 ##(一)命名风格 [强制]代码中的命名均不能以下划线或美元符 ...
- Alibaba Java Coding Guidelines安装使用教程
P3c是阿里代码规范检查工具,该插件由阿里巴巴 P3C 项目组研发. 代码已经开源,GitHub:https://github.com/alibaba/p3c 阿里介绍文章:https://mp.we ...
- 代码规范之Alibaba Java Coding Guidelines
一.Alibaba Java Coding Guidelines 1.整体介绍: Alibaba Java Coding Guidelines 专注于Java代码规范,目的是让开发者更加方便.快速规范 ...
最新文章
- SaltStack:Salt SSH
- 对Struts2的认识(-)
- vue开发(2) 使用vue-cli来构建项目
- 给插店一个成功案例给自己一次机会
- 30万奖金等你拿 | “信也科技杯”第五届数据解决方案应用大赛火热报名中!...
- java23中设计模式——结构模式——Flyweight(享元)
- 问题 A: 深度学习
- 【大数据新手上路】“零基础”系列课程--MySQL 数据整库迁移到 MaxCompute
- Liunx服务器部署系列
- Sql server锁,独占锁,共享锁,更新锁,乐观锁,悲观锁
- 借Google Guava学习发现和开发通用功能模块
- 小技巧 - 如何在线下载 Google Play 里面的应用?
- Android物理按键功能更改
- 蚂蚁金服上市估值2k亿美金!会开发到底有多吃香?
- 解决从GitHub拉取、提交代码一直验证失败的问题
- 详细BP神经网络预测算法及实现过程实例
- XiaoHu日志 6/10~6/12
- 博弈背景下的记忆化搜索/题意理解 (HDU 2452 Navy maneuvers)
- MySQL字符集设定与查询
- python程序简单快速写能谱实验word报告