Manuals >User's Guide >Using Transforms and Functions
Print version of this Book (PDF file)
prevnext

Declarations and Implementation Examples

These program files contain a variety of example information:

    • userc.h provides declarations for important types, such as complex
    • xf_util.c.h provides declarations for the utility functions that operate on real, complex, and matrix data
    • userc.c and userc_io.c contain examples showing how to write C functions and how to add them to IC-CAP

Function Types

You can add three types of functions to IC-CAP. These functions are designed to operate on Real, Complex, and Matrix data. Although you must choose one of these types, your function does not need to perform mathematical operations. For example, you can implement functions that perform instrument I/O operation.

The function average_double() in userc.c is an example of a function that operates on real data. This function is defined in Figure 34 where the function arguments are:

inputs     A 2-dimensional array of double precision real numbers that contains zero or more input data sets

num_inputs     An integer indicating the number of input data sets contained in inputs

points_per_input     An array of integers indicating the number of data points in each data set in inputs

output     An array of double precision real numbers used to store the results of the function.

num_out_points     An integer indicating the number of data points in output

variables     An array of double precision real numbers containing zero or more variables passed to the function

num_variables     An integer indicating the number of values contained in variables

parameters     An array of strings (char*) containing zero or more parameter names or other strings passed to the function

num_parameters     An integer indicating the number of strings contained in parameters

points_per_curve     An integer indicating the number of points in the main sweep of the setup which owns the input data sets.

The function cplx_conj() in userc.c is an example of a function that operates on complex data. Its arguments are identical to average_double() except that the inputs, output, and variables arguments contain complex numbers instead of real numbers.

The function matrix_transpose() in userc.c is an example of a function that operates on matrix data. Its arguments are identical to cplx_conj() except that the inputs and output arguments contain matrices instead of complex numbers. Refer to the userc.h and userc.c files for information on manipulating complex numbers and matrices.

Figure 34 The average_double() Function Operates on Real Data

Adding Functions to the Function Browser

This section describes six functions for adding the new function to the Function Browser and provides declarations for them. These IC-CAP functions (Table 29) make a pointer to the new function, as well as counts indicating how many instances of each possible input type the function expects to receive. For example, an extraction function may need to receive two data set inputs, zero real numbers, and four model parameters. The system stores the address of the function, and uses the counts to construct editors at run-time, when the function is selected for use by a transform. You can elect to receive data sets in the form of real arrays, complex arrays, or matrix arrays. You can also choose to run the function automatically when its inputs change or to run it when the Extract command is executed for a setup.


Note

For the following functions, you must use the funcptr argument as described; otherwise, a core dump or other erratic behavior may occur when IC-CAP calls the new function.


The arguments for these functions are defined as:

name    A string (char*) containing the name for the new function as it should appear in the IC-CAP Function Browser

funcptr    A function pointer that is the actual name of the new function as defined in userc.c

ni    An integer indicating the number of input data sets required by the new function

op    An integer indicating the number of points in the output data set created by the new function. This is often set to -1, which indicates that the number of points returned by the function will be the same as the number of points in the Outputs within the current setup. A value of -2 indicates that the number of points returned by the function will be the same as the number of points in the largest data set passed to the function.

nvr    An integer indicating the number of variables (real/complex number arguments) required by the new function

npr    An integer indicating the number of parameter names (or other strings) required by the new function

xfft    An enumerated type used to set the type of the new function. A function can be an extraction, a math function, or a special function. An extraction is executed when you issue the Extract command for the Active setup or Active DUT and a math function is automatically executed if any of its inputs change. A special function must always be executed manually. Refer to the description of the xffunc_type enum in xf_util.c.h for the available choices. The functions, add_double_c_func1, add_complex_c_func1, or add_matrix_c_func1 do not contain this argument. If they are used to add the new function to the Function Browser, the function is assumed to be a math function.

bdf    This argument is reserved for future use. Always set it to 0.

After a function is installed in the Function Browser, a series of calls should be made immediately to provide labels for the data set expressions, numeric expressions, and parameter inputs that appear in the editor of any transform using the function. For information about providing labels, refer to Labeling the Editor Input Fields.

Table 29 Functions for Adding a New Function to the Function Browser 
Function
Definition
add_double_c_func1
Installs a user-defined function in the Function Browser. Funcptr should be the name of a C function taking an argument list identical to average_double(). Refer to userc.c, for examples of this function call. Syntax:
 
 void add_double_c_func1 ( /* char* name,
FUNCPTR_TYPE funcptr, int ni,int op, int
nvr, int npr */ ) ;
add_double_c_func2
Installs a user-defined function in the Function Browser. Funcptr should be as in add_double_c_func1. The type of the new function can be set with the xfft argument. The bdf argument is reserved for future use. Always set it to 0. Syntax:
 
 void add_double_c_func2 ( /* char* name,
FUNCPTR_TYPE funcptr, int ni, int op,
int nvr, int npr, xffunc_type xfft, int
bdf */ ) ; 
add_complex_c_func1
Installs a user-defined function in the Function Browser. Funcptr should be the name of a C function taking an argument list identical to cplx_conj(). Refer to userc.c for examples of this function call. Syntax:
 
 void add_complex_c_func1 ( /* char*
name, FUNCPTR_TYPE funcptr, int ni, int
op, int nvr, int npr */ ) ; 
add_complex_c_func2
Installs a user-defined function in the Function Browser. Funcptr should be as in add_complex_c_func1. The type of the new function can be set with the xfft argument. The bdf argument is reserved for future use. Always set it to 0. Syntax:
 
 void add_complex_c_func2 ( /* char*
name, FUNCPTR TYPE funcptr, int ni, int
op, int nvr, int npr, xffunc type xfft,
int bdf */ ) ; 
add_matrix_c_func1
Installs a user-defined function in the Function Browser. Data sets consisting of complex matrices (s-parameter data) are supplied when this function is called. Declarations for the matrices can be found in userc.h. Funcptr should be the name of a C function taking an argument list identical to matrix_transpose(). Refer to userc.c for an example of this function call. Syntax:
 
 void add_matrix_c_func1 ( /* char* name,
FUNCPTR_TYPE funcptr, int ni, int op,
int nvr, int npr */ ) ; 
add_matrix_c_func2
Installs a user-defined function in the Function Browser. Funcptr should be as in add_matrix_c_func1. The type of the new function can be set with the xfft argument. The bdf argument is reserved for future use. Always set it to 0. Syntax:
 
 void add_matrix_c_func2 ( /* char* name,
FUNCPTR TYPE funcptr, int ni, int op, int
nvr, int npr, xffunc type xfft, int bdf
*/ ) ; 

Argument List Guidelines

The argument lists for new functions must agree with IC-CAP's requirements. For example, add_complex_c_func1() tells the system that a function such as cplx_conj expects complex data set inputs, output array, and numeric variables. This is also the case for cplx_conj().

As another example, add_double_c_func1() is used to tie in average_double(), which expects double data set inputs, output array, and numeric variables. New C functions, like cplx_conj() and average_double(), must be installed using the appropriate call, so that IC-CAP can invoke the function. Otherwise, core dumps can result.

Adding Function Descriptions to the Function Browser

By default, when you create a new function in IC-CAP, the function appears in the User Defined category in the Function Browser dialog box. You can create dialog box documentation for the function and/or place it in another category. The process consists of two basic steps:

    • Create a text file with the documentation
    • Declare a variable to identify the location and name of the text file

To document and categorize user-defined functions:

  1   Create a text file using any text editor.

  2   Create a record for each function using the following form:

<function_name>
"<group1>"[,"<group2>"]...
<multiline description>
-
<multiline list of extracted parameters>

where

<function_name> appears exactly (spelling/case) as you created it in IC-CAP

<"group1"> is the label of the category (new or existing) you want the function to be listed under in the Function Browser. Note that additional groups are optional. If you want a function to appear in more than one category, list each category name, separated by commas.

<multiline description> is the text you want displayed in the Description field

