System Level Design Languages:Basic C Language Constructs

Basic C Language Constructs

C and C++ are extensive, and too complex to be fully described here. The intention here is to discuss these languages from a hardware point of view and not get into many of their details. We assume here that the reader is familiar with the basics of these two languages, and the basic constructs of C are listed only as a reminder. In a few cases, the similar C++ syntax is also described. For further study on C language, refer to Ref. [3]. A sample C code is shown in Figure 86.39. However, complete C and C++ code examples can be found in Sections 86.3 and 86.4, and Chapter 89. Description of the C language constructs given below, becomes easier to comprehend by referring to this example code.

C language constructs include the following list:

Preprocessors: They are commands that are processed at compile time (not run-time). They begin with a # sign. Several preprocessor examples are #include, #define, #ifdef, #ifndef, #undef, #endif, etc. An example of preprocessors usage is shown in Figure 86.39 at line 1.

Data types: This language has several predefined data types such as int, int64, char, unsigned char, float, double, etc. (line 9 and line 10 in Figure 86.39). It also accepts enumerations (with the enum keyword) and user-defined types (with typedef, union, and struct keywords).

Functions: There are no procedures in C language. However, there are functions and there is a special data type called void meaning nothing. For example, a function returning void implies no

System Level Design Languages-0221

return value for the function (line 2 in Figure 86.39), and a function with void as its parameter is considered as a function with no parameters. A C program consists of several functions and a main function called main() (line 7 in Figure 86.39). main() is the starting point of a program and thus the use of this function is mandatory in all C programs. It has two arguments called argc and argv that are used for the program’s parameters. The former shows the number of program parameters (including the program itself), while the latter contains the parameters themselves. For example, if we have a program named mycopy.exe with two filenames as its parameters, and if we use the string “mycopy fn1.c fn2.txt” in the command line, then argc becomes 3 and argv is an array containing mycopy, fn1.c, and fn2.txt, respectively.

Another important point about functions is function prototyping. If function f1 is to be used inside function f2, f1 must appear before f2. This is because the compiler needs to know about f1 when it is compiling f2. In such cases, compilation errors can be avoided by prototyping f1 before f2. Prototyping is simply defining a function at the beginning of a C file. In prototyping, the function’s name and optionally its arguments are listed followed by a semicolon. By prototyp- ing, the compiler recognizes a function before reaching its implementation. It is recommended that all functions have a prototype.

Conditions and conditional statements: A conditional statement partitions a portion of code to several parts. On some conditions one (or more) of these parts are executed. The conditional statements include if-else (line 11 and line 14 in Figure 86.39), ?-:, and switch-case constructs. The conditions are Boolean statements (0 for false and nonzero value for true) and can be combined by other Boolean statements, and with && (logical AND), || (logical OR), and the unary operator ! (logical not).

Loops: Loop and iteration constructs in C include for-loops (line 18 in Figure 86.39), while-loops (line 25 in Figure 86.39), and do-while loops. Examples for these constructs are listed below.

System Level Design Languages-0222

C also provides two statements for controlling program flow inside a loop: break and continue. When using break, the flow exits from its current block and continues from the next statement after the block. In contrast, continue causes the flow to exit from the current loop (or block) iteration and start the next iteration.

Variables: Variables in C/C++ are of several kinds, including simple variables (i in Figure 86.39), static arrays (str in Figure 86.39), dynamic arrays and pointers (int_ptr in Figure 86.39). The syntax of a simple variable declaration is

type var_name [=initial_value]; With this syntax, an integer can be defined as int int_var; A static array is an array of a defined type. A precise amount of memory will be allocated when these variables are defined. For example, an array of 100 integers is defined by int int_array [100]; If an integer uses two bytes of the memory, when the compiler reaches the above definition statement, it will allocate 200 bytes of memory for int_array variable.

Another type of variables, which is an important strength point of the C language, is a pointer. A pointer is an address that corresponds to a variable’s address. Pointers are represented by a ∗ preceding variable names. For example, in intint_ptr; int_ptr, is a variable that points to an integer.

Another operator that is related to pointers is the & (address-of) operator. It is used before a variable (for example &int_var) to show the address of that variable. For example if int_var is 1000 and if we assign &int_var to an integer pointer like int_ptr, since this integer pointer points to the address of int_var, ∗int_ptr is equal to 1000.

C also allows two or more dimensional pointers. For example, a pointer to another pointer is defined by ∗∗ (argv in Figure 86.39). Pointers are a complicated concept in C/C++ and care must be taken in using them. It is strongly recommended to study pointers in more detail before starting to use them.

Dynamic arrays are pointers, to which memory can be assigned at run-time. Allocating memory can be done by several memory allocation functions (such as malloc in C, shown in line 16 in Figure 86.39, and new in C++). It is necessary to free an allocated memory of a variable after using it, because it will not be de-allocated automatically (like static arrays). Memory leaks are resulted from improper de-allocation. Memory de-allocation functions are free in C, shown in line 27 in Figure 86.39, and delete in C++.

Another interesting point about pointers and dynamic arrays is void∗ or a pointer to the void type. As stated above, void in C/C++ means nothing, but when it is used as a pointer, it means anything. If a variable of type void∗ is used as a function parameter, any type of pointer can be passed to that function for that parameter (for example, char∗, int∗, etc.). In addition if a void∗ variable is defined inside a function, memory can be allocated with any type to that variable. For example, if v_ptr is a void∗, what is shown below generates an array of 100 characters:

System Level Design Languages-0224

An important point about variables in C/C++ is type casting (similar to line 16 in Figure 86.39). Unlike languages like PASCAL, in C/C++ it is permitted to define a variable of type t1 in a function and use it as a variable of type t2 in the body of that function. Type casting is also used in parameter passing in function calls. As type casting (like pointers) is a very complicated concept in C/C++, it is recommended that the reader studies type casting in detail before starting to use it.

Bit-level operators: Another feature of the C language, which can also be useful for hardware designs, is the bit-level operators. These operators consider their operands as a set of bits. They perform their operations on the corresponding bits of each operand. These operations include

& for bitwise AND of two variables

| for OR of two variables

^ for XOR of two variables

• ~ for one’s complement

• (( for left shift

• )) for right shift

As an example, consider the case where there are two character variables c1 (=7) and c2 (=1). The ‘c3 = c1 & c2’ statement in this program results in c3 becoming 1 (00000111 & 00000001).

This is because the & operator performs bit-by-bit ANDing of c1 and c2 and puts the result in bits of c3.

The variable bit-length can also be defined in C/C++. For example, if we want to have a 4-bit variable, we can define it as int fbit_var:4;

Defining bit-length for variables is only allowed in a struct.

Communication with the outside world: Several library functions (usually defined in stdio.h and stdlib.h header files) are used for inputting data from the user or file and outputting the results of a program to the output display or a file. A number of useful functions for I/O tasks include

printf (line 12, line 23, and line 26 in Figure 86.39), fprintf, scanf, fscanf, open, fopen, read, fread, write, fwrite, close, and fclose functions are also available for working with different types of files. Functionalities of these functions are evident from their names.

In C++, two standard streams cin and cout are defined for input and output streams. Two operations � and � are also overloaded for inputting data to a specified variable, and sending the value of the specified variable to the output. These operations are defined in the iostream header file.

Comments

Popular posts from this blog

SRAM:Decoder and Word-Line Decoding Circuit [10–13].

ASIC and Custom IC Cell Information Representation:GDS2

Timing Description Languages:SDF