前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【UVM COOKBOOK】Sequences||Hierarchical Sequences

【UVM COOKBOOK】Sequences||Hierarchical Sequences

作者头像
空白的贝塔
发布2021-12-06 15:21:21
3780
发布2021-12-06 15:21:21
举报
文章被收录于专栏:摸鱼范式摸鱼范式

Hierarchical Sequences

在处理Sequences时,考虑到测试平台可能会需要对不同功能测试,可以对功能进行分层拆解。在与每个代理相关联的最低层是API Sequences。利用API Sequence来完成工作的中间层是worker Sequence。最后,在控制整个测试顶部是一个虚拟sequence,它协调不同目标测序器上的工作sequence的运行

API Sequences

API sequence是sequence层次结构中的最低层。他们做的工作最少,因为他们在运行时做一个非常有针对性的行动。API sequence应该执行小的原子操作,比如在总线上执行读取、在总线上执行写、在总线上执行读修改写或等待中断或其他信号。API sequence将包含在systemverilog pkg中,该包定义了要在其上运行sequence的代理。两个示例API sequence将如下:

代码语言:javascript
复制
//API Sequence for doing a Read
class spi_read_seq extends uvm_sequence #(spi_item);
    `uvm_object_utils(spi_read_seq)
    const string report_id = "spi_read_seq"; 
 rand bit [7:0] addr;
 bit [15:0] rdata;
    
 task body();
  req = spi_item::type_id::create("spi_request"); start_item(req);
  if ( !(req.randomize() with {req.addr == local::addr;} )) 
   `uvm_error(report_id, "Randomize Failed!") finish_item(req);
  rdata = req.data;
 endtask : body
    
    task read(input bit [7:0] addr, output bit [15:0] read_data, input uvm_sequencer_base seqr, input uvm_sequence_base parent = null);
  this.addr = addr; this.start(seqr, parent); 
        read_data = req.data;
 endtask : read

endclass : spi_read_seq

//API Sequence for doing a Write
class spi_write_seq extends uvm_sequence #(spi_item);
 `uvm_object_utils(spi_write_seq)
 const string report_id = "spi_write_seq"; 
 rand bit [7:0] addr;
 rand bit [15:0] wdata;

    task body();
  req = spi_item::type_id::create("spi_request"); start_item(req);
  if ( !(req.randomize() with {req.addr == local::addr;req.data == local::wdata; } )) 
  `uvm_error(report_id, "Randomize Failed!") finish_item(req);
 endtask : body

    task write(bit [7:0] addr, bit [15:0] write_data, uvm_sequencer_base seqr, uvm_sequence_base parent = null); 
        this.addr = addr;
  this.wdata = write_data;
  this.start(seqr, parent);
 endtask : write
    
endclass : spi_write_seq

Worker Sequences

Worker sequence利用低级API sequence来构建中层sequence。这些中层sequence可以做诸如dut配置、加载内存等事情。通常,一个Worker sequence将只向一个sequencer发送单个sequence item。Worker sequence是这样的:

代码语言:javascript
复制
//Worker sequence for doing initial configuration for Module A
class moduleA_init_seq extends uvm_sequence #(spi_item);
 `uvm_object_utils(moduleA_init_seq)
 const string report_id = "moduleA_init_seq"; 
 spi_read_seq read;
 spi_write_seq write;

    task body();
  read = spi_read_seq::type_id::create("read"); 
  write = spi_write_seq::type_id::create("write");
//Configure registers in Module
//Calling start 
  write.addr = 8'h20; 
  write.wdata = 16'h00ff; 
  write.start(m_sequencer, this);
//Using the write task
  write.write(8'h22, 16'h0100, m_sequencer, this);
//Other register writes
//Check that Module A is ready 
  read.addr = 8'h2c; 
  read.start(m_sequencer, this); 
  if (read.rdata != 16'h0001) 
   `uvm_fatal(report_id, "Module A is not ready") 
 endtask : body
endclass : moduleA_init_seq

Virtual Sequences

virtual sequence用于调用和协调所有的Worker sequence。在大多数情况下,设计需要在发送随机数据之前进行初始化。virtual sequence可以调用初始化Worker sequence,然后调用其他Worker sequence,如果需要执行低级操作,还可以调用其他Worker sequence,甚至是API sequence。virtual sequence将包含对目标sequencer的句柄(推荐),或在virtual sequencer上运行,该virtual sequencer允许访问运行Worker sequence和API sequence所需的所有sequencer。下面就是一个例子

代码语言:javascript
复制
//Virtual Sequence controlling everything
class test1_seq extends uvm_sequence #(uvm_sequence_item);
 `uvm_object_utils(test1_seq)
 const string report_id = "test1_seq"; 
// These handles will be assigned by an init method in the test
 uvm_sequencer_base spi_seqr; 
 uvm_sequencer_base modA_seqr; 
 uvm_sequencer_base modB_seqr;
 moduleA_init_seq modA_init;
 moduleB_init_seq modB_init;
 moduleA_rand_data_seq modA_rand_data; 
 moduleB_rand_data_seq modB_rand_data;
 spi_read_seq spi_read;
 bit [15:0] read_data;
 
    task body();
  modA_init = moduleA_init_seq::type_id::create("modA_init");
        modB_init = moduleB_init_seq::type_id::create("modB_init");
  modA_rand_data = moduleA_rand_data_seq::type_id::create("modA_rand_data");
  modB_rand_data = moduleB_rand_data_seq::type_id::create("modB_rand_data");
  spi_read = spi_read_seq::type_id::create("spi_read");
//Do Initial Config
  fork
   modA_init.start(spi_seqr, this); 
   modB_init.start(spi_seqr, this);
  join
//Now start random data (These would probably be started on
  different sequencers for a real design) fork
  modA_rand_data.start(modA_seqr, this); 
  modB_rand_data.start(modB_seqr, this);
  join
//Do a single read to check completion
      spi_read.read(8'h7C, read_data, spi_seqr, this);
   if (read_data != 16'hffff) 
    `uvm_error(report_id, "Test Failed!") 
 endtask : body
endclass : test1_seq
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 摸鱼范式 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • API Sequences
  • Worker Sequences
  • Virtual Sequences
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档