- indicates the end of text for the Description field and beginning of text for the Extracted Parameters field

<multiline list of extracted parameters> is the list of parameters you want displayed in the Extracted Parameters field (where applicable)

When creating each record observe the following guidelines:

    • Use an exclamation mark (!) as a comment symbol in column 1
    • Use a single asterisk (*) on a line to indicate a record separator (no spaces allowed)
    • Use a single hyphen (-) on a line to indicate the separation between text for the Description field and text for the Extracted Parameters field (no spaces allowed)


Note


Multiple functions can be declared in a single file or in separate files.


To declare the variable identifying your function documentation:

  1   Create the variable ICCAP_USER_FUNCTION_BROWSE_DATA in any of the following files:
     $ICCAP_ROOT/iccap.cfg  (for site-wide use)
     $HOME/.iccap  (for individual use, all sessions)
     .iccap in any startup directory  (for individual use, particular session)

The program searches the startup directory first, then $HOME, then the installation directory. For information on changing these files, refer to the Installation manual.

  2   Set the variable to the path and filename(s) of your function documentation file(s); for example:

ICCAP_USER_FUNCTION_BROWSE_DATA = {$HOME}/my_func.txt
When listing multiple files, separate filenames by colons.

  3   Re-start IC-CAP. The program reads the listed files, in addition to the supplied function file, and display all functions in the Function Browser.

Labeling the Editor Input Fields

This section describes the functions used for labeling the fields appearing in transform editors. Also, custom functions and transforms may show appropriate labels to remind you of the types of arguments needed at run-time.

The following definitions are used in this section:

    • An input, or data set input, denotes a data set or an expression involving datasets.
    • A numeric variable is a field in which a user can provide a real number or expression.
    • A parameter is a field in which a user can provide the name of a model or DUT parameter, an arbitrary string expression (as is the case with the USERC_system function), or the name of an IC-CAP system variable.

Table 30 Labeling the Fields Functions 
Function
Definition
add_input_name
Specifies a label appearing for a data set input field when a user-defined function is used in a transform. Refer to userc.c for examples of this call. This should be called once for each data set input required. The number of data set inputs required is specified as ni in one of the calls described in Adding Functions to the Function Browser. Limit the length of the name argument to 12 characters; otherwise it may be truncated when displayed by IC-CAP. Syntax:
 
 void add_input_name ( /* char* name */ ) ;
add_variable_name
Specifies a label appearing for a numeric variable field when a user-defined function is used in a transform. Refer to userc.c for examples of this call. This should be called once for each numeric variable required. The number of numeric variables required is specified as nvr in one of the calls described in Adding Functions to the Function Browser. Limit the length of the name argument to 12 characters; otherwise it may be truncated when displayed by IC-CAP. Syntax:
 
 void add_variable_name (/* char* name */ );
add_parameter_name
Specifies a label appearing for a parameter field when a user-defined function is used in a transform. Refer to userc.c for examples of this call. This should be called once for each parameter required. The number of parameters required is specified as npr in one of the calls described in Adding Functions to the Function Browser. Limit the length of the name argument to 12 characters; otherwise it may be truncated when displayed by IC-CAP. Syntax:
 
 void add_parameter_name (/* char* name */ );

Utility Functions

IC-CAP provides a set of utility functions to use when writing transforms in C language. Most of these functions are declared in xf_util.c.h. Some functions, for which the source is provided, appear only in userc.c or userc.h. Each is described in the following tables.

Table 31 Accessing Model and DUT Parameters Functions 
Function
Definition
get_par_w_check
Finds a parameter's value, given its name. The value is passed back via the double* second argument. Return values are:
   0 = parameter found
   -1 = parameter not found
Syntax:

 
 extern int get_par_w_check ( /* char
*param_name, double *return_data */ ); 
set_par_w_check
Sets a parameter's value. The value is passed in via the double* second argument. Return values are:
   0 = parameter found
   -1 = parameter not found
Syntax:

 
 extern int set_par_w_check ( /* char
*param_name, double val */ ); 
set_par_w_check_ptr
Sets a parameter's value. The value is passed in via the double* second argument. This is more suitable for FORTRAN calling than C, since the second argument is by address. Return values are:
   0 = parameter found
   -1 = parameter not found

Syntax:
 
 extern int set_par_w_check_ptr ( /* char
*param_name, double *val */ ); 

Table 32 Accessing System Variables Functions 
Function
Definition
get_var_w_check
Finds a system variable's value, given its name. The value is passed back via the double* second argument. Return values are:
   0 = system variable found
   -1 = system variable not found

Syntax:
 
 extern int get_var_w_check ( /* char 
*variable_name, char *return_data */ );
get_var_str_w_check
Finds a system variable's string value, given its name. The value is returned by reference in the second argument. A static area is used for the returned string, so copy the returned string if you want to save the value and intend to call this function again. Return values are:
   0 = system variable found
   -1 = system variable not found

Syntax:
 
 extern int get_var_str_w_check ( /* char
*variable_name, char **return_data */ ); 
set_var_w_check
Sets a system variable's value. The value is passed in via the double second argument. Return values are:
   0 = system variable found
   -1 = system variable not found
Syntax:

 
 extern int set_var_w_check ( /* char
*variable_name, double val */ ); 
set_var_str_w_check
Sets a system variable's value. The value is passed in via the char* second argument. This differs from the previous call in that the IC-CAP system variable is assigned a string rather than a numeric value. Return values are:
   0 = system variable found
   -1 = system variable not found
Syntax:

 
 extern int set_var_str_w_check ( /* char
*variable_name, char* val */ ); 

The following utilities compute values for parameters or system variables (which the above two sections address separately). These functions also generate output automatically in the same style as the built-in IC-CAP extraction functions. Source for these functions appears in userc.c

Table 33 Accessing Parameters or System Variables Function 
Function
Definition
get_par_or_var
Finds a parameter's or a system variable's value, given its name. In a conflict, preference is given to the parameter over the system variable. The value is passed back via the double* second argument. Return values are:
   0 = parameter or system variable found
   -1 = parameter or system variable not found

Syntax:
 
 extern int get_par_or_var ( /* char
*parameter_name, double *return_data */); 
set_par_or_var
Sets a parameter's or a system variable's value. In a conflict, preference is given to the parameter over the system variable. The value is passed in via the double
second argument. Return values are:

   0 = parameter or system variable found
   -1 = parameter or system variable not found

Syntax:
 
 extern int set_par_or_var ( /* char
*parameter_name, double val */ ) ; 

Routines are provided to read values from IC-CAP data sets and to obtain information about the sweeps present in the setup. You can write new data values onto existing outputs and transforms.

Table 34 Accessing Parameters or System Variables Functions 
Function
Definition
get_data_w_check
Gets the value of a single point in an IC-CAP data set (an Input, Output, or transform). A complex number will be fetched from the IC-CAP data set and placed in data_fetched. The data set name is the first argument. The second argument should specify 'M' (measured) data, or 'S' (simulated). The row and col arguments should be 1,1 unless dealing with 2-port data. The index argument can range from 0 to (size of dataset -1). The final argument is the address of a 'complex' struct (see userc.h). An example is provided in xf_util.c.h. Return values are:
   0 = dataset is found, and msb, row, col, and index
          are all in range
   -1 = any error condition

Syntax:
 
 extern int get_data_w_check ( /* char*
dsname, char msb, int row, int col, int
index, complex* data_fetched */ ) ; 
set_data_w_check
Sets the value of a single point in an IC-CAP Output or transform. Setting values in an Input is not supported, because IC-CAP computes and overwrites these automatically. The data set name is the first argument. The second argument should specify 'M' (measured) data, or 'S' (simulated). When 'B' (both) is specified, the complex number will be stored in both the Measured and Simulated parts of the data set. The row and col arguments should be 1,1 unless dealing with two-port data. The index argument can range from 0 to (size of dataset -1). The final argument is the address of a 'complex' struct (see userc.h). An example is provided in xf_util.c.h. Return values are:
   0 = dataset is found, and msb, row, col, and index
          are all in range
   -1 = any error condition

Syntax:
 
 extern int set_data_w_check ( /* char*
dsname, char msb, int row, int col, int
index, complex* data_poked */ ) ; 

Advanced functions are available for querying about the inputs used in a setup. Consult /usr/iccap/src/xf_util.c.h for usage and examples of the following functions.

 int get_num_of_points ( /* char* setup_path, int swp_order */) ;
double get_sweep_start ( /* char* setup_path, int swp_order */) ;
double get_sweep_stop ( /* char* setup_path, int swp_order */) ;
double get_sweep_stepsize (/* char* setup_path,int swp_order */);
int get_num_of_curves ( /* char* setup_path */) ;
int get_points_per_curve ( /* char* setup_path */) ;
int get_max_sweep_order ( /* char* setup_path */) ;
int get_sweep_type ( /* char* setup_path, int sweep_order */) ;
int get_sweep_mode ( /* char* setup_path, int sweep_order */) ;
int get_log_sweep_dec_or_oct ( /* char* setup_path, int swp_order 
*/) ;

Table 35 Using a Dialog Box for User Input Functions 
Function
Definition
get_number
Uses a dialog box to query the user for a number. It returns -l if the user chooses CANCEL, otherwise it returns 0. The desired value is returned by reference in return_data.
 
 int get_number ( /* char* prompt , double
default_value, double* return_data*/ ) ; 
get_string
Uses a dialog box to query the user for a string. It returns -1 if the user chooses CANCEL, otherwise it returns 0. The desired value is returned by reference in return_data.
 
 int get_string ( /* char* prompt, char*
default_value, char** return_data */) ; 


Note


A static area is used for the returned string. You should copy the returned string, or use it before calling this function again.


Table 36 Posting to the Error Box Functions 
Function
Definition
error_message
Sends an error message to the system error box. The message should have "\n" at its end for multiple messages.
 
 void error_message ( /* char* msg */ ) ; 
standard_fail_msg
Sends object name, function name, and msg to errbox in a standard format. Refer to userc.c, for the source to this function. The message should have "\n" at its end for multiple messages.
 
 static void standard_fail_msg ( /* char*
msg */ ); 
object_name
Gets the name of the transform or Macro under which this function is running.
 
 extern char* object_name (); 
function_name
Gets the name of the present user-defined function, as it appears in the Function Browser.
 
 extern char* function_name () ; 

Table 37 Calling Menu Functions 
menu_func
Permits your C functions to invoke IC-CAP menu selections. It behaves like the menu_func statement in PEL. However, this function accepts only 2 arguments, and does not provide the ability for Anticipating Dialog Boxes that are provided by the menu_func call in PEL. It returns -1 if the IC-CAP object does not exist or does not support the selected menu function name. Otherwise it returns 0, including when the menu function is found and executed but produces errors. For additional information on calling menu functions, refer to Chapter 11, "Creating and Running Macros."
 
 int menu_func ( /* char* obj_name, char*
func_name */ ) ; 

Handling Signals and Exceptions

Two important signals generated within IC-CAP under certain conditions are: SIGFPE and SIGINT.

SIGFPE

This signal occurs when the code executes an operation like a divide by zero. By default, there is no provision in IC-CAP for trapping this signal. If this signal occurs during the execution of a transform, the function or macro will continue to execute and upon completion, an error message is displayed indicating a floating point error occurred.

SIGINT

This signal is generated when you issue the Interrupt command. By default, there is no provision in IC-CAP for trapping this signal. The function or macro is interrupted immediately. Note: For complex operations, it may take several minutes before control is returned.

These signals, and others, are declared in $ICCAP_ROOT/src/sighandler.hxx. They are explained in UNIX manual pages, including signal(2) and sigvector(2). If your application requires special error recovery for the SIGFPE or SIGINT signals, it is possible to modify the signal handling to trap them.

Modifying Signal Handling Behavior

