寄存器模型的完善和嵌入
实现reg2mcdf_adapter类的方法reg2bus以及bus2reg。
class reg2mcdf_adapter extends uvm_reg_adapter;
`uvm_object_utils ( reg2mcdf_adapter)
function new ( string name = "reg2mcdf_adapter" ) ;
super . new ( name) ;
provides_responses = 1 ;
endfunction
function uvm_sequence_item reg2bus ( const ref uvm_reg_bus_op rw) ;
reg_trans t = reg_trans:: type_id :: create ( "t" ) ;
t. cmd = ( rw. kind == UVM_WRITE) ? `WRITE : `READ;
t. addr = rw. addr;
t. data = rw. data;
return t;
endfunction
function void bus2reg ( uvm_sequence_item bus_item, ref uvm_reg_bus_op rw) ;
reg_trans t;
if ( ! $cast ( t, bus_item) ) begin
`uvm_fatal ( "CASTFAIL" , "Provided bus_item is not of the correct type" )
return ;
end
rw. kind = ( t. cmd == `WRITE) ? UVM_WRITE : UVM_READ;
rw. addr = t. addr;
rw. data = t. data;
rw. status = UVM_IS_OK;
endfunction
endclass
在mcdf_env中分别声明register block,adapter和predictor,并完成例化,同时在connect阶段中完成句柄的连接。
class mcdf_env extends uvm_env;
. . .
mcdf_rgm rgm;
reg2mcdf_adapter adapter;
uvm_reg_predictor #( reg_trans) predictor;
`uvm_component_utils ( mcdf_env)
. . .
function void build_phase ( uvm_phase phase) ;
. . .
rgm = mcdf_rgm:: type_id :: create ( "rgm" , this ) ;
rgm. build ( ) ;
adapter = reg2mcdf_adapter:: type_id :: create ( "adapter" , this ) ;
predictor = uvm_reg_predictor#( reg_trans) :: type_id :: create ( "predictor" , this ) ;
endfunction
function void connect_phase ( uvm_phase phase) ;
. . .
rgm. map. set_sequencer ( reg_agt. sequencer, adapter) ;
reg_agt. monitor. mon_ana_port. connect ( predictor. bus_in) ;
predictor. map = rgm. map;
predictor. adapter = adapter;
virt_sqr. rgm = rgm;
endfunction
寄存器模型的使用
virtual task body ( ) ;
`uvm_info ( get_type_name ( ) ,
rgm = p_sequencer. rgm;
this . do_reg ( ) ;
this . do_formatter ( ) ;
this . do_data ( ) ;
endtask
将mcdf_data_consistence_basic_virtual_sequence原有的由总线sequence实现的寄存器读写,改为由寄存器模型操作的寄存器读写方式。
task do_reg ( ) ;
bit[ 31 : 0 ] wr_val, rd_val;
uvm_status_e status;
wr_val = ( 1 << 3 ) + ( 0 << 1 ) + 1 ;
rgm. chnl0_ctrl_reg. write ( status, wr_val) ;
rgm. chnl0_ctrl_reg. read ( status, rd_val) ;
void '( this . diff_value ( wr_val, rd_val, "SLV0_WR_REG" ) ) ;
wr_val = ( 2 << 3 ) + ( 1 << 1 ) + 1 ;
rgm. chnl1_ctrl_reg. write ( status, wr_val) ;
rgm. chnl1_ctrl_reg. read ( status, rd_val) ;
void '( this . diff_value ( wr_val, rd_val, "SLV1_WR_REG" ) ) ;
wr_val = ( 3 << 3 ) + ( 2 << 1 ) + 1 ;
rgm. chnl2_ctrl_reg. write ( status, wr_val) ;
rgm. chnl2_ctrl_reg. read ( status, rd_val) ;
void '( this . diff_value ( wr_val, rd_val, "SLV2_WR_REG" ) ) ;
`uvm_do_on ( idle_reg_seq, p_sequencer. reg_sqr)
endtask
将mcdf_full_random_virtual_sequence原有的由总线sequence实现的寄存器读写,改为由寄存器模型预先设置寄存器值,再统一做总线寄存器更新的方式,并且由后门读取的方式取得寄存器值。
task do_reg ( ) ;
bit[ 31 : 0 ] ch0_wr_val;
bit[ 31 : 0 ] ch1_wr_val;
bit[ 31 : 0 ] ch2_wr_val;
uvm_status_e status;
rgm. reset ( ) ;
ch0_wr_val = ( $urandom_range ( 0 , 3 ) << 3 ) + ( $urandom_range ( 0 , 3 ) << 1 ) + $urandom_range ( 0 , 1 ) ;
ch1_wr_val = ( $urandom_range ( 0 , 3 ) << 3 ) + ( $urandom_range ( 0 , 3 ) << 1 ) + $urandom_range ( 0 , 1 ) ;
ch2_wr_val = ( $urandom_range ( 0 , 3 ) << 3 ) + ( $urandom_range ( 0 , 3 ) << 1 ) + $urandom_range ( 0 , 1 ) ;
rgm. chnl0_ctrl_reg. set ( ch0_wr_val) ;
rgm. chnl1_ctrl_reg. set ( ch1_wr_val) ;
rgm. chnl2_ctrl_reg. set ( ch2_wr_val) ;
rgm. update ( status) ;
#100 ns;
rgm. chnl0_ctrl_reg. mirror ( status, UVM_CHECK, UVM_BACKDOOR) ;
rgm. chnl1_ctrl_reg. mirror ( status, UVM_CHECK, UVM_BACKDOOR) ;
rgm. chnl2_ctrl_reg. mirror ( status, UVM_CHECK, UVM_BACKDOOR) ;
`uvm_do_on ( idle_reg_seq, p_sequencer. reg_sqr)
endtask
寄存器内建序列的应用
在mcdf_reg_builtin_virtual_sequence类中,使用uvm_reg_hw_reset_seq,uvm_reg_bit_bash_seq和uvm_reg_access_seq对MCDF寄存器模块展开全面测试。
task do_reg ( ) ;
uvm_reg_hw_reset_seq reg_rst_seq = new ( ) ;
uvm_reg_bit_bash_seq reg_bit_bash_seq = new ( ) ;
uvm_reg_access_seq reg_acc_seq = new ( ) ;
@( negedge p_sequencer. intf. rstn) ;
@( posedge p_sequencer. intf. rstn) ;
`uvm_info ( "BLTINSEQ" , "register reset sequence started" , UVM_LOW)
rgm. reset ( ) ;
reg_rst_seq. model = rgm;
reg_rst_seq. start ( p_sequencer. reg_sqr) ;
`uvm_info ( "BLTINSEQ" , "register reset sequence finished" , UVM_LOW)
`uvm_info ( "BLTINSEQ" , "register bit bash sequence started" , UVM_LOW)
p_sequencer. intf. rstn <= 'b0;
repeat ( 5 ) @( posedge p_sequencer. intf. clk) ;
p_sequencer. intf. rstn <= 'b1;
rgm. reset ( ) ;
reg_bit_bash_seq. model = rgm;
reg_bit_bash_seq. start ( p_sequencer. reg_sqr) ;
`uvm_info ( "BLTINSEQ" , "register bit bash sequence finished" , UVM_LOW)
`uvm_info ( "BLTINSEQ" , "register access sequence started" , UVM_LOW)
p_sequencer. intf. rstn <= 'b0;
repeat ( 5 ) @( posedge p_sequencer. intf. clk) ;
p_sequencer. intf. rstn <= 'b1;
rgm. reset ( ) ;
reg_acc_seq. model = rgm;
reg_acc_seq. start ( p_sequencer. reg_sqr) ;
`uvm_info ( "BLTINSEQ" , "register accesssequence finished" , UVM_LOW)
endtask