E (verification language)
Encyclopedia
e is a hardware verification language
Hardware verification language
A Hardware Verification Language, or HVL, is a programming language used to verify the designs of electronic circuits written in a hardware description language. HVLs typically include features of a high-level programming language like C++ or Java as well as features for easy bit-level...

 (HVL) which is tailored to implementing highly flexible and reusable verification testbenches
Test bench
A test bench is a virtual environment used to verify the correctness or soundness of a design or model .The term has its roots in the testing of electronic devices, where an engineer would sit at a lab bench with tools for measurement and manipulation, such as oscilloscopes, multimeters, soldering...

.

History

e was first developed in 1992 in Israel by Yoav Hollander for his Specman
Specman
Specman is an EDA tool, that provides advanced automated Functional verification of hardware designs. It provides an environment for working with, compiling, and debugging testbench environments written in the e Hardware Verification Language...

 software. In 1995 he founded a company, InSpec (later renamed Verisity), to commercialize the software. The product was introduced at the 1996 Design Automation Conference
Design Automation Conference
The Design Automation Conference, or DAC, is a combination of a technical conference and a trade show, both specializing in electronic design automation....

. Verisity has since been acquired by Cadence Design Systems
Cadence Design Systems
Cadence Design Systems, Inc is an electronic design automation software and engineering services company, founded in 1988 by the merger of SDA Systems and ECAD, Inc...

.

Features

Main features of e are:
  • Random and constrained random stimulus generation
  • Functional coverage metric definition and collection
  • Temporal language that can be used for writing assertions
  • Aspect-oriented programming
    Aspect-oriented programming
    In computing, aspect-oriented programming is a programming paradigm which aims to increase modularity by allowing the separation of cross-cutting concerns...

     language with reflection capability
  • Language is DUT-neutral in that you can use a single e testbench to verify a SystemC/C++ model, an RTL model, a gate level model, or even a DUT residing in a hardware acceleration box (using the UVM Acceleration for e Methodology)
  • Can create highly reusable code, especially when the testbench is written following the Universal Verification Methodology
    Universal Verification Methodology
    The Universal Verification Methodology is a standardized methodology for verifying integrated circuit designs. UVM is derived mainly from the OVM which was, to a large part, based on the eRM for the e Verification Language developed by Verisity Design in 2001...

     (UVM)
    • Formerly known as e Re-use Methodology (eRM)
    • UVM e library and documentation can be downloaded here: UVM World
  • The most mature and technically advanced Hardware Verification Language (HVL) in the industry
  • The most productive Hardware Verification Language (HVL) in the industry today, because it was specifically designed for hardware verification

Language Features

The e language uses an aspect-oriented programming
Aspect-oriented programming
In computing, aspect-oriented programming is a programming paradigm which aims to increase modularity by allowing the separation of cross-cutting concerns...

 (AOP) approach, which is an extension of the object-oriented programming
Object-oriented programming
Object-oriented programming is a programming paradigm using "objects" – data structures consisting of data fields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as data abstraction,...

 approach to specifically address the needs required in functional verification. AOP is a key feature in that it allows for users to easily bolt on additional functionality to existing code in a non-invasive manner. This permits easy reuse and code maintenance which is a huge benefit in the hardware world, where designs are continually being tweaked to meet market demands throughout the project lifecycle. AOP also addresses cross cutting concerns (features that cut across various sections of the code) easily by allowing users to extend either specific or all instances of a particular struct to add functionality. Users can extend several structs to add functionality related to a particular feature and bundle the extensions into a single file if desired, providing for more organized file partitioning.

Example


Anything outside the markers is a comment
<'
extend sys {
// This is a comment Verilog style
-- This is a comment in VHDL style
post_generate is also {
out("... and everything else within the markers is executable code.");
};
};
'>

Classes

e also has two kinds of classes:
  • Dynamic classes are labeled with the keyword 'struct'. Structs are used for creating data that only exists temporary and may be cleaned by the garbage collector.
  • Static classes are labeled with the keyword 'unit'. Units are used for creating the permanent testbench structure.


A class may contain fields, methods, ports and constraints. Fields can be of type integer, real, enum, string and even complex objects. The code segment shows a unit called 'environment_u' being instantiated within the e root 'sys'. This environment_u class contains a list of 5 packet_s objects and this packet_s class contains two fields and a method.

Example


<'
// This is a dynamic class with two fields
struct packet_s {
field0: uint (bits: 32); // This field is called 'field0' and is a
// 32 bit wide unsigned integer.
field1: byte; // This field is called 'field1' and is a byte.

// This method is called once a packet_s object has been generated
post_generate is also {
out(field0); // Printing the value of 'field0'
};
};

// This is a static class with a list of five packet struct
unit environment_u {
my_pkt[5]: list of packet_s;
};

// sys is the root for every e environment and instantiates the 'test_env' object
extend sys {
test_env: environment_u is instance;
};
'>

Randomization

In e each field is randomized by default. Field randomization can be controlled by hard constraints, soft constraints or even be turned off completely. Soft constraints are used as the default constraints, and may be automatically overridden by the test layer if a conflict occurs. Otherwise it behaves like a regular constraint.

Example


<'
struct my_pkt_s {
destination_address: uint (bits: 48); // this field is randomized and is not constrained.
data_payload : list of byte;
!parity_field : uint (bits: 32); // '!' prevents the parity_field from being randomized.

keep soft data_payload.size in [64..1500]; // a soft constraint, used to provide a default randomization
keep data_payload.size not in [128..256]; // this is a hard constraint
};
'>

Assertions

e supports assertions with temporal expressions. A temporal expression is used at the same syntactic level as fields and methods and is thereby declarative by nature. A temporal expression describes timed behavior.

Example


