As discussed in "Syntax Hierarchy" on page 49, e contains a very strict syntax hierarchy. Procedural actions can only be defined inside methods. Methods are struct members. e methods are similar to C functions, Verilog tasks, and VHDL processes. An e method is an operational procedure containing actions that define its behavior. A method can have parameters, local variables, and a return value. You can define a method only within a struct and you must create an instance of the struct before you can execute the method. The syntax to define a method is as follows:
method-name ([parameter-list]) [: return-type] is {action;...};
The components of a method definition are as shown in Table 6-1 below:
method-name | A legal e name. | |
---|---|---|
parameter-list | A list composed of zero or more parameter declarations of the form param-name: param-type separated by commas. The parentheses around the parameter list are required even if the parameter list is empty. | |
param-name | A legal e name. | |
param-type | Specifies the parameter type. |
Example 6-1 shows a method definition.
Example that shows a simple method definition <' struct packet { //Struct definition addr: uint(bits:2); //Field of a struct member zero_address (): bool is { //Define method name zero_address //No arguments, return type boolean if(addr == 0) then { out("Packet has address 0"); result = TRUE; //An implicit variable result is automatically //created and is of the same type as the return //which in this case is bool. } else { result = FALSE; }; //end of if-else //The value of result when it reaches the end of the method call //is the return value of the method. }; //end of method definition '>
Methods have the following characteristics:
Methods can contain actions including variable declarations.
Methods can have zero or up to 14 input parameters.
Methods may or may not return a value.
Methods may or may not consume time. (The methods discussed in this chapter do not consume time.)
Methods can read or write the following values:
Locally declared variables within the method.
Fields within the local struct.
Arguments and return value (implicit result variable) of the method.
Fields in other structs using path notation.
Example 6-2 shows various fields that can be accessed in a method.
Example shows the different values that can be accessed inside a method - Fields within the local struct - len - Arguments - min_len - Local variable - count - Implicit result variable - result - Hierarchical path notation - d_struct_i.addr <' struct c_struct { //Struct definition len: uint; //Field len legal: bool; //Field legal d_struct_i: d_struct; //Field struct instantiation legal_length(min_len: uint):bool is { var count: int; //Local variable has a default value of 0. if (len >= min_len) then { //Directly access len, a field in //c_struct. min_len is an argument. result = TRUE; count += 1; //Increment local variable count by 1. } else { result = FALSE; }; if (count == 1)then { //Check the value of the local variable. d_struct_i.addr = 0; //Set the value of the addr field in //d_struct_i instance to be 0. Access //field in another struct. out("Incremented counter"); }; }; //end of method legal_length }; //end of c_struct definition struct d_struct {//Define d_struct addr: uint; }; //end of d_struct definition '>
Local variables are declared within a method using the var action. Local variables can only be accessed within that method. Local variables can have the same types as fields. Default initial values of local variables are shown in Table 6-2.
Variable Type | Default Value | Example |
---|---|---|
int/uint | 0 | var count: uint; |
list | empty | var b_list: list of byte; |
bool | FALSE | var legal: bool; |
struct | NULL | var tmp_packet: packet = new; (The keyword new or gen is needed for var declaration so that the fields of the struct can be accessed.) |
Methods are not executed unless they are invoked. One invokes a method by simply calling the method in a predefined or a user-defined method. Example 6-3 shows how the method legal_length defined in Example 6-2 is invoked from a predefined post_generate() method of the struct c_struct.
Example shows how the method legal_length is invoked in the predefined post_generate() method. The post_generate() method is explained later in the book. <' extend c_struct { //struct definition post_generate() is also { legal = legal_length(64); //legal gets the return value of method //64 is the min_len arg passed to method }; }; //end of c_struct extend '>
Similar to structs and units, methods can also be extended. Methods are commonly extended in three ways:
is first extension adds code before the existing method definition.
is also extension adds code after the existing method definition.
Example 6-4 shows an instance in which all three extensions of the method are used. Existing method definition means the code loaded thus far.
Example shows how to extend methods using the three extensions. <' struct meth { m() is { //Original method definition out("This is..."); }; }; extend meth { m() is also { //Add code to end of existing definition out("This is also..."); //Prints after "This is...". }; }; extend meth { m() is first { //Add code to beginning of existing definition out("This is first..."); //Prints before "This is...". }; }; '> Comment block: At this point the method looks like the following m() is { out("This is first..."); out("This is..."); out("This is also..."); }; <' extend meth { m() is only { //Replace existing definition out("This is only..."); }; }; '> Comment block: At this point the method looks like the following m() is { out("This is only..."); };