UVM-sequence

1.概述

在UVM世界,利用其核心特性,在创建了组件和顶层环境,并完成组件之间的TLM端口连接之后,下面使环境运转,运转的必要条件是组件之间需要有事务(transaction)传送。
围绕下面几个核心词来阐述它们的作用、分类以及之间的互动关系。

  • sequence item
  • sequence
  • sequencer
  • driver
    如果按照交通道路的车流来打比方,sequence就是道路,sequence item是道路上行驶的货车,sequence是目的地的关卡,而driver便是最终目的地卸货的地方。从软件实施的层面来讲,这里的货车是从sequence一端出发的,在经过了sequencer,最终抵达了driver,经过driver的卸货,每一辆货车也就完成了它的使命。而driver对每一件到站的货物,经过它的扫描处理,将它分解为更小的信息量,提供给DUT。
    基本概念:
  • sequence item是driver与DUT每次互动的最小粒度内容
  • 通过SV的随机化和sequence item对随机化的支持,产生的每个sequence item对象中的数据内容都不同
  • driver和sequencer的通信时通过TLM端口实现
  • driver和sequencer是component,uvm_sequence_item和uvm_sequence是object
  • uvm_sequence和uvm_sequence_item并不处于UVM树结构中,所以顶层无法直接做配置。sequence活动起来,会挂载在sequencer上,这样sequence就可以依赖于sequencer的结构关系,通过sequencer来获取顶层配置
  • 数据传输机制采取get模式,而不是put模式,get模式是driver从sequencer获取item

在这里插入图片描述
序列组件的互动

  • sequence对象会产生目标数量的sequence item对象。借助于SV的随机化和sequence item对随机化的支持,使得产生的每个sequence item对象中的数据内容都不同
  • 产生的sequence item会经过sequencer再流向driver
  • driver得到每一个sequence item,经过数据解析,将数据按照与DUT的物理接口协议写入到接口上,对DUT形成有效的激励

由于sequence需要得知driver与DUT互动状态,driver在每解析并消化完一个sequence item后,它会将最后的状态信息写回sequence item对象再返回给sequencer,最终抵达sequence对象一侧。
对于常见的用法,driver往往是一个sequence item消化完,报告给sequencer和sequence,同时再请求消化下一个sequence item
继承关系
uvm_sequence_item和uvm_sequence都是基于uvm_object,它们不同于uvm_component只在build阶段作为UVM环境的“不动产”进行创建和配置,而是可以在任何阶段创建。
在这里插入图片描述
sequence存在的意义:

  • sequence是一个组件,可以通过TLM端口与driver传输item对象
  • 当有多个sequence挂载在sequencer上时,sequencer有充分的仲裁机制来合理分配和传送item,继而实现并行item数据传送至driver的测试场景
  • 由于sequence是一个object,而uvm_object是独立于build阶段的,这就使得用户可以有选择地、动态地在合适时间点挂载所需的sequence和item
    选择get模式的原因:
  • 从效率上看,采用get模式,当item从sequence产生,穿过sequencer到达driver时,就可以结束该传输(假如不需要返回值)。采用put模式,sequencer将item传送至driver,同时必须收到返回值才可以发起下次传输。
  • 从sequencer的仲裁特性看,当多个sequence同时挂载到sequencer上面,driver作为initiator,一旦发出get请求,它会通过sequencer,继而获得仲裁后的item

2.sequence和item

