知识点
- uvm知识点
-
-
- 1. 如果在item中对某个field约束是0-10范围内;在seq中randomize(),这个field会是一个0-10之间的数值;但是在seq randomize之后对该field赋值100,则实际发出去的item 该field 为100;
- 2. task中参数赋值例子
- 3. 约束的重载
- 4.uvm_teste_top在uvm_root中实例化,具体完成过程看uvm_root.sv代码
- 5. sv中调用function或者task可以不带();但是java要求function在没有参数的时候也要写();所以在sv中好的习惯是function或者task名字后带();这样可以明确的知道这个是一个call function
- 6. 几种打印方法
- 7. 函数及其参数赋值
- 8. 静态的方法和成员可以使用声明句柄的方式来调用;也可以直接使用类来调用;
- 9. uvm实战中,register model要点
- 10. transaction是继承uvm_sequence_item,uvm_sequence_item 继承uvm_transaction; 如果transaction中定义的域加入field_automation机制,则不用自己重写do_copy/do_compare/convert2string等函数;但是自己重写这些函数对于调试更加方便;
- 11. get_type_name()/get_name()/get_full_name()
- 12. sequence中一般不建议加入@ #等消耗时间的操作;
-
uvm知识点
1. 如果在item中对某个field约束是0-10范围内;在seq中randomize(),这个field会是一个0-10之间的数值;但是在seq randomize之后对该field赋值100,则实际发出去的item 该field 为100;
2. task中参数赋值例子
item中field定义
`uvm_object_utils_begin(pkt_item)
`uvm_field_enum(cmd_type,cmd, UVM_ALL_ON)
`uvm_field_int(w_data, UVM_ALL_ON)
`uvm_field_int(rd_data, UVM_ALL_ON)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_object_utils_end
constraint addr_type_cons {addr>0; addr<10;}
在seq中定义task
task reg_wr(
bit[31:0] addr=32'h00000000,
bit[31:0] w_data=32'h11223344,
cmd_type cmd=MEM_WR
);
//call other task
endtask
// call reg_wr
reg_wr(.addr(32'h00000004),w_data(100))
//不用列出所有的port, 没有列出的port使用task定义时候的default值
3. 约束的重载
如果在一个item的约束中对addr 约束范围0-10; 在其子类item中 对addr约束范围>100;(两者有冲突),则实现对约束的重载。例子可以参考uvm实战8.1.2
4.uvm_teste_top在uvm_root中实例化,具体完成过程看uvm_root.sv代码
$cast(uvm_test_top, factory.create_component_by_name(test_name, "", "uvm_test_top", null));
task uvm_root::run_test(string test_name="");
uvm_factory factory= uvm_factory::get();
bit testname_plusarg;
int test_name_count;
string test_names[$];
string msg;
uvm_component uvm_test_top;
process phase_runner_proc; // store thread forked below for final cleanup
testname_plusarg = 0;
// Set up the process that decouples the thread that drops objections from
// the process that processes drop/all_dropped objections. Thus, if the
// original calling thread (the "dropper") gets killed, it does not affect
// drain-time and propagation of the drop up the hierarchy.
// Needs to be done in run_test since it needs to be in an
// initial block to fork a process.
uvm_objection::m_init_objections();
`ifndef UVM_NO_DPI
// Retrieve the test names provided on the command line. Command line
// overrides the argument.
test_name_count = clp.get_arg_values("+UVM_TESTNAME=", test_names);
// If at least one, use first in queue.
if (test_name_count > 0) begin
test_name = test_names[0];
testname_plusarg = 1;
end
// If multiple, provided the warning giving the number, which one will be
// used and the complete list.
if (test_name_count > 1) begin
string test_list;
string sep;
for (int i = 0; i < test_names.size(); i++) begin
if (i != 0)
sep = ", ";
test_list = {test_list, sep, test_names[i]};
end
uvm_report_warning("MULTTST",
$sformatf("Multiple (%0d) +UVM_TESTNAME arguments provided on the command line. '%s' will be used. Provided list: %s.", test_name_count, test_name, test_list), UVM_NONE);
end
`else
// plusarg overrides argument
if ($value$plusargs("UVM_TESTNAME=%s", test_name)) begin
`uvm_info("NO_DPI_TSTNAME", "UVM_NO_DPI defined--getting UVM_TESTNAME directly, without DPI", UVM_NONE)
testname_plusarg = 1;
end
`endif
// if test now defined, create it using common factory
if (test_name != "") begin
if(m_children.exists("uvm_test_top")) begin
uvm_report_fatal("TTINST",
"An uvm_test_top already exists via a previous call to run_test", UVM_NONE);
#0; // forces shutdown because $finish is forked
end
//使用factory创建uvm_test_top,实例名是test_name;
$cast(uvm_test_top, factory.create_component_by_name(test_name,
"", "uvm_test_top", null));
if (uvm_test_top == null) begin
msg = testname_plusarg ? {"command line +UVM_TESTNAME=",test_name} :
{"call to run_test(",test_name,")"};
uvm_report_fatal("INVTST",
{"Requested test from ",msg, " not found." }, UVM_NONE);
end
end
if (m_children.num() == 0) begin
uvm_report_fatal("NOCOMP",
{"No components instantiated. You must either instantiate",
" at least one component before calling run_test or use",
" run_test to do so. To run a test using run_test,",
" use +UVM_TESTNAME or supply the test name in",
" the argument to run_test(). Exiting simulation."}, UVM_NONE);
return;
end
begin
if(test_name=="")
uvm_report_info("RNTST", "Running test ...", UVM_LOW);
else if (test_name == uvm_test_top.get_type_name())
uvm_report_info("RNTST", {"Running test ",test_name,"..."}, UVM_LOW);
else
uvm_report_info("RNTST", {"Running test ",uvm_test_top.get_type_name()," (via factory override for test \"",test_name,"\")..."}, UVM_LOW);
end
// phase runner, isolated from calling process
fork begin
// spawn the phase runner task
phase_runner_proc = process::self();
uvm_phase::m_run_phases();
end
join_none
#0; // let the phase runner start
wait (m_phase_all_done == 1);
// clean up after ourselves
phase_runner_proc.kill();
report_summarize();
if (finish_on_completion)
$finish;
endtask
5. sv中调用function或者task可以不带();但是java要求function在没有参数的时候也要写();所以在sv中好的习惯是function或者task名字后带();这样可以明确的知道这个是一个call function
6. 几种打印方法
- uvm_report_info
uvm_report_info(get_type_name(),$psprintf("rq_attr = %0h",rq_attr));
REPORT_TAG = $sformatf("RST_AGENT_DRV[%0s]",cfg.id);
uvm_report_fatal(REPORT_TAG,"Unsupported cmd_type in sequence item");
uvm_report_fatal(REPORT_TAG, {"rst_agent_cfg must be set for: ", get_full_name(), ".cfg"});
if (cfg.use_rst_in) begin
uvm_report_error(REPORT_TAG,$sformatf(
"Reset %s is configured to use rst_in as its control, so it should not receive a sequence item, but one was just sent. Ignoring sequence item.\n",cfg.id));
- display
$display("hello");
$display("data =%h", data);
$fatal("Failed to get BFM");
- uvm_info
`uvm_info(get_type_name(),"ckseq",UVM_LOW)
`uvm_fatal("REG/NULL_ITEM","bus2reg: bus_item argument is null")
if (!$cast(gp,bus_item)) begin
`uvm_error("WRONG_TYPE","Provided bus_item is not of type uvm_tlm_gp")
`uvm_info(get_type_name(),
$sformatf("Writing 'h%0h at 'h%0h via map \"%s\"...",
data, addrs[i], rw.map.get_full_name()), UVM_FULL);
`uvm_info(“TRACE”,$sformatf("%m"),UVM_HIGH)
`uvm_info(“TRACE”,$sformatf(“port_id value of %0d”,port_id),UVM_HIGH)
`uvm_info(“TRACE”,{"\n",req.sprint()},UVM_HIGH)
7. 函数及其参数赋值
- 函数的形参必须给默认值default;
assign_value(.dmac(11));如果在call function的时候,没有给某个形参赋值,则函数内部使用该形参得默认值,smac是default 0 赋值给tr
task assign_value(bit [47:0] dmac=0,
bit [47:0] smac=0);
my_transaction tr;
$display("seq begin");
if(starting_phase != null)
starting_phase.raise_objection(this);
repeat (10) begin
// $display("seq begin loop ");
tr = new("tr");
assert(tr.randomize() with {tr.pload.size==200;});
tr.dmac=dmac; //赋值
tr.smac=smac;
start_item(tr);
// $display("seq begin loop3 ");
finish_item(tr);
// $display("seq begin loop4 ");
uvm_report_info(get_type_name(),$psprintf("tr.dmac = %0h",tr.dmac));
uvm_report_info(get_type_name(),$psprintf("tr.smac = %0h",tr.smac));
end
$display("seq begin end ");
#100;
if(starting_phase != null)
starting_phase.drop_objection(this);
endtask
8. 静态的方法和成员可以使用声明句柄的方式来调用;也可以直接使用类来调用;
class lion_cage;
// protected static lion cage[$];
protected static animal cage[$];
static function void cage_lion(animal l);
cage.push_back(l);
endfunction : cage_lion
static function void list_lions();
$display("Lions in cage");
foreach (cage[i])
$display(cage[i].get_name());
endfunction : list_lions
endclass : lion_cage
//在top中使用
lion_cage lc;
lion_h = new(2, "Kimba");
lc.cage_lion(lion_h);
lc.list_lion();
9. uvm实战中,register model要点
- 可以在reference model中发起reg的read/write操作
- 可以在sequence中发起这个操作,reference model/sequence都是调用register model的 read/write操作,
- 不论是在reference model还是sequence中,都是通过句柄访问register model
- register model一般在base_test中定义;
- 然后通过句柄传到env的reference model中;
- sequence中调用register model 可以通过先把句柄传入seuqncer中,然后通过p_sequencer访问
- sequence中调用register model 也可以通过uvm_config_db 的方法把register model 传进来;
class bus_base_seq extends uvm_sequence #(pcie_cpl_item);
class bus_base_seq extends uvm_sequence #(pcie_cpl_item);
`uvm_object_utils(bus_base_seq)
`uvm_declare_p_sequencer(pcie_cpl_sequencer)
global_pkt_config my_pkt_config;
// Register model:
reg_top_block reg_rm;
pcie_cpl_item rsp;
// Properties used by the various register access methods:
rand uvm_reg_data_t data; // For passing data
uvm_status_e status; // Returning access status
function new(string name = "bus_base_seq");
super.new(name);
endfunction
// Getting a handle to the register model
task body;
//uvm_config_db 得到register model
if(!uvm_config_db #(reg_top_block)::get(null, get_full_name(), "reg_top_block", reg_rm)) begin
`uvm_error("body", "Could not find reg_top_block")
end
endclass
10. transaction是继承uvm_sequence_item,uvm_sequence_item 继承uvm_transaction; 如果transaction中定义的域加入field_automation机制,则不用自己重写do_copy/do_compare/convert2string等函数;但是自己重写这些函数对于调试更加方便;
11. get_type_name()/get_name()/get_full_name()
get_type_names是类的名字;
get_name是对象的名字;
driver driver_h;
在driver中
`uvm_info(get_type_name(),get_name(),UVM_LOW)
driver[get_type_name] driver_h[get_name];
uvm_test_top.env_h.driver_h(get_full_name())
对于sequence
# UVM_INFO tb_classes/fibonacci_sequence.svh(28) @ 0: uvm_test_top.env_h.sequencer_h@@fibonacci [fibonacci_sequence] #####
# UVM_INFO tb_classes/fibonacci_sequence.svh(29) @ 0: uvm_test_top.env_h.sequencer_h@@fibonacci [fibonacci_sequence] fibonacci(get_type_name/ get_name)
# UVM_INFO tb_classes/fibonacci_sequence.svh(30) @ 0: uvm_test_top.env_h.sequencer_h@@fibonacci [fibonacci_sequence] uvm_test_top.env_h.sequencer_h.fibonacci(get_full_name)
另外一种用法
`uvm_info(get_full_name(),uvm_component_h.get_type_name(),UVM_LOW)
`uvm_info(get_full_name(),uvm_component_h.get_full_name(),UVM_LOW)