The Curious World of Ports and Exports in VMM 1.2
Posted by John Aynsley on 4th February 2010
John Aynsley, CTO, Doulos
In a previous post I discussed the new blocking transport interface of VMM 1.2, and described how a producer can call the b_transport method implemented by a consumer. In this post, I will describe how to connect the producer to the consumer using the new features of VMM 1.2.
The new features discussed here were inspired by the SystemC TLM-2.0 standard. In SystemC, two modules wishing to communicate get connected using so-called “ports” and “exports”. Although the underlying concept is both elegant and powerful, the terminology “port” and “export” often seems to cause confusion. Since this is now part of VMM 1.2, I will explain. Let us consider a simple example of a producer calling the b_transport method implemented in a consumer.
class my_tx extends vmm_data; // User-defined transaction class
…
class producer extends vmm_xactor;
vmm_tlm_b_transport_port #(producer, my_tx) m_port;
my_tx tx;
…
m_port.b_transport(tx, delay);
…
class consumer extends vmm_xactor;
vmm_tlm_b_transport_export #(consumer, my_tx) m_export;
task b_transport(int id = -1, my_tx trans, ref int delay);
…
class my_env extends vmm_group;
producer m_producer;
consumer m_consumer;
virtual function void connect_ph;
m_producer.m_port.tlm_bind( m_consumer.m_export );
endfunction
…
What is happening here is that the producer is calling b_transport through a port, the consumer is providing an implementation of b_transport using an export, and the top-level environment is connecting (or “binding”) the port to the export. The tlm_bind method is creating the link between the port and the export such that when the producer calls b_transport, it is the implementation of b_transport within the consumer that actually gets called.
Both the port and the export declarations are parameterized with the type of the transactor (producer/consumer) and the type of the transaction (my_tx). You may notice that the implementation of b_transport has an extra int id argument. This can be used to distinguish between transactions arriving from different producers. I will discuss this in my next blog post.
The purpose of ports and exports is to provide a structured way of making method calls between VMM transactors (or SystemC modules) such that the dependencies between each transactor and its environment can be minimized. To call b_transport the code within the producer only need refer to the port and has no direct dependencies on any code outside that transactor. Similarly, to call the b_transport method implemented within the consumer, the environment only need refer to the export. It is only when the port and export are connected within the connect_ph method of the environment that a specific dependency is established between the producer and consumer transactors.
What about those terms “port” and “export”? The term port was originally borrowed from VHDL and Verilog. In SystemC, a port allows an interface method call to be made up-and-out-of a module. When SystemC was enhanced to add the mirror image construct that allows an interface method call to be made down-and-into a module the term “export” was chosen because an export provides or “exports” an interface, whereas a port “imports” an interface.
If we could re-write history, I guess we might have chosen the term “import” instead of “port”. Perhaps that would have caused less confusion. Or maybe not!
Posted in SystemC/C/C++, Transaction Level Modeling (TLM) | 1 Comment »

Rahul V. Shah