item的使用:

  • 如果数据使用来做驱动,应该定义为rand,同时按照驱动协议给出合适的constraint
  • 通过宏`uvm_field_XX声明必要的数据成员,以便日后使用uvm_object的基本数据方法的自动实现,例如print()
  • UVM要求item的创建和随机化都发生在sequence的body()任务中
  • item对象的声明周期始于sequence中的body方法中的create_item(),直到被driver消化后,item生命周期结束,如果要对item做操作,可以合理利用copy()或clone()等数据方法
    sequence的分类:
  • 扁平化(flat sequence)。只用来组织更小的粒度,即item实例构成的组织
  • 层次类(hierarchical sequence)。由更高层次的sequence来组织底层的sequence,让这些sequence按照顺序方式或者并行方式,挂载到同一个sequencer上
  • 虚拟类(virtual sequence)。是最终控制整个测试场景的方式,鉴于整个环境中往往存在不同种类的sequencer和其对应的sequence,我们需要一个虚拟的sequence来协调顶层的测试场景。 其特点是该序列本身并不会固定挂载于某一种sequencer类型上,而是将其内部不同类型sequence最终挂载到不同的sequencer上面。 这也是virtual sequence不同于hierarchical sequence的最大一点。
    sequence中的步骤:
  • 通过create_item()创建request item对象
  • 调用start_item()方法,将item挂载到sequencer上,准备发送item
  • 在完成发送item之前,对item进行随机化
  • 调用finish_item()方法完成item发送

3.sequencer和driver

driver同sequencer之间的TLM通信采取了get模式,即由driver发起请求,从sequencer一端获得item,再由sequencer将其传递至driver
在这里插入图片描述

1.端口连接和方法:

//driver的TLM端口
uvm_seq_item_pull_port #(REQ,RSQ) 
//sequence的端口
uvm_seq_item_pull_imp #(REQ,RSP,this_type) 
//driver和sequence的端口连接
seq_item_port.connect(sequencer::seq_item_export)
task get_next_item(output REQ req_arg)
采取blocking方式等待从sequence中获取一个item;
function void item_done(input RSP rep_arg = null)
通知sequence当前的item已经消化完毕
function void put_response(input RSP rep_arg)
采用nonblocking方式发送response,成功返回

2.事务传输

sequence_item中:

  • 创建item—create_item(bus_trans::get_type(),m_sequence,“rsp”)
  • 发送item—start_item()等待获取sequencer的授权许可,立即返回结果
  • 在start_item()和finish_item()之间,对item做随机化
  • 完成发送item—finish_item(),阻塞,等待driver的item_done()返回
  • 如果driver返回rsp,可调用get_response对rsp处理,注意句柄转换
    driver中:
  • 通过TLM端口seq_item_port.get_next_item(REQ),从sequencer获取item
  • clone() 获取的REQ,生成response item
  • 通过seq_item_port.item_done(RSP),告诉sequence item已经”消化“完毕
    高层环境中:
  • connect_phase中对TLM端口做连接,driver.seq_item_port.connect(sequencer.seq_item_export)完成driver和sequencer的连接
    在顶层test中:
  • 利用uvm_sequnce类的方法,uvm_sequnce::start(“sequencer的句柄”)实现sequence挂载到sequencer上

4.sequencer 和 sequence

4.1 常用的方法和宏

针对将sequence挂载到sequencer上的应用:

uvm_sequence::start(uvm_sequencer_base sequencer, uvm_sequencer_base parent_sequence = null, int this_priority = -1, bit call_pre_post = 1)

第一个参数:sequencer的句柄
第二个参数:上层sequence
第三个参数:优先级
第四个参数:建议使用默认值指定pre_body()和post_body()执行次序
针对将item挂载到sequencer上的应用

uvm_sequence::start_item(uvm_sequence_item item, int set_priority = -1, uvm_sequencer_base aequencer = null);

第一个参数:item对象
第二个参数:优先级
第三个参数:指定item和其parent sequence挂载到sequencer是否是一个,默认相同

uvm_sequence::finish_item(uvm_sequence_item, int set_priority = -1);

第一个参数:item对象
第二个参数:优先级
通过uvm_sequence::start()来挂载root sequence,而在内部的child sequence则可以通过宏`uvm_do来实现
对于一个item完整传送,sequence要在sequencer一侧获得通过权限
拆解步骤:

  • 创建item
  • 通过start_item()方法等待获取sequencer的授权许可
  • 得到授权后,执行parent sequence的方法pre_do()
  • 对item进行随机化
  • 通过finish_item()方法对item进行随机化处理后,执行parent sequence 的mid_do()方法,以及调用uvm_sequencer::send_request()和uvm_sequencer::wait_for_item_done()来将item发送至driver在完成与driver之间的握手
  • 最后执行parent sequence的post_do()

4.2 sequencer 仲裁特性

设置仲裁模式:

uvm_sequencer::set_arbitration(UVM_SEQ_ARB_TYPE val)
  • UVM_SEQ_ARB_FIFO: 默认模式。来自sequences的发送请求,按照FIFO先进先出的方式被依次授权和优先级没有关系
  • UVM_SEQ_ARB_WEIGHTED: 不同sequence的发送请求,将按照它们的优先级权重随机授权
  • UVM_SEQ_ARB_RANDOM: 不同的请求会被随机授权,而无视它们的抵达顺序和优先级
  • UVM_SEQ_ARB_STRICT_FIFO: 不同的请求会按照它们的优先级以及抵达顺序来依次授权,因此与优先级和抵达时间都有关
  • UVM_SEQ_ARB_STRICT_RANDOM: 不同的请求,会按照它们的最高优先级随机授权,与抵达时间无关
  • UVM_SEQ_ARB_USER: 用户可以自定义仲裁方法user_priority_arbitration()来裁定哪个sequence的请求被优先授权

锁定机制:lock()和grab()区别

  • lock():当sequencer按照仲裁机制授权给该sequence,一旦该sequence拿到授权,就不会将授权返回。只有当sequence执行**unlock()**时,才会释放这一锁定的权限
  • grab():下一次授权周期就可以无条件地获取授权,也就是说,当已经有他sequence获得授权时,grab()就无法获得授权
    注意:
    如果sequence使用了lock()或者grab()方法,必须在sequence结束前调用unlock()或者ungrab()方法来释放权限,否则sequencer会进入死锁状态而无法继续为其余sequence授权。

5.sequence的层次化

5.1 hierarchical sequence

hierarchical sequence本身直接挂载到sequencer上,与virtual sequence 相比,它们两者之间的共同点就是对于各个sequence的协调,不同点在于,hierarchical sequence 面对的对象是同一个sequencer,即hierarchical sequence本身也会挂载到sequencer上面,而对于virtual sequence而言,它内部不同sequence可以允许面向不同的sequencer种类。
在这里插入图片描述

5.2 virtual sequence

解决多个sequence挂载到多个sequencer上的问题
在这里插入图片描述

如果将各个模块环境的element sequence 和hierarchical sequence都作为可以复用的sequence资源,那么就需要一个可以容纳各个sequence的容器来承载它们,同时也需要一个合适的routing sequence 来组织不同结构中sequencer,这样的sequence和sequencer分别称之为virtual sequence和virtual sequencer.
与上述sequence的不同点:

  • virtual sequence 可以承载不同目标表sequencer的sequence群落,而组织协调这些sequence的方式则类似于高层次的hierarchical sequence。virtual sequence一般只会挂载到virtual sequencer上面。
  • virtual sequencer 是一个链接所有底层sequence句柄的地方,它是一个中心化路由器
  • virtual sequencer本身不传送item数据,不需要与driver进行连接。UVM需要在顶层的connect阶段,做好virtual sequence中各个sequencer句柄与底层sequencer实体对象对接,避免句柄悬空。

特点:

  • virtual sequence中有各个子模块的sequence
  • virtual sequence 使用宏`uvm_declare_p_sequencer定义了一个virtual sequencer类型的变量p_sequencer,通过p_sequencer可以索引到virtua sequencer中的声明的各个sequencer句柄
  • virtual sequencer中有各个子模块环境的sequencer句柄,其本身并不传递item,承担一个路由的作用
  • 顶层环境中例化virtual sequencer,然后将virtual sequencer中各个sequencer句柄同各个子模块中的sequencer实例做连接,避免句柄悬空
  • 顶层test中将virtua sequence挂载在virtual sequencer上

5.3 layering sequence

通过层次化的sequence可以分别构建transaction layer、transport layer和physical layer等从高抽象级到低抽象级的transaction转化。这种层次化的sequence构建方式,称之为layering sequence。
参考:
https://blog.csdn.net/SummerXRT/article/details/117752637

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值