UVM环境自动生成工具(2)uvmdvgen

介绍

OpenTitan是一个谷歌的开源RISC-V项目,这里借用了项目中的uvm环境生成脚本uvmdvgen来生成环境。

使用流程是通过命令后缀指定环境和agent名称,然后脚本依据路径下的mako模板替换生成环境,脚本基于python实现。

项目链接:
GitHub - lowRISC/opentitan: OpenTitan: Open source silicon root of trust

使用步骤

环境

脚本基于python实现,github目录有环境要求,个人在centos7 python 3.14测试。

脚本在util/路径,-h可以看到帮助说明,-a用于生成agent,-s指示agent主从分开,-e用于生成env,-c从CIP库生成否则从DV库生成,-hr、hi、ha指示包含寄存器模型、中断和alert,-ea指示env中包含的agent,-ao指示agent生成在路径,-ro指示env生成在的路径。

复制代码
$ util/uvmdvgen.py -h
usage: uvmdvgen.py [-h] [-a] [-s] [-e] [-c] [-hr] [-hi] [-ha]
                   [-ea agt1 agt2 [agt1 agt2 ...]] [-ao [hw/dv/sv]]
                   [-eo [hw/ip/<ip>]] [-v VENDOR]
                   [ip/block name]

生成agent

使用脚本生成环境包括2步,首先通过-a生成agent,再通过-e -ea生成集成agent的env。

在端口通过指令生成i2c agent,这里是生成在当前目录,也可以加-ao指定目录。

复制代码
$ util/uvmdvgen.py i2c -a

在i2c/i2c_agent可以看到生成文件。

但实际生成的是纯空文件,或者说替换了名字的空模板,内容还要自己从头写,所以指令agent可以是任何名称,例如i3c、i4c,不一定是DV库中的agent。

在项目的hw/dv/sv路径中有一些uvm agent,包含jtag、uart、spi、i2c等,是有完整内容的,可以直接拷贝到自己的环境。

生成env

在vrf目录生成一个环境,包含axi apb pcie agent,和前相似agent名可以任意。

复制代码
util/uvmdvgen.py vrf -e -ea axi apb pcie

在vrf/dv路径下可以看到生成环境,这个脚本还是比较自动的,首先env中可以看到例化各个agent,传递了配置,连接了scb,连接了top_seqr。不过也有缺点,同名agent只能例化1次否则要手动修改,还有就是没有ref model和对应scb连接。

其他vseq、vseqr不再赘述,tb中例化了agent同名if,并config_db发送到了agent中,基本流程都有实现。

脚本实现

脚本通过python实现,可以看一下实现方法。

uvmdvgen.py

脚本接收了参数,并根据-a还是-e决定执行gen_agent还是gen_env。

复制代码
if args.gen_agent:
	gen_agent.gen_agent(args.name, args.has_separate_host_device_driver, args.agent_outdir, args.vendor)
if args.gen_env:
    gen_env.gen_env(args.name, args.is_cip, args.has_ral, args.has_interrupts, args.has_alerts,args.num_edn, args.env_agents, args.env_outdir, args.vendor)

gen_agent.py

首先将agent内文件定义成包含元组的列表,按照路径、agent名、文件名和后缀形式保存。

复制代码
agent_srcs = [(agent_dir,               name + '_', 'if',            '.sv'),
              (agent_dir,               name + '_', 'item',          '.sv'),
              (agent_dir,               name + '_', 'agent_cfg',     '.sv'),
              (agent_dir,               name + '_', 'agent_cov',     '.sv'),
              (agent_dir,               name + '_', 'monitor',       '.sv'),
              (agent_dir,               name + '_', 'driver',        '.sv'),
              (agent_dir,               name + '_', 'host_driver',   '.sv'),
              (agent_dir,               name + '_', 'device_driver', '.sv'),
              (agent_dir,               name + '_', 'agent_pkg',     '.sv'),
              (agent_dir,               name + '_', 'agent',         '.sv'),
              (agent_dir,               name + '_', 'agent',         '.core'),
              (agent_dir,               "",         'README',        '.md'),
              (agent_dir + "/seq_lib",  name + '_', 'seq_list',      '.sv'),
              (agent_dir + "/seq_lib",  name + '_', 'base_seq',      '.sv')]

然后通过for循环读出,使用mako组件,根据名称找到同路径下预存的.tpl模板,然后在模板文件中替换名称。

复制代码
for tup in agent_srcs:
    path_dir = tup[0]
    src_prefix = tup[1]
    src = tup[2]
    src_suffix = tup[3]

    ftpl = src + src_suffix + '.tpl'
    fname = src_prefix + src + src_suffix

    # read template
    tpl = Template(filename=str(importlib.resources.files('uvmdvgen') / ftpl))
    with open(path_dir + "/" + fname, 'w') as fout:
        fout.write(
            tpl.render(name=name,
                       has_separate_host_device_driver=
                       has_separate_host_device_driver,
                       vendor=vendor))

实际替换过程均在模板中实现,以driver.sv.tpl为例,模板就是空的,所以生成agent也是空文件,如有一些通用需求,可以直接修改.tpl模板。

复制代码
class ${name}_driver extends dv_base_driver #(.ITEM_T(${name}_item),
                                              .CFG_T (${name}_agent_cfg));
  `uvm_component_utils(${name}_driver)

  // the base class provides the following handles for use:
  // ${name}_agent_cfg: cfg

gen_env.py

和gen_agent.py相似,替换过程均在模板中实现,env的模板更复杂一些,所以生成出来的不是空文件,以env.sv.tpl为例,会根据agent列表for循环生成集成的代码。例如有添加ref model的需求,直接修改模板文件即可。

复制代码
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
% for agent in env_agents:
    // create components
    m_${agent}_agent = ${agent}_agent::type_id::create("m_${agent}_agent", this);
    uvm_config_db#(${agent}_agent_cfg)::set(this, "m_${agent}_agent*", "cfg", cfg.m_${agent}_agent_cfg);
    cfg.m_${agent}_agent_cfg.en_cov = cfg.en_cov;
% endfor
  endfunction

总结

脚本定位还是生成模板,不能直接运行,agent也只是壳子,需要再人工完成。不过毕竟不是专门生成环境的工具,实现过程比较清晰,适合写平台脚本参考。

参考
UVM验证环境生成工具-Open Titan UVM Generator - SOC验证工程师 - 博客园

相关推荐
Ether IC Verifier1 天前
SystemVerilog 数据类型详解
php·systemverilog·uvm·ic验证
liuluyang53025 天前
UVM 工厂机制 完整可编译运行 Demo
uvm·uvm工厂机制
liuluyang53025 天前
UVM工厂机制
uvm·工厂机制
liuluyang53025 天前
UVM工厂机制(二)
uvm·工厂机制
liuluyang5301 个月前
SystemVerilog常用关键词与函数
uvm·systermverilog
liuluyang5301 个月前
SV主要关键词详解
fpga开发·uvm·sv
liuluyang5302 个月前
clk_mux_seq sv改进
fpga开发·uvm
谷公子的藏经阁2 个月前
DVCon 2025 论文精华导读及下载链接
ai·论文·systemverilog·uvm·dvcon
蓝天下的守望者4 个月前
SystemVerilog中 `timescale的使用问题
systemverilog·uvm·vcs
蓝天下的守望者4 个月前
uvm_field_automation机制学习
uvm