[CU]uvm lab6-router
注1:uvm lab1 - __见贤思齐 - 博客园 (cnblogs.com)
注2:uvm lab2 - __见贤思齐 - 博客园 (cnblogs.com)
注3:uvm lab3 - __见贤思齐 - 博客园 (cnblogs.com)
注4:uvm lab4 - __见贤思齐 - 博客园 (cnblogs.com)
注5:uvm lab5 - __见贤思齐 - 博客园 (cnblogs.com)
注6:synopsys uvm1.2 lab guide - IC验证资料 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
注7:uvm1.2 lab链接UVM1.2 Lab验证资料(入门必备) - IC验证资料 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
学习目标
(1) register model的构建与使用;
1.test.sv
(1) config_db::set()或resource_db::set()的使用;
1 program automatic test; 2 import uvm_pkg::*; 3 4 `include "test_collection.sv" 5 6 initial begin 7 //interface的config_db::set()/resource_db::set()可以放置到该initial begin end块中; 8 uvm_resource_db#(virtual router_io)::set("router_vif","",router_test_top.router_if); 9 uvm_resource_db#(virtual reset_io)::set("reset_vif","",router_test_top.reset_if); 10 uvm_resource_db#(virtual host_io)::set("host_vif","",router_test_top.host_if); 11 uvm_reg::include_coverage("*", UVM_CVR_ALL); 12 $timeformat(-9, 1, "ns", 10); 13 run_test(); 14 end 15 16 endprogram
2.test_collection.sv
(1) hdl_path的config_db::set();
(2) 注意raise_objection与drop_objection的第二个参数;
1 `ifndef TEST_COLLECTION__SV 2 `define TEST_COLLECTION__SV 3 4 `include "router_env.sv" 5 6 class test_base extends uvm_test; 7 `uvm_component_utils(test_base) 8 9 router_env env; 10 virtual router_io router_vif; 11 virtual reset_io reset_vif; 12 virtual host_io host_vif; 13 14 top_reset_sequencer top_reset_sqr; 15 16 function new(string name, uvm_component parent); 17 super.new(name, parent); 18 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 19 endfunction 20 21 virtual function void build_phase(uvm_phase phase); 22 super.build_phase(phase); 23 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 24 env = router_env::type_id::create("env", this); 25 uvm_resource_db#(virtual router_io)::read_by_type("router_vif",router_vif,this); 26 uvm_resource_db#(virtual reset_io)::read_by_type("reset_vif",reset_vif,this); 27 28 uvm_config_db#(virtual router_io)::set(this,"env.i_agt[*]","vif",router_vif); 29 uvm_config_db#(virtual router_io)::set(this,"env.o_agt[*]","vif",router_vif); 30 uvm_config_db#(virtual reset_io)::set(this,"env.r_agt","vif",reset_vif); 31 32 top_reset_sqr=top_reset_sequencer::type_id::create("top_reset_sqr",this); 33 34 uvm_resource_db#(virtual host_io)::read_by_type("host_vif",host_vif,thif); 35 uvm_config_db#(virtual host_io)::set(this,"env.h_agt","vif",host_vif); 36 37 uvm_config_db#(uvm_object_wrapper)::set(this,"env.*.sqr.reset_phase", "default_sequence",null); 38 uvm_config_db#(uvm_object_wrapper)::set(this,"top_reset_sqr.reset_phase", "default_sequence", top_reset_sequence::get_type()); 39 40 uvm_config_db#(string)::set(this,"env","hdl_path","router_test_top.dut"); 41 endfunction 42 43 virtual function void connect_phase(uvm_phase phase); 44 super.connect_phase(phase); 45 46 foreach(env.i_agt[i]) begin 47 top_reset_sqqr.pkt_sqr.push_back(env.i_agt[i].sqr); 48 end 49 50 top_reset_sqr.r_sqr=env.r_agt.sqr; 51 top_reset_sqr.h_sqr=env.h_agt.sqr; 52 endfunction 53 54 virtual function void end_of_elaboration_phase(uvm_phase phase); 55 super.end_of_elaboration_phase(phase); 56 env.regmodel.set_coverage(UVM_CVR_ALL); 57 endfunction 58 59 virtual task shutdown_phase(uvm_phase phase); 60 super.shutdown_phase(phase); 61 phase.raise_objection(this); 62 env.sb.wait_for_done(); 63 phase.drop_objection(this); 64 endtask: shutdown_phase 65 66 virtual function void final_phase(uvm_phase phase); 67 super.final_phase(phase); 68 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 69 if(uvm_report_enabled(UVM_DEBUG, UVM_INFO, "TOPOLOGY")) begin 70 uvm_top.print_topology(); 71 end 72 if(uvm_report_enabled(UVM_DEBUG, UVM_INFO, "FACTORY")) begin 73 uvm_factory::get().print(); 74 end 75 endfunction 76 endclass 77 78 `include "packet_da_3.sv" 79 80 class test_da_3_inst extends test_base; 81 `uvm_component_utils(test_da_3_inst) 82 83 function new(string name, uvm_component parent); 84 super.new(name, parent); 85 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 86 endfunction 87 88 virtual function void build_phase(uvm_phase phase); 89 super.build_phase(phase); 90 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 91 set_inst_override_by_type("env.i_agent*.seqr.*", packet::get_type(), packet_da_3::get_type()); 92 endfunction 93 endclass 94 95 class test_da_3_type extends test_base; 96 `uvm_component_utils(test_da_3_type) 97 98 function new(string name, uvm_component parent); 99 super.new(name, parent); 100 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 101 endfunction 102 103 virtual function void build_phase(uvm_phase phase); 104 super.build_phase(phase); 105 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 106 set_type_override_by_type(packet::get_type(), packet_da_3::get_type()); 107 endfunction 108 endclass 109 110 class test_da_3_seq extends test_base; 111 `uvm_component_utils(test_da_3_seq) 112 113 function new(string name, uvm_component parent); 114 super.new(name, parent); 115 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 116 endfunction 117 118 virtual function void build_phase(uvm_phase phase); 119 super.build_phase(phase); 120 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 121 uvm_config_db#(bit[15:0])::set(this, "env.i_agent*.seqr", "da_enable", 16'h0008); 122 uvm_config_db#(int)::set(this, "env.i_agent*.seqr", "item_count", 20); 123 endfunction 124 endclass 125 126 class test_host_bfm extends test_base; 127 `uvm_component_utils(test_host_bfm) 128 function new(string name, uvm_component parent); 129 super.new(name,parent); 130 endfunction 131 132 virtual function void build_phase(uvm_phase phase); 133 super.build_phase(phase); 134 135 uvm_config_db#(uvm_object_wrapper)::set(this,"env.*.configure_phase","default_sequence",null); 136 uvm_config_db#(uvm_object_wrapper)::set(this,"env.*.main_phase","default_sequence",null); 137 uvm_config_db#(uvm_object_wrapper)::set(this,"env.h_agt.sqr.main_phase","default_sequence",host_bfm_sequence::get_type()); 138 endfunction: build_phase 139 endclass: test_host_bfm 140 141 class test_host_ral extends test_base; 142 `uvm_component_utils(test_host_ral) 143 function new(string name, uvm_component parent); 144 super.new(name,parent); 145 endfunction 146 147 virtual function void build_phase(uvm_phase phase); 148 super.build_phase(phase); 149 150 uvm_config_db#(uvm_object_wrapper)::set(this,"env.*.configure_phase","default_sequence",null); 151 uvm_config_db#(uvm_object_wrapper)::set(this,"env.*.main_phase","default_sequence",null); 152 uvm_config_db#(uvm_object_wrapper)::set(this,"env.h_agt.sqr.main_phase","default_sequence",host_ral_test_sequence::get_type()); 153 endfunction: build_phase 154 endclass: test_host_ral 155 156 class test_ral_selftest extends test_base; 157 `uvm_component_utils(test_ral_selftest) 158 string seq_name="uvm_reg_bit_bash_seq"; 159 uvm_reg_sequence selftest_seq; 160 top_reset_sequence top_reset_seq; 161 162 function new(string name, uvm_component parent); 163 super.new(name,parent); 164 endfunction 165 166 virtual function void build_phase(uvm_phase phase); 167 super.build_phase(phase); 168 169 uvm_config_db#(uvm_object_wrapper)::set(this,"*","default_sequence",null); 170 endfunction: build_phase 171 172 virtual task run_phase(uvm_phase phase); 173 phase.raise_objection(this, "starting reset tests"); 174 top_reset_seq=top_reset_sequence::type_id::create("top_reset_seq",this); 175 top_reset_seq.start(top_reset_sqr); 176 clp.get_arg_value("+seq=",seq_name); 177 $cast(selftest_seq, uvm_factory::get().create_object_by_name(seq_name)); 178 selftest_seq.model=env.regmodel; 179 selftest_seq.start(env.h_agt.sqr); 180 phase.drop_objection(this,"Done with register tests"); 181 endtask: run_phase 182 183 endclass: test_ral_selftest
3.router_env.sv
(1) regmodel, adapter, predictor的声明及例化;
(2) connect_phase内,建立regmodel的uvm_reg_map与uvm_reg_adapter, bus_sequencer的联系,建立predictor与uvm_reg_map, uvm_reg_adapter以及bus_agent的联系;
1 `ifndef ROUTER_ENV__SV 2 `define ROUTER_ENV__SV 3 4 `include "input_agent.sv" 5 `include "reset_agent.sv" 6 `include "output_agent.sv" 7 `include "ms_scoreboard.sv" 8 9 `include "host_agent.sv" 10 11 12 class router_env extends uvm_env; 13 `uvm_component_utils(router_env) 14 15 reset_agent r_agent; 16 input_agent i_agent[16]; 17 scoreboard sb; 18 output_agent o_agent[16]; 19 host_agent h_agent; 20 21 ral_block_host_regmodel regmodel; //regmodel 22 reg_adapter adapter; //adapter23 24 typedef uvm_reg_predictor #(host_data) hreg_predictor; 25 hreg_predictor hreg_predictor; //predictor26 27 function new(string name, uvm_component parent); 28 super.new(name, parent); 29 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 30 endfunction 31 32 virtual function void build_phase(uvm_phase phase); 33 super.build_phase(phase); 34 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 35 36 r_agent = reset_agent::type_id::create("r_agent", this); 37 uvm_config_db #(uvm_object_wrapper)::set(this, {r_agent.get_name(), ".", "seqr.reset_phase"}, "default_sequence", reset_sequence::get_type()); 38 39 foreach (i_agent[i]) begin 40 i_agent[i] = input_agent::type_id::create($sformatf("i_agent[%0d]", i), this); 41 uvm_config_db #(int)::set(this, i_agent[i].get_name(), "port_id", i); 42 uvm_config_db #(uvm_object_wrapper)::set(this, {i_agent[i].get_name(), ".", "seqr.main_phase"}, "default_sequence", router_input_port_reset_sequence::get_type()); 43 uvm_config_db #(uvm_object_wrapper)::set(this, {i_agent[i].get_name(), ".", "seqr.main_phase"}, "default_sequence", packet_sequence::get_type()); 44 end 45 46 sb = scoreboard::type_id::create("sb", this); 47 48 foreach (o_agent[i]) begin 49 o_agent[i] = output_agent::type_id::create($sformatf("o_agent[%0d]",i),this); 50 uvm_config_db #(int)::set(this, o_agent[i].get_name(), "port_id", i); 51 end 52 53 h_agent = host_agent::type_id::create("h_agent", this); 54 adapter = reg_adapter::type_id::create("adapter",this); //adapter的例化;55 56 uvm_config_db #(ral_block_host_regmodel)::get(this, "", "regmodel", regmodel); 57 58 if (regmodel == null) begin 59 string hdl_path; 60 if (!uvm_config_db #(string)::get(this, "", "hdl_path", hdl_path)) begin 61 `uvm_warning("HOSTCFG", "HDL path for backdoor not set!"); 62 end 63 regmodel = ral_block_host_regmodel::type_id::create("regmodel", this); 64 regmodel.build(); 65 regmodel.lock_model(); 66 regmodel.set_hdl_path_root(hdl_path); 67 end 68 69 uvm_config_db#(ral_block_host_regmodel)::set(this, h_agt.get_name(), "regmodel", regmodel); 70 uvm_config_db#(uvm_object_wrapper)::set(this,{h_agt.get_name(), ".", "sqr.configure_phase"}, "default_sequence", ral_port_unlock_sequence::get_type()); 71 hreg_predict=hreg_predictor::type_id::create("h_reg_predict",this); //predictor的例化; 72 endfunction 73 74 virtual function void connect_phase(uvm_phase phase); 75 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 76 foreach (i_agent[i]) begin 77 i_agent[i].analysis_port.connect(sb.before_export); 78 end 79 foreach (o_agent[i]) begin 80 o_agent[i].analysis_port.connect(sb.after_export); 81 end 82 83 regmodel.default_map.set_sequencer(h_agent.seqr, adapter); 84 85 regmodel.default_map.set_auto_predict(0); 86 hreg_predict.map=regmodel.get_default_map(); 87 hreg_predict.adapter=adapter; 88 h_agt.analysis_port.connect(hreg_predict.bus_in); 89 endfunction 90 endclass 91 92 `endif
4.top_reset_sequence.sv
1 class top_reset_sequence extends uvm_sequence; 2 `uvm_object_utils(top_reset_sequence) 3 `uvm_declare_p_sequencer(top_reset_sequencer) 4 5 reset_sequence r_seq; 6 router_input_port_reset_sequence i_seq; 7 host_reset_sequence h_seq; 8 uvm_event reset_event=uvm_event_pool::get_global("reset"); 9 10 function new(string name="top_reset_sequence"); 11 super.new(name); 12 `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH) 13 `ifdef UVM_POST_VERSION_1_1 14 set_automatic_phase_objection(1); 15 `endif 16 endfunction 17 18 virtual task body(); 19 `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH) 20 fork 21 `uvm_do_on(r_seq,p_sequencer.r_sqr); 22 foreach(p_sequencer.pkt_sqr[i]) begin 23 fork 24 int j=i; 25 begin 26 reset_event.wait_on();//该处采用了wait_on()而不是wait_trigger,与sequence和driver行为相关; 27 `uvm_do_on(i_seq,p_sequencer.pkt_sqr[j]); 28 end 29 join_none 30 end 31 begin 32 reset_event.wait_on(); 33 `uvm_do_on(h_seq, p_sequencer.h_sqr) 34 end 35 join 36 endtask 37 38 `ifdef UVM_VERSION_1_1 39 virtual task pre_start(); 40 `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH) 41 if((get_parent_sequence()==null) && (starting_phase!=null)) 42 starting_phase.raise_objection(this); 43 endtask 44 virtual task post_start(); 45 `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH) 46 if((get_parent_sequence()==null) && (starting_phase!=null)) 47 starting_phase.raise_objection(this); 48 endtask 49 `endif 50 endclass
5.host_data & reg_adapter
5.1 host_data
1 class host_data extends uvm_sequence_item; 2 typedef enum {READ, WRITE} kind_e; 3 rand kind_e kind; 4 rand uvm_status_e status; 5 rand bit[15:0] addr; 6 rand bit[15:0] data; 7 8 `uvm_object_utils_begin(host_data) 9 `uvm_field_int(addr, UVM_ALL_ON) 10 `uvm_field_int(data, UVM_ALL_ON) 11 `uvm_field_enum(kind_e, kind, UVM_ALL_ON) 12 `uvm_field_enum(uvm_status_e, status, UVM_ALL_ON) 13 `uvm_object_utils_end 14 15 function new(string name="host_data"); 16 super.new(name); 17 `uvm_info("Trace", $sformatf("%m"), UVM_HIGH); 18 status.rand_mode(0); 19 endfunction 20 endclass
5.2 reg_adapter
1 class reg_adapter extends uvm_reg_adapter; 2 `uvm_object_utils(reg_adapter) 3 4 function new(string name="reg_adapter"); 5 super.new(name); 6 `uvm_info("Trace", $sformatf("%m"), UVM_HIGH); 7 endfunction 8 9 virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw); 10 host_data tr; 11 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 12 13 tr = host_data::type_id::create("tr"); 14 tr.kind = (rw.kind == UVM_READ) ? host_data::READ : host_data::WRITE; 15 tr.addr = rw.addr; 16 tr.data = rw.data; 17 return tr; 18 19 endfunction 20 21 virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw); 22 host_data tr; 23 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 24 25 if (!$cast(tr, bus_item)) begin 26 `uvm_fatal("NOT_HOST_REG_TYPE", "bus_item is not correct type"); 27 end 28 rw.kind = (tr.kind == host_data::READ) ? UVM_READ : UVM_WRITE; 29 rw.addr = tr.addr; 30 rw.data = tr.data; 31 rw.status = tr.status; 32 33 endfunction 34 endclass
6.host_sequences
6.1host_sequence_base
1 class host_sequence_base extends uvm_sequence #(host_data); 2 `uvm_object_utils(host_sequence_base) 3 4 virtual host_io vif; 5 uvm_sequencer_base p_sqr; 6 7 function new(string name = "host_sequence_base"); 8 super.new(name); 9 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 10 endfunction 11 12 virtual task pre_start(); 13 p_sqr=get_sequencer(); 14 ... 15 endtask 16 17 ... 18 endclass
6.2host_reset_sequence
1 class host_reset_sequence extends host_sequence_base; 2 `uvm_object_utils(host_reset_sequence) 3 4 function new(string name="host_reset_sequence"); 5 super.new(name); 6 endfunction 7 8 virtual task body(); 9 vif.wr_n = 1'b1; 10 vif.rd_n = 1'b1; 11 vif.address = 'z; 12 vif.data = 'z; 13 endtask 14 15 endclass
6.3host_bfm_sequence
1 class host_bfm_sequence extends host_sequence_base; 2 `uvm_object_utils(host_bfm_sequence) 3 4 function new(string name = "host_bfm_sequence"); 5 super.new(name); 6 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 7 endfunction 8 9 virtual task body(); 10 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 11 `uvm_do_with(req, {addr == 'h0; kind == host_data::READ;}); 12 13 if(req.data != 'h5a03) begin 14 `uvm_fatal("BFM_ERR",$sformatf("HOST_ID is %4h instead of 'h5a03",req.data)) 15 end 16 17 `uvm_do_with(req, {addr == 'h100; kind == host_data::READ;}); 18 19 if(req.data != '1) begin 20 `uvm_fatal("BFM_ERR",$sformatf("HOST_ID is %4h instead of 'hffff",req.data)) 21 end 22 23 `uvm_do_with(req, {addr == 'h100; data == '0; kind == host_data::WRITE;}); 24 `uvm_do_with(req, {addr == 'h100; kind == host_data::READ;}); 25 26 if(req.data != '0) begin 27 `uvm_fatal("BFM_ERR",$sformatf("HOST_ID is %4h instead of 'h0000",req.data)) 28 end 29 30 endtask 31 32 endclass
6.4host_ral_sequence_base
(1)uvm_reg_sequence内通过config_db::set()方法获取regmodel的句柄;
1 class host_ral_sequence_base extends uvm_reg_sequence #(host_sequence_base); 2 `uvm_object_utils(host_ral_sequence_base) 3 ral_block_host_regmodel regmodel; 4 5 function new(string name = "host_ral_sequence_base"); 6 super.new(name); 7 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 8 endfunction 9 10 virtual task pre_start(); 11 super.pre_start(); 12 if(!uvm_config_db#(ral_block_host_regmodel)::get(p_sqr.get_parent(),"","regmodel", regmodel)) begin 13 `uvm_info("RAL_CFG","regmodel not set through configureation.",UVM_MEDIUM) 14 if(regmodel==null) begin 15 `uvm_fatal("RAL_CFG","regmodel not set") 16 end 17 end 18 endtask 19 endclass
6.5host_ral_test_sequence
1 class host_ral_test_sequence extends host_ral_sequence_base; 2 `uvm_object_utils(host_ral_test_sequence) 3 4 function new(string name="host_ral_test_sequence"); 5 super.new(name); 6 endfunction 7 8 virtual task body(); 9 uvm_status_e status; 10 uvm_reg_data_t data; 11 12 regmodel.HOST_ID.read(.status(status), .value(data), .path(UVM_BACKDOOR), .parent(this)); 13 ... 14 endtask 15 endclass
7.reset_sequence.sv & reset_agent.sv(省略,见uvm lab5)
8.input_agent.sv & iMonitor.sv & driver.sv(省略)
9.output_agent.sv & oMonitor.sv(省略)
10.scoreboard.sv & ms_scoreboard.sv(省略)
11.host_agent.sv & host_driver.sv & host_monitor.sv & host_sequencer.sv
1 `ifndef HOST_AGENT__SV 2 `define HOST_AGENT__SV 3 4 `include "host_sequence.sv" 5 6 typedef uvm_sequencer #(host_data) host_sequencer; 7 typedef class host_driver; 8 typedef class host_monitor; 9 10 class host_agent extends uvm_agent; 11 virtual host_io sigs; // DUT host interface 12 uvm_analysis_port #(host_data) analysis_port; 13 host_sequencer seqr; 14 host_driver drv; 15 host_monitor mon; 16 17 `uvm_component_utils(host_agent) 18 19 function new(string name, uvm_component parent); 20 super.new(name, parent); 21 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 22 endfunction 23 24 virtual function void build_phase(uvm_phase phase); 25 super.build_phase(phase); 26 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 27 28 // The agent retrieves virtual interface. 29 uvm_config_db#(virtual host_io)::get(this, "", "host_io", sigs); 30 31 if (is_active) begin 32 seqr = host_sequencer::type_id::create("seqr", this); 33 drv = host_driver::type_id::create("drv", this); 34 uvm_config_db#(virtual host_io)::set(this, "drv", "host_io", sigs); 35 uvm_config_db#(virtual host_io)::set(this, "seqr", "host_io", sigs); 36 end 37 mon = host_monitor::type_id::create("mon", this); 38 uvm_config_db#(virtual host_io)::set(this, "mon", "host_io", sigs); 39 endfunction 40 41 virtual function void connect_phase(uvm_phase phase); 42 super.connect_phase(phase); 43 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 44 if (is_active) begin 45 drv.seq_item_port.connect(seqr.seq_item_export); 46 end 47 endfunction 48 endclass 49 50 class host_driver extends uvm_driver #(host_data); 51 virtual host_io sigs; 52 event go; 53 54 `uvm_component_utils(host_driver) 55 56 function new(string name, uvm_component parent); 57 super.new(name, parent); 58 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 59 endfunction 60 61 virtual function void build_phase(uvm_phase phase); 62 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 63 if (!uvm_config_db#(virtual host_io)::get(this, "", "host_io", sigs)) begin 64 `uvm_fatal("CFGERR", "DUT host interface not set"); 65 end 66 endfunction 67 68 virtual task pre_reset_phase(uvm_phase phase); 69 sigs.wr_n = 'x; 70 sigs.address = 'x; 71 sigs.data = 'x; 72 endtask 73 74 virtual task reset_phase(uvm_phase phase); 75 sigs.wr_n = '1; 76 sigs.address = '1; 77 sigs.data = '1; 78 endtask 79 80 virtual task post_reset_phase(uvm_phase phase); 81 // -> go; 82 endtask 83 84 virtual task run_phase(uvm_phase phase); 85 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 86 // suspend(); 87 forever begin 88 seq_item_port.get_next_item(req); 89 `uvm_info("RUN", { "Before process\n", req.sprint() }, UVM_FULL); 90 data_rw(req); 91 `uvm_info("RUN", { "After process\n", req.sprint() }, UVM_FULL); 92 seq_item_port.item_done(); 93 end 94 endtask 95 96 virtual task data_rw(host_data req); 97 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 98 case(req.kind) 99 host_data::READ: begin 100 sigs.wr_n = '1; 101 sigs.cb.address <= req.addr; 102 @(sigs.cb); 103 req.data = sigs.cb.data; 104 end 105 host_data::WRITE: begin 106 sigs.wr_n = '0; 107 sigs.data = req.data; 108 sigs.cb.address <= req.addr; 109 @(sigs.cb); 110 sigs.wr_n = '1; 111 sigs.data = 'z; 112 end 113 default: begin `uvm_fatal("REGERR", "Not a valid Register Command"); end 114 endcase 115 endtask 116 117 task suspend(); 118 wait(go.triggered); 119 endtask 120 endclass 121 122 class host_monitor extends uvm_monitor; 123 uvm_analysis_port #(host_data) analysis_port; 124 virtual host_io sigs; 125 event go; 126 127 `uvm_component_utils(host_monitor) 128 129 function new(string name, uvm_component parent); 130 super.new(name, parent); 131 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 132 endfunction 133 134 virtual function void build_phase(uvm_phase phase); 135 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 136 if (!uvm_config_db#(virtual host_io)::get(this, "", "host_io", sigs)) begin 137 `uvm_fatal("CFGERR", "DUT host interface not set"); 138 end 139 analysis_port = new("analysis_port", this); 140 endfunction 141 142 virtual task run_phase(uvm_phase phase); 143 host_data tr; 144 suspend(); 145 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 146 forever begin 147 tr = host_data::type_id::create("tr", this); 148 data_rw(tr); 149 analysis_port.write(tr); 150 end 151 endtask 152 153 virtual task post_reset_phase(uvm_phase phase); 154 -> go; 155 endtask 156 157 virtual task data_rw(host_data tr); 158 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 159 if(!sigs.mon.wr_n) begin 160 tr.kind = host_data::WRITE; 161 tr.addr = sigs.mon.address; 162 tr.data = sigs.mon.data; 163 `uvm_info("Got WRITE", {"\n", tr.sprint()}, UVM_DEBUG); 164 @(sigs.mon); 165 end else begin 166 fork 167 begin 168 fork 169 @(sigs.mon.wr_n); 170 @(sigs.mon.address); 171 join_any 172 disable fork; 173 tr.addr = sigs.mon.address; 174 tr.data = sigs.mon.data; 175 if(!sigs.mon.wr_n) begin 176 tr.kind = host_data::WRITE; 177 `uvm_info("Got WRITE", {"\n", tr.sprint()}, UVM_DEBUG); 178 end else begin 179 tr.kind = host_data::READ; 180 `uvm_info("Got READ", {"\n", tr.sprint()}, UVM_DEBUG); 181 end 182 @(sigs.mon); 183 end 184 join 185 end 186 endtask 187 188 task suspend(); 189 wait(go.triggered); 190 endtask 191 endclass 192 193 `endif
12.host.ralf
1 # This file contains the DUT register and memory definitions 2 3 # 4 # Lab 7 - Task 6 5 # Populate each of the following register and memory specification. 6 # 7 register HOST_ID { 8 # ToDo 9 field REV_ID { 10 bits 8; 11 access ro; 12 reset 'h03; 13 } 14 field CHIP_ID { 15 bits 8; 16 access ro; 17 reset 'h5A; 18 } 19 } 20 21 register PORT_LOCK { 22 # ToDo 23 field LOCK { 24 bits 16; 25 access w1c; 26 reset 'hffff; 27 } 28 } 29 30 register REG_ARRAY { 31 # ToDo 32 field USER_REG { 33 bits 16; 34 access rw; 35 reset 'h0; 36 } 37 } 38 39 memory RAM { 40 # ToDo 41 size 4k; 42 bits 16; 43 access rw; 44 } 45 46 # 47 # The block level declaration is done for you. This include the hdl_path name for 48 # the signals in the DUT. Later on, the hdl_path will be in RAL backdoor access. 49 # 50 block host_regmodel { 51 bytes 2; 52 register HOST_ID (host_id) @'h0000; 53 register PORT_LOCK (lock) @'h0100; 54 register REG_ARRAY[256] (host_reg[%d]) @'h1000; # array must specify HDL index 55 memory RAM (ram) @'h4000; 56 }
13.ral_host_regmodel.sv
(1) uvm_reg和uvm_reg_model的定义;
(2) add_hdl_path(), add_reg(), add_mem()的使用;
1 `ifndef RAL_HOST_REGMODEL 2 `define RAL_HOST_REGMODEL 3 4 import uvm_pkg::*; 5 6 class ral_reg_HOST_ID extends uvm_reg; 7 uvm_reg_field REV_ID; 8 uvm_reg_field CHIP_ID; 9 10 function new(string name = "HOST_ID"); 11 super.new(name, 16,build_coverage(UVM_NO_COVERAGE)); 12 endfunction: new 13 virtual function void build(); 14 this.REV_ID = uvm_reg_field::type_id::create("REV_ID"); 15 this.REV_ID.configure(this, 8, 0, "RO", 0, 8'h03, 1, 0, 1); 16 this.CHIP_ID = uvm_reg_field::type_id::create("CHIP_ID"); 17 this.CHIP_ID.configure(this, 8, 8, "RO", 0, 8'h5A, 1, 0, 1); 18 endfunction: build 19 20 `uvm_object_utils(ral_reg_HOST_ID) 21 22 endclass : ral_reg_HOST_ID 23 24 25 class ral_reg_PORT_LOCK extends uvm_reg; 26 rand uvm_reg_field LOCK; 27 28 function new(string name = "PORT_LOCK"); 29 super.new(name, 16,build_coverage(UVM_NO_COVERAGE)); 30 endfunction: new 31 virtual function void build(); 32 this.LOCK = uvm_reg_field::type_id::create("LOCK"); 33 this.LOCK.configure(this, 16, 0, "W1C", 0, 16'hffff, 1, 0, 1); 34 endfunction: build 35 36 `uvm_object_utils(ral_reg_PORT_LOCK) 37 38 endclass : ral_reg_PORT_LOCK 39 40 41 class ral_reg_REG_ARRAY extends uvm_reg; 42 rand uvm_reg_field USER_REG; 43 44 function new(string name = "REG_ARRAY"); 45 super.new(name, 16,build_coverage(UVM_NO_COVERAGE)); 46 endfunction: new 47 virtual function void build(); 48 this.USER_REG = uvm_reg_field::type_id::create("USER_REG"); 49 this.USER_REG.configure(this, 16, 0, "RW", 0, 16'h0, 1, 0, 1); 50 endfunction: build 51 52 `uvm_object_utils(ral_reg_REG_ARRAY) 53 54 endclass : ral_reg_REG_ARRAY 55 56 57 class ral_mem_RAM extends uvm_mem; 58 function new(string name = "RAM"); 59 super.new(name, `UVM_REG_ADDR_WIDTH'h1000, 16, "RW", build_coverage(UVM_NO_COVERAGE)); 60 endfunction 61 virtual function void build(); 62 endfunction: build 63 64 `uvm_object_utils(ral_mem_RAM) 65 66 endclass : ral_mem_RAM 67 68 69 class ral_block_host_regmodel extends uvm_reg_block; 70 rand ral_reg_HOST_ID HOST_ID; 71 rand ral_reg_PORT_LOCK PORT_LOCK; 72 rand ral_reg_REG_ARRAY REG_ARRAY[256]; 73 rand ral_mem_RAM RAM; 74 uvm_reg_field HOST_ID_REV_ID; 75 uvm_reg_field REV_ID; 76 uvm_reg_field HOST_ID_CHIP_ID; 77 uvm_reg_field CHIP_ID; 78 rand uvm_reg_field PORT_LOCK_LOCK; 79 rand uvm_reg_field LOCK; 80 rand uvm_reg_field REG_ARRAY_USER_REG[256]; 81 rand uvm_reg_field USER_REG[256]; 82 83 function new(string name = "host_regmodel"); 84 super.new(name, build_coverage(UVM_NO_COVERAGE)); 85 endfunction: new 86 87 virtual function void build(); 88 this.default_map = create_map("", 0, 2, UVM_LITTLE_ENDIAN); 89 this.HOST_ID = ral_reg_HOST_ID::type_id::create("HOST_ID"); 90 this.HOST_ID.build(); 91 this.HOST_ID.configure(this, null, ""); 92 this.HOST_ID.add_hdl_path('{ 93 94 '{"host_id", -1, -1} 95 }); 96 this.default_map.add_reg(this.HOST_ID, `UVM_REG_ADDR_WIDTH'h0, "RW", 0); 97 this.HOST_ID_REV_ID = this.HOST_ID.REV_ID; 98 this.REV_ID = this.HOST_ID.REV_ID; 99 this.HOST_ID_CHIP_ID = this.HOST_ID.CHIP_ID; 100 this.CHIP_ID = this.HOST_ID.CHIP_ID; 101 this.PORT_LOCK = ral_reg_PORT_LOCK::type_id::create("PORT_LOCK"); 102 this.PORT_LOCK.build(); 103 this.PORT_LOCK.configure(this, null, ""); 104 this.PORT_LOCK.add_hdl_path('{ 105 106 '{"lock", -1, -1} 107 }); 108 this.default_map.add_reg(this.PORT_LOCK, `UVM_REG_ADDR_WIDTH'h100, "RW", 0); 109 this.PORT_LOCK_LOCK = this.PORT_LOCK.LOCK; 110 this.LOCK = this.PORT_LOCK.LOCK; 111 foreach (this.REG_ARRAY[i]) begin 112 int J = i; 113 this.REG_ARRAY[J] = ral_reg_REG_ARRAY::type_id::create($psprintf("REG_ARRAY[%0d]",J)); 114 this.REG_ARRAY[J].build(); 115 this.REG_ARRAY[J].configure(this, null, ""); 116 this.REG_ARRAY[J].add_hdl_path('{ 117 118 '{$psprintf("host_reg[%0d]", J), -1, -1} 119 }); 120 this.default_map.add_reg(this.REG_ARRAY[J], `UVM_REG_ADDR_WIDTH'h1000+J*`UVM_REG_ADDR_WIDTH'h1, "RW", 0); 121 this.REG_ARRAY_USER_REG[J] = this.REG_ARRAY[J].USER_REG; 122 this.USER_REG[J] = this.REG_ARRAY[J].USER_REG; 123 end 124 this.RAM = ral_mem_RAM::type_id::create("RAM"); 125 this.RAM.build(); 126 this.RAM.configure(this, "ram"); 127 this.default_map.add_mem(this.RAM, `UVM_REG_ADDR_WIDTH'h4000, "RW", 0); 128 endfunction : build 129 130 `uvm_object_utils(ral_block_host_regmodel) 131 132 endclass : ral_block_host_regmodel 133 134 135 136 `endif