The TLM implemenation declaration macros provide a way for components to provide multiple implemenation ports of the same implementation interface. When an implementation port is defined using the built-in set of imps, there must be exactly one implementation of the interface.
For example, if a component needs to provide a put implemenation then it would have an implementation port defined like:
class mycomp extends uvm_component;
uvm_put_imp#(data_type, mycomp) put_imp;
...
virtual task put (data_type t);
...
endtask
endclass
There are times, however, when you need more than one implementation for an interface. This set of declarations allow you to easily create a new implemenation class to allow for multiple implementations. Although the new implemenation class is a different class, it can be bound to the same types of exports and ports as the original class. Extending the put example above, lets say that mycomp needs to provide two put implementation ports. In that case, you would do something like:
//Define two new put interfaces which are compatible with uvm_put_ports
//and uvm_put_exports.
`uvm_put_imp_decl(_1)
`uvm_put_imp_decl(_2)
class my_put_imp#(type T=int) extends uvm_component;
uvm_put_imp_1#(T) put_imp1;
uvm_put_imp_2#(T) put_imp2;
...
function void put_1 (input T t);
//puts comming into put_imp1
...
endfunction
function void put_2(input T t);
//puts comming into put_imp2
...
endfunction
endclass
The important thing to note is that each `uvm_<interface>_imp_decl creates a new class of type uvm_<interface>_imp<suffix>, where suffix is the input argument to the macro. For this reason, you will typically want to put these macros in a seperate package to avoid collisions and to allow sharing of the definitions.