Monday, December 7, 2015

What is difference between copy and clone method in UVM

There are two methods we use to copy data of one uvm_object (transaction or sequence item) to another.
Copy and
Clone.

Here I will explain you difference between copy and clone.

See below code.
========================================================================
// do_copy method:
function void do_copy(uvm_object rhs);
  bus_item rhs_;
  if(!$cast(rhs_, rhs)) begin
  uvm_report_error("do_copy:", "Cast failed");
  return;
  end
  super.do_copy(rhs); // Chain the copy with parent classes
  delay = rhs_.delay;
  addr = rhs_.addr;
  op_code = rhs_.op_code;
  slave_name = rhs_.slave_name;
  data = rhs_.data;
  response = rhs_.response;
endfunction: do_copy

// Example of how do_copy would be used:
// Directly:
bus_item A, B;
A.copy(B); // A becomes a deep copy of B
// Indirectly:
$cast(A, B.clone()); // Clone returns an uvm_object which needs
// to be cast to the actual type
========================================================================
A.copy(B); is deep copy of  B. 
While B.clone() returns a new object of type uvm_object which we cast to type "bus_items". So in a way A becomes deep copy of B.

Below here I am mimicking behavior of copy and clone method of UVM

typedef base_class;
typedef derived_class;
function base_class create();
  derived_class tmp;
  tmp = new();
  return tmp;
endfunction
class base_class;
  int A = 7;
  virtual function do_copy(base_class rhs);
  endfunction
  virtual function copy(base_class rhs);
    do_copy(rhs);
  endfunction
  virtual function base_class clone();
    base_class base;
    base = create();
    base.copy(this);
    return (base);
  endfunction
endclass
class derived_class extends base_class;
  int A = 5;
  function do_copy(base_class rhs);
    derived_class derived;
    $cast(derived,rhs);
    super.do_copy(rhs);
    A = derived.A;
  endfunction
endclass

module test();
  derived_class d1,d2,d3;
  initial
  begin
    d1 = new();
    d1.A = 10;
    d3 = new();
    d3.copy(d1);
    $cast(d2,d1.clone());
    $display("A in d1 is %0d",d1.A);
    $display("A in d2 is %0d",d2.A);
    $display("A in d3 is %0d",d3.A);
    d1.A = 20;
    $display("A in d1 is %0d",d1.A);
    $display("A in d2 is %0d",d2.A);
    $display("A in d3 is %0d",d3.A);
  end 
endmodule

Output : 
A in d1 is 10
A in d2 is 10
A in d3 is 10
A in d1 is 20
A in d2 is 10
A in d3 is 10

There are two function used here copy and clone.
copy : d3.copy(d1); which is simply deep copy of d1 to d3. It works as below.
1. d3 calls copy function which is defined in base_class.
2. copy function calls do_copy, as do_copy is virtual method, always latest definition of function will be executed. There is only one implementation of a virtual method per class hierarchy, and it is always the one in the latest derived class. So do_copy from "derived class" will be called.

clone : $cast(d2,d1.clone()); This method works as below.
1. d1.clone() calls definition of clone from base class.
2. clone calls create method which, returns handle of type derived_class.
3. A child class handle can be directly assign to base class.
4. base.copy(this); This is basically deep copy of this(here d1) to base.
5. So clone method return class variable of type "base_class" which we need to cast in derived_class, then only we can access member of class.

If you have noticed, here there is one dilemma. 

base.copy(this); calls copy function from base class , which call do_copy of derived class. So in turn do_copy is called from handle of object of type base_class. So how in do_copy it can access variable A, since it is not defined in base_class.
Reason is that "A" is being used by do_copy function which is in derived class. So context of A will be derived_class. 
If I have written base.A then it would not work

Sunday, October 25, 2015

TLM (Transaction Level Modeling)

What is TLM?

TLM provide API. API is application programming interface. Let me explain API in some simple terms. In software, say in movie ticket booking application, the application gives you information about theater and seats and when you select it and go for payment, API connects it with payment gateway which deals with your credit card information. For Mobile app developer that payment gateway is independent software or module, which is connected through API. So seat selecting module and payment gateway both are independent module, don't know or don't dependent on each other, connected through API.

In testbench driver and sequencer are two individual block, which is independent to each other, but can communicate through API, which is TLM.

TLM works on some terminology like,

Producer : who produces transaction. In our case Sequencer.
Consumer : Who consumes transaction. Here Driver
Port : It is actually a TLM port which either put the transaction in producer or get the transaction in consumer.
Export : It is a TLM port which either implement put method in consumer or get method in producer
Put : It is blocking task which put transaction(seq_item) from producer.
Get : It is blocking task which get seq_item from consumer.
Try_put : Same as put but its non blocking (a function basically) with return type as bit. It return TRUE if process is successful else return FALSE.
Try_Get : Same as Get. But non blocking (function)

TLM connection would be as below

m_driver.seq_item_port.connect(m_sequencer.seq_item_export);

seq_item_port from driver is connected to seq_item_export of sequencer.
Driver will call seq_item_port.get_next_item(req_item).

Due to above connection made in environment, it will actually call m_sequencer.seq_item_export.get_next_item which finally calls get_next_item of sequencer.


seq_item_port.get_next_item(req) and seq_item_port.item_done() is the handshake mechanism between driver and sequencer. Once this handshake done, only then driver can ask for next seq_item.

Symbolic Notation :
Square : Indicate Port
Circle : Indicate Export
Diamond : Indicate Analysis Port

 












In Figure 1 Put method is implemented is in consumer, So export (Circle) will be at consumer.
Figure 2 get method is implemented in produce , so Port (Sqiare) will be producer.
Figure 3 , write method is implemented in subscriber, so export is always subscriber and here consumer will be analysis port.