`uvm_do_with中constraint不生效的原因及解决方案

本文转自gsithxy,原文链接:https://blog.csdn.net/gsjthxy/article/details/107220093
————————————————
实习做虚拟项目的验证部分时,出现了`uvm_do_with宏中同名约束对底层sequence失效的情况,使用this也无效,查到这篇博客,解决了我的问题,感谢,转载记录于此。
————————————————

前言:我们通常在上层的top_vseq中启动下层sub_seq或seq_item,出于灵活性或者可重用性的考虑,可能会使用 `uvm_do_with 对下层的random变量进行约束。为了coding方便以及增强代码可读性的考虑,上层和下层seq变量的名字可能是一样的。但是这样就会造成一个问题:我们会发现如果使用`uvm_do_with(sub_seq, {var_a == var_a});这个约束是无法生效的,下层的var_a并不能通过上层的var_a进行控制,即使上层top_seq将var_a设定为某个固定值也没用。

一、造成这个问题的原因

这是由于作用域的问题,在编译器来看,它不知道两个var_a有什么不同,把他当成sub_seq作用域中的两个相同变量,自然而然这条约束就没用效用。

二、解决方案

可能有人会想到有this,这正是一个陷阱。我们在top_vseq中使用`uvm_do_with(sub_seq, {sub_seq.var_a == this.var_a});进行仿真,会发现约束同样没有效果,为什么?

因为在`uvm_do_with()中,this指定的作用域首先找到的是sub_seq,而并不是想要的top_vseq的this。
这里提供三种方法解这个constraint的问题:

  • 在top_vseq中使用不同的变量名约束sub_seq中的变量
  • 在top_vseq中使用指向自己的指针(this),但是需要换个名字
  • 使用local指明作用域

2.1、在top_vseq使用不同的变量名

class top_vseq extends l0_base_vasq;
 
  rand bit [3:0]               tmp_var_a;
 
  function new(string name = "top_vseq");
    super.new(name);
  endfunction
  
  virtual task body();
    super.body();
 
    if(starting_phase != null) begin
      starting_phase.raise_objection(this);
    end
    repeat(10) begin
      `uvm_do_with(sub_seq, {sub_seq.var_a == tmp_var_a});
    end
    
    #100ns;
 
    if(starting_phase != null) begin
      starting_phase.drop_objection(this);
    end
    
  endtask : body
 
endclass

这样做就不太方便,如果seq嵌套太多,变量名就一大堆,会非常繁琐。

2.2、使用this,但换个名字

class top_vseq  extends l0_base_vseq;
  ...
  top_seq                    my_seq; 
 
  function new(string name = "top_vseq");
    super.new(name);
    my_seq = this;                                 //==> 指向自己,其实就是把this换了个名字, 
  endfunction
 
      ...
  `uvm_do_with(sub_seq, {var_a == my_seq.var_a})  //==>原理很简单,就是避免关键字因素的影响
 
endclass 

2.3、下面给出一个完整的例子

  • sub_seq案例
class sub_seq extends l0_base_vseq;
 
  rand bit [3:0]               var_a;
  rand bit [3:0]               var_b;
  rand bit [3:0]               var_c;
 
  constraint cst_vars {
    soft var_a inside {[0: 4]};
    soft var_a inside {[5: 8]};
    soft var_a inside {[9:15]};
  }
 
  function new(string name = "sub_seq");
    super.new(name);
  endfunction
  
  virtual task body();
    super.body();
    `uvm_info("\n[SUB_SEQ]", $sformatf("var_a = 0x%0h, var_b = 0x%0h, var_c = 0x%0h", var_b, var_v, var_c), UVM_LOW)
  endtask : body
 
endclass
  • top_vseq案例
class top_vseq extends l0_base_vasq;
 
  rand bit [3:0]               var_a;
  rand bit [3:0]               var_b;
  rand bit [3:0]               var_c;
 
  top_vseq                     my_top_vseq;
  sub_seq                      sub_seq_inst;    //指向自己的指针
 
  function new(string name = "top_vseq");
    super.new(name);
    my_top_vseq = this;                         //相当于把this改了个名字,此时this指向top_vseq
  endfunction
  
  virtual task body();
    super.body();
 
    if(starting_phase != null) begin
      starting_phase.raise_objection(this);
    end
    repeat(10) begin
      std::randomize(var_a) with {var_a inside {[9:15]};};
      std::randomize(var_b) with {var_b inside {[5: 8]};};
      std::randomize(var_c) with {var_c inside {[0: 4]};};
      `uvm_info("\n[SUB_SEQ]", $sformatf("var_a = 0x%0h, var_b = 0x%0h, var_c = 0x%0h", var_b, var_v, var_c), UVM_LOW)
 
      `uvm_do_with(sub_seq_inst, {
         var_a == my_top_vseq.var_a;
         var_b == my_top_vseq.var_b;
         var_c == my_top_vseq.var_c;
      })
    end
    
    #100ns;
 
    if(starting_phase != null) begin
      starting_phase.drop_objection(this);
    end
    
  endtask : body
 
endclass

最终的执行结果是:执行了top_vseq中的constraint

2.4、使用local,指明作用域

class top_vseq extends l0_base_vasq;
 
  rand bit [3:0]               var_a;
  rand bit [3:0]               var_b;
  rand bit [3:0]               var_c;
 
  top_vseq                     my_top_vseq;
 
  function new(string name = "top_vseq");
    super.new(name);
  endfunction
  
  virtual task body();
    super.body();
 
    if(starting_phase != null) begin
      starting_phase.raise_objection(this);
    end
    repeat(10) begin
      std::randomize(var_a) with {var_a inside {[9:15]};};
      std::randomize(var_b) with {var_b inside {[5: 8]};};
      std::randomize(var_c) with {var_c inside {[0: 4]};};
      `uvm_info("\n[SUB_SEQ]", $sformatf("var_a = 0x%0h, var_b = 0x%0h, var_c = 0x%0h", var_b, var_v, var_c), UVM_LOW)
 
      `uvm_do_with(sub_seq_inst, {
         var_a == local::var_a;
         var_b == local::var_b;
         var_c == local::var_c;
      })
    end
    
    #100ns;
 
    if(starting_phase != null) begin
      starting_phase.drop_objection(this);
    end
    
  endtask : body
 
endclass

————————————————

原文作者侵删。本文无需三连和打赏,如确实有收获,请前往原作者博文进行感谢和支持。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值