<'
unit temporal_example_u {
event a; // declaring an event 'a'
event b; // declaring an event 'b'
event c; // declaring an event 'c'

// This assertion expects that the next cycle after event a
// has been detected that event b followed by event c occurs.
expect @a => {@b;@c}
};
'>

Coverage

e supports coverage that are grouped according to their sampled event and those groups are internally structured with items. Items can be simple items or complex items such as crossed items or transitional items.

Example


unit coverage_example_u {
event cov_event_e; // collecting coverage will be tied to this event

cover cov_event_e is {
item a: uint (bits: 4); // this item has 16 buckets from 0 to 15
item b: bool; // this item has two buckets: TRUE and FALSE
cross a, b; // this item contains a cross multiplication matrix of a and b
trans b; // this item is derived of item b and has four buckets
// transitioning each TRUE - FALSE combination
};
};

Example


unit message_example_u {
example_message_method is {
out("This is an unconditional, unformatted output message.");
outf("This is an uncoditional, formatted output message displaying in HEX %x",15);
print "This is an uncoditional message.";
message( LOW, "This is a conditional message, usually tied to a message logger. ",
"You can also concatenate strings like this and even add objects like ",me,
" in this output." );
messagef( LOW, "This conditional output is formatted %x.",15 );
};
};

Interfacing With Other Languages

An e testbench is likely to be run with RTL or higher-level models. Bearing this in mind, e is capable of interfacing with VHDL, Verilog
Verilog
In the semiconductor and electronic design industry, Verilog is a hardware description language used to model electronic systems. Verilog HDL, not to be confused with VHDL , is most commonly used in the design, verification, and implementation of digital logic chips at the register-transfer level...

, C/C++ and SystemVerilog
SystemVerilog
In the semiconductor and electronic design industry, SystemVerilog is a combined Hardware Description Language and Hardware Verification Language based on extensions to Verilog.-History:...

.


Example of an e <-> Verilog Hookup


// This code is in a Verilog file tb_top.v
module testbench_top;
reg a_clk;
always #5 a_clk = ~a_clk;
initial begin
a_clk = 0;
end
endmodule



This code is in a signal_map.e file
<'
unit signal_map_u {
// Define a port named 'a_clk_p'
a_clk_p: in simple_port of bit is instance;
// Set the port's hdl_path property to point to the 'a_clk' signal in the top-level testbench
keep a_clk_p.hdl_path

"~/testbench_top/a_clk";
};
'>


Aspect-Oriented Programming Support in e
The process of functional verification requires to raise the level of abstraction of any Design Under Test (DUT) beyond the RTL level. This necessity calls for a language that is capable of encapsulating data and models, which is readily available in object-oriented languages. To address this need has been designed to be e an object-oriented language and on top of that has been augmented with aspect-oriented mechanisms that facilitate not only writing highly flexible and reusable testbenches, but also helps verification engineers by enabling to patch discovered RTL bugs without having to rewrite or touch any of the already existing code base.

Aspect-oriented programming in e allows verification engineers to structure their testbench in aspects. An object is therefore the sum of all its aspects, which may be distributed over multiple files. The following sections illustrate basic aspect-oriented mechanisms in e.

Subtyping Mechanism

Subtyping is the prime example of what object-oriented languages without aspect-oriented features can not accomplish. Subtyping allows a verification engineer to add functionality to an already defined/implemented class without having to derive from a base class. The following code shows the original implementation of a base-class and how it is extended. Please note that once the extension took place, all base-class objects contain the extensions as well. Please note that the constraints given in the two different subtypes would usually cause a contradiction, however both subtypes are handled separately and thus each subtype yields a different constraint calculation.

Subytping Mechanism Example


subtyping_example.e
<'
// This enum type definition is used to declare the subytpes ODD and EVEN
type ctrl_field_type_t: [ODD, EVEN];
unit base_ex_u {
// The subtype_field is the determinant field which calculation is being applied
subtype_field: ctrl_field_type_t;
data_word : uint (bits: 32);
parity_bit : bit;

// Subtyping the ODD type
when ODD'subtype_field base_ex_u {
// This is a simple constraint that XORs the index bit 0 of data_word and increments that value
keep parity_bit (data_word[0:0] ^ data_word[0:0] + 1);
};

// Subtyping the EVEN type
when EVEN'subtype_field base_ex_u {
// This constraint is the same as above, however the increment is not done
keep parity_bit (data_word[0:0] ^ data_word[0:0]);
};
};
'>

Extending Methods

The original unit definition is given in file1.e. The aspect-oriented mechanism used in this example shows how to execute code before and after an already implemented method.

Method Extension Example


This code is in file1.e
<'
unit aop_example_u {
meth_ext is {
out("This is the original method implementation.");
};
};
'>



This code in in file2.e
<'
extend aop_example_u {
meth_ext is first {
out("This method extension is executed before the original method implementation.");
};

meth_ext is also {
out("This method extension is executed after the original method implementation.");
};
};
'>

Sources
  • The e language blog (Team Specman)
  • http://www.ieee1647.org/
  • http://www.deepchip.com/items/0488-05.html (good feedback from users on their experiences with the e language)
  • http://www.cadence.com/products/functional_ver/specman_elite/index.aspx
  • http://www.us.design-reuse.com/articles/article5646.html
  • Janick Bergeron: Writing Testbenches: Functional Verification of HDL Models, Second Edition, Kluwer Academic Publishers, 2003, ISBN 1-4020-7401-8
  • http://www.amiq.ro/eparser.html
  • http://www.thinkverification.com/
  • http://www.dvteclipse.com/help.html?documentation/e/index.html
The source of this article is wikipedia, the free encyclopedia.  The text of this article is licensed under the GFDL.
 
x
OK