赞
踩
目录
3.回调函数 pre_randomize和post_randomize
4.1使用constraint_mode(0)关闭约束后用randomize_with{}重新定义约束
4.2子类extends父类,然后定义同名约束覆盖父类的约束
如果在一个类中定义了多个约束块儿,以便为了后续根据实际需要打开所需的约束块儿时,该如何操作?(就像一个筋膜枪,你要根据实际需要调节频率(约束频率范围))
具体讲解在代码注释中讲解
- class Packet;
- rand int length;
-
- //以下2个约束块儿互相排斥,切不可将2个约束块儿同时打开,否则会随机出错误结果
- constraint c_short//定义约束1<=length<=32
- {
- length inside {[1:32]};
- }
-
- constraint c_long //定义约束1000<=length<=1023
- {
- length inside {[1000:1023]};
- }
- endclass
-
- program test;
- Packet p;
-
- initial begin
- p = new();
- p.c_short.constraint_mode(0); //关闭c_short约束块儿
- assert(p.randomize());//此时length只在1000-1023中随机
- $display("P:length is %d",p.length);//1000-1023
-
- p.constraint_mode(0); //关闭所有约束条件
- p.c_short.constraint_mode(1); //打开c_short约束
- assert(p.randomize());//此时length只在1-32中随机
- $display("P:length is %d",p.length);//1-32
- end
- endprogram
如果我们在一个类中定义了n个随机变量,在后续调用该类的时候,我们想根据实际需要控制类中的某个变量是否要随机化,该如何操作?
关键词:类实例化名.变量名.rand_mode(0关闭/1开启)
- class Packet;
- rand bit [7:0] length, payload[];
-
- constraint c_valid
- {
- length > 0;
- payload.size() == length;
- }
- endclass
-
- program test;
- Packet p;
-
- initial begin
- p = new();
-
- p.length.rand_mode(0); //关闭length的随机功能
- p.length = 42; //未现在不随机的length赋值
- $display("P:length is %d",p.length);//42
-
- assert (p.randomize());
- p.length.rand_mode(1); //打开length的随机功能
- $display("P:length is %d",p.length);//0-255
- end
- endprogram
如果我们定义了一个类,在后续调用时想在原来约束的基础上进一步加约束该如何操作?
关键词:类实例化名.randomize()with{所需约束}
- class Transaction;
- rand bit [31:0] addr, data;
- constraint c1
- {
- addr inside{[0:100],[1000:2000]};
- }
- endclass
-
-
- program test;
- Transaction t;
- initial begin
- t = new();
-
- assert(t.randomize() with {addr >= 50; addr <= 1500; data < 10;});//在c1的基础上进一步约束范围
- $display("t::addr=%d,data=%d",t.addr,t.data);//addr is 50-100 or 1500-2000,data is 0-10
-
- assert(t.randomize() with {addr == 2000; data > 10;});//addr赋值2000,data大于10
- $display("t::addr=%d,data=%d",t.addr,t.data);//addr is 2000,data 大于10
- end
- endprogram
若外部所加约束与内部约束冲突,则看内部约束是否加了soft关键字,若加了则以外部约束为准,若没加则报错
该方法和2.1类似,都是对单个变量是否随机化进行操作,所不同的是操作方式
关键词:类句柄.randomize(变量名)。表示只随机该变量,其它变量不随机
- class Rising;
- byte low;
- rand byte med, hi;
- constraint c_up
- {
- low < med;
- med < hi;
- }
- endclass
-
- program test;
- Rising r;
- initial begin
- r = new();
- r.randomize(); //对所有随机变量在约束上进行随机
- r.randomize(med); //只随机med,hi保持上一个值
- r.randomize(low); //只随机low,但low不是随机变量,med和hi保持上一个值
- end
- endprogram
回调函数是指在父类中定义一个空方法,然后在不同子类中实现这些空方法
他们都是function, 不消耗仿真时间;
只要调用了randomize函数,在执行randomize函数之前先执行pre_randomize函数,再执行randomize函数,最后执行post_randomize函数。他们通常用来设置一些非随机的变量或者计算随机数据中的错误,如果如randomize调用失败,那么post_randomize将不会被执行,但是pre_randomize不管 randomize是否成功都会执行。
- class wr_tran;
- int constraint_en;
- int broadcast;
- rand int wr_addr;
- rand int wr_data;
- rand bit valid;
-
- constraint generic_c
- {
- valid ==1;
- wr_addr<100;
- }
-
- function void pre_randomize();//定义预处理函数
- $display("call the pre_randomize !");
- if(!constraint_en)
- generic_c.constraint_mode(0);
- endfunction
-
- function void post_randomize();//定义后处理函数
- $display("call post_randomize !");
- if(wr_addr ==1)
- broadcast =1;
- else
- broadcast =0;
- endfunction
- endclass
-
- module m1;
- wr_tran tr;
-
- initial begin
- tr =new();
-
- tr.constraint_en=0;//为pre_randomize提供条件
-
- tr.randomize() with {tr.wr_addr==200;tr.wr_data==3;tr.valid==0;};
- $display("tr.wr_addr=%d,tr.wr_data=%d,tr.valid=%d,tr.broadcast=%d",tr.wr_addr, tr.wr_addr,tr.valid,tr.broadcast);
- end
- endmodule
执行结果如图所示:
可见先打印了pre中的字符串,然后执行randomize为几个变量定值,然后执行post函数打印字符串,由于wr_addr 赋值为3,所以broadcas为0。
具体解释见下面代码注释
- class constrainend;
- rand bit x;
- rand bit [1:0] y;
-
- constraint c_xy //对x,y定义约束
- {
- (x==0)-> y==0;
- }
- endclass
-
- program test;
- constrainend p;
-
- initial begin
- p=new();
-
- p.c_xy.constraint_mode(0); 将实例p中对x,y的约束关闭
-
- assert(p.randomize() with {x==0; y==0;});//随机化x,y,并添加一个新约束
-
- $display("x = %d",p.x);//不会再被原类中的约束限制,而是被randomzie_with约束限制
- $display("y = %d",p.y);
- end
- endprogram
具体解释见下面代码注释
- class constrainend;
- rand bit x;
- rand bit [1:0] y;
-
- constraint c_xy
- {
- (x==0)-> y==0;
- }
- endclass
-
- class overwrite extends constrainend;//子类继承父类,会继承属性和方法,所以父类的约束也继承了
- constraint c_xy//子类如果想定义一个新约束覆盖父类,则需要定义一个同名约束
- {
- x==0;
- y==0;
- }
- endclass
-
- program test;
- overwrite p;
-
- initial begin
- p=new();
-
- assert(p.randomize());//在子类约束的基础上随机化
-
- $display("x = %d",p.x);
- $display("y = %d",p.y);
- end
- endprogram
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。