fifo force


前言

在我们DUT的RTL中,经常会有很多的FIFO,很多时候,我们需要检查这些FIFO的空满,是否对系统有影响。本文主要介绍如何在验证环境中,随机force FIFO的空满。
本文基于UVM的框架,自顶向下进行描述,先介绍sequence中的实现,再介绍random_fifo_force的具体实现。


一、fifo_force_smoke_vseq

在fifo_force_smoke_vseq中,只需要利用fork–join_any,开两个进程,一个进程是执行base sequence中的body(),另外一个进程是执行random_fifo_force()。

class fifo_force_smoke_vseq extends base_vseq;
	//...
    task body();
    	fork
    		super.body();
    		random_fifo_force();
    	join_any
    endtask : body
endclass : fifo_force_smoke_vseq 

二、random_fifo_force

实现fifo的随机force,需要实现以下几个步骤:
1 从文件读入需要force fifo的路径;
2 对force的实现进行封装;
3 随机需要force的信号和时间;

2.1 从文件读入force的路径

从文件读入force路径的代码实现如下:

	string fifo_list = ""
    if($value$plusargs("fifo_list=%s", fifo_list)) begin
      `uvm_info(`gfn, $sformatf("Loading fifo list %s", fifo_list), UVM_LOW)
    end	
    fifo_list_reader rd = new();
    rd.read_from_file(fifo_list); 

其中,fifo_list_reader的实现思路是,拿到文件句柄后,按行读出文件路径,匹配tb开头的字符串,再将低有效或者高有效的路径分别存入sig_path和sig_n_path,实现代码如下:

class fifo_list_reader;
  string sig_path[$];
  string sig_n_path[$];
  string lines[$];

  function new();
  endfunction //new()

  function automatic void read_from_file(string fname);
    integer fp = $fopen(fname, "r");
    string  line;
    string  head = "tb";
    while($fgets(line, fp)) begin
      if(line.len() > 2 && line[0] == head[0] && line[1] == head[1]) begin
        line = line.substr(0, line.len()-2);
        lines.push_back(line);
      end
    end
    $fclose(fp);
    assert (lines.size() % 2 == 0) else begin
      `uvm_fatal("FIFO_LIST_READER", $sformatf("Line size not even! %d", lines.size()))
    end
    for(int i = 0; i < lines.size(); i += 2) begin
      string line1 = lines[i];
      string line2 = lines[i+1];
      if(line1.len() == line2.len() + 2) begin
        sig_n_path.push_back(line1);
        sig_path.push_back(line2);
      end
      else if(line2.len() == line1.len() + 2) begin
        sig_n_path.push_back(line2);
        sig_path.push_back(line1);
      end
      else begin
        `uvm_fatal("FIFO_LIST_READER", $sformatf("Unrecognized pattern!\]\n%s\n%s", line1, line2))
      end
    end
    assert (sig_path.size() == sig_n_path.size()) else begin
      `uvm_fatal("FIFO_LIST_READER", $sformatf("path size n equal: %d vs %d", sig_path.size(), sig_n_path.size()))
    end
    foreach(sig_path[i]) begin
      `uvm_info("FIFO_LIST_READER", sig_path[i], UVM_LOW)
    end
  endfunction
endclass //fifo_list_reader

2.2 对force的实现进行封装

将2.1中读入的路径,分别封装好force的实现,放入fifo_forcer的大数组中,方便后续随机挑选。

	fifo_full_empty_forcer fifo_forcer[$];
	@(negedge clk_rst_vif.rst);  //等待复位释放
    foreach(rd.sig_path[i]) begin
      sec_fifo_full_empty_forcer forcer = new(rd.sig_path[i], rd.sig_n_path[i]);
      fifo_forcer.push_back(forcer);
    end	

其中,fifo_full_empty_forcer的实现思路是,在new函数,通过rtl_handler,对RTL force路径进行封装,再在不同的方法中去操作这个封装的句柄,实现代码如下:

class fifo_full_empty_forcer;
  rtl_handler#(1) sig;
  rtl_handler#(1) sig_n;

  bit on = 0;

  function new(string rtl_path, string rtl_n_path);
    sig = new(rtl_path);
    sig_n = new(rtl_n_path);
  endfunction //new()

  function void force_val(bit value = 1);
    assert(sig.force_val(value));
    assert(sig_n.force_val(~value));
  endfunction

  task automatic force_time(bit value, time f_time);
    if(on) begin
      `uvm_fatal("FIFO_FORCER", "Already on!")
    end
    fork
      `uvm_info("FIFO_FORCER", $sformatf("%s for %t", sig.path, f_time), UVM_HIGH)
      sig.force_time(value, f_time);
      sig_n.force_time(~value, f_time);
      handle_on(f_time);
    join_none
  endtask //automatic force_time

  // total delay is 4 * f_time
  task automatic handle_on(time f_time);
    on = 1;
    #(4 * f_time);
    on = 0;
  endtask //automatic

  function void release_val();
    assert(sig.release_val()); 
    assert(sig_n.release_val()); 
  endfunction
endclass //fifo_full_empty_forcer

底层rtl_handler的具体实现如下:

class rtl_handler #(int WIDTH);
  string path;

  function new(string rtl_path);
    path = rtl_path;
  endfunction

  function int force_val(logic[WIDTH-1:0] value);
    return uvm_hdl_force(path, value);
  endfunction

  task automatic force_time(logic[WIDTH-1:0] value, time f_time);
    assert(this.force_val(value)) else begin
      `uvm_fatal("SEC_RTL_HANDLER", $sformatf("Error force path %s", path))
    end;
    #f_time;
    assert(this.release_val()) else begin
      `uvm_fatal("SEC_RTL_HANDLER", $sformatf("Error release path %s", path))
    end;
  endtask //automatic force_time

  function int release_val();
    return uvm_hdl_release(path);
  endfunction

  function int read(output logic[WIDTH-1:0] value);
    return uvm_hdl_read(path, value);
  endfunction
endclass //rtl_handler #(int WIDTH)

2.3 随机需要force的信号和时间

随机选取信号,随机force的时间长度,执行force

    forever begin
      int idx;
      int signal_size = fifo_forcer.size();
      std::randomize(idx) with {
        idx < signal_size;
        idx >= 0;
      };
      if(fifo_forcer[idx].on == 0) begin
        int time_ns;
        std::randomize(time_ns) with {
          time_ns dist {
            [10:40] := 40,
            [41:100] := 20,
            [101:400] := 10
          };
        };
        fifo_forcer[idx].force_time(1, time_ns * 1ns);
      end
      repeat($urandom_range(1,10))@(negedge cfg.clk_rst_vif.clk);
    end

总结

本文主要介绍DUT中FIFO的full和empty的随机force思路,并给出了具体的代码实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值