前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【UVM COOKBOOK】Sequences||sequence item与事务方法

【UVM COOKBOOK】Sequences||sequence item与事务方法

作者头像
空白的贝塔
发布2021-10-28 15:52:45
1.5K0
发布2021-10-28 15:52:45
举报
文章被收录于专栏:摸鱼范式摸鱼范式

不想错过我的推送,记得右上角-查看公众号-设为星标,摘下星星送给我

欢迎大家加入2023届数字IC交流群,QQ群号 628200294

“后台回复COOKBOOK,即可获取PDF笔记以及原版COOKBOOK ”

后台回复即可获取

Sequence Items

UVM产生激励是通过sequence sequencer以及driver三者配合实现的。生成激励的flow的框架是围绕sequence构建的,但是生成数据流使用sequence_items作为数据对象。由于 sequence_items 是构建sequence的基础,因此在设计时需要注意一些问题。Sequence_item的内容由driver在pin一级的时序决定的;通过支持随即约束,sequence item能够更加简单地生成新的item;此外,还包括了其他参数如用于分析的回调钩子。

数据属性成员

sequence_item 的内容与driver的需求密切相关。driver根据sequence_items 的内容来确定要执行哪种类型的pin级事务。item的内容一般有以下几种:

  • 控制 - 即什么类型的传输,数据有多大
  • Payload - 即传输的主要数据内容
  • 配置 - 即操作模式、错误行为等
  • 分析 - 即有助于分析的字段,例如时间戳、校验和等

随机化注意事项

Sequence_items 在sequence内随机化然后发送到driver中。因此,激励数据属性声明为 rand,并且默认生成值合法或在将他约束到一个合法范围内。在一个sequence中,sequence_items通常使用内联约束随机化,这些约束和item内部的约束共同作用产生最终结果。

由于 sequence_items 用于请求和响应sequence和driver之间的传输的,因此遵循准则。是请求属性应该是 rand,而响应属性不应该是rand。这样可以优化随机化过程,并确保任何收集的响应信息不会被任何随机化破坏。例如,考虑以下总线协议 sequence_item:

代码语言:javascript
复制
class bus_seq_item extends uvm_sequence_item; 
// Request data properties are rand 
 rand logic[31:0] addr; 
 rand logic[31:0] write_data; 
 rand bit read_not_write; 
 rand int delay; 
// Response data properties are NOT rand 
 bit error; 
 logic[31:0] read_data; 
 `uvm_object_utils(bus_seq_item) 
 function new(string name = "bus_seq_item"); 
  super.new(name); 
 endfunction 
// Delay between bus cycles is in a sensible range 
 constraint at_least_1 { delay inside {[1:20]};} 
// 32 bit aligned transfers 
 constraint align_32 {addr[1:0] == 0;} 
// etc 
endclass: bus_seq_item 

Sequence Item 方法

uvm_sequence_item 通过 uvm_transaction 类从 uvm_object 继承而来。uvm_object 有许多虚方法,用于实现常见的数据对象功能(复制、克隆、比较、打印、事务记录),建议覆盖这些虚拟方法让 sequence_item 更具通用性。sequence_item 通常用于分析流量,推荐添加有助于功能覆盖或分析的实用函数。

事务方法

简介

当使用从 uvm_objects 派生的数据对象类时,包括从 uvm_transactions、uvm_sequence_items 和 uvm_sequences 派生的类,有很多便利的方法。进一步的,这些方法中的每一个都会调用一个或多个虚方法,这些虚方法留给用户根据对象内数据成员做具体实现。这些方法及其相应的虚方法总结在下表中。

“表格就不翻译了,其实这里将相当于内置了一些回调钩子,方法的原型可以自行查阅 ”

do_xxx 方法可以使用 `uvm_field_xxx 宏来实现和,但生成的代码效率低下,难以调试并且容易出错。推荐手动实现这些方法,从而改进测试平台性能和内存占用。更加详细的讨论,可以去查阅宏消耗收益分析章节。

“这里是说,使用域自动化机制的宏,会导致平台存在冗余,从而拖慢仿真,所以从仿真性能的角度来说,根据自己需要去实现这些方法,更加高效。不过个人觉得仁者见仁智者见智,具体还得看规模,毕竟手动去实现还得花时间。 ”

考虑以下 sequence_item,其中包含表示大多数常见数据类型的属性:

代码语言:javascript
复制
class bus_item extends uvm_sequence_item; 
// Factory registration 
 `uvm_object_utils(bus_item) 
// Properties - a selection of common types: 
 rand int delay; 
 rand logic[31:0] addr; 
 rand op_code_enum op_code; 
 string slave_name; 
 rand logic[31:0] data[]; 
 bit response; 
 function new(string name = "bus_item"); 
  super.new(name); 
 endfunction 
endclass: bus_item 

这个item中所需要实现的常见方法包括:

do_copy

do_copy 方法的目的是提供一种对数据对象深度拷贝的方法。do_copy 方法可以单独使用,也可以通过 uvm_objects.clone() 方法调用,该方法会创建对象的独立副本。对于 sequence_item 而言,该方法将按如下方式实现:

代码语言:javascript
复制
// do_copy method: 
function void do_copy(uvm_object rhs); 
 bus_item rhs_; 
 if(!$cast(rhs_, rhs)) begin 
  uvm_report_error("do_copy:", "Cast failed"); 
  return; 
  end 
 super.do_copy(rhs);  // Chain the copy with parent classes
 delay = rhs_.delay; 
 addr = rhs_.addr; 
 op_code = rhs_.op_code; 
 slave_name = rhs_.slave_name; 
 data = rhs_.data; 
 response = rhs_.response; 
endfunction: do_copy 
// Example of how do_copy would be used: 
// Directly: 
bus_item A, B; 
A.copy(B);  // A becomes a deep copy of B
// Indirectly: 
$cast(A, B.clone());  // Clone returns an uvm_object which needs
// to be cast to the actual type 

“正如前面所说的,个人认为需要根据实际情况在性能和代码编写时间上做tradeoff。 ”

请注意,rhs 参数是 uvm_object 类型,因为它是一个虚方法,因此在复制其字段之前要将其转换为实际事务类型。这种考虑是出于,对所有的字段进行拷贝并不总是有意义的。

“深拷贝是将数据对象中每个单独属性的值复制到另一个的,而不是仅复制数据句柄的浅拷贝。 ”

do_compare

do_compare 方法由 uvm_object.compare() 方法调用,用于比较两个相同类型的数据对象,以确定它们的内容是否相等。do_compare() 方法应该只对需要比较的字段进行比较。

uvm_comparer 策略对象必须传递给 do_compare() 方法才能与虚方法模板兼容,但在比较函数中没有必要使用它,不使用它可以提高性能。

“不得不吐槽一句,UVM很多特性,cookbook都觉得没必要用,都是为了提高性能 ”

代码语言:javascript
复制
// do_compare implementation: 
function bit do_compare(uvm_object rhs, uvm_comparer comparer); 
 bus_item rhs_; 
// If the cast fails, comparison has also failed 
// A check for null is not needed because that is done in the compare() 
// function which calls do_compare() 
 if(!$cast(rhs_, rhs)) begin 
  return 0; 
 end 
 return((super.do_compare(rhs, comparer) && 
    (delay == rhs_.delay) && 
    (addr == rhs.addr) && 
    (op_code == rhs_.op_code) && 
    (slave_name == rhs_.slave_name) && 
    (data == rhs_.data) && 
    (response == rhs_.response)); 
endfunction: do_compare 
// Useage example - do_compare is not used directly 
bus_item A, B; 
if(!A.compare(B)) begin 
 // Report and handle error 
end 
else begin 
  // Report and handle success 
end 
convert2string

为了把数据对象将调试或状态信息打印到仿真器的控制行或log里,需要有一种方法将对象内容转换为字符串表示 ,这就是 convert2string() 方法的目的。调用该方法将返回一个字符串,会包含每个属性的值,这些属性的格式是为转录显示或写入文件而设置的。而格式由用户决定:

代码语言:javascript
复制
// Implementation example: 
function string convert2string(); 
 string s; 
 s = super.convert2string(); 
// Note the use of \t (tab) and \n (newline) to format the data in 
 columns 
// The enumerated op_code types .name() method returns a string 
 corresponding to its value 
 $sformat(s, "%s\n delay \t%0d\n addr \t%0h\n op_code \t%s\n slave_name \t%s\n", s, delay, addr, op_code.name(), slave_name); 
// For an array we need to iterate through the values: 
 foreach(data[i]) begin 
  $sformat(s, "%s data[%0d] \t%0h\n", s, i, data[i]); 
 end 
 $sformat(s, "%s response \t%0b\n", s, response); 
 return s; 
endfunction: convert2string 
do_print

do_print() 方法由 uvm_object.print() 方法调用。它的目的是使用 uvm_printer 策略类之一打印出 uvm 数据对象的字符串表示。实现该方法的最简单方法是将uvm_printer 的字符串设置为 convert2string() 方法返回的值。

代码语言:javascript
复制
function void do_print(uvm_printer printer); 
 printer.m_string = convert2string(); 
endfunction: do_print 

另一种更高性能的版本可以用 $display() 打印 convert2string() 返回的值,但这就不能用uvm_printer 策略类的各种功能来格式化数据。

代码语言:javascript
复制
function void do_print(uvm_printer printer); 
 $display(convert2string()); 
endfunction: do_print 

要实现完全优化,请避免同时使用 print() 和 sprint() 方法并直接调用 convert2string() 方法。

do_record

do_record() 方法的目的是将数据对象看作波形 GUI 中的事务。与打印数据对象方法一样,其原理是记录的字段能够在事务查看器中查看。do_record() 方法中使用的 `uvm_record_field 宏的底层实现是与仿真器有关,例如对于 Questa 仿真器使用 $add_attribute() 系统调用:

