SystemVerilog随机约束

本文首发于微信公众号“芯片学堂”,作者JKZHAN

上一篇文章《暗藏玄机的SV随机化》介绍了SystemVerilog的各种随机化方法,本文将在其基础上引入SystemVerilog的随机约束方法(constraints)。通过使用随机约束,我们可以将随机限制在一定的空间内,有针对性地提高功能覆盖率。

SV随机约束的应用,就像是我们用陈述性(declarative)的语句告诉仿真器我们要的随机数要满足哪些条件,然后仿真器的约束解算器(constraint solver)就会去找到能够满足我们所有描述语句的解,再从这些解中随机选出来一个值作为随机的结果。

01 约束解算器(Constraint Solver)

约束解算器是SV仿真器重要的一部分,它被专门用来求解约束。这里说的求解,就是指的仿真程序通过某种算法,找到能够满足我们所有约束条件的随机值的过程。如果随机被过约束(over-constraint)了,或者存在随机值的组合情况不能满足约束,则约束解算器就会解算失败。在实际应用中,仿真程序就会报错,然后打印出来告诉我们是哪段约束没有解算成功。

理解约束解算器的重要性,可以想想如果没有约束解算器会怎么样?举一个简单的栗子,现在我们有一个约束条件:变量A的随机值总是小于变量B的随机值。如果没有约束功能,代码可以这么实现:

do begin
    A = $urandom; 
    B = $urandom;
end while (! (A<B));

使用约束语句代码是这样的:

class ictalking;
        rand bit [7:0] A, B;
    constraint c_ab { A > B; }
endclass

可以看得出来,如果没有约束解算器,我们在描述约束的时候就会变得比较绕,通常会花掉很多时间去重复执行相同的一段代码,有时候甚至会跑了半天都撞不出来一个满足约束的随机值,更别说那些复杂的约束了。有了约束解算器,我们就可以在其框架内加入各种约束语句,它总能帮我们快速找到那个解。

02 约束的关系和控制

约束的解算顺序:约束的解算顺序可以使用solve-before来控制。约束解算器会优先求解before之前的约束,因此使用solve-before会影响随机数组合的概率分布情况。

class ictalking;
  rand bit [7:0] A, B;
  constraint c_a { A > B; }
  constraint c_order {solve A before B;}
  // 顺序约束可以写在同一个约束块中,
  // 也可以分开写在不同的约束块中(如本例)
endclass

硬约束和软约束:当我们在不同的层次对随机变量附加约束的时候,软约束可以被后面指定的约束给覆盖。典型的应用场景是在UVM的sequence_item(或者叫transaction)定义时,我们可以通过软约束指定默认的随机约束,这样方便我们后面在继承或者例化的时候可以使用更高优先级的约束对其覆盖。

class ictalking;
    rand int count;
  constraint c_count {
    soft count inside {[666:888]}; // 指定软约束需要使用关键字soft
  }
endclass

ictalking ict = new();
ict.randomize() with { count inside {[123:456]}; }

约束的控制开关:默认情况下,所有的约束一写上默认使能,即约束解算器就会按照这些约束开始算。但SV提供约束条件的控制方法constraint_mode(),可以很方便的控制约束是否启用,以及查询约束的启用状态。

// 继续上面的例子

int con_status;
ictalking ict_obj1 = new();
ictalking ict_obj2 = new();

ict_obj1.c_count.constraint_mode(0); // 不启用ict_obj1中的约束c_count
ict_obj2.c_count.constraint_mode(1); // 启用ict_obj2中的约束c_count
ict_obj1.count.rand_mode(0); // 顺便提一嘴,随机变量类似的可以使用rand_mode开关随机功能

con_status = ict_obj1.c_count.constraint_mode(); // 获得ict_obj1中约束c_count的启用状态 

03 五花八门的约束代码

SV中的约束非常灵活,下面给出一些常用的约束代码,不包含完整的testbench代码,可以作为参考和总结。

  • 范围约束:使用inside指定随机数的范围或者枚举值
