UVM Tutorial for Candy Lovers – 3. Transactions and Sequences

本文通过糖果交易类和序列详细介绍了SystemVerilog的验证方法,包括基本交易类定义、约束块使用、序列创建及子序列调用,展示了如何构建复杂的验证场景。

This post will provide an explanation on the SystemVerilog code itself. Please see Recipe for the class diagram.

Transactions

Jelly-Bean Transaction

The jelly_bean_transaction class defines the jelly-bean recipe based on flavor, color, and other characteristics. It also has the property called taste to hold the reaction of the jelly_bean_taster (DUT) to the flavor. The relationship between the flavor and color is defined in the constraint block (line 12). For example, if the flavor is apple, the color must be red or green (not blue).

Update (April 2, 2014): In this example, we used so-called UVM field macros (lines 23 to 27) to save the effort of writing “do-hook” functions. I would recommend writing your own “do-hook” functions instead of using these macros once you become familiar with UVM. For more information, please see Field Macros and “Do” Hooks.

class jelly_bean_transaction extends uvm_sequence_item;
   typedef enum bit[2:0] { NO_FLAVOR, APPLE, BLUEBERRY, BUBBLE_GUM, CHOCOLATE } flavor_e;
   typedef enum bit[1:0] { RED, GREEN, BLUE } color_e;
   typedef enum bit[1:0] { UNKNOWN, YUMMY, YUCKY } taste_e;
 
   rand flavor_e flavor;
   rand color_e  color;
   rand bit      sugar_free;
   rand bit      sour;
   taste_e       taste;
 
   constraint flavor_color_con {
      flavor != NO_FLAVOR;
      flavor == APPLE     -> color != BLUE;
      flavor == BLUEBERRY -> color == BLUE;
   }
 
   function new(string name = "");
      super.new(name);
   endfunction: new
 
   `uvm_object_utils_begin(jelly_bean_transaction)
      `uvm_field_enum(flavor_e, flavor, UVM_ALL_ON)
      `uvm_field_enum(color_e, color, UVM_ALL_ON)
      `uvm_field_int(sugar_free, UVM_ALL_ON)
      `uvm_field_int(sour, UVM_ALL_ON)
      `uvm_field_enum(taste_e, taste, UVM_ALL_ON)
   `uvm_object_utils_end
endclass: jelly_bean_transaction

Sugar-Free Jelly Bean

The jelly_bean_transaction class can be extended to various classes. For example, to create only sugar-free jelly beans, the child class can define the constraint as shown in line 4.

class sugar_free_jelly_bean_transaction extends jelly_bean_transaction;
   `uvm_object_utils(sugar_free_jelly_bean_transaction)
 
   constraint sugar_free_con {
      sugar_free == 1;
   }
 
   function new(string name = "");
      super.new(name);
   endfunction: new
endclass: sugar_free_jelly_bean_transaction

Sequences

One Jelly Bean

The sequence creates the recipes of the jelly beans being generated. The first sequence is the simplest, as it is designed to create a single jelly bean. The line 10 creates a single jelly-bean transaction (a recipe), then the line 12 randomizes the recipe.

class one_jelly_bean_sequence extends uvm_sequence#(jelly_bean_transaction);
   `uvm_object_utils(one_jelly_bean_sequence)
 
   function new(string name = "");
      super.new(name);
   endfunction: new
 
   task body();
      jelly_bean_transaction jb_tx;
      jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
      start_item(jb_tx);
      assert(jb_tx.randomize());
      finish_item(jb_tx);
   endtask: body
endclass: one_jelly_bean_sequence

Same-Flavored Jelly Beans (Sequence of Transactions)

Now let’s create the multiple jelly beans of the same flavor. The number of jelly beans being created is specified with the class property called num_jelly_beans. The line 4 constrains the num_jelly_beans to be between 2 and 4. The line 14 creates a single jelly bean, and the line 15 randomizes its color and flavor. With this jelly bean as the standard, the line 18 creates jelly beans of the same flavor, as many as specified by the num_jelly_beans. In-line constraint on the line 21 guarantees the same flavor to be generated.

class same_flavored_jelly_beans_sequence extends uvm_sequence#(jelly_bean_transaction);
   rand int unsigned num_jelly_beans; // knob
 
   constraint num_jelly_beans_con { num_jelly_beans inside { [2:4] }; }
 
   function new(string name = "");
      super.new(name);
   endfunction: new
 
   task body();
      jelly_bean_transaction           jb_tx;
      jelly_bean_transaction::flavor_e jb_flavor;
 
      jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
      assert(jb_tx.randomize());
      jb_flavor = jb_tx.flavor;
 
      repeat (num_jelly_beans) begin
         jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
         start_item(jb_tx);
         assert(jb_tx.randomize() with { jb_tx.flavor == jb_flavor; });
         finish_item(jb_tx);
      end
   endtask: body
 
   `uvm_object_utils_begin(same_flavored_jelly_beans_sequence)
      `uvm_field_int(num_jelly_beans, UVM_ALL_ON)
   `uvm_object_utils_end
endclass: same_flavored_jelly_beans_sequence

Gift-Boxed Jelly Beans (Sequence of Sequences)

The code below demonstrates how to create multiple-flavored jelly beans. The number of flavors is specified with the class property called num_jelly_bean_flavors (line 2). On the 4th line, the sequence randomly picks two to three flavors. The main part of the sequence is the repeat block (from the line 12), where a sequence of same_flavored_jelly_beans_sequences is created.

