电子说
SystemC是基于C++的系统级设计语言,兼具描述硬件电路模型和面向对象的抽象能力。在芯片设计开发中,常用于芯片架构的建模、性能仿真和评估、软硬件联合仿真等场景。尤其是在融合TLM2.0事务级建模方法以后,SystemC的模型也出现事务级、cycle级等不同抽象等级的划分,用于不同的场景需求。
随着基于systemC建模的广泛适用,对SC模型的验证也是应运而生;正如Systemverilog用于对verilog的验证。SystemC Verification (SCV)就是SC中的一个验证库,其包含了:
transaction-based verification
data introspection
constrainted and weighted randomization
这篇文章准备介绍SCV中的约束随机:constrainted randomization。在systemverilog中随机约束是CDV的一大利器,SV中具有丰富的随机表达语法,比如inside、dist、solve before、->、unique等。C/C++中却不具备如此丰富的约束能力,而SCV作为SC的验证库,引入了约束随机描述。
Basic Randomization
无论是sc内建的基本数据类型,如sc_int/sc_uint等;还是自定义的struct数据,都可以使用scv_smart_ptr修饰,进行基本的随机化操作。常见的用法如下:
//基本数据类型随机 scv_smart_ptr< sc_uint<8> > data; data->next(); //自定义数据结构随机 struct packet_t { int data; int array[10]; }; scv_smart_ptr< packet_t > p; // generate a random value and assign it to the data field p->data.next(); //generate a random value and assign it to the array element with index 3 p->array[3].next(); // generate random values for all fields and all array elements p->next(); // generate random values for all fields and all array elements, //except for the data field p->data.disable_randomization(); p->next();
scv_smart_ptr会例化一个内部的随机对象,使用next方法产生随机值。
对于自定义符合数据结构,也可以只针对其中部分参数进行随机;不需要随机的参数,使用disable_randomization关闭随机。
Constrained Randomization
上述的简单约束,可以使用scv_smart_ptr实现。对于其他的复杂约束,则需要借助scv_constraint_base实现。(scv_smart_ptr可以认为是systemverilog中的random函数,而constraint或者solve-before,则必须要在class中实现)。
用法如下:
class write_constraint : virtual public scv_constraint_base { public: scv_smart_ptr< rw_task_if::write_t > write; SCV_CONSTRAINT_CTOR(write_constraint) { SCV_CONSTRAINT( write->addr() < 0x00FF ); SCV_CONSTRAINT( write->addr() != write->data() ); } }; //上面SCV代码的systemverilog等效格式: class write_constraint extend scv_constraint_base ; rand rw_task_if::write_t write; constraint write_constraint { write.addr < 0x00FF; write.addr != write.data; } endclass
在scv_constraint_base扩展出的子类中,需要随机的参数仍需要使用scv_smart_ptr修饰。使用SCV_CONSTRAINT_CTOR声明一段约束,SCV_CONSTRAINT用于添加一条约束表达式。
约束表达式可以支持:算术表达式(+,-,*,/),关系表达式(==, !=, >, >=, <, <=),逻辑表达式( !, &&, ||)。约束表达式有三种:
1. SCV_CONSTRAINT代表是一种hard constraint;
2. SCV_SOFT_CONSTRAINT表达一种soft constraint;
3. SCV_BASE_CONSTRAINT代表基类中的约束。
此处的hard和soft constraint含义和systemverilog中soft修饰随机的含义基本一致。
上述的随机类定义好后,便可以进行实例化和随机。前面提到的disable_randomization仍然可以使用,并且统一使用next方法进行随机生成。
write_constraint c("write constraint"); for (int i=0; i<2; ++i) { c.next(); cout << *c.write << endl; } write_constraint c("write constraint"); c.write->addr->disable_randomization(); for (int i=0; i<2; ++i) { c.write->addr = i; c.next(); cout << *c.write << endl; }
Weight and Biased Randomization
在systemverilog随机约束中,经常会使用到inside、dist,用来表达带有权重的随机。同样,SCV支持指定范围随机和带权重的随机,通过scv_bag实现。scv_bag可以用来收集需要范围随机信息以及权重信息。
单值权重设置使用scv_bag 表达,实例:
scv_bagbag; bag.push(1,60); bag.push(2,40); scv_smart_ptr data; data->set_mode(bag); data->next(); //systemverilog的等效表达 rand int data; data dist {1:/60,2:/40};
在scv_bag收集好权重信息后,通过set_mode函数传递给参数的随机对象即可。范围权重设置使用scv_bag< pair< int,int> >表达,实例:
scv_smart_ptrdata; scv_bag< pair< int,int> > distribution; distribution.push( pair (0,1), 40); distribution.push( pair (2,10), 60); data->set_mode(distribution); data->next(); //systemverilog的等效表达 rand int data; data dist {[0:1]:/60,[2:10]:/40};
从上面可以看出如果需要添加范围约束和权重约束,就必须要定义scv_bag,添加约束范围和权重,并通过set_mode设置,稍显复杂。因此SCV中引入keep_only和keep_out方法,用于添加随机约束范围,类似systemverilog中的inside和~inside。
scv_smart_ptri; i->keep_only(0,4); i->keep_out(2); i->next(); // generate a value among { 0, 1, 3, 4 } //如果使用scv_bag方式,方法如下: scv_smart_ptr i; scv_bag bag; bag.add(0); bag.add(1); bag.add(3);bag.add(4); i->next();
keep_only和keep_out除了可以接受固定数值外,还可以接收list类型的变量。
scv_smart_ptri; list i_range; i_range.push_back(0); i_range.push_back(4); i->keep_only(i_range); i->keep_out(2); i->next(); // generate a value among { 0, 3, 4 }
总结来看,设置随机约束有如下方式:
set_mode方法
keep_only、keep_out方法
SCV_CONSTRAINT约束表达式
set_mode和keep_only/out的随机约束设置会进行覆盖。使用reset_distribution方法可以取消set_mode和keep_only/out方法设置的随机约束。实例如下:
scv_smart_ptri; i->keep_only(0,4); i->keep_out(2); i->next(); // generate a value among { 0, 1, 3, 4 } scv_bag b; b.add(2); b.add(7); i->set_mode(b); i->next(); // generate a value among {2,7} i->reset_distribution(); i->next(); // generate a value between INT_MIN and INT_MAX.
写在最后
SCV 约束除了作为SC模型的验证随机约束外,一方面可以把SC模型阶段的验证激励复用到中后期的RTL验证;
另一方面还可以在CPU核相关的C语言case中使用,由于SCV是基于C/C++语言,因此可以比较容易地和C based case结合,具体融合方式需要一些转接件,这个后续有机会再做介绍。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !