TLM FIFO Implementation

As we have seen that TLM put() & TLM get() methods are blocking in nature. What does that mean? In fact, during put() and get() method execution, there is a single process running which passes the control from the port to the export & back again. So, in TLM terminology – it’s called that TLM put() & TLM get() methods are blocking in nature.

Now there may be situations where Producers and Consumers both are expected to work independently. How that can be achieved? In UVM, TLM provides a channel called “uvm_tlm_fifo” to facilitate this feature. Using “uvm_tlm_fifo”, Producer can work in one process to create the transactions while Consumer needs to operate on those transactions in an another process.

“uvm_tlm_fifo” implements all the TLM interface methods, so Producer puts the transaction into the TLM FIFO and Consumer independently extracts the transactions from the TLM FIFO (as shown in Figure 1 below).

tlm_fifo
Figure 1: uvm_tlm_fifo implementation

Here is an example UVM code shown below for the UVM TLM FIFO implementation:

// Description: Example UVM code below shows how to connect a TLM producer and TLM consumer using a ‘uvm_tlm_fifo’ which a non-blocking way of connection.

`include “uvm_macros.svh”

module test;

import uvm_pkg::*;

/// Transaction declaration

 

`uvm_object_utils(my_txn)

/// Data members
typedef enum {READ, WRITE} kind_t;
kind_t kind;
rand bit [7:0] addr;
rand byte data;

// Constructor
function new (string name = “”);
super.new(name);
kind = kind_t'($urandom_range(0,1));
endfunction: new

endclass: my_txn

/// Producer declaration
class producer extends uvm_component;
`uvm_component_utils(producer)

/// put port declaration
uvm_blocking_put_port #(my_txn) my_put_port;

/// Constructor
function new (string name, uvm_component parent);
super.new(name, parent);
my_put_port = new(“my_put_port”, this);
endfunction: new

/// Run task
task run_phase (uvm_phase phase);
for(int i=1; i<11; i++)
begin
my_txn txn;
txn = my_txn::type_id::create(“txn”, this);
my_put_port.put(txn);
`uvm_info(“PID”, $sformatf(“Transaction no. %0d sent as %s”, i, txn.kind), UVM_LOW);
#10;
end
endtask: run_phase

endclass: producer

/// Consumer declaration
class consumer extends uvm_component;
`uvm_component_utils(consumer)

/// get port declaration
uvm_blocking_get_port #(my_txn) my_get_port;

/// Constructor
function new (string name, uvm_component parent);
super.new(name, parent);
my_get_port = new(“my_get_port”, this);
endfunction

/// Run task
task run_phase (uvm_phase phase);
for(int ii=1; ii<11; ii++)
begin
my_txn t;
t = my_txn::type_id::create(“t”, this);
my_get_port.get(t);
`uvm_info(“CID”, $sformatf(“Transaction no. %0d is received as %s”, ii, t.kind), UVM_LOW);
#10;
end
endtask: run_phase

endclass: consumer

/// Environment declaration
class env extends uvm_env;

/// Instance declaration
uvm_tlm_fifo #(my_txn) my_tlm_fifo;
producer p1;
consumer c1;

/// Constructor
function new (string name = “env”);
super.new(name);
my_tlm_fifo = new(“my_tlm_fifo”, this);
endfunction: new

/// Build function
function void build_phase (uvm_phase phase);
super.build_phase(phase);
p1 = producer::type_id::create(“p1”, this);
c1 = consumer::type_id::create(“c1”, this);
endfunction: build_phase

// Connect function
function void connect_phase (uvm_phase phase);
p1.my_put_port.connect(my_tlm_fifo.put_export);
c1.my_get_port.connect(my_tlm_fifo.get_export);
endfunction: connect_phase

/// Run phase
task run_phase (uvm_phase phase);
phase.raise_objection(this);
#1000;
phase.drop_objection(this);
endtask: run_phase

endclass: env

env e;

initial
begin
e = new();
run_test();
end

endmodule: test


I believe you found this post useful about UVM TLM FIFO.

Thank you..Good day!

 


amazon