ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

日常记录(52)workshop整理

2022-02-09 15:05:34  阅读:260  来源: 互联网

标签:UVM regmodel seq sequence 52 workshop uvm phase 日常


top的program中与case的class中。

1 导入UVM的方法

在top的program内部,import uvm_pkg::*,在Makefile的vcs中,添加-ntb_opts uvm-1.1选项

 

2 top的timeformat

系统函数,参数为:时间精度,时间小数,后缀,显示位宽

 

3 top的vcs选项

控制使用哪一个case(top下的case)                   +UVM_TESTCASE=

控制uvm_info的显示等级                                       +UVM_VERBOSITY=

 

4 生成vpd波形文件

+vcs+vpdpluson的vcs选项,生成vpd文件。使用dve打开。

+UVM_TR_RECORD将transaction的信息存入vpd文件中。

+UVM_LOG_RECORD将uvm_info的信息存入vpd文件中,其中用req.sprint方式输出更直观。

 

5 uvm类树继承关系

 

 

6 打印拓扑关系、注册在工厂的类,以及配置的重载信息

依次如下

uvm_top.print_topology()

factory.print()

uvm_top.print()

 

UVM内部部分

1 uvm_info展开

内部有几个函数,主要利用uvm_report_enabled、 uvm_report_info实现。

 

2 \$size的sv函数

$size(param1, param2)
param1是被测量的变量,param2是测量的变量维度。1为最外层维度。

 

3 is_active的类型

在uvm_agent中,其类型为uvm_active_passive_enum

 

4 scb中的类顺序比较函数

uvm_in_order_class_comparator的使用。

最终report的过程中,m_matches、m_mismatches分别输出匹配和不匹配的个数。

为了在16路的交换机上进行包的对比,对应的tr也需要进行按照顺序的方式对比。

如果只有一路,直接将定义的uvm_anapysis_export给到uvm_in_order_class_comparator的before_export和after_export上,这样就接收后,是直接传入比较类中,无需imp了。

用了imp以后,imp将da进行识别,传入不同的比较类。

`ifndef _SCOREBOARD_SV_
`define _SCOREBOARD_SV_

`uvm_analysis_imp_decl(_before)
`uvm_analysis_imp_decl(_after)

class scoreboard extends uvm_scoreboard;
    // data or class properties
    `uvm_component_utils(scoreboard)
    uvm_analysis_imp_before#(packet, scoreboard) export_before;
    uvm_analysis_imp_after#(packet, scoreboard) export_after;
    uvm_in_order_class_comparator#(packet) comparator[16];

    // initialization
    function new(string name="scoreboard", uvm_component parent);
        super.new(name, parent);
    endfunction : new

    virtual function void build_phase(uvm_phase phase);
        export_before = new("export_before", this);
        export_after = new("export_after", this);
        for (int i = 0; i < 16; i++) begin
            comparator[i] = uvm_in_order_class_comparator#(packet)::type_id::create(
                $sformatf("comparator[%0d]", i), this);
        end
    endfunction: build_phase

    virtual function void write_before(packet tr);
        `uvm_info($sformatf("SB_INPUT_GET%0d", tr.da), "scoreboard get a packet", UVM_LOW)
        comparator[tr.da].before_export.write(tr);
    endfunction: write_before

    virtual function void write_after(packet tr);
        `uvm_info($sformatf("SB_OUTPUT_GET%0d", tr.da), "scoreboard get a packet", UVM_LOW)
        comparator[tr.da].after_export.write(tr);
    endfunction: write_after

    virtual function void report_phase(uvm_phase phase);
        for (int i = 0; i < 16; i++) begin
            `uvm_info($sformatf("SB_REPORT[%0d]",i), $sformatf("Match %0d, MisMatch %0d",
                comparator[i].m_matches, comparator[i].m_mismatches[i]), UVM_LOW)
        end
    endfunction: report_phase
endclass : scoreboard
`endif

 

5 phase的顺序

https://blog.csdn.net/qq_37884273/article/details/114239843

一般在report这个phase的顶层输出点信息。比如上面的scb。

 

 

 

6 设置drain_time

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/packet_sequence.sv#L37-L41

在发送端,给seq的body上的starting_phase设置。

1 获取objection:starting_phase.get_objection();

2 设置drain_time:objection.set_drain_time(this, 1us);

 

7 uvm_sequence_library说明

在上一段的第5个,说明了它是继承了seq的,因此设置它到seqr的default_sequence上,类型还是uvm_object_wrapper(uvm_config_db函数用到)。

1. 注册:

使用uvm_object_utils和`uvm_sequence_library_utils,还需要init_sequence_library;在new函数中。

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/packet_seq_lib_pkg.sv

2. 配置:

在case中配置时,先定义和实例化uvm_sequence_library_cfg,然后传给seq_lib的config中

        seq_cfg = new("seq_cfg", UVM_SEQ_LIB_RAND, 2, 2);
        uvm_config_db#(uvm_sequence_library_cfg)::set(
            this, "env.i_agt[*].seqr.main_phase", "default_sequence.config", seq_cfg);

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/test_collection.sv#L76-L78

3. 添加:

使用静态方法添加:packet_seq_lib是一个class,使用add_typewide_sequence添加seq到seq_lib中。

packet_seq_lib::add_typewide_sequence(packet_sequence::get_type());

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/test_collection.sv#L80

4. 修改:

