For C routines to interact with e code, the C files have to be integrated with Specman Elite. A special script sn_compile.sh is provided with the Specman Elite installation to compile and link C code and e code in Specman Elite.
To integrate C code and e code in Specman Elite perform the following steps:
Declare the C routines in e code using the is C routine keywords. These keywords in the e code indicate to the sn_compile.sh script that the particular routine or e method is implemented as a C routine. Therefore the computation of the return value for that routine or method is done in C code.
Often the C code needs access to e types or methods. Export the e types or methods used by C routines by adding C export statements in the e code. The C export statements in e code allow C code to access e types or methods.
Generate the C header files (.h files) from the e files using the sn_compile.sh script with the -h_only option. These C header files contain information declared in e code with is C routine keywords and C export statements. These header files are compiled in the C domain.
Include the generated header files in your C files using the #include C syntax. These header files provide information about accessing e types or methods from C files.
Compile all your C files using the gcc compiler (gcc with -c and -o options) to create object (.o files).
Compile your e files that contain C directives and link them with your simulator and C object files using the sn_compile.sh script with -l option and the -o option to create an executable binary file.
Execute this binary file at the operating system command prompt to run Specman Elite along with the compiled C code instead of running the standard Specman Elite binary.
Figure 16-1 below shows the integration mechanism. The exact commands to execute are shown later in Example 16-4.
A simple example described in this section shows how the integration of e files and C files takes place. This example uses a C routine, wrap_mean_sqrt, declared as a global e routine, mean_sqrt(), to calculate the mean square root of a list of packets.
First, a global e routine, mean_sqrt() must be declared. This routine mean_sqrt() is implemented using the C routine wrap_mean_sqrt. Example 16-1 shows the declaration of mean_sqrt() routine.
File name: wrap_mean_sqrt.e
<'
-- Declare a global e routine named mean_sqrt which takes a list
-- of integers as an argument. The return type is also int.
-- The computation of this routine is performed in C code using
-- the C routine wrap_mean_sqrt
routine mean_sqrt(l:list of int):int is C routine wrap_mean_sqrt;
'>
The e routine mean_sqrt() declared earlier is invoked in e code simply by calling it like an e method. Example 16-2 calls mean_sqrt() and passes it a list of packet lengths. The mean_sqrt() calls the wrap_mean_sqrt C routine and passes it the list of packet lengths.
File: packets_statistics.e
File calls the mean_sqrt e routine
to compute the mean square root of packet
lengths in a list. The mean_sqrt e routine
calls the C routine wrap_mean_sqrt.
<'
-- Definition of the packet struct
struct packet {
kind : [good,bad];
addr : uint (bits : 2) ;
len : uint (bits : 6) ;
data [len] : list of byte ;
!parity : byte ;
};
-- Definition of port struct
struct port {
packets : list of packet; -- List of packets
!len_mean_sqrt : int; -- Mean square root value
!packets_lens : list of uint (bits:6); -- List of lengths
check() is also {
-- Create a list of packet lengths
packets_lens = packets.apply( it.len );
-- Print the list of packet lengths
print packets_lens;
-- Call the mean_sqrt e routine with a list of packet
-- lengths. This routine calls the C routine
-- wrap_mean_sqrt to perform the computation.
len_mean_sqrt = mean_sqrt( packets_lens );
-- Print the computed value.
print len_mean_sqrt;
};
};
-- Instantiate the port struct
extend sys {
port : port;
};
'>
The wrap_mean_sqrt C routine is implemented by means of another C routine compute_mean_sqrt. Therefore, there are three C files, wrap_mean_sqrt.c, and compute_mean_sqrt.h, compute_mean_sqrt.c. Example 16-3 shows the C code for all three files.
File name: wrap_mean_sqrt.c #include "compute_mean_sqrt.h" #include "wrap_mean_sqrt_.h" int wrap_mean_sqrt( SN_LIST( int ) e_list_of_int ) { int i; int result; int list_size; double * c_list_of_double; list_size = SN_LIST_SIZE( e_list_of_int ); c_list_of_double = (double *)calloc( list_size, sizeof(double) ); for (i=0; i < list_size; i++ ) { c_list_of_double[i] = (double)SN_LIST_GET( e_list_of_int, i, int); }; result = (int)compute_mean_sqrt( c_list_of_double, list_size ); free( c_list_of_double ); return( result ); } // wrap_mean_sqrt //End of file wrap_mean_sqrt.c ---------------------------------------------------------------------- ---------------------------------------------------------------------- File name: compute_mean_sqrt.h double compute_mean_sqrt( double *nums, int size ); //End of file compute_mean_sqrt.h ---------------------------------------------------------------------- ---------------------------------------------------------------------- File name: compute_mean_sqrt.c #include <math.h> #include "compute_mean_sqrt.h" double compute_mean_sqrt( double *nums, int size ) { int i; double sum = 0; for ( i=0; i<size; i++ ) { sum += sqrt( nums[ i ] ); }; return( sum/size ); }; //End of file compute_mean_sqrt.c ----------------------------------------------------------------------
Example 16-4 shows the commands required to compile and link e code and C code defined to implement the mean_sqrt() e routine. These commands are executed at the operating system prompt (for example the UNIX command prompt).
This example does not contain e code. It contains commands executed at the operating system prompt(%) The file wrap_mean_sqrt.e contains the e routine declaration for mean_sqrt that points toC routine wrap_mean_sqrt. The .h file is generated using the sn_compile.sh -h_only option.
The following command generates the wrap_mean_sqrt_.h file. % sn_compile.sh -h_only wrap_mean_sqrt.e -o wrap_mean_sqrt_.h The file compute_mean_sqrt.c performs the mean square root computation. The file
wrap_mean_sqrt.c contains an implementation of the wrap_mean_sqrt C routine. This routine
calls the compute_mean_sqrt routine. The file wrap_mean_sqrt.c also includes the .h file
wrap_mean_sqrt_.h that was generated in the previous step. Compile the files using the gcc
-c -o option. These commands create the object files. % gcc -c compute_mean_sqrt.c -o mean_sqrt.o % gcc -c wrap_mean_sqrt.c -o wrap_mean_sqrt.o Compile the e files and C object files to create a new Specman Elite binary file. Use the
command sn_compile.sh -l. The -o option is used to specify the name of the new Specman
Elite binary called float_mean_sqrt. % sn_compile.sh -l "mean_sqrt.o wrap_mean_sqrt.o" \ wrap_mean_sqrt.e -o float_mean_sqrt Run the new Specman Elite binary instead of running the standard Specman Elite binary
(specman). % ./float_mean_sqrt This brings up the Specman prompt. The new binary that is executing contains both standard
Specman Elite behavior plus the C code. Load the packet_statistics.e file and run the test
using the test command. In this environment, calls can be made to the mean_sqrt() global e
routine. Specman wrap_mean_sqrt> load packets_statistics.e Specman packets_statistics> test