Home > Community > Blogs > Functional Verification > e templates a nifty way to create re useable code
Login with a Cadence account.
Not a member yet?
Create a permanent login account to make interactions with Cadence more convenient.

Register | Membership benefits
Get email delivery of the Functional Verification blog (individual posts).


* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

e Templates: A Nifty Way To Create Reusable Code

Comments(3)Filed under: Functional Verification, Testbench simulation, Verification methodology , eRM, Coverage-Driven Verification, OVMWorld, coverage driven verification (CDV), Open Verification Methodology, IES, System Verification, Incisive Enterprise Simulator (IES), e, IEEE 1647, OVM e, OOP, Aspect Oriented Programming, Object Oriented Programming, when sub-typing, funtional verification, IES-XL, OVM-e, hvl, verification, specman elite, esl tlm synthesis rtl dac estimation planning, team specman, macros, Functional Verificatioa, TLM, Trailblazer, ClubT, coverage driven verification, innovation, when inheritance

Hi All,

An e template (known as a parameterized type in other programming languages) is a feature that has been around for several releases and can be a great way of creating re-usable code.  Templates can be used anywhere a user would like to create a single re-useable object that might operate on different data types.  An example would be to create a scoreboard (if you were not already using the ovm_scbd package) that can be instantiated to perform checking on packets, transactions, or any other type of data structure of interest. 

Below is a short example of a simple FIFO scoreboard implemented using a template:


File: scoreboard.e
template unit scoreboard of (<T'type>) {

    // Instantiate the TLM analysis ports to receive items for adding items to the scoreboard and checking
    add_pkt: in interface_port of tlm_analysis of <T'type> using prefix=add_pkt_ is instance;
    check_pkt: in interface_port of tlm_analysis of <T'type> using prefix=check_pkt_ is instance;

    // The actual scoreboard list
   !sblist: list of <T'type>;  

   // Implement the _write() method of the TLM analysis port
   add_pkt_write(p: <T'type>) is {
      message(NONE, "scoreboard added item: ", p);

   // Implement the _write() method of the TLM analysis port
   check_pkt_write(p: <T'type>) is
      if (deep_compare_physical(p, sblist[0], 10).is_empty()) then {sblist.delete(0);};
      message(NONE, "scoreboard checked item: ", p);

Using the above code, a user can instantiate the same scoreboard code to handle any type of data structure.


File: env.e

unit env_u {
   packet_sb: scoreboard of (packet_s) is instance;  // Scoreboard to handle packets
   transaction_sb: scoreboard of (transaction_s) is instance;  // Scoreboard to handle transactions

Hope this little technical tidbit helps.

Happy verifying!




By neriya on August 11, 2010
can you please shed some light on the difference between Templates and Macros ?

By Corey Goss on August 17, 2010
Hi neriya,
This is a very good question that caused me to scratch my head a bit in order to really capture the exact differences as one can write a macro that would look similar to the template in the above example.  The converse is not true though as macros in e have many applications.  I took a quick look in the Specman docs to and came across the following article (section 6.6 of the Specman e language reference) that addresses this exact question.  Below is a cut and paste from this section:  
Templates vs. Macros
In some sense, templates are similar to define-as macros. Both define parameterized code, which is instantiated by substituting parameters. In principle, a statement macro can be used for that purpose, if it has type syntactic arguments and a struct definition in its replacement code. Calling that macro will create a specific struct, which is analogous to creating a template instance.
However, there are several important differences that make using templates preferable:
  - A macro must be instantiated explicitly in the code. Multiple explicit instantiations of the same macro causes an error, because the instances are multiple definitions of the same struct. Templates are instantiated automatically, the first time a specific instance is referred to in the code.
  - A template definition is fully syntactically analyzed, and any syntax errors within a template definition are reported when the template is defined ("Template Definition Errors" ). A macro definition, in contrast, is not syntactically analyzed, and most syntax errors--except basic errors such as unbalanced parentheses in the code--are discovered only when the macro is called.
  - With regard to name resolution and related issues, template code is treated in the context of the template definition, regardless of where a given template instance is referred to for the first time. Macro code, in contrast, is treated in the context of the macro call itself. For instance, if the macro replacement code tries to access the package-accessible field of a struct defined in the same package, the macro call will not compile if it resides in a different package.
Let me know if you have any further questions on this.
Corey Goss

By Yuri Tsoglin on August 24, 2010
I just wanted to illustrate a difference between templates and macros (the first of the differences mentioned above by Corey), on the example given in the article.
When you write:
template unit scoreboard of (\T'type/) {        // I use \.../ because this site doesn't allow to post triangular brackets ...
and later "scoreboard of (packet_s)" appears anywhere in your code, the relevant template instance type is created automatically.
We could have implemented the same with a define-as macro, for example:
define \scoreboard'statement/ "scoreboard_decl of \T'type/" as {
unit scoreboard_\T'type/ {
...... // here would come the same code we have in the template
But macro is not instantiated automatically, so if you want to instantiate it with a certain type as the parameter, you should do it explicitly in the code. So, the template usage code from the article would be looking like this:
scoreboard_decl of packet_s;
scoreboard_decl of transaction_s;
unit env_u {
  packet_sb: scoreboard_packet_s is instance;  // Scoreboard to handle packets
  transaction_sb: scoreboard_transaction_s is instance;  // Scoreboard to handle transactions
Note also that the 'scoreboard_decl ...' statement must appear exactly once for each "instance", otherwise you would get a 'duplicate struct declaration' error.
Another drawback of using a macro like this is that you have to invent your own syntax (both the syntax for declaration - "scoreboard_decl of XXX", and the syntax for the type name itself - "scoreboard_XXX"), while the syntax for templates is already given to you by the language.
Yuri Tsoglin, Specman R&D

Leave a Comment

E-mail (will not be published)
 I have read and agree to the Terms of use and Community Guidelines.
Community Guidelines
The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.