Home > Articles > Programming

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

3.2 Data Types

This section discusses the basic data types in e.

3.2.1 Scalar Types

Scalar types in e are one of the following:

  • Numeric

  • Boolean

  • Enumerated

3.2.1.1 Numeric and Boolean Scalar Types

Table 3-6 shows predefined numeric and boolean types in e.

Table 3-6. Scalar Types

Type Name

Function

Usage Example

int

Represents numeric data, both negative and non-negative integers. Default Size = 32 bits

length: int;
addr: int (bits:24); // 24-bit vector

uint

Represents unsigned numeric data, non-negative integers only. Default Size = 32 bits

delay: uint;
addr: uint (bits:16); // 8-bit vector

bit

An unsigned integer in the range 0–1.

Size = 1 bit

valid: bit; // 1-bit field

byte

An unsigned integer in the range 0–255.

Size = 8 bits

data: byte; // 8-bit field
data: uint (bits:8); // Equivalent
                     //definition

time

An integer in the range 0–263-1. Default Size = 64 bits

delay: time; //64-bit time variable

bool

Represents truth (logical) values, TRUE (1) and FALSE (0). Default Size = 1 bit

frame_valid: bool; //TRUE or
                   //FALSE

3.2.1.2 Enumerated Scalar Types

Enumerated types define the valid values for a variable or field as a list of symbolic constants. For example, the following declaration defines the variable instr_kind as having two legal values.

<'
//Implicit enumerated type. immediate=0, register=1
 type instr_kind: [immediate, register];
'>

These symbolic constants have associated unsigned integer values. By default, the first name in the list is assigned the value zero. Subsequent names are assigned values based upon the maximum value of the previously defined enumerated items + 1.

It is also possible to assign explicit unsigned integer values to the symbolic constants. This method is used when the enumerated types may not be defined in a particular order.

<'
//Explicit enumerated type. immediate=4, register=8
type instr_kind: [immediate=4, register=8];
'>

It is sometimes convenient to introduce a named enumerated type as an empty type.

'>
type packet_protocol: []; //Define empty type
'>

Once the protocols that are meaningful in the program are identified the definition of the type can be extended.

'>
//Extend this type in a separate file.
//No need to touch the original file.
extend packet_protocol : [Ethernet, IEEE, foreign];

//Define a struct that uses a field of the above type.
struct packet {
kind: packet_protocol; //Define a field of type
                       //packet_protocol. Three possible values.
};
'>

3.2.1.3 Scalar Subtypes

A subtype can be created from one of the following:

  • A predefined numeric or boolean type (int, uint, bool, bit, byte, time)

  • A previously defined enumerated type

  • A previously defined scalar subtype

Creation of subtypes is shown in the example below.

<'
//Define an enumerated type opcode
type opcode: [ADD, SUB, OR, AND];

//Define a subtype using the previously defined type
//This subtype includes opcodes for logical operations
//OR, AND
type logical_opcode: opcode [OR, AND];

//Define a subtype of a predefined scalar type, 4 bit
//unsigned vector
type small: uint(bits:4);

//Define a struct that uses the above types
struct instruction {
op1: opcode; //Field of type opcode
op2: logical_opcode; //Field of type logical_opcode
length: small; //4 bit unsigned vector
};

'>

3.2.2 List Types

List types hold ordered collections of data elements. Items in a list can be indexed with the subscript operator [ ], by placement of a non-negative integer expression in the brackets. List indexes start at zero. You can select an item from a list by specifying its index. For example, my_list[0] refers to the first item in the list named my_list. Lists can be of any type. However, a list of lists is not allowed. All items in a list must be of the same type. Lists are dynamically resizable and they come with many predefined methods.

Lists are defined by using the list of keyword in a variable or a field definition.

<'
struct packet {
addr: uint(bits:8); // 8-bit vector
data1: list of byte; //List of 8-bit values
};
struct sys {
packets[10]: list of packet; //List of 10 packet structures
values: list of uint(bits:128); //List of 128-bit vectors
};
'>

e does not support multidimensional lists (lists of lists). To create a list with sublists in it, you can create a struct to contain the sublists, and then create a list of such structs as the main list. In the example above, the packet struct contains a list of bytes. In sys struct, there is a list of 10 packets. Thus, sys contains a list of lists.

3.2.2.1 Keyed Lists

A keyed list data type is similar to hash tables or association lists found in other programming languages. Keyed lists are defined with the keyword key. The declaration below specifies that packets is a list of packets, and that the protocol field in the packet type is used as the hash key. Keyed lists are very useful for searching through a list with a key.

<'
type packet_protocol : [Ethernet, IEEE, foreign];
struct packet {
    protocol: packet_protocol;
};
struct dtypes {
    m() is { //Method definition explained later in book
        // Define local variable, keyed list
        var packets : list (key: protocol) of packet;
    };
};
'>

3.2.3 The String Type

A string data type contains a series of ASCII characters enclosed by quotes (“ ”). An example of string declaration and initialization is shown below.

<'
struct dtypes {
    m() is { //Define a method (procedure)
     var message: string; //Define a variable of type string
     message = "Beginning initialization sequence...";
                         //String value
     print message; //Print string
    };
};
'>
  • + Share This
  • 🔖 Save To Your Account