rand int temp_var;
constraint c_var_1 {temp_var inside {[2000:2021]}; }      // 限定范围
constraint c_var_2 {temp_var inside {2008, 2016, 2019}; } // 限定枚举值
constraint c_var_3 {! (temp_var inside {[1:2007]});       // 反向限定范围
  • 条件约束:SV中有两种写条件约束的方式:implication(有些地方会翻译成蕴藏或者关联等等)和 if-else,用来指定在某些条件下才做进一步的约束。
rand bit mode;
rand int count;
constraint c_var_1 { mode == 1 -> count < 2021; } // 使用implication操作符->
constraint c_var_2 { if (mode == 1) {count < 2021;} else {count > 6000;} } // 使用if-else
  • 权重约束:约束可以指定随机值的权重,主要有两种方式:dist和randcase。dist一般用在constraint约束块中,但randcase一般用在程序执行块中,比如某个函数、任务或者initial块等。
rand bit mode;
rand int count;
constraint c_var_1 {
    mode == READ  -> count inside {[2008:2016]};
    mode == WRITE -> count inside {[2017:2021]};
  mode dist {READ := 4, WRITE := 6}; // mode随机成READ的概率为40%,WRITE为60%
}

initial begin
  repeat (100) begin
    randcase
        2: $display("In 1st branch."); // 在100次循环中,执行分支1的概率是20%
        7: $display("In 2nd branch."); // 在100次循环中,执行分支2的概率是70%
        1: $display("In 3rd branch."); // 在100次循环中,执行分支3的概率的10%
    endcase
  end
end
  • 唯一约束:唯一约束使用unique关键字来限定变量之间的值是唯一的,即两两之间互不相等。
rand int a, b, c;
rand int array[5];
int q[$] = `{200, 53, 656};

constraint c_unique {
  unique {a, b, c};     // 该约束要求a和b和c两两之间互不相等
  unique {a, b, array}; // 该约束要求a和b和array中的所有值互不相等
  unique {array};       // 该约束要求array数组内的5个值互不相等
  unique {a, q};        // 该约束要求a随机出来的值不等于q中的任一值
}
  • 循环约束:在对队列或者数组进行随机化的时候,可以使用foreach来对其循环施加约束。
rand int q[$];
constraint c_foreach {
  q.size() inside {[3:8]};
  foreach (q[i]) {
    if (i > 0) q[i] > q[i-1]; // 约束q队列的下一个值总比上一个值大
  }
}
  • 缩位约束:缩位约束会相对复杂一些,但是很好理解。
    • 缩位运算:比如对于数组arr[5],arr.sum就是arr[0] + arr[1] + ... + arr[4]。除sum之外,还有product、and、or、xor,分别表示乘积、与、或、异或运算。
    • 这些缩减运算的方法的返回值类型,跟队列或者数组的元素类型一样,因此当类型不匹配的时候,需要做类型转换的操作。
    • 缩减运算的方法可以可选的加with条件,用来筛选队列或者数组中的元素。另外关键字item表示当前的数组元素,item.index表示当前数组元素的索引。
rand bit qbit[$];
rand int qint[$];

constraint c_qbit {
  qbit.size() inside {[4:6]};
  (qbit.sum with (int'(item))) == 3; // 将当前元素item转为int类型,并约束所有元素有且只有3个为1
}

constraint c_qint {
  qint.size() inside {[5:9]};
  (qint.sum with ((item.index < 3) ? item : 0)) == 45; // 约束qint队列的前三个加起来等于45
}
  • 静态约束:静态约束使用的关键字static跟静态变量是一样的。静态约束表示的是所有的对象实例都使用的同一个约束,所以使用constraint_mode()进行开关控制的时候具有全局性。
class ictalking;
  rand int count;
  static constraint c_count {count > 34;}
endclass

module testbench;
  initial begin
        ictalking ict_obj1 = new();
        ictalking ict_obj2 = new();
        ict_obj1.c_count.constraint_mode(0); // 关掉的之后ict_obj2中的c_count也会失效
    ...
  end
endmodule
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容

  • 本文首发于微信公众号“芯片学堂”,作者JKZHAN 我习惯将验证空间理解为:验证中原则上需要覆盖的芯片所有有可能出...
    芯片学堂阅读 5,115评论 0 1
  • 1.数据类型 VerilogHDL中有2种变量类型:wire和reg,这两种变量是4值类型的(即有四种状态)。 S...
    一条摸水鱼阅读 14,462评论 0 3
  • 有些特定场景下,我们可能需要将约束块或者随机变量开启使能或者关闭来构造工程师们想要的激励而不影响其他已经调试过的c...
    小可爸爸阅读 1,296评论 0 2
  • 本文首发于微信公众号“芯片学堂”,作者JKZHAN 回调(callback)是一种在很多编程语言中都会使用的编程技...
    芯片学堂阅读 1,536评论 0 1
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,532评论 28 53