To modify the handling of either of these signals (or any others), you must comply with certain IC-CAP programming conventions; failure to do so could cause the program to terminate.

If a user C function modifies signal handling during its execution, it must also restore the prior state of signal handling before it returns. The example demonstrates how this might be accomplished.

If you modify the signal handling for SIGFPE, you should also modify it for SIGINT. This is based on the need to restore the default SIGFPE handler before returning from the User C code. If you modify it for SIGFPE and don't modify it for SIGINT, an Interrupt could force a premature return from User C code, resulting in a failure to restore IC-CAP's signal handler for floating point errors. The example in Figure 35 satisfies this need by causing SIGINT to be ignored while the SIGFPE handling is changed and then restored to IC-CAP's default. Do not alter the handling of SIGUSR1 and SIGUSR2; both signals are used internally by IC-CAP for error trap and recovery purposes.


Note


IC-CAP employs the sigvector signal handling facility (see the UNIX manual page sigvector(2)). Any User C code that modifies signal handling should employ the same facility. That is, the system calls described under signal(2) and sigset(2V) should not be used within IC-CAP.


Figure 35 Signal Handling Example
 #include <stdio.h>
#include <sighandler.hxx>

struct sigvec newINTvec, oldINTvec;
struct sigvec newFPEvec, oldFPEvec; 

/* arrange to ignore SIGINT signal */ 
newINTvec.sv_mask = 0 ; 
newINTvec.sv_flags = 0 ; 
newINTvec.sv_handler = SIG_IGN; 

/* oldINTvec receives 'backup' of IC-CAP sigvector for 
SIGINT */
sigvector(SIGINT, &newINTvec, &oldINTvec);

/* now you can do what you want, without fear of interruption 
*/

/* this arranges to ignore SIGFPE signal, e.g. */ 
newFPEvec.sv_mask = 0 ; 
newFPEvec.sv_flags = 0 ; 
newFPEvec.sv_handler = SIG_IGN;

/* oldFPEvec receives 'backup' of IC-CAP sigvector for 
SIGFPE */ 
sigvector(SIGFPE, &newFPEvec, &oldFPEvec);

/* do any math, with floating point errors ignored ... */

/* Restore IC-CAP handler for SIGFPE! */ 
/* Should be done while SIGINT is still being ignored */ 
sigvector(SIGFPE, &oldFPEvec, (struct sigvec *) NULL);

/* Restore IC-CAP handler for SIGINT! */ 
sigvector(SIGINT, &oldINTvec, (struct sigvec *) NULL);

The following functions are provided for signal handling:

icecap_ignore_sigfpe()

Allows execution to continue without an error when a floating point error occurs in User C code. Save the return value for use with the icecap_reenable_sigfpe function to reenable normal signal handling—stop execution and present an error message when a floating point error occurs in User C code.

Example:

 userc_function(....)
 { 
    int oldFPEval;
    .
    . 
    oldFPEval=icecap_ignore_sigfpe();
    /* Following code will ignore floating point errors */
    x=x/0;
    .
    . 
    icecap_reenable_sigfpe(oldFPEval);
    /* following code will again trigger FPE errors */
 . 
 . 
 } 
icecap_ignore_sigint()

Allows execution to continue without an error message when the stop sign is pressed. Save the return value for use with the icecap_reenable_sigint function to reenable normal signal handling—stop execution and present an error message when the stop sign is pressed. See the example for "icecap_ignore_sigfpe()."

icecap_reenable_sigfpe(oldfpeVal)

Reenables signal handling on exit from your User C code for floating point errors. Use the return value from icecap_ignore_sigfpe to reenable the normal signal handling for a floating point error—stop execution and present an error message. See the example for "icecap_ignore_sigfpe()."

icecap_reenable_sigint(oldintVal)

Reenables signal handling on exit from your User C code when the stop sign is pressed. Use the return value from icecap_ignore_sigint to reenable the normal signal handling that occurs when the stop sign is pressed—stop execution and present an error message. See the example for "icecap_ignore_sigfpe()."


prevnext