Tuesday, August 9, 2011

How to calculate the sum of data in a queue of bits in SystemVerilog?


    The built-in array method sum() will return a value according to the type of queue.
    such as:
    bit flags[$];
    ....
    flags.sum() will return 0 or 1 because the type of queue is bit

    Solution

    To actually sum the queue data use:
    mysum = flags.sum() with (int'(item));
    Below is an example for reference:
    module test;
     bit flags[$];
     int mysum;
     initial
     begin
     flags[0] =1;
     flags[1]=1;
     mysum = flags.sum();  //this will return 0 or 1
     $display("%0d",mysum);
     mysum = flags.sum() with (int'(item));  //this will return the total value of every element.
     $display("%0d",mysum);
    end
    endmodule

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)

Tuesday, April 26, 2011

Killing Sequences on Sequencer Abruptly

Sometimes you may need to drive input until you see come condition or some timer expires. Once you meet that condition, you need to stop generating stimulus. The code for this scenario look like below.


//Test
begin
    fork
    begin
        wait(rtl_linkup == 1);
    end
    begin
       forever
           idles_transmit.start(Sequencer);
    end
  join_any
  disable fork;
end


In the above code we are driving idles until rtl_linkup condition is observed. But here there is a problem, As we are trying kill idles_transmit sequence abruptly when condition is met, this may cause the sequencer to be in intermittent state. This will cause the problem on the next sequences which trigger on the same sequencer. As sequencer is in intermittent state it may not get grant and will wait for for grant forever. To avoid this problem we need to reset the sequencer after killing threads. The code look like below.


//Test
begin
   fork
      begin
        wait(rtl_linkup == 1);
      end
      begin
           forever
              idles_transmit.start(Sequencer);
      end
   join_any
   disable fork;
   Sequencer.stop_sequence();
end


In the above code the stop_sequences call will reset the sequencer variables and won't cause any problem for the next sequences which are triggered on same sequencer. Here also we have another problem with the sequence thread which is killed with disable fork. Sometimes by the time thread is killed request might have been sent to driver. if thread is killed and stop_sequence is called before receiving the item_done, item_done will cause fatal error as request fifo is empty. So we need to kill thread and call of stop_sequence only after receiving item_done from driver. The code will look like below.


//Sequence .
class idles_transmit extends ovm_sequence #(REQ= packet);
    bit received_item_done;
    task body();
       wait_for_grant();
       assert(req.randomize());
       send_req(req);
       received_item_done = 0;
       wait_for_item_done();
       received_item_done = 1;
   endtask
endclass


//Test
begin
    fork
        begin
            wait(rtl_linkup == 1);
        end
        begin
             forever
                  idles_transmit.start(Sequencer);
        end
     join_any
     @(posedge idles_transmit.received_item_done);
     disable fork;
      Sequencer.stop_sequence();
end


In the above code we are trying to kill the thread and reseting sequencer state only after receiving the ite_done for the request sent, which is the idle way to stop thread.

Sunday, April 10, 2011

IT'S NOT HOW GOOD YOU ARE, IT'S HOW GOOD YOU WANT TO BE

IT'S NOT HOW GOOD YOU ARE, IT'S HOW GOOD YOU WANT TO BE - PAUL ARDEN

Everybody will have dreams and want to be Good with Success in Life. In similar lines, I came across above book and found it has beautiful points to follow.
Here is the gist of Book.

1. Nearly all rich and powerful people are not notably talented, educated, charming or good-looking. They become rich and powerful by wanting to be rich and powerful.
2. Your vision of where or who you want to be is the greatest asset you have. Without having a goal it's difficult to score.
3. All creative people need something to rebel against, it's what gives their lives excitement, and it's creative people who make the clients' lives exciting.
4. There is no instant solution, to become good. It is only through experience and mistakes.
5. You can achieve the unachievable. Always aim beyond what you are capable of. Try to do things that you are incapable of.
6. Always dream about how good you want to be.
7. Energy is the 75 % of the job. 
8. Don't seek praise. Seek criticism. So that you can always improve your idea.
9. If You are involved in something that goes wrong, never blame others. Blame no one but yourself. If you accept responsibility, you are in a position to do something about it.
10. Give away everything you know, and more will come back to you.
11. Don't look for the next opportunity. The one you have in hand is the opportunity.
12. Eliminate the Negative.
13. Don't promise what you can't deliver. 
14. Know your client Aims for whom you are working.
15. Always show a client what he want's first, he is then relaxed and is prepared to look at what you want to show him.
16. Don't take No for an answer.
17. When it can't be done, do it. If you don't do it, it doesn't exist.
18. If you can't solve the problem, it's because you are playing by the rules.
19. The person who doesn't make mistakes is unlikely to make anything.
20. It's wrong to be right.
21. Don't be afraid of Silly Ideas.
22. How you perceive yourself is how others will see you.
23. It's not what you know. It is who you know.
24. Don't give a speech. Put on a show.
25. Rough Layouts sell ideas better than polished ones. Show the client a scribble. Explain it to him, talk to him through it, let him use his imagination. Work with him rather than confronting with idea. 
26. If you get stuck, use a different pen.
27. Don't hand over to a team hoping that they will produce the magic. It's for you to lead them along the path of enlightenment.
28. Don't be afraid to work with the best.
29. Don't try to win awards. Be true to your subject and you will be far more likely to create something that is timeless.
30. Success is going from failure to failure with no loss of enthusiasm.
31. The first thing to decide before you walk into any negotiation is what to do if the other fellow says no.
32. Those who lack courage will always find a philosophy to justify it. 
33. If everything seems under control you're not going fast enough.
34. We don't see things as they are. We see them as we are.


Finally at some point we need to draw line somewhere.