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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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()."
|