Wednesday, May 26, 2021

Monday, May 24, 2021

constraint example

class A; rand bit[7:0] x[], y[]; constraint x_y_val { x.size() inside {[0:15]}; y.size() inside {[0:15]}; (x.size() + y.size()) <= 16; foreach(x[i]) { x[i] inside{[0:16]}; } foreach(y[i]) { y[i] inside{[0:16]}; } unique{x,y}; } endclass module top(); A a; initial begin a=new; for(int i=0;i<2;i++) begin a.randomize; $display("%0p", a); end end endmodule

Monday, July 17, 2017

cast p_sequencer m_sequencer details

We can use p_sequencer as a handle to the sequencer and through that we can access other sequencers or environment hierarchy in the sequence where uvm_declare_p_sequencer macro has been used.
Below is my understanding and relevant information. You may please correct if required.
`define uvm_declare_p_sequencer(SEQUENCER) \
SEQUENCER p_sequencer;\
virtual function void m_set_p_sequencer();\
super.m_set_p_sequencer(); \
if( !$cast(p_sequencer, m_sequencer)) \
`uvm_fatal("DCLPSQ", \
$sformatf("%m %s Error casting p_sequencer, please verify that this sequence/sequence item is intended to execute on this type of sequencer", get_full_name())) \
endfunction

p_sequencer type is specified in the argument(SEQUENCER) of `uvm_declare_p_sequencer macro.
When we call `uvm_declare_p_sequencer from sequence, it calls super.m_set_p_sequencer function, which internally will call m_set_sequencer of uvm_base_sequencer. 
When we call start task of sequence, it internally calls for set_item_context, set_item_context calls set_sequencer, set_sequencer assigns handle of sequencer (which we have passed in start task of sequence) to m_sequencer using static cast (***This is first casting or down casting)
virtual function void set_sequencer(uvm_sequencer_base sequencer);
m_sequencer = sequencer;
m_set_p_sequencer();
endfunction

