The analysis port is used to perform non-blocking broadcasts of transactions. It is by components like monitors/drivers to publish transactions to its subscribers, which are typically scoreboards and response/coverage collectors. For each port, more than one component can be connected. Even if a component is not connected to the port, simulation can continue, unlike put/get ports where simulation is not continued.
The uvm_analysis_port consists of a single function, write(). Subscriber component should provide an implementation of write()method. UVM provides the uvm_subscriber base component to simplify this operation, so a typical analysis component would extend uvm_subscriber and its export is analysis_export.
Lets write a example.
In the example, we will define a monitor component and a subscriber.
(S)Monitor source code:
In monitor, call the function write() pass the transaction.
class monitor extends uvm_monitor;
uvm_analysis_port #(instruction) anls_port;
function new(string name, uvm_component p = null);
super.new(name,p);
anls_port = new("anls_port", this);
endfunction
Tlm_fifo provides storage of transactions between two independently running processes just like mailbox. Transactions are put into the FIFO via the put_export and fetched from the get_export.
(S)Methods
Following are the methods defined for tlm fifo.
function new(string name,
uvm_component parent = null,
int size = 1)
The size indicates the maximum size of the FIFO; a value of zero indicates no upper bound.
virtualfunctionint size()
Returns the capacity of the FIFO. 0 indicates the FIFO capacity has no limit.
virtualfunctionint used()
Returns the number of entries put into the FIFO.
virtualfunctionbit is_empty()
Returns 1 when there are no entries in the FIFO, 0 otherwise.
virtualfunctionbit is_full()
Returns 1 when the number of entries in the FIFO is equal to its size, 0 otherwise.
virtualfunctionvoid flush()
Removes all entries from the FIFO, after which used returns 0 and is_empty returns 1.
Example
Lets implement a example.
In this example, we will use a tlm_fifo to connect producer and consumer.
The producer component generates the transaction and using its put_port pot() method, sends transaction out. The consumer component, to get the transaction from outside, uses get() method of get_port. These two ports are connected to tlm_fifo in the env class. In this example, producer and consumer are initiators as both components are calling the methods.
(S)Producer source code:
class producer extends uvm_component;
uvm_blocking_put_port#(int) put_port;
function new(string name, uvm_component p = null);
super.new(name,p);
put_port = new("put_port", this);
endfunction
task run;
int randval;
for(int i = 0; i < 10; i++)
begin #10;
randval = $urandom_range(4,10);
`uvm_info("producer",
$sformatf("sending %d",randval), UVM_MEDIUM)
put_port.put(randval);
end endtask
endclass : producer
(S)Consumer source code: class consumer extends uvm_component;
uvm_blocking_get_port#(int) get_port;
function new(string name, uvm_component p = null);
super.new(name,p);
get_port = new("get_port", this);
endfunction
task run;
int val;
forever begin get_port.get(val);
`uvm_info("consumer",
$sformatf("receiving %d", val), UVM_MEDIUM)
end endtask