日常记录(57)vseqr与vseq。AHB2

AHB2项目虽然有不少错误,但是从整体架构上比较规范。

https://gitee.com/bai-mengwei/AHB2

RTL

可能由于只是一个VIP,只有一个interface。在interface里具有断言的写法。

比如:其中的disable iff等表示需要系统不在复位状态,即rst=1时进行断言。

        property size7_addr_p;
                @(posedge HCLK) disable iff(!HRESETn)
                        HSIZE == 7 |-> HADDR[6:0] == 0;
        endproperty

        SIZE7_ADDR_BOUD: assert property(size7_addr_p);
    

日常记录(57)vseqr与vseq。AHB2

SIM

一共6个代码。在sim文件夹中,有Makefile文件。文件中用vcs先把一些文件夹添加为搜索路径,然后编译文件总的pkg、top。这两个文件都在env文件夹中。

日常记录(57)vseqr与vseq。AHB2

 

ENV

1. 一共6个代码。env文件夹中,top是顶层用于调用run_test函数,然后调用对应的test_case.

2. 在调用前,实例化interface,include 总的pkg(ahb_test_pkg,在test目录下),而test_case也在test目录里

注意这里的top是module,而整个项目没有program。一般时候,用top进行实例化interface后,是将program再次实例化,然后整个验证在program里。

日常记录(57)vseqr与vseq。AHB2

 

 日常记录(57)vseqr与vseq。AHB2

 

 

TEST

1. ahb_test_pkg是总的pkg,包括了各种svh文件,也包括了uvm的头部

`include uvm_macros.svh
import uvm_pkg::*

2. ahb_test.svh包括了所有的test_case,继承了uvm_test并注册到工厂中,因此可以调用。

日常记录(57)vseqr与vseq。AHB2

3. 在每个 test_case调用过程中,基本类定义了env、和env_cfg,以及各种各类的vseq。

vseq来自于env文件夹中。

vseq从本质上是普通的seq,但是它的行为是调用真实的seq(在 task body中实现。)

vseqr本质上也是普通的seqr,但是它的内部包括了各种seqr的声明。并在env中进行了实例化连接(vseqr被各种agent的seqr进行赋值)。

日常记录(57)vseqr与vseq。AHB2

传输过程

传输

在test_case中的run_phase,创建一个vseq,然后启动。

当一个特定的vseq启动,并使用env下的vseqr作为发送装置。可惜该发送装置没有接drv,不能让vseq在task_body中调用start_item, uvm_do等。而是进行了一些赋值操作。

日常记录(57)vseqr与vseq。AHB2

1.基类vseqr:

首先调用base_vseq,将env的vseqr中的内容分别取出(m_sequencer),并进行赋值。

class ahb_base_vseq extends uvm_sequence#(uvm_sequence_item);

        `uvm_object_utils(ahb_base_vseq)

        ahb_vseqr vseqr_h;
        ahb_mseqr mseqr_h;
        ahb_sseqr sseqr_h;
        reset_seqr reset_seqr_h;

        reset_seq reset_seq_h;
        set_seq set_seq_h;

        ahb_idle_mseq idle_mseq_h;
        ahb_incrx_mseq incrx_mseq_h;
        ahb_wrapx_mseq wrapx_mseq_h;
        ahb_crt_mseq crt_mseq_h;
        ahb_incrbusy_mseq incrbusy_mseq_h;

        ahb_reset_sseq reset_sseq_h;
        ahb_ready_sseq ready_sseq_h;
        ahb_err_sseq err_sseq_h;

        extern function new(string name = "ahb_base_vseq");
        extern task body();

endclass: ahb_base_vseq

        //Constructor
        function ahb_base_vseq::new(string name = "ahb_base_vseq");
                super.new(name);
        endfunction

        //Body
        task ahb_base_vseq::body();
                if(!$cast(vseqr_h, m_sequencer))
                begin
                        `uvm_fatal(get_full_name(), "Virtual Sequencer cast failed!")
                end

                reset_seqr_h = vseqr_h.reset_seqr_h;
                mseqr_h = vseqr_h.mseqr_h;
                sseqr_h = vseqr_h.sseqr_h;
        endtask

2. 对应类vseqr:

然后通过子类,对实际的seq进行创建和启动。实际的seq需要使用其对应的实际的seqr,而这些seqr在agent中声明后,已经接入了agent对应的drv中了,因此可以发出去。

class ahb_reset_vseq extends ahb_base_vseq;

        `uvm_object_utils(ahb_reset_vseq)

        extern function new(string name = "ahb_reset_vseq");
        extern task body();

endclass: ahb_reset_vseq

        //Constructor
        function ahb_reset_vseq::new(string name = "ahb_reset_vseq");
                super.new(name);
        endfunction

        //Body
        task ahb_reset_vseq::body();
                super.body();

                reset_seq_h = reset_seq::type_id::create("reset_seq_h");
                reset_sseq_h = ahb_reset_sseq::type_id::create("reset_sseq_h");

                fork
                        reset_sseq_h.start(sseqr_h);
                join_none

                reset_seq_h.start(reset_seqr_h);

        endtask

3. 对应的seq

就使用了创建、开始、随机化以及修改,发送。然后被agent对应的drv拿到,开始驱动。

class reset_seq extends reset_base_seq;

        `uvm_object_utils(reset_seq)

        extern function new(string name = "reset_seq");
        extern task body();

endclass: reset_seq

        //Constructor
        function reset_seq::new(string name = "reset_seq");
                super.new(name);
        endfunction

        //Body
        task reset_seq::body();
                req = ahb_mxtn::type_id::create("req");
                start_item(req);
                        assert(req.randomize() with {burst_mode == SINGLE;});
                        req.reset = 0;
                finish_item(req);
        endtask

 说明总结

(1.vseq是临时创建并启动的,它需要一个对应的seqr)

(2.这个seqr是一个vseqr,它不是让对应的seq发送到drv的,而是存储真实的seqr的,因此在vseq基类的task body中,没有send,而是进行赋值)

 

RESET_AGENT

1. 这里的seqr和seq就很普通了。seqr只有一个注册过程,seqs包括了几个对应的类。

2. agent中对drv和seqr进行了连接

 日常记录(57)vseqr与vseq。AHB2

 

上一篇:剑指 Offer 57 - II. 和为s的连续正数序列


下一篇:57、字符数组