Thursday, May 5, 2011

Aldec - Events

Aldec - Events

You can observe the Aldec Events in above link

Macros to simplify the Register Write/Read Operations using OVM_RGM Package

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

  1. Two Register Files with names IEEE and EXTE.
  2. IEEE Register File will have Reg0 and Reg1 Register.
    • Reg0 will have Fields with names F1 and F2.
  3. 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)
 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)