IP验证学习之case编写
目录
前言
一:编写base_test
二.编写testcase
virtual_sequence:
reg_sequence:
数据流sequence:
总结
前言
读者阅读时要能够体会简单的case的控制过程。因为很多时候环境不需要你搭建,但case却要写很多。
整体的UVM环境读者可以使用脚本工具自行创建就好,不懂的地方 多问问前辈和AI~
参考:绿皮书,白皮书
一:编写base_test
在编写完env或者配置完成时,接下来的工作就是要编写testcase了,这一步分成了两类。
1.所有的驱动都会在在testcase里按照流程一步步的配置,即封装一些task ,如mem_write,mem_read等任务。
2.调用virtual sequence ,在virtual sequence中调度多个sequence进行工作。
从UVM的应用角度来说,更加推荐使用virtual sequence 调度多个sequence的方式编写自己的testcase。但是如果项目中用到了第三方的IP,那么大概率环境用的是第一种方式,其复用性上会差一点。
我以第二种方式开始介绍。
在此之前首先对UVM的顶层控制有一个了解,如图:virtual sequence里面例化了所有sequence,virtual sequencer里面例化了环境里的sequencer,这两个东西读者可以理解成容器。
virtual sequence里可以调度sequence的次序,产生次数等,同时可以指定其子sequence在哪个sequencer上运行。
virtual sequencer集成了多个sequencer的作用就是方便控制全局的sequencer,与virtual sequence相互作用。
可以说有virtual sequence 就会有 virtual sequencer,其中vritual sequence通常作为顶层控制器控制全局sequence,而virtual sequencer 一般而言就是集成sequencer。
下图展示了sequence作为顶层控制的思想和具体流程。
当有了env后,我们首先需要做的就是用一个或者多个base_test封装env,根据多个base_test的不同需求编写。
比如 DUT中存在两个通路,可以准备三个base_test分别验证其中一条通路或者两条通路都打开的场景。
class base_test extends uvm_test;......env_config env_cfg;env m_env;......function void build_phase(uvm_phase phase);......m_env = env::type_id::create("m_env",this); //实例化envenv_cfg.config_env();env_cfg.has_xxx_scoreboard = 0 ; //这里就是配置env以及内部的参数,仅供参考//如果有VIP的话,还需要配置一下VIP里的default_sequenceuvm_config_db#(uvm_object_wrapper)::set(this,"m_env.apb_env.apb_slave_env.slave*.sequencer.run_phase","default_sequence",svt_apb_slave_memory_sequence::type_id::get());uvm_config_db#(uvm_object_wrapper)::set(this,"m_env.apb_env.apb_master_env.sequencer.main_phase","default_sequence",null/*svt_apb_slave_memory_sequence::type_id::get()*/);endfunction:build_phasefunction void base_test::final_phase(uvm_phase phase);......//在仿真结束的最后阶段可以加入一个检查环境是否存在 UVM_ERROR 或者 UVM_WARNING 的语句err_num = server.get_severrity_count(UVM_ERROR)+ server.get_severrity_count(UVM_FATAL);+ server.get_severrity_count(UVM_WARNING);if(!err_num) `uvm_info("UVM_CASE_PASS", “******** UVM TEST PASSED *********",UVM_NONE)else `uvm_info("UVM_CASE_FAIL", “******** UVM TEST FAILED *********",UVM_NONE)endfunction:final_phaseendclass
由于base_test在这里的作用主要就是搭建一个个框架管道,所以可以不用添加各个run阶段的phase(但有时也不是绝对的,有的人也会给base_test添加一些基础激励类的配置)。
二.编写testcase
在编写testcase的时候,通常会继承于base_test。一般环境最先会先写一个smoke_test(冒烟测试),即不需要配置任何寄存器,以DUT默认的配置直接发起数据流操作。
不过这里还是以编写配置寄存器的case为例,介绍一下如何写case。
class register_test extends base_test;......task main_phase(uvm_phase phase);dut_register_vseq u_reg_vseq;phase.raise_objection(this);u_reg_vseq = new();u_reg_vseq.start(m_env.reg_vseqr); //启动一个虚拟序列,并将其运行在指定的sequencer上,这里就是启动寄存器虚拟序列,将其运行在reg_vseqr上。phase.drop_objection(this);endtaskendclass
上面这个case十分简单,仅仅只是调用virtual sequence进行启动,所以代码量很小。下面来看一下 virtual sequence 以及其调用的各个sequence的具体内容。
virtual_sequence:
class dut_register_vseq extends uvm_sequencer;register_sequence reg_seq; //申明寄存器配置的sequence的句柄//其他sequence......task body(); //写sequence主要就是完成body任务,在virtual sequence里就是完成调配各个sequence的顺序或者功能等。`uvm_do(reg_seq) //在当前的sequencer上调用并启动寄存器配置的sequence。apb_rw_seq.mem_write_(32'h4000_0004,32'h1); //如果对于DUT而言是一些直连线访问,可以模拟一个寄存器访问操作直接访问寄存器。`uvm_do(input_seq, p_sequencer.input_seqr) ; //启动input_seq这个序列,指定它在virtual_seuqnecer下面的input_seqr里面运行。endtaskendclass
可以看到virtual sequence里面就是配置子sequence,指定它们在哪个sequencer上运行,并做一些其他读写操作。
完成基本的sequence启动项配置后,再来看看其中的两个sequence是怎样写的。编写sequence主要是编写task_body。
reg_sequence:
class register_sequence extends uvm_sequence;......task_body();uvm_status_e status; //这是和寄存器有关的变量,用于检查是否寄存器操作是否成功。uvm_reg_data_t data; //用于存储寄存器读写操作的数据rgm.logic_sel.logic_sel.set(1);rgm.update(status,UVM_FRONTDOOR); //前门访问endtaskendclass
数据流sequence:
class op_in_seq#(DATA_WIDTH = 4) extends uvm_sequence //声明了一个带参数的sequence......task body();op_in_seq_item`PARAM_LIST req; // `PARAM_LIST 是宏定义的参数列表,用于配置例化对象`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH)`uvm_do(req)endtask
endclass
在上述例子里,在virtual_sequence中分别调用了寄存器配置的sequence和发送数据流的sequence,两者各司其职,为了灵活的配置顺序,通常还会用fork...join的方式并行执行一些sequence.
在面对一个全新的IP时,最初写case是比较慢的,但是当编写sequence到一定程度上后,接下来的testcase就是把原先编写好的sequence组合起来用于验证。
总结
UVM环境的环境搭建关键还是要看具体的DUT情况才可以,实际工作中写case就已经花费了很多时间,通常公司也会引入AI agent自动生成一些验证框架和sequence等,方便验证编写case。