首页 > 其他分享 >初识Layering Sequence

初识Layering Sequence

时间:2023-03-05 13:56:53浏览次数:46  
标签:Layering layer seq Sequence sqr phy 初识 uvm sequencer

一、为什么需要Layering Sequence

随着集成电路技术的发展,芯片的复杂度日益提升。对验证而言,为了更好地应对这种复杂性,一方面是提高各个级别的可移植性和复用性,另一方面是提高抽象级别,减小复杂度。
Layering Sequence这正是从第二个方面出发衍生的,它能够将高抽象级的uvm_sequence_item和低抽象级的uvm_sequence_item相互转换。

二、Layering Sequence机制

下面以《芯片验证漫游指南》13.5.3节为例,简单分析Layering Sequence的工作机制

1、高抽象级的layer_trans和低抽象级的bus_trans

首先定义一个低抽象级的bus_trans,并且将其打包成为packet_seq

点击查看代码
//低抽象级的bus_trans
class bus_trans extends uvm_sequence_item;
    rand phy_cmd_t cmd;
    rand int addr;
    rand int data;
    constraint cstr{
      soft addr == 'h0;
      soft data == 'h0;
    }
    ...
endclass

//打包后的packet_seq
class packet_seq extends uvm_sequence;
    rand int len;
    rand int addr;
    rand int data[];
    rand phy_cmd_t cmd;
    constraint cstr{
      soft len inside {[30:50]};
      soft addr[31:16] == 'hFF00;
      data.size() == len;
    }
    ...
    task body();
      bus_trans req;
      foreach(data[i])
        `uvm_do_with(req, {cmd == local::cmd; 
                           addr == local::addr;
                           data == local::data[i];})
    endtask
  endclass

其对应的sequencer是:

点击查看代码
 class phy_master_sequencer extends uvm_sequencer;
    layering_sequencer up_sqr;
	...
endclass

接下来定义一个高抽象级layer_trasn

点击查看代码 ```verilog class layer_trans extends uvm_sequence_item; rand layer_cmd_t layer_cmd; rand int pkt_len; rand int pkt_idle; constraint cstr { soft pkt_len inside {[10: 20]}; layer_cmd == FREQ_LOW_TRANS -> pkt_idle inside {[300:400]}; layer_cmd == FREQ_MED_TRANS -> pkt_idle inside {[100:200]}; layer_cmd == FREQ_HIGH_TRANS -> pkt_idle inside {[20:40]}; } ... endclass ```

其对应的sequencer是:

点击查看代码 ```verilog class layering_sequencer extends uvm_sequencer; ... endclass ```

可以看到高抽象级的layer_trans和低抽象级的bus_trans差别很大,也没有任何层次上的关系,因此需要有中间的转化层将两者进行转化后才能够正常发送给DUT。

2、转化层的sequece

用adapter_seq作为转化层

点击查看代码
class adapter_seq extends uvm_sequence;
    `uvm_object_utils(adapter_seq)
    `uvm_declare_p_sequencer(phy_master_sequencer)//句1
    function new(string name = "adapter_seq");
      super.new(name);
    endfunction
    task body();
      layer_trans trans;
      packet_seq pkt;
      forever begin
          p_sequencer.up_sqr.get_next_item(req);//句2-1
        void'($cast(trans, req));
        repeat(trans.pkt_len) begin
            `uvm_do(pkt)//句3
          delay(trans.pkt_idle);
        end
          p_sequencer.up_sqr.item_done();//句2-2
      end
    endtask
    virtual task delay(int delay);
    endtask
  endclass

3、layering sequence的工作机制

下面结合结构图分析一下layering sequence的工作机制

  • 句1:通过uvm_declare_p_sequencer宏指定adapter_seq的item由phy_master_sequencer来发送,也构建了adapter_seq访问phy_master_sequencer成员变量和成员方法的桥梁(详见初识m_sequencer、p_sequencer和uvm_declare_p_sequencer宏

  • 句2-1:如图绿色曲线所示,通过p_sequencer访问phy_master_sequencer中的up_sqr,而up_sqr在test中通过句4将up_sqr指向layer_sqr(test代码第13行)。此时adapter_seq能够调用layer_sqr的get_next_item任务取得一个高抽象级的layer_trans。

  • 句3:按照已取得的layer_trans中的属性(pkt_len和pkt_idle)约束低抽象级的packet_seq类型的pkt的属性,并交给phy_master_sequencer通过driver发送给DUT。

  • 句2-2:依旧通过绿色曲线所示通路,使用item_done通知layer_sqr。

4、在test中的连接关系

test代码:

点击查看代码
class test extends uvm_test;
    layering_sequencer layer_sqr;
    phy_master_agent phy_agt;
    `uvm_component_utils(test1)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      layer_sqr = layering_sequencer::type_id::create("layer_sqr", this);
      phy_agt = phy_master_agent::type_id::create("phy_agt", this);
    endfunction
    function void connect_phase(uvm_phase phase);
      phy_agt.sqr.up_sqr = layer_sqr;//句4
    endfunction
    task run_phase(uvm_phase phase);
      top_seq seq;
      adapter_seq adapter;
      phase.raise_objection(phase);
      seq = new();
      adapter = new();
      fork
          adapter.start(phy_agt.sqr);//句5
      join_none
        seq.start(layer_sqr);//句6
      phase.drop_objection(phase);
    endtask
  endclass
  • 句4:将phy_master_sequencer中的up_sqr指向layer_sqr,构建与layer_sqr的通路,使得adapter能够取得layer_trans。
  • 句5:将adapter_seq挂载到phy_master_sequencer。
  • 句6:将top_seq挂载到layer_sqr。

一些其他问题:

  • 为什么使用fork-join_none:在adapter_seq的body()中使用的forever语句,使得adapter_seq永不停歇的取得高抽象级item,转化成低抽象级的item去执行。因此使用fork-join_none使adapter_seq不阻挡其他功能正常运行。
  • 为什么采用句4和get_next_item()而不是TLM的方式:这是为了最大程度的提高复用性和减小复杂度。

参考资料

  1. 《芯片验证漫游指南——从系统理论到UVM的验证全视界》刘斌著
  2. Universal Verification Methodology (UVM) 1.2 User’s Guide

完整代码如下:

点击查看代码
module layer_seq;
  import uvm_pkg::*;
  `include "uvm_macros.svh"

  typedef class phy_master_sequencer;
  typedef enum {CLKON, CLKOFF, RESET, WRREG, RDREG} phy_cmd_t;
  typedef enum {FREQ_LOW_TRANS, FREQ_MED_TRANS, FREQ_HIGH_TRANS} layer_cmd_t;

  class bus_trans extends uvm_sequence_item;
    rand phy_cmd_t cmd;
    rand int addr;
    rand int data;
    constraint cstr{
      soft addr == 'h0;
      soft data == 'h0;
    }
    `uvm_object_utils_begin(bus_trans)
      `uvm_field_enum(phy_cmd_t, cmd, UVM_ALL_ON)
      `uvm_field_int(addr, UVM_ALL_ON)
      `uvm_field_int(data, UVM_ALL_ON)
    `uvm_object_utils_end
    function new(string name = "bus_trans");
      super.new(name);
    endfunction
  endclass

  class packet_seq extends uvm_sequence;
    rand int len;
    rand int addr;
    rand int data[];
    rand phy_cmd_t cmd;
    constraint cstr{
      soft len inside {[30:50]};
      soft addr[31:16] == 'hFF00;
      data.size() == len;
    }
    `uvm_object_utils(packet_seq)
    function new(string name = "reg_test_seq");
      super.new(name);
    endfunction
    task body();
      bus_trans req;
      foreach(data[i])
        `uvm_do_with(req, {cmd == local::cmd; 
                           addr == local::addr;
                           data == local::data[i];})
    endtask
  endclass

  class layer_trans extends uvm_sequence_item;
    rand layer_cmd_t layer_cmd;
    rand int pkt_len;
    rand int pkt_idle;
    constraint cstr {
      soft pkt_len inside {[10: 20]};
      layer_cmd == FREQ_LOW_TRANS -> pkt_idle inside {[300:400]};
      layer_cmd == FREQ_MED_TRANS -> pkt_idle inside {[100:200]};
      layer_cmd == FREQ_HIGH_TRANS -> pkt_idle inside {[20:40]};
    }
    `uvm_object_utils(layer_trans)
    function new(string name = "layer_trans");
      super.new(name);
    endfunction
  endclass

  class adapter_seq extends uvm_sequence;
    `uvm_object_utils(adapter_seq)
    `uvm_declare_p_sequencer(phy_master_sequencer)
    function new(string name = "adapter_seq");
      super.new(name);
    endfunction
    task body();
      layer_trans trans;
      packet_seq pkt;
      forever begin
        p_sequencer.up_sqr.get_next_item(req);
        void'($cast(trans, req));
        repeat(trans.pkt_len) begin
          `uvm_do(pkt)
          delay(trans.pkt_idle);
        end
        p_sequencer.up_sqr.item_done();
      end
    endtask
    virtual task delay(int delay);
    endtask
  endclass

  class top_seq extends uvm_sequence;
    `uvm_object_utils(top_seq)
    function new(string name = "top_seq");
      super.new(name);
    endfunction
    task body();
      layer_trans trans;
      `uvm_do_with(trans, {layer_cmd == FREQ_LOW_TRANS;})
      `uvm_do_with(trans, {layer_cmd == FREQ_HIGH_TRANS;})
    endtask
  endclass

  class layering_sequencer extends uvm_sequencer;
    `uvm_component_utils(layering_sequencer)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
  endclass

  class phy_master_sequencer extends uvm_sequencer;
    layering_sequencer up_sqr;
    `uvm_component_utils(phy_master_sequencer)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
  endclass

  class phy_master_driver extends uvm_driver;
    `uvm_component_utils(phy_master_driver)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    task run_phase(uvm_phase phase);
      REQ tmp;
      bus_trans req;
      forever begin
        seq_item_port.get_next_item(tmp);
        void'($cast(req, tmp));
        `uvm_info("DRV", $sformatf("got a item \n %s", req.sprint()), UVM_LOW)
        seq_item_port.item_done();
      end
    endtask
  endclass

  class phy_master_agent extends uvm_agent;
    phy_master_sequencer sqr;
    phy_master_driver drv;
    `uvm_component_utils(phy_master_agent)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      sqr = phy_master_sequencer::type_id::create("sqr", this);
      drv = phy_master_driver::type_id::create("drv", this);
    endfunction
    function void connect_phase(uvm_phase phase);
      drv.seq_item_port.connect(sqr.seq_item_export);
    endfunction
  endclass

  class test extends uvm_test;
    layering_sequencer layer_sqr;
    phy_master_agent phy_agt;
    `uvm_component_utils(test1)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      layer_sqr = layering_sequencer::type_id::create("layer_sqr", this);
      phy_agt = phy_master_agent::type_id::create("phy_agt", this);
    endfunction
    function void connect_phase(uvm_phase phase);
      phy_agt.sqr.up_sqr = layer_sqr;
    endfunction
    task run_phase(uvm_phase phase);
      top_seq seq;
      adapter_seq adapter;
      phase.raise_objection(phase);
      seq = new();
      adapter = new();
      fork
        adapter.start(phy_agt.sqr);
      join_none
      seq.start(layer_sqr);
      phase.drop_objection(phase);
    endtask
  endclass

  initial begin
    run_test("test");
  end
endmodule

标签:Layering,layer,seq,Sequence,sqr,phy,初识,uvm,sequencer
From: https://www.cnblogs.com/ChengMobai/p/LayeringSequence.html

相关文章

  • 题解 CF1406D【Three Sequences】
    看错题了,我很生气。problemYouaregivenasequenceof$n$integers$a_1,a_2,\ldots,a_n$.Youhavetoconstructtwosequencesofintegers$b$and$c......
  • DiffuSeq: Sequence to Sequence Text Generation with Diffusion Models
    目录概符号说明流程代码GongS.,LiM.,FengJ.,WuZ.andKongL.DiffuSeq:Sequencetosequencetextgenerationwithdiffusionmodels.InInternationalConfe......
  • hdu 5288 OO’s Sequence
    题目链接:​​http://acm.hdu.edu.cn/showproblem.php?pid=5288​​解法:定义两个数组L[i],R[i],表示第i数左侧和右侧最接近它且值是a[i]因子的数字的位置,那么第i个数能贡献......
  • 跟着鹏哥学C—初识C语言2(编程题)
    编程题:求两个数的较大值题目内容:写一个函数求两个数的较大值分析:比较两个数的大小,然后输出较大的那个数我看到这个题的时候,想的是将两个数进行相减x-y,得到的结果,如果大于0,则......
  • 跟着鹏哥学C—初识C语言2
    1.选择语句(if语句)#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intmain(){intinput=0;printf("你会C语言吗?(1/0)>:");scanf("%d",&input);if(input==1......
  • 初识C语言3/3
    #include<stdio.h>intmain()intAdd(intx,inty)//这个int和下面的return想呼应,意思是返回整数z{intz=0;z=x+y;returnz;}{intarrl[10]={0};......
  • 初识C语言3/2
    符号知识点小记录:#include<stdio.h>intmain(){inta=1;intb=2;intc=a||b;intd=a&&b;printf("%d\n,%d",c,d);//1,1return0;}1:关系操作符:2:逻......
  • Codeforces 438D The Child and Sequence 势能线段树
    势能线段树|拉线段树题单时发现的这道花神游历各国的骚操作至今让我印象深刻,原来有名字所谓势能,大意就是原本你在高空,操作一点下降一点,势能变少一点..当你落地时,修改......
  • 初识C语言
    单目操作符小练习#include<stdio.h>intmaain(){inta=10;intb=~a;intc=++a;//前置++:先自身++,再使用它的用途intd=a++;//后......
  • Angularjs 初识
    AngularJS简介AngularJS是为了克服HTML在构建应用上的不足而设计的。HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了。所以我做了一些......