The Sequences or macros provided by OVM_RGM can't be used inside the Testcases and those can be used in one of the RGM Sequence only. Also these macros won't allow us to write Field write/read operations.
To avoid this problem in one of our project, our team has come up with a list of some generic Sequences and Macros for OVM_RGM Usage to enable easy Register Operations.
To understand this assume following structure for Register Database for small environment looks like below.
The Register Database will have
To avoid this problem in one of our project, our team has come up with a list of some generic Sequences and Macros for OVM_RGM Usage to enable easy Register Operations.
To understand this assume following structure for Register Database for small environment looks like below.
The Register Database will have
- Two Register Files with names IEEE and EXTE.
- IEEE Register File will have Reg0 and Reg1 Register.
- Reg0 will have Fields with names F1 and F2.
- EXTE Register File will have Reg0.
Generalized Sequence Written for Register Operations:
class Rd_Wr_RGMSequence #(string REGFILENAME = "" ,type REGNAME = ovm_rgm_pkg::ovm_rgm_register_base) extends ovm_rgm_sequence;
rand bit [`OVM_RGM_DWIDTH:0] REQVAL;
bit [`OVM_RGM_DWIDTH:0] RSPVAL;
rand ovm_rgm_op_direction_t OP;
ovm_rgm_pkg::ovm_rgm_container container;
REGNAME rgm_reg;
string path1,path2;
ovm_rgm_pkg::ovm_rgm_register_base reg_rsp_var,r;
`ovm_object_param_utils_begin(Rd_Wr_RGMSequence #(REGFILENAME,REGNAME))
`ovm_field_int(REQVAL,OVM_PRINT)
`ovm_object_utils_end
function new(string name = "Rd_Wr_RGM RANDOM SEQUENCE");
super.new(name);
endfunction
task body();
rgm_reg=REGNAME::type_id::create("SEQRGM");
path1=rgm_reg.get_type_name();
path1 = path1.tolower();
path2 = REGFILENAME.tolower();
path1 = {path2,".",path1};
case (OP)
OP_RD: begin
`rgm_read_by_name(rgm_reg,path1)
get_reg_response(rgm_reg,reg_rsp_var);
this.RSPVAL=rgm_reg.value;
end
OP_WR: begin
`rgm_write_by_name_with(rgm_reg,path1,{value==local::REQVAL;})
get_reg_response(rgm_reg,reg_rsp_var);
end
endcase
ovm_report_info(get_type_name(),"Body of the Rd_WR_RGM sequence ENDING\n");
endtask
endclass
Macros for different Register Operations:
//
//Macro to perform register read
//usage : regread("IEEE",Reg0,bit[4:0]read,p_sequencer Pointer)
//
`define regread(REGFILENAME,REGNAME,DATAREAD,SEQUENCERREF)\
begin\
import `RGM_PKG::*;\
`RGM_PKG::Rd_Wr_RGMSequence #(REGFILENAME,REGNAME) seq;\
seq = `RGM_PKG::Rd_Wr_RGMSequence #(REGFILENAME,REGNAME)::type_id::create("readrgmsequence");\
assert(seq.randomize() with {OP==OP_RD;});\
seq.print();\
seq.start(SEQUENCERREF);\
DATAREAD=seq.RSPVAL;\
end
//
//Macro to perform register write
//usage : regwrite("IEEE",Reg0,'h09,p_sequencer Pointer)
//
`define regwrite(REGFILENAME,REGNAME,WRITEDATA,SEQUENCERREF)\
begin\
import `RGM_PKG::*;\
bit[`OVM_RGM_DWIDTH:0] writedata;\
`RGM_PKG::Rd_Wr_RGMSequence #(REGFILENAME,REGNAME) seq;\
seq = `RGM_PKG::Rd_Wr_RGMSequence #(REGFILENAME,REGNAME)::type_id::create("RD_WR_RGM_SEQUENCE");\
writedata=WRITEDATA;\
assert(seq.randomize() with {OP==OP_WR;REQVAL==local::writedata;});\
seq.print();\
seq.start(SEQUENCERREF);\
end
//
//Macro to perform register field write
//usage : regfldwrite("IEEE",Reg0,{F1:2'b0},p_sequencer Pointer)
//
`define regfldwrite(REGFILENAME,REGNAME,FIELDS,SEQUENCERREF)\
begin\
import `RGM_PKG::*;\
bit[`OVM_RGM_DWIDTH:0] REQVAL;\
REGNAME regfld;\
ovm_rgm_fld_props fld_props=new();\
string path1,path2;\
ovm_rgm_register_base r; \
string s;\
int i=0;\
integer field_updates [string]=FIELDS;\
regfld=REGNAME::type_id::create("FLDRGM");\
s=regfld.get_type_name();\
path1 = s.tolower();\
s=REGFILENAME;\
path2 = s.tolower();\
path1 = {path2,".",path1};\
$cast(r,SEQUENCERREF.container.get_reg_by_name(path1,0));\
while(r.get_field_props(i,fld_props))\
begin\
if(field_updates.exists(fld_props.name_))\
begin\
$display("i am setting the filed %s with %d",fld_props.name_,field_updates[fld_props.name_]);\
r.set_field_value(fld_props.name_,field_updates[fld_props.name_]);\
end\
++i;\
end\
REQVAL=r.read();\
`regwrite(REGFILENAME,REGNAME,REQVAL,SEQUENCERREF)\
end
//
//Macro to perform register field read
//usage : regfldread("IEEE",mode_control,int dataread[string],p_sequencer)
//dataread is an Associative array which indicates the required fields interested
`define regfldread(REGFILENAME,REGNAME,DATAREAD,SEQUENCERREF)\
begin\
import `RGM_PKG::*;\
bit[`OVM_RGM_DWIDTH:0] REQVAL;\
REGNAME regfld;\
ovm_rgm_fld_props fld_props = new();\
string path1,path2;\
integer update [string];\
string s;\
int i=0;\
regfld=REGNAME::type_id::create("FLDRGM");\
s=regfld.get_type_name();\
path1 = s.tolower();\
s=REGFILENAME;\
path2 = s.tolower();\
path1 = {path2,".",path1};\
$cast(regfld,SEQUENCERREF.container.get_reg_by_name(path1));\
`regread(REGFILENAME,REGNAME,REQVAL,SEQUENCERREF)\
regfld.value=REQVAL;\
while(regfld.get_field_props(i,fld_props))\
begin\
update[fld_props.name_]=regfld.get_field_value(fld_props.name_);\
++i;\
end\
DATAREAD=update;\
end
Examples of Usages:
RGM_PKG define will indicate the Chipspecific RGM Package name
To perform the Register Field Read Operation
integer read_data[string];
byte data;
`regfldread("IEEE",`RGM_PKG::Reg0,read_data,p_sequencer.REG_SEQR)
//
//Macro to perform register read
//usage : regread("IEEE",Reg0,bit[4:0]read,p_sequencer Pointer)
//
`define regread(REGFILENAME,REGNAME,DATAREAD,SEQUENCERREF)\
begin\
import `RGM_PKG::*;\
`RGM_PKG::Rd_Wr_RGMSequence #(REGFILENAME,REGNAME) seq;\
seq = `RGM_PKG::Rd_Wr_RGMSequence #(REGFILENAME,REGNAME)::type_id::create("readrgmsequence");\
assert(seq.randomize() with {OP==OP_RD;});\
seq.print();\
seq.start(SEQUENCERREF);\
DATAREAD=seq.RSPVAL;\
end
//
//Macro to perform register write
//usage : regwrite("IEEE",Reg0,'h09,p_sequencer Pointer)
//
`define regwrite(REGFILENAME,REGNAME,WRITEDATA,SEQUENCERREF)\
begin\
import `RGM_PKG::*;\
bit[`OVM_RGM_DWIDTH:0] writedata;\
`RGM_PKG::Rd_Wr_RGMSequence #(REGFILENAME,REGNAME) seq;\
seq = `RGM_PKG::Rd_Wr_RGMSequence #(REGFILENAME,REGNAME)::type_id::create("RD_WR_RGM_SEQUENCE");\
writedata=WRITEDATA;\
assert(seq.randomize() with {OP==OP_WR;REQVAL==local::writedata;});\
seq.print();\
seq.start(SEQUENCERREF);\
end
//
//Macro to perform register field write
//usage : regfldwrite("IEEE",Reg0,{F1:2'b0},p_sequencer Pointer)
//
`define regfldwrite(REGFILENAME,REGNAME,FIELDS,SEQUENCERREF)\
begin\
import `RGM_PKG::*;\
bit[`OVM_RGM_DWIDTH:0] REQVAL;\
REGNAME regfld;\
ovm_rgm_fld_props fld_props=new();\
string path1,path2;\
ovm_rgm_register_base r; \
string s;\
int i=0;\
integer field_updates [string]=FIELDS;\
regfld=REGNAME::type_id::create("FLDRGM");\
s=regfld.get_type_name();\
path1 = s.tolower();\
s=REGFILENAME;\
path2 = s.tolower();\
path1 = {path2,".",path1};\
$cast(r,SEQUENCERREF.container.get_reg_by_name(path1,0));\
while(r.get_field_props(i,fld_props))\
begin\
if(field_updates.exists(fld_props.name_))\
begin\
$display("i am setting the filed %s with %d",fld_props.name_,field_updates[fld_props.name_]);\
r.set_field_value(fld_props.name_,field_updates[fld_props.name_]);\
end\
++i;\
end\
REQVAL=r.read();\
`regwrite(REGFILENAME,REGNAME,REQVAL,SEQUENCERREF)\
end
//
//Macro to perform register field read
//usage : regfldread("IEEE",mode_control,int dataread[string],p_sequencer)
//dataread is an Associative array which indicates the required fields interested
`define regfldread(REGFILENAME,REGNAME,DATAREAD,SEQUENCERREF)\
begin\
import `RGM_PKG::*;\
bit[`OVM_RGM_DWIDTH:0] REQVAL;\
REGNAME regfld;\
ovm_rgm_fld_props fld_props = new();\
string path1,path2;\
integer update [string];\
string s;\
int i=0;\
regfld=REGNAME::type_id::create("FLDRGM");\
s=regfld.get_type_name();\
path1 = s.tolower();\
s=REGFILENAME;\
path2 = s.tolower();\
path1 = {path2,".",path1};\
$cast(regfld,SEQUENCERREF.container.get_reg_by_name(path1));\
`regread(REGFILENAME,REGNAME,REQVAL,SEQUENCERREF)\
regfld.value=REQVAL;\
while(regfld.get_field_props(i,fld_props))\
begin\
update[fld_props.name_]=regfld.get_field_value(fld_props.name_);\
++i;\
end\
DATAREAD=update;\
end
Examples of Usages:
RGM_PKG define will indicate the Chipspecific RGM Package name
To perform the Register Field Read Operation
integer read_data[string];
byte data;
`regfldread("IEEE",`RGM_PKG::Reg0,read_data,p_sequencer.REG_SEQR)
data=read_data["F1"];
To perform the Register Field Write Operation
integer fields_write [string];
fields_write = '{"F1":8'h12,"F2":8'h45} ;
`regfldwrite("IEEE",`RGM_PKG::Reg0,fields_write,p_sequencer.REG_SEQR)
No comments:
Post a Comment