1. Sequenece机制基础
1.1 概念
控制和产生一系列的激励,并通过sequencer将激励发送给driver。
是一个产生和发送数据的过程,需要消耗仿真时间,要用在task phase中启动。
将激励的产生与驱动分离,提高了测试平台中组件的可重用性,使得事务的产生更加灵活。

1.2 原理


1.3 相关宏
- uvm_do系列宏
uvm_do系列的其他七个宏其实都是用uvm_do_on_pri_with宏来实现的。
- uvm_create与uvm_send
uvm_create:实例化transaction。
uvm_send:将处理完的transaction发送出去。
uvm_send_pri:将transaction交给sequencer时设定优先级。 - uvm_rand_send系列宏
前提:transaction已经被分配了空间。
意义:如果一个transaction占用的内存比较大,那么很可能希望前后两次发送的transaction都使用同一块内存,只是其中的内容可以不同,这样比较节省内存。 - start_item与finish_item
必须要先实例化transaction后才可以调用这两个任务。
可以在transaction实例化后、finish_item调用前对其进行随机化。
指定transaction优先级,要在调用start_item和finish_item时都要加入优先级参数。不指定默认为-1。 - pre_do、mid_do与post_do

pre_do任务的参数用于表明uvm_do宏是在对一个transaction还是在对一个sequence进行操作。
mid_do和post_do的两个参数是正在操作的sequence或者item的指针,但是其类型是uvm_sequence_item类型。通过cast可以转换成目标类型。
意义:增加uvm_do系列宏的功能。
1.4 三种启动方式
(1)直接使用start方式启动sequence
(2)配置sequencer中的default_sequence(test中的build_phase完成)
(3)使用`uvm_do系列宏、`uvm_send系列宏、`uvm_rand_send系列宏启动sequence
当一个sequence启动后会自动执行sequence的body任务。
前两种方式除了执行body外,还会自动调用sequence的pre_body与post_body任务。第三种则不会。
1.5 sequencer仲裁算法
| 算法参数 | 说明 |
| SEQ_ARB_FIFO | 默认算法。先入先出,不考虑优先级。 |
| SEQ_ARB_WEIGHTED | 优先执行高权值的sequence |
| SEQ_ARB_RANDOM | 随机执行sequence |
| SEQ_ARB_STRICT_FIFO | 按照优先级,同一优先级,先入先出 |
| SEQ_ARB_STRICT_RANDOM | 按照优先级,同一优先级,随机 |
| SEQ_ARB_USER | 用户自定义。需扩展uvm_sequencer并且重载user_priority_arbitration |
1.6 sequence对sequencer的占用或失效
1.6.1 用lock()和grab()排他性占用sequencer
sequence的body()中 使用lock()…unlock()或grab()…ungrab(), 可以让在其中间发送(假设中间的sequence具有最高级)的所有transaction连续地获取sequencer的仲裁,从而连续地发送到driver而不被别的sequence打断。
两者区别——仲裁机制不一样:
(1)lock()会放在仲裁队列的末尾,sequencer将原来就在仲裁队列里的transaction发送完后才执行lock的transaction,一旦lock占用sequencer后,只有unlock后才释放。
(2)grab()会放在仲裁队列的最前面,grab操作比lock操作优先级更高,sequencer会立即执行grab的transaction,同样一旦grab占用sequencer后,只有ungrab后才释放。
(3)grab实时性强,是插队操作。unlock则不是。
1.6.2 sequence的is_revelant函数和wait_for_relevant任务
sequencer在仲裁时, 会查看sequence的is_relevant函数的返回结果, 为1说明此sequence有效并参加仲裁, 否则无效。
可以通过重载is_relevant函数来使sequence失效。
当sequencer将所有有效transaction发送完毕后,它会调用处于无效状态的sequence的wait_for_relevant任务。当wait_for_relevant返回后,sequencer还会继续调用is_relevant函数。
在wait_for_relevant任务中,user一定要将使sequence的无效状态的条件清除。否则系统会进入死循环。
1.7 在sequence中获得my_sequencer中变量的值
假设我们需要在 sequence 中使用 my_sequencer 类型中的 dmac和smac 变量。
两种方法:
(1)通过cast转换将m_sequencer转换成my_sequencer类型,并引用其中的dmac和smac。
(2)使用`uvm_declare_p_sequencer(my_sequencer),会自动将m_sequencer通过cast转换成p_sequencer。这个过程在pre_body()之前就完成了。因此在sequence中可以直接使用成员变量p_sequencer来引用dmac和smac。
2. Virtual Sequence
假设我们有如下图的需求,DUT有许多接口,不同接口需要不同的sequence产生激励,那我们要如何控制不同Sequence的执行顺序呢?

在此,我们引入virtual sequence的概念。Virtual sequence是 具有管理多个sequence,并控制它们之间关系功能 的sequence。

配套的,我们需要使用virtual sequencer来管理多个sequencer。

代码实现如下:






3. Sequence library(了解即可)
3.1 概念
– 一个sequence
– 包含了一组在其内部注册了的sequence类型
– 可通过对其进行配置,创建并执行一系列的sequence/sequence item
3.2 功能
– 其他sequence可以向sequence library注册
– 可根据配置产生并且执行已经在其内部注册过的sequence
– 具有多种内嵌的选择sequence的算法
– 支持用户自定义的sequence选择算法
– 注册方式的多样化

3.3 向sequence library中注册sequence
3.3.1 永久注册
(1)创建sequence library类。// 从uvm_sequence派生时要指明此sequence library所产生的transaction类型
class simple_seq_library extends uvm_sequence_library#(my_transaction);
function new(string name= "simple_seq_library");
super.new(name);
// 在new函数中要调用init_sequence_library,否则其内部的候选sequence队列就是空的
init_sequence_library();
endfunction
`uvm_object_utils(simple_seq_library)
// 要调用 uvm_sequence_library_utils注册
`uvm_sequence_library_utils(simple_seq_library);
endclass
(2)创建sequence并注册进simple_seq_library中。// 第一个是此sequence的名字,第二个是要加入的sequence library的名字
`uvm_add_to_seq_lib(seq0, simple_seq_library)
(3)将simple_seq_library配置给sequencer的default_sequence,以启动sequence lib。
3.3.2 临时添加——使用类配置
(1)创建sequence library类和sequence类。
(2)在test中根据实际需求将sequence添加到sequence library中,simple_seq_library为注册目标的sequence library。simple_seq_library::add_typewide_sequence(my_sequence::get_type());
(3)将simple_seq_library配置给sequencer的default_sequence,以启动sequence lib。
3.3.3 在某一个单独的sequence library实例中添加sequence
(1)创建sequence library类和sequence类。
(2)在test中声明sequence library句柄,在build_phase中实例化sequence对象,向sequence library中注册sequence。simple_seq_library m_seqlib;
virtual function void build_phase(uvm_phase phase);
...
m_seqlib = simple_seq_library::type_id::create(“m_seqlib”, this);
m_seqlib.add_sequence(my_sequence::get_type());
...
endfunction
(3)将simple_seq_library配置给sequencer的default_sequence,以启动sequence lib。
3.4 相关参数及配置

selection_mode参数可选配置如下:

参数配置两种方法如下:

代码示例仓库:
https://gitee.com/mala_wong/uvm_sequence_test
参考资料:
• 白皮书《UVM实战》第6章 UVM中的sequence
• B站教程 《UVM基础》P32-P37 P52-P57
• CSDN博文
https://blog.csdn.net/weixin_43830240/article/details/111193810
https://blog.csdn.net/weixin_43830240/article/details/111220598?spm=1001.2014.3001.5501