seq_lib下的seq需要说明它的starting_phase不是seqr的,因此为null,它的starting_phase是seq_lib的,因此需要以下的get_parent_sequence。

同样参考继承关系,seq_lib和seq都是seq_base的,定义出的parent就是一个基类。

        uvm_sequence_base parent = get_parent_sequence();
        if (parent != null) begin
            starting_phase = parent.starting_phase;
        end

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/packet_sequence.sv#L32-L35

 

RAL设定

主工程代码:https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/

0:不使用ral方式,

和传统一样

定义agent、seqr、seq、drv,然后seq初始化,通过seqr发给drv,drv驱动获取数据(drv打印出来返回结果就行了)。

交互主要seq和drv。

 

1 ralf文件定义和生成:

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/host.ralf

其中的空格不可省去。the blank between id and bracket can't be ignored.

register HOST_ID {
  field REV_ID {
    bits 8;
    access ro;
    reset 'h03;
  }
  field CHIP_ID {
    bits 8;
    access ro;
    reset 'h5A;
  }
}

register PORT_LOCK {
  field LOCK {
    bits 16;
    access w1c;
    reset 'hffff;
  }
}

register REG_ARRAY {
  field USER_REG {
    bits 16;
    access rw;
    reset 'h0;
  }
}

memory RAM {
  size 4k;
  bits 16;
  access rw;
}

block host_regmodel {
  bytes 2;
  register HOST_ID        (host_id)       @'h0000;
  register PORT_LOCK      (lock)          @'h0100;
  register REG_ARRAY[256] (host_reg[%d])  @'h1000; # array must specify HDL index
  memory   RAM            (ram)           @'h4000;
}

 

2. 通过该ralf文件生成regmodel

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/Makefile#L31-L32

最终通过RALFILE文件生成的regmodel文件为:ral_RALPOSTFIX.sv。其中会有ral_block_RALPOSTFIX类。是uvm_reg_block的regmodel。

ralgen -uvm -t $(RALPOSTFIX) $(RALFILE)

 

3. 有了regmodel后,设置组件连接

定义好agent中指定的seqr、adapter、seq。

说明:

1.组件连接关系和数据流

其中的seqr就是普通的seqr,但是不再通过default_sequence带入seq,发送给drv。

seqr、drv、adapter、seq。

由上层的agent(case)的task_phase中创建seq,并赋予seq的regmodel值,然后发送(通过start)。

    virtual task configure_phase(uvm_phase phase);
        super.configure_phase(phase);
        `uvm_info("RAL_HOST_AGENT", $sformatf("%m"), UVM_MEDIUM)

        seq = ral_host_sequence::type_id::create("host_seq", this);
        seq.regmodel = this.regmodel;
        phase.raise_objection(this);
        seq.start(null);
        phase.drop_objection(this);

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/ral_host_agent.sv#L43-L52

其中的regmodel需要实例化和配置(注意seqr的设置):

regmodel中需要接入seqr和adapter,因此这里同时实例了seqr、adapter。

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/ral_host_agent.sv#L28-L35

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        // switch to ral model 
        uvm_config_db#(uvm_object_wrapper)::set(this, "seqr.configure_phase", "default_sequence", null);
        // start.
        regmodel = ral_block_host_regmodel::type_id::create("ral_block_host_regmodel", this);
        adapter = reg_adapter::type_id::create("reg_adapter", this);

        uvm_config_db#(string)::get(this, "", "hdl_path", hdl_path);
        regmodel.build();
        regmodel.lock_model();
        regmodel.set_hdl_path_root(hdl_path); 
    endfunction: build_phase

在connect_phase接入:

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/ral_host_agent.sv#L38-L41

    virtual function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        regmodel.default_map.set_sequencer(seqr, adapter);
    endfunction: connect_phase

 

2. adapter的新增的

继承uvm_reg_adapter,不是component。其中的reg2bus和bus2reg实现好。

https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/reg_adapter.sv

 

3. seq是特定的,也算新增了

继承uvm_reg_sequence,后者的继承关系需要自己定,默认继承于sequence即可。

 

seq的内部body中,需要由外层传入的regmodel,实现regmodel的读写功能。此外需要数据、状态,用于控制。

 https://github.com/baimengwei/5pS-5Yiw566A5Y6G5LiK55qE56ys5LiA5Liq/blob/main/ral_host_sequence.sv

    virtual task body();
        uvm_status_e status;
        uvm_reg_data_t data;
        if (starting_phase!=null) begin
            starting_phase.raise_objection(this);
        end
        regmodel.PORT_LOCK.read(.status(status), .value(data), .path(UVM_FRONTDOOR), .parent(this));
        `uvm_info("RAL_READ", $sformatf("read_port_lock %0h", data), UVM_MEDIUM)
        regmodel.PORT_LOCK.write(.status(status), .value('1), .path(UVM_FRONTDOOR), .parent(this));
        `uvm_info("RAL_WRITE", $sformatf("read_port_lock %0h", data), UVM_MEDIUM)
        regmodel.PORT_LOCK.read(.status(status), .value(data), .path(UVM_FRONTDOOR), .parent(this));
        `uvm_info("RAL_READ", $sformatf("read_port_lock %0h", data), UVM_MEDIUM)
        if (starting_phase!=null) begin
            starting_phase.drop_objection(this);
        end
    endtask: body

 

标签:UVM,regmodel,seq,sequence,52,workshop,uvm,phase,日常
来源: https://www.cnblogs.com/bai2022/p/15875025.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有