set_sequencer also calls m_set_p_sequencer(declaring `uvm_declare_p_sequencer macro should override the m_set_p_sequencer hence m_set_p_sequencer defined in macro should be executed) which will cast m_sequencer back into p_sequencer using dynamic $cast. (***This is reverse casting or up casting)

MY QUESTIONs:
1. Why do we need this reverse/up casting? what is intended and achieved with this step?
2. Can we pass virtual sequencer as an argument to uvm_declare_p_sequencer inside both virtual sequence and non-virtual sequence? 
3. In case when we are using virtual sequence, and passed virtual sequencer as an argument to uvm_declare_p_sequencer inside it , when we call this virtual sequence from test , we pass null in the start task of the virtual sequence. In this case what will happen? m_sequencer = null and then , m_sequencer = p_sequencer and p_sequencer = m_sequencer , is that correct understanding? OR m_sequencer = p_sequencer and then m_sequencer = null and p_sequencer = m_sequencer , is that correct understanding?

Saturday, July 15, 2017

conc_cast_dynamic_up_vs_down

class Base;
endclass

class Exten extends Base;
endclass

program main;
  initial begin
    Base B;
    Exten E;
    B = new();
    //##E = new();          //##DEBUG: MASTER: doing this will also not allow us to down cast
    if(!$cast(E,B)) begin   //##DEBUG: MASTER: NOTE: as this unsuccessful cast will return '0' value
      $display("\n");
      $display(" Base class object B can'T be assigned to Extended class Handle.");
      $display(" So this implies 'down casting is not possible'\n");
    end
    // Deallocate object B
    //##DEBUG: MASTER: NOTICE: even if we do not include below null assignment, result will be same
    B = null;
    E = new();
    if($cast(B,E)) begin    //##DEBUG: MASTER: NOTE: as this successful cast will return '1' value
      $display(" Extended class object E can be assigned to Base class Handle.");
      $display(" So this implies 'up casting is only possible'\n");
    end
  end
endprogram

//##DEBUG: MASTER: run results
/*
ncsim> run

 Base class object B can'T be assigned to Extended class Handle.
 So this implies 'down casting is not possible'

 Extended class object E can be assigned to Base class Handle.
 So this implies 'up casting is only possible'

Simulation complete via implicit call to $finish(1) at time 0 FS + 1
*/

conc_cast_cases_updown_null_static_dynamic

class Parent ;
virtual task disp ();
    $display(" This is class Parent ");
  endtask
endclass

class Child extends Parent ;
  task disp ();
    $display(" This is class Child ");
  endtask
endclass

program main ;
  Parent P;
  Child C;

  initial
    begin
      C = new();
      $display(" DEBUG: MASTER: step1: doing P = C ");
      P=C;
      $display(" DEBUG: MASTER: step2: calling P.disp() ");
      P.disp();
      $display(" DEBUG: MASTER: step3: calling C.disp() ");
      C.disp();
      $display(" DEBUG: MASTER: step4: doing C=null ");
      C=null;
      $display(" DEBUG: MASTER: step5: doing $cast(C,P) ");
      $display(" $cast(C,P) = %b ",$cast(C,P));
      //##C=P;          //##static cast is not working !!!???
      $cast(C,P);       //##dynamic cast is working
      //##C=P;          //##static cast is not working !!!???
      $display(" DEBUG: MASTER: step6: calling C.disp() ");
      C.disp();
    end
endprogram

//## DEBUG: MASTER: run results
/*
ncsim> run
 DEBUG: MASTER: step1: doing P = C 
 DEBUG: MASTER: step2: calling P.disp() 
 This is class Child 
 DEBUG: MASTER: step3: calling C.disp() 
 This is class Child 
 DEBUG: MASTER: step4: doing C=null 
 DEBUG: MASTER: step5: doing $cast(C,P) 
 $cast(C,P) = 00000000000000000000000000000001 
 DEBUG: MASTER: step6: calling C.disp() 
 This is class Child 
Simulation complete via implicit call to $finish(1) at time 0 FS + 1
./conc_cast_updown_null_static_dynamic.sv:13 program main ; 
ncsim> exit
*/

conc_cast_p_then_null_c_then_use_casted_p

class Parent ;
virtual task disp ();
    $display(" This is class Parent ");
  endtask
endclass

class Child extends Parent ;
  task disp ();
    $display(" This is class Child ");
  endtask
endclass

program main ;
  Parent P;
  Child C;

  initial
    begin
      C = new();
      P=C;
      C = null;
      P.disp();
    end
endprogram

//##run results: DEBUG: MASTER
/*
ncsim> run
 This is class Child 
Simulation complete via implicit call to $finish(1) at time 0 FS + 1
./conc_cast_then_null_then_use_casted.sv:13 program main ; 
ncsim> exit
*/

conc_cast_staticcompile_vs_dynamicrun



class parent_;
  virtual function foo_();
     $display("I am parent with member of values ");
  endfunction
endclass

class child_ extends parent_;
   bit foo_mem;
   function foo_();
     //##void'(super.foo_());           //##DEBUG: MASTER: regardless of casting/virtual, you may want to uncomment this to see the super effect, when function returns nothing , you should use with void
     $display("I am child with member of values %d",foo_mem);
   endfunction
endclass

module foo_foo;
  parent_ parent_handle;
  parent_ parent_handle_1;
  child_ child_handle;

  initial begin
    child_handle = new();
    $cast(parent_handle,child_handle);  //##DEBUG: MASTER: This is dynamic cast and it can be called as task or func. It will return 0 at RUNTIME if not proper valid casting.
    parent_handle_1 = child_handle;     //##DEBUG: MASTER: This is static cast and will give COMPILETIME error if not proper
    void'(parent_handle_1.foo_());      //##DEBUG: MASTER: when function returns nothing , you should use with void
    void'(parent_handle.foo_());        //##DEBUG: MASTER: when function returns nothing , you should use with void
    $display("BOTH DYNAMIC AND STATIC CASTING GAVE SAME RESULT");
  end
endmodule

//##run results:
/*
ncsim> run
I am child with member of values 0      //##DEBUG: MASTER: --> function called from parent_handle_1, but after casting with child_handle
I am child with member of values 0      //##DEBUG: MASTER: --> function called from parent_handle, but after casting with child_handle
BOTH DYNAMIC AND STATIC CASTING GAVE SAME RESULT
ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit
*/