class gift_boxed_jelly_beans_sequence extends uvm_sequence#(jelly_bean_transaction);
   rand int unsigned num_jelly_bean_flavors; // knob
 
   constraint num_jelly_bean_flavors_con { num_jelly_bean_flavors inside { [2:3] }; }
 
   function new(string name = "");
      super.new(name);
   endfunction: new
 
   task body();
      same_flavored_jelly_beans_sequence jb_seq;
      repeat (num_jelly_bean_flavors) begin
         jb_seq = same_flavored_jelly_beans_sequence::type_id::create(.name("jb_seq"), .contxt(get_full_name()));
         assert(jb_seq.randomize());
         jb_seq.start(.sequencer(m_sequencer), .parent_sequence(this));
      end
   endtask: body
 
   `uvm_object_utils_begin(gift_boxed_jelly_beans_sequence)
      `uvm_field_int(num_jelly_bean_flavors, UVM_ALL_ON)
   `uvm_object_utils_end
endclass: gift_boxed_jelly_beans_sequence

This post has an emphasis on the transactions and sequences in the jelly-bean verification environment. The next post will provide an explanation on the verification components.

<think>嗯,用户问的是UVM中this关键字的含义和在方法中的作用。首先,我需要回忆一下SystemVerilog和UVM中的相关知识。记得在面向对象编程中,this通常指当前对象的实例。但在UVM中,可能有一些特定的用法或者需要注意的地方。 首先,根据引用里的内容,特别是引用[4]提到了this和local的作用域,以及引用[3]提到静态方法中不能使用this。用户可能想知道在UVM的方法中,this是如何工作的,比如在sequence或者component中的使用情况。 接下来,我需要确认UVM中的this是否和普通的SystemVerilog中的this相同。通常,this用于区分类的成员变量和方法的参数,尤其是在命名冲突的时候。例如,如果方法的参数和类的成员变量同名,可以用this来明确指定后者。 然后,用户提供的引用[2]中有一个例子,里面在virtual_sequence里使用了p_sequencer,这可能涉及到this的使用。但例子中没有直接出现this,可能需要进一步分析。不过,引用[4]中的例子展示了用local::来访问当前作用域的变量,这可能与this不同,但需要比较两者的区别。 另外,引用[3]指出在静态方法中不能使用this,这在UVM中同样适用。因此,在UVM组件中,比如在uvm_component或者uvm_object的子类中,如果方法是非静态的,可以使用this,而静态方法则不能。 用户的问题可能还涉及到如何在UVM环境中正确使用this来调用类的方法或访问成员变量,尤其是在存在继承或覆盖的情况下。例如,在子类中调用父类的方法时,是否需要用super,而this则指当前子类的实例。 可能还需要考虑UVM中的一些特殊结构,比如sequence的body方法里,使用this来访问sequence的成员变量或方法,或者在使用`uvm_do宏时,this的作用是什么。 总结一下,this在UVM中的主要作用应该和在SystemVerilog中一致,即引用当前实例的成员,区分局部变量和成员变量,支持链式调用,以及在方法调用中传递当前对象。同时需要注意静态上下文中不能使用this,避免作用域混淆。</think>### UVM中this关键字的含义与作用解析 在UVM(Universal Verification Methodology)中,`this`关键字继承自SystemVerilog的面向对象特性,**用于指向当前类的实例对象**。其核心作用是通过明确作用域来增强代码的可读性和准确性[^3][^4]。 #### 一、this关键字的核心作用 1. **明确作用域标识** 当**类成员变量与局部变量同名**时,使用`this`可明确指定访问的是当前对象的成员变量。例如: ```systemverilog class my_driver extends uvm_driver; bit [31:0] data; task send_packet(bit [31:0] data); this.data = data; // 将参数data赋值给类成员data endtask endclass ``` 2. **链式方法调用** 在方法中返回当前对象引用(`return this`),支持链式调用: ```systemverilog class config_obj extends uvm_object; int mode; function config_obj set_mode(int mode); this.mode = mode; return this; endfunction endclass // 调用示例 cfg = new().set_mode(1).set_mode(2); ``` 3. **作为方法参数传递** 将当前对象传递给其他方法,常见于回调或工厂模式: ```systemverilog class my_monitor extends uvm_monitor; function void connect_phase(uvm_phase phase); analysis_port.connect(this); // 传递当前monitor实例 endfunction endclass ``` #### 二、UVM中的特殊注意事项 1. **静态上下文中禁止使用** 静态方法(`static function/task`)中不能使用`this`,因为静态方法不依赖对象实例[^3]。 2. **与`super`的配合使用** 在方法覆盖(override)时,`this`指当前对象,而`super`用于调用父类方法: ```systemverilog class child_seq extends base_seq; task body(); super.body(); // 调用父类body() this.start(); // 调用当前类的start() endtask endclass ``` 3. **与`local::`的区别** `local::`用于索引**当前作用域**的变量(如任务、函数内),而`this`始终指向类实例成员[^4]: ```systemverilog task my_task(int data); this.data = local::data; // this.data为类成员,local::data为任务参数 endtask ``` #### 三、典型应用场景 | 场景 | 示例代码片段 | 作用说明 | |---------------------|---------------------------------------|---------------------------| | 序列(sequence)构建 | `this.start(p_sequencer);` | 启动当前序列 | | 配置对象传递 | `cfg.copy(this);` | 复制当前对象配置 | | 回调函数注册 | `uvm_callbacks#(this_type)::add(...)` | 注册当前类回调 | ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值