|
|
|
|
|
|
|
|
|
|
|
Introduction to C Interface
|
|
|
There are times when one wants to interface with C code, Like if you had modeled a algo in C, later if you want same code in e for checking if your DUT is working as per the algo. e language provides mechanism to interface with c language, it is called c interface. It provides following features |
|
|
|
|
|
- You can pass data between e modules and C modules.
- You can use e data types in C code.
- You can call e methods and manipulate e data from C code.
- You can access any global data under sys in C code.
- You can call C routines from e code, even if that C routine has no knowledge of e.
|
|
|
|
|
|
Working with C language require data to be passed in both direction. i.e. from C to E, and E to C. While passing data types which are complex in nature like struct, byte so on, we need to use special data types. We will see both of this in detail below. |
|
|
|
|
|
Mapping e Types to C Types
|
|
|
Declaration of e types in C is done with the following |
|
|
|
|
|
|
|
|
|
|
|
SN_TYPE
|
|
|
Declares an e type in C. Use this macro whenever an e enum or struct must be declared in C. |
|
|
|
|
|
The following types are mapped directly to C types and can be used without the SN_TYPE macro: |
|
|
- SN_TYPE(int) => int.
- SN_TYPE(uint) => uint.
- SN_TYPE(bool) => bool.
- SN_TYPE(string) => char *.
|
|
|
|
|
|
1 #include <stdio.h>
2 #include "c_interface.h"
3
4 SN_TYPE(byte) c_interface (
5 SN_TYPE(string) name,
6 SN_TYPE(packet) packet1
7 ) {
8 SN_TYPE(byte) data;
9 // Do something here
10 return data;
11 }
You could download file c_interface.c here
|
|
|
|
|
|
SN_LIST
|
|
|
Declares an e list type in C. This macro is used whenever an e list must be declared in C. |
|
|
|
|
|
1 #include <stdio.h>
2
3 SN_TYPE(bool) c_interface_list (
4 SN_TYPE(string) list_of_names,
5 SN_TYPE(packet) packet1
6 ) {
7 // Do something here
8 }
You could download file c_interface_list.c here
|
|
|
|
|
|
|
|
|
|
|
|
Creating New Objects in C
|
|
|
You can create e objects in C with the SN_STRUCT_NEW, SN_LIST_NEW and SN_STRING_NEW. |
|
|
|
|
|
- SN_STRUCT_NEW : This macro returns a new, initialized struct of that type. All fields of the struct, including lists, are initialized as in e.
- SN_LIST_NEW : The macro returns a new, initialized, empty list of that type.
- SN_STRING_NEW : The macro allocates a new string (according to the size that was specified in the parameter) and returns a pointer to the new string.
|
|
|
|
|
|
|
|
|
Importing/Exporting to C
|
|
|
There are many ways to import C functions into e as listed below. |
|
|
|
|
|
- You can declare a global e routine to be implemented as a C routine.
- You can declare a local e method to be implemented as a C routine.
- You can declare a local e method to be implemented as a dynamic C routine or foreign dynamic C routine.
|
|
|
|
|
|
routine e-routine-name(param,...) [:result-type] |
|
|
[is C routine c-routine-name] |
|
|
|
|
|
Global e method
|
|
|
In this case, you can call the C routine directly from anywhere in your e code. The syntax for declaring a C routine as a global routine is: |
|
|
|
|
|
routine e-routine-name(param,...) [:result-type] |
|
|
[is C routine c-routine-name] |
|
|
|
|
|
This syntax is a statement. This statement must be compiled and statically linked with Specman Elite and the compiled C code. (The e code that calls the specified routine can be either loaded or compiled.) |
|
|
|
|
|
Example-Global routine |
|
|
|
|
|
1 #include <stdio.h>
2
3 void c_interface1 () {
4 printf("Hello World\n");
5 }
You could download file c_interface1.c here
|
|
|
|
|
|
Below is e code which uses the above c function. |
|
|
|
|
|
1 <'
2 extend sys {
3 c_hello() is C routine c_interface1;
4
5 run() is also {
6 c_hello();
7 };
8 };
9 '>
You could download file c_interface1.e here
|
|
|
|
|
|
Compiling the example |
|
|
|
|
|
Operation
|
Commands
|
Create c object file
|
gcc -c -o c_interface1.o c_interface1.c
|
Link c to e
|
sn_compile.sh -l c_interface1.o c_interface1.e -o c_interface1.run
|
Simulate
|
c_interface1.run -c "test"
|
|
|
|
|
|
|
Local e method
|
|
|
In this case, you define an e method within a struct and indicate that the method's body is implemented as a C routine. When you call the e method, the name of the enclosing struct instance is passed to the C routine and the C routine is executed. This way of calling C routines is useful when the C routine manipulates the fields of a particular struct instance. The syntax for declaring an e method whose body is implemented as a C routine is: |
|
|
|
|
|
e-method-name(param,...) [:result-type] is C routine c-routine-name |
|
|
|
|
|
Example-Local routine |
|
|
|
|
|
1 #include <stdio.h>
2 #include "c_interface2.h"
3
4 void c_interface2 (int i, char* s) {
5 int n;
6 if ( i < 5) {
7 for (n = 0; n < i; n ++) {
8 printf("Hello World\n");
9 }
10 } else {
11 printf("%s\n",s);
12 }
13 }
You could download file c_interface2.c here
|
|
|
|
|
|
1 <'
2 routine c_hello(i : int, s : string) is C routine c_interface2;
3
4 extend sys {
5
6 run() is also {
7 c_hello(1,"Test");
8 c_hello(5,"Hello Deepak");
9 };
10 };
11 '>
You could download file c_interface2.e here
|
|
|
|
|
|
Compiling the example |
|
|
|
|
|
Operation
|
Commands
|
Create h file
|
sn_compile.sh -h_only c_interface2.e -o c_interface2.h
|
Create c object file
|
gcc -c -o c_interface2.o c_interface2.c
|
Link c to e
|
sn_compile.sh -l c_interface2.o c_interface2.e -o c_interface2.run
|
Simulate
|
c_interface2.run -c "test"
|
|
|
|
|
|
|
|
|
|
local e method as dynamic Object
|
|
|
In either case, you define an e method within a struct and indicate that the method's body is implemented as a C routine. When you call an e method implemented as a dynamic C routine, the name of the enclosing struct instance is passed to the C routine and the C routine is executed. If the e method is implemented as a foreign dynamic C routine, the enclosing struct is not passed. The syntax for declaring an e method whose body is implemented as a dynamic C routine is: |
|
|
|
|
|
e-method-name(param,...) [:result-type] is [also|first|only] [foreign] dynamic C routine [lib-name :][c-routine-name ] |
|
|
|
|
|
1 #include <stdio.h>
2
3 void c_interface (int i, char* s) {
4 int n;
5 if ( i < 5) {
6 for (n = 0; n < i; n ++) {
7 printf("Hello World\n");
8 }
9 } else {
10 printf("%s\n",s);
11 }
12 }
You could download file c_interface3.c here
|
|
|
|
|
|
1 <'
2 extend sys {
3 c_interface(i:int, s:string) is foreign dynamic C routine c_interface3:;
4
5 run() is also {
6 var i : int = 1;
7 c_interface(1,"");
8 c_interface(5,"Hello Deepak");
9 };
10 };
11 '>
You could download file c_interface3.e here
|
|
|
|
|
|
Compiling the example |
|
|
|
|
|
Operation
|
Commands
|
Create c object file
|
gcc -c c_interface3.c
|
Create lib file
|
ld -E -shared -o c_interface3.so c_interface3.o
|
Simulate
|
specman -c "load c_interface3;test"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|