代码语言:javascript
复制
function void do_record(uvm_recorder recorder); 
 super.do_record(recorder);  // To record any inherited data members
 `uvm_record_field("delay", delay) 
 `uvm_record_field("addr", addr) 
 `uvm_record_field("op_code", op_code.name()) 
 `uvm_record_field("slave_name", slave_name) 
 foreach(data[i]) begin 
  `uvm_record_field($sformatf("data[%0d]", i), data[i]) 
 end 
 `uvm_record_field("response", response) 
endfunction: do_record 

要在Quseta仿真器里查看事务,你需要:

  • 向上面的代码一样实现do_record
  • 把recording_detail设置为UVM_FULL,像下面这样
代码语言:javascript
复制
set_config_int("*", "recording_detail", UVM_FULL); 

“这里用的方法就是类型为int的config_db,不知道为什么2019版的cookbook还要用这个,应该在UVM1.2中,废除了set_config_*和set_config_*。可能还是参考的1.1d的版本 ”

实现了do_record并且打开recording_detail后,在sequencer中就能调用事务流句柄,名字是aggregate_items。

“使用do_record方法会把信息记录到数据库文件里,个人没用过这个功能,应该和打印类似,只是更加专注与某时某刻字段的状态,各个仿真器查看的方式应该有所不同,这里不做展开 ”

do_pack 和 do_unpack

这两种方法并不常用,它们的目的是将数据对象转换为bit流(即整数),从而在不同的语言之间传递,例如在 SystemVerilog 和 C/C++ 之间。这两种方法的推荐实现可能会随着即将推出的 Questa 版本而改变,这里没有记录。但是,它们记录在论文中,可以在成本效益分析中找到。

to_struct 和 from_struct

to_struct() 和 from_struct() 方法可以选择性地插入到事务中,从而对象的数据成员转换为适合格式,更加有利于emulator地综合。结构体定义本身包含在一个单独的包中,这个包在emulator和simulator之间共享。这个带有 struct 定义的包被导入到包含agent类的包中。也被导入到使用该结构的任何 BFM 中。

“好像是更加方便帕拉丁、zebu之类的硬件仿真加速器使用 ”

to_struct() 和 from_struct() 函数未在 UVM 基类库中定义。因此他们地命名不遵循其他事务函数的 do_*() 约定。

调用事务对象的 to_struct() 函数并返回对象的结构体。然后可以直接使用该结构体将信息发送到emulator。

代码语言:javascript
复制
function item_s to_struct(); 
 to_struct.addr  = addr; 
 to_struct.data  = data; 
  to_struct.injerr  = injerr; 
endfunction : to_struct 

当从仿真器接收到信息时,它应该被转换回一个UVM测试环境中的对象。from_struct() 方法就是实现这一需求的。

代码语言:javascript
复制
function void from_struct(item_s item); 
 addr  = item.addr; 
 data  = item.data; 
 injerr  = item.injerr; 
endfunction : from_struct 

END

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 摸鱼范式 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Sequence Items
    • 数据属性成员
      • 随机化注意事项
        • Sequence Item 方法
        • 事务方法
          • 简介
            • do_copy
            • do_compare
            • convert2string
            • do_print
            • do_record
            • do_pack 和 do_unpack
            • to_struct 和 from_struct
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档