2
Getting Started with CDBA
This chapter gives you the information you need to write CDBA functions. This includes the following topics:
- CDBA Described
- Generator Functions
- Producer and Consumer Functions
- CDBA Naming Conventions
- Basics for Writing CDBA Functions
- Using the Virtuoso Design Environment
- Specifying Run-Time Options
- General Rules for Using CDBA
- Troubleshooting Your Programs
CDBA Described
CDBA consists of procedural access layers on top of the OpenAccess database. CDBA insulates programs from changes made to the underlying physical data model. CDBA also takes advantage of the next generation of computing hardware and software environments.
CDBA functions include Component Description Format (CDF) functions and technology file functions. For more information on CDF functions, see the Component Description Format User Guide.
CDBA considers the following aspects of a good design:
Robustness
CDBA is as robust as possible without sacrificing performance. Objects and IDs are strongly typed, providing as much type checking as possible at compile time. Debugging facilities are designed into CDBA.
Performance
High performance is critical to a database for electronic design automation. To make CDBA run as fast as possible, most access functions are defined in a way that makes it possible to implement them as macros if needed.
Separate System and User Address Spaces
CDBA allows the database and your application to reside in separate process address spaces and communicate only via inter-process communication.
Multiprocessing Environment
CDBA is designed so that, in the future, the database and your application can run on two or more processors.
Example, Include, and Library Files to Use
Examples for using either CDBA or CDF functions are in
your_install_dir/itkDB/samples/DB
your_install_dir/itkDB/samples/CDF
The data structures and functions for CDBA and CDF are defined in
your_install_dir/itkDB/include/ITKDB.h
your_install_dir/itkDB/lib/ITKDB.a
Finding OpenAccess Shared Libraries
Your programs need to find the OpenAccess shared libraries. The recommended method is the following.
-
Install your programs in the appropriate directory.
as <program_name> -
Install a symbolic link called <program_name> in the
dfII/bindirectory. The link should point to../../../share/bin/cdnWrapperWithOA.
The cdnWrapperWithOA script adds QTDIR, tools/lib, and the OpenAccess library path to LD_LIBRARY_PATH and calls the executable.
Generator Functions
Generator functions perform an action repeatedly on items, one by one, in a database that consists of either design data (OpenAccess) or technology data (technology file).
Sequence of Actions Used
Two functions usually work together to generate this sequence of actions: a function to start the generator (using the component StartGen) and a function to continue generating (using the component Gen) until all values have been acted on.
Together these two functions follow this sequence:
- Initialize a particular generator.
- Retrieve and act on each item in the file, one at a time. With each iteration of the generator function, a name and value for the item retrieved is returned.
- Stop the generator.
Relationships Represented
Generator functions in CDBA represent one-to-many relationships in the logical data model. Through generators, you can visit every element of the relationship. These relationships can be direct or derived.
In a direct relationship, the objects are linked to a data structure such as a linked list. In a derived relationship, there are no direct pointers linking the objects, and the relationship is derived from other information, such as matching objects that have the same name.
For more detailed information on these types of relationships, see “CDBA Database Objects”.
Arguments in Generator Functions
In all generator functions, the first argument is always the generator state identifier returned from the startgen function. The rest of the arguments (ranging from one to many) are pointers to one or more user-defined variables used to return what is being generated. Arguments to generator functions are returned by means of indirection.
You supply pointers to objects of a given type as arguments. These pointers are updated by the generator function if it is successful. The pointers are invalid if the generator or function returns FALSE.
Values Returned
A generator function using pointers succeeds if all the following are true:
- The generator function can assign these user variables by indirection
- The variables are valid
- The variables can be safely referenced by the user
A returned value of FALSE signals that
- The values of the variables should not be used because they are undefined (never assigned and most likely contain garbage) or are invalid
- The generator is finished, with no more variables to assign values to
See Chapter 12, “CDBA Relative Object Design Functions,” for information on generator functions in technology files.
Naming Conventions for Generator Functions
Generator functions include the following components
-
Prefix for application or interface used (such as
dd,db, ortech) - Sequence in the generation process
- Relationship between elements, if applicable
Sequence Indicated in Generator Functions
All generator functions use the following components:
-
StartGen, indicating the function to prepare and start the generator -
Gen, indicating the function to generate -
StopGen, indicating the function to stop the generator
Relationship between Elements
The name of a generator function describes the elements of the one-to-many relationship it represents, and the actions between them.
In some generator functions, the relationship between the elements is written as sourceTodest, as in the function names MasterToInst or LayerToPurpose
When the one-to-many relationship starts from the cellview, you can omit both the source and the To connective. For example, instead of using the name dbGenCellViewToMaster, you can use the name dbGenMaster.
The Generator State
The style of generators is based on a generator state, which stores the internal state of each active generator in a data structure allocated and managed by the database. The user has complete control over starting, stopping, and stepping through multiple generators simultaneously.
Because generator states are allocated and are therefore always visible to CDBA, you can implement various checks to prevent users from undesirable interactions, such as deleting the next active element in the middle of a generation loop. When the internal structure of generator states is hidden from the user, only the following type definition is visible in the header file.
typedef dbGenState * dbGenStateId;
Starting the Generator
Each generator must be explicitly initialized by calling a specific StartGen function with the appropriate context information. The StartGen function returns a pointer to a newly allocated and initialized structure containing the generator state.
Example
dbGenStateId pState; /* generates all terms in a cellview */
pState = dbStartGenTerm(cvId); /* starts the generator */
Generator Loop
After a generator is initialized, you can call the corresponding Gen function to get the relationship elements one at a time. A Gen function takes the generator state as its first argument. The argument is followed by pointers to formal variables used in the generator loop. If there are multiple formal variables, they must appear in the same order as they appear in the name of the generator.
The generator state is updated to reflect the new state of the generator loop. The generator function returns FALSE if there are no more elements in the relationship, and TRUE if there are more elements to generate. This makes it possible to implement a generator loop with a while statement.
Example
while (dbGenTerm(pState, &termId)) {
...
func(termId); /* loop through and process each element */
...
}
Stopping the Generator
At the end of a generator loop, you must call the StopGen function to notify CDBA that you are done with the generator. CDBA frees the generator state and invalidates the pointer to prevent its reuse. The dbStopGen function works for all generators.
Example
dbStopGen(pState);
Example
/* Using the shapes generator to generate all shapes on a */
/* given layer-purpose pair */
dbGenStateId pState; /* pointer to generator state */
dbShapeId shapeId; /* formal argument */
/* Initializes the generator */
pState = dbStartGenShape( cvId );
/* Uses a while loop to generate all shapes. */
while (dbGenShape( pState, &shapeId ) )
{
/* processes shapeId */
...
/* user can even pass generator state to another function */
/* for further generation inside that function */
func( pState, shapeId );
...
break; /* user has complete control */
...
};
/* Inform the system that the generator is no longer active */
/* so the system can deallocate the generator state */
dbStopGen( pState );
Get Functions
Arguments to Get functions are returned by means of indirection. You supply pointers to objects of a given type as arguments. These pointers are updated by the Get function if it is successful. The pointers are invalid if the generator or function returns FALSE.
All Get functions return any parameters through the propType and propValue pointers. The parameter returned by propValue is either "evaluated" or "raw" data. Unless specifically directed, all Get functions evaluate parameters before return. The "dumper" is the only utility or application that needs the unevaluated expression.
If you want the unevaluated parameter expression, use techSetEvaluate (FALSE) before calling the Get function of your choice. Remember to call techSetEvaluate (TRUE) when you are finished.
Producer and Consumer Functions
CDBA provides producer functions, which produce results processed by the consumer functions you provide. Each time you call a CDBA producer function, you must specify a pointer to your consumer function as one of the producer function arguments. For each item successfully produced, the producer calls your consumer function as the argument. This process is repeated until there are no more items to produce or the consumer returns FALSE to the producer.
Example
/* myConsumer( ) -
*
* This is a sample of a simple consumer function for the
* dbProduceMemName( ) function. It prints the member
* (such as member index) of the given full name and
* the member name produced by the producer function.
*/
Boolean myConsumer( memName, memIndex ) String memName;
int *memIndex;
{ printf( "Member %d is %s\n", memIndex, memName ); (*memIndex)++; return(TRUE); } /* The following is a function that calls * dbProduceMemName( ) */ void Afunc( ) { Boolean myConsumer( );
int memIndex = 0;
dbProduceMemName("(A,B,C)", myConsumer, &memIndex);
}
CDBA Naming Conventions
Adoption of uniform naming conventions and standard terminologies for CDBA and application-specific names for functions, constants, or global variables are critical for making design framework II simple to use.
Components of Function Names
-
Functions whose names include
Createadd sections to the technology file that do not exist, or replace entire or partial sections that do exist. -
Functions whose names include
Setupdate existing data or add new data to existing sections of the technology file. -
Functions whose names include
Getreturn data from sections of the technology file, or an error message if the data does not exist. -
Functions whose names include
Deleteremove a specified piece of data from a section of the technology file.
See “Getting Started with CDBA” for more information on components of function names. See “General Terms” for a table on these components.
Components of Function Names
Construct a function name from related components. The combination of the components you use depends on what the function does.
General Rules
The following are some general guidelines for constructing function names:
- All names must be unique in the first 32 characters so that they are portable across systems.
-
All names in CDBA, whether they are names of functions, constants, or global variables, begin with a package prefix and are composed of words connected in a predefined order. To avoid name conflicts with other packages, CDBA developers prefix
dbto every function and global variable name offered in CDBA. - If you are an application developer, add a unique three-character package prefix to your function and global variable names to avoid name conflicts with CDBA function and global variable names.
- If the function implements a binary operation, then both the source and destination objects need to be specified. However, if the function implements a unary operation, you need to specify only one object or element.
-
Function arguments are always given consistent, meaningful names that show their type and how they must be used.
The following function is a good model for this guideline.
dbCreatePolygon(cellViewId,layer,purpose,nPoints,arrayOfPoints)
Frequently Used Components
The following are frequently used components within names and examples for each. For a more complete list of components, see “General Terms”.
|
Condition being tested for (applies only to predicate functions) |
|
Examples of Use of Components in Function Names
The following are examples of how these components are used with each other in a function name:
dbCreateRect
dbGetRectLP
dbGenLPToShape
dbIsRect
dbIsIdEqual
ilGetString
Components and Usage to Avoid in Function Names
To make names simple for users whose native language is not English, do not include the following in names:
- Articles (a, an, or the)
- Plurals (such as layers or points)
- Past tense forms of verbs
- Phonetic abbreviations such as 2 (as an abbreviation for to) or 4 (as an abbreviation for four)
Case Used in CDBA Names
All characters appear in lowercase except for the first character after each word boundary (such as ilGetInt).
The first character of a CDBA name, the package prefix, is always in lowercase. If you are an application developer, you must always capitalize the first letter of your prefixes to avoid naming conflicts with CDBA names.
Using Abbreviations in Function Names
To avoid unreasonably long names, abbreviate words longer than seven characters. Exceptions can be made when an easy-to-remember abbreviation does not exist.
The rules that apply to a single word within a name also apply to an abbreviation of a word within a name. A word or its abbreviation appears in lowercase except for the first character after a word boundary.
An abbreviation for multiple words within a name, however, can consist of all uppercase letters if each word is abbreviated to its first letter. For example, you can abbreviate layer-purpose to LP. If an official abbreviation exists for a word, use it in all appropriate names, regardless of the length of the name.
Naming Conventions for Function Arguments
The following sections describe types of function arguments.
Creation Functions
Arrange arguments for creation functions in the following order:
Context
Specify context arguments in descending order of generality (from general to specific). In the following examples, cellViewId is the most general type of context argument.
dbCreateRect( cellViewId, ...)
dbCreatePolygon( cellViewId, ...)
Attributes
For the object being created, specify attributes after the context arguments in descending order of importance. In the following examples, layer is a more important attribute than purpose.
dbCreateRect(..., layer, purpose, ...)
dbCreatePolygon(..., layer, purpose, ...)
Argument Interdependencies
Specify descriptive arguments before the arguments they describe. The number of points always precedes the array of points it describes, as shown here:
dbCreatePolygon(cellViewId, layer, purpose, nPoints, pointArray)
This function also illustrates the arguments, attributes, and argument interdependencies in a creation function.
Retrieval Functions
Arguments in retrieval functions that return data using function arguments must be in the same order as when the object was first created. Examples are
dbGetPolygon( polygonId, &nPoints, &pointArray )
dbGetPolygonLP( shapeId, &layer, &purpose )
Conventions for Prototype Functions
The following are conventions for describing arguments that appear in prototype functions:
-
Pointers to data structures used to pass data to the function being called or to return data to the calling routine are indicated by adding the prefix
pto the type name such aspBBox. -
When data is returned using the pointer, a comment follows the argument description (for example, “
/* modifies BBox */”). - Using a pointer replaces the old convention of preceding the argument with an ampersand (&). This old convention demonstrated normal usage, but left confusion about the argument type.
Return Value Conventions
Most database functions in CDBA return Boolean status values indicating whether their operations are successful. A few retrieval functions, however, do return data as values of the functions so that calls can be nested within other expressions. Many of these retrieval functions are implemented as macros: therefore, errors are caught at compile time rather than at run time.
Scalar values returned via function arguments are always copied over to your storage space. You must declare these variables in your own program and pass pointers to them in function calls.
Naming Conventions for Name Types
After a package prefix, there is an optional third lowercase character that describes the type of the name.
The following table shows the character and meaning corresponding to each name type.
| Name type | Character | Meaning |
|---|---|---|
|
An internal function. These functions must not be called directly by application programs. |
||
Exceptions to Naming Conventions
Many existing property names were chosen when there was no system-wide, uniform naming convention. Because it is impractical for Cadence to change the names of existing properties, you need to learn historical names in addition to new names that conform to the uniform naming convention.
Rather than only following the new naming convention, keep applications as consistent as possible. If a different naming convention was originally used within an application, use the old convention to keep names consistent within the application. An example of an exception is the NLP (netlist property) prefix given to properties used by the netlister (because this prefix is in uppercase). To avoid unnecessary confusion for the user, give new properties for the netlister the same prefix.
Basics for Writing CDBA Functions
To write CDBA functions, you should know the following:
- Design framework II requirements
- Basic C data types used in CDBA
- Coding standards for writing CDBA functions
Design Framework II Requirements
Even though design framework II is written in portable C code, it does make basic assumptions about the compiler and the computer it runs on. The following assumptions must be true for a machine and its compiler before design framework II can run:
-
Integers (
int) are 32 bits wide. -
Long integers (
long) are 32 bits wide. -
Short integers (
short) are 16 bits wide. -
Characters (
char) are 8 bits wide. - Virtual address space must be at least 16 megabytes (MB).
Design framework II runs most efficiently when the following requirements are met:
- The amount of virtual memory available is at least 64 megabytes (MB).
- The amount of main memory available is at least 8 megabytes (MB) for applications using CDBA.
Design framework II can run correctly without these memory requirements, but the performance can become unacceptable.
Supported Platforms and Compilers for Integrator’s Toolkit (itk)
The supported development platforms and C compilers are the following.
C Data Types Used in CDBA
To simplify programming and improve code readability, the following data types are predefined in db.h, the header file that must be included in every CDBA program.
Boolean
A Boolean specifies that the variable or function can only take the value of one of two predefined constants.
String
Strings specify that the variable or function is of type (char *), a pointer to a character string. A NULL string is not equivalent to an empty string.
FuncIntPtr
FuncIntPtr declarations specify that the variable or function indicates a pointer to a function that returns an integer. This type is useful for passing functions as arguments to other functions, such as when handler functions are registered.
FuncBooleanPtr
FuncBooleanPtr specify that the variable or function points to a function that returns a Boolean value. This type is useful for passing functions as arguments to other functions, such as when handler functions are registered.
Enumerated Types and Enumerated Constants
Variables that can only take on one of a limited number of values are declared in the C programming language as enumerated types (enums) whenever possible. You can also use the #define construct to define enumerations as unsigned integer constants.
All enumerated constants begin with the prefix dbc, and enumerated constants that belong to the same enumerated type are often grouped together using the same root words. Typically, an enumerated type has an unknown value, which is returned in some error conditions.
Examples
The following are examples of enumerated types:
#define dbcConstantOne 1
#define dbcConstantTwo 2
enum dbPurpose {
dbcUnknownPurpose,
dbcDrawingPurpose,
dbcWirePurpose,
dbcPinPurpose
};
typedef enum dbPurpose dbPurpose;
Coding Standards for CDBA Functions
Coding standards exist for code in general, for header files, and for calls to macros.
General Coding Standards
To write C programs that work in CDBA, follow these coding standards:
- Use only reentrant code. Because most commands can be nested, not using reentrant code can possibly lead to recursive calls on the same functions.
- Do not use global and static variables.
- Begin function names and global variables with a unique three-character prefix to avoid name conflicts. Use three-character prefixes in your applications to avoid name conflicts with Cadence packages, which often use two-character prefixes. The first character must be uppercase.
- Use a default case to catch all unexpected values in every switch statement, particularly ones that switch on an enumerated type. This default case is extremely important to keep the code from breaking when new enumerated types are added.
- Do not rely on the integer value of one enumerated constant being greater than the value of another enumerated constant, unless explicitly permitted by documentation in the manual.
- Do not directly address the members in a structure, unless this is explicitly permitted by documentation in the manual.
-
Within a structure, declare all unions that contain a tag member, in addition to the union member. The tag member must be an enumeration of the union members, plus the special constant NULL. The value of NULL must be 0, which indicates an un-initialized structure. Set the tag member whenever the value is set.
The following is an example of this.struct pkgUnion { enum { pkgcNull = 0 pkgcIntType = 1 pkgcFloatType = 2 pkgcBooleanType = 3 } tag; union { int aInt; float aFloat; char aBoolean; } value };
typedef struct pkgUnion pkgUnion;
-
Do not call any UNIX system function that can interfere with the operation of the graphics editor. In addition to all system functions that deal with signals and graphics, avoid using system functions (such as
sbrk,setjmp, andlongjmp) that affect the operating environment and can potentially have adverse effects on Cadence software. -
Do not use the
stdin,stdout, andstderrstandard file descriptors for input and output. Use functions provided by CDBA for getting interactive user input and for displaying prompts and messages. - Install all binary programs built on top of CDBA in the standard Cadence release hierarchy, just as you install the Cadence binary programs. The proper operation of CDBA depends on certain standard directories and files, which are stored in the Cadence release hierarchy.
Header Files
To use the C language effectively, Cadence provides the header file (itkDB.h for CDBA) containing internal data structure declarations, as well as constant definitions. Because of the way DFII is implemented, the contents of header files can change in the future. Do not write your programs based on undocumented details exposed by this header file. Always refer to this manual for information about CDBA.
Macros and Functions
CDBA allows most database access routines to be implemented as either a function or a macro. For programming ease, most of the macros in CDBA are implemented so they can be called like a function, without any undesirable side effects. Macros without undesirable side effects have the same db prefix as functions. Therefore, you do not have to distinguish between these macros and any functional counterparts.
The following are special considerations and good practices in using macros and functions:
-
A performance-critical routine can occasionally require so much code that it is desirable to implement the routine both as a macro and as a function. Thus, you can choose between the two implementations according to the needs of your application. In this situation, the macro implementation must be given the prefix
dbmto distinguish it from the function implementation.
In only a few cases, you must distinguish between a macro and a procedure that have the same functionality. This distinction is necessary because procedure calls can take up too much execution time, and macro calls can take up too much code space.
An additional prefix letter,m, is added to the name of the macro after the package prefixdb(as indbm) so you can choose between the two implementations. -
In the C programming language, macros can be defined so their arguments appear many times within the macro expansion. Therefore, it is a bad programming practice to put expressions with permanent side effects (such as assignments) in the argument list of a macro call. Never pass as arguments to macros any expressions that have side effects.
Even when you use expressions with no permanent side effects, the processing of the macro is slowed by repeated evaluations of the same expression, and therefore, the macro can expand into a larger amount of in line code. -
If a macro refers to any of its arguments more than once and is therefore vulnerable to side effects, you must give it the prefix
dbmto alert the user that it is such a macro. Use the prefix even when the macro has no functional counterpart. - It is always good practice to first assign the value of an expression to a variable, then to use that variable in the argument list of a macro. If a routine is documented as being implemented as a macro, you must refrain from calling it with any expression in the argument list. The argument lists in your macro calls must contain only variables or simple expressions.
Using the Virtuoso Design Environment
Include the header file itkDB.h in every source file that refers to one of the Cadence Integrator’s Toolkit: Database (ITKDB) routines.
You can access the Virtuoso Design Environment routines through one of the library archives in the your_install_dir/dfII/lib directory. All Virtuoso procedures do intensive checking to help find programming inconsistencies quickly.
Include the itkDB.a file in the list of library archives given to the loader when linking an executable binary for your program. The order of libraries is important. The itkDB.a library must appear after all libraries that refer to ITKDB routines. Otherwise, the loader is not able to link your program successfully.
itkDB.a archive library depends on the libplotCommon.so shared library, which has a dependency on freetype.so. Applications that compile with itkDB.a must therefore, link with freetype.so. For example, the itkDB sample makefiles link the samples with freetype.so.
If you build your application with itkDB.a, license 111 must be present to run the application. License 111 is checked out every time you invoke any application from within the Virtuoso tool suite. This ensures that a valid user is trying the run the application.
If license 111 is not present, the application issues the following message and exits.
dbInit: Existence of Cadence(R) Design Framework II license (product 111) is required to execute ITKDB based program.
In advanced nodes version, itkDB.a will also checkout license 95111 along with license 111.
ICADVM20.1 Only
In advanced nodes, Virtuoso_Adv_Node_Framework license must be present in addition to license 111 to run an application. If either of these licenses is not present, the application issues an error message and exits.
Refer to the standard documentation that comes with your Cadence programs for details.
Specifying Run-Time Options
You can specify several processing options for your program. For example, if your program has the name myProg, the command line to run your program is
myProg [-dbAssert] [-dbCheck] [-dbBind] your_options
For more information on run-time options, refer to “CDBA Input and Output Functions”.
General Rules for Using CDBA
Cadence carefully documents all features of CDBA in this manual. You must use these features only as documented. Do not use undocumented features or try to take shortcuts when using design framework II.
Troubleshooting Your Programs
Even when you write your program carefully, it still might not work correctly. In addition, the source of the problem might not be obvious if there are many interactions with the database. Under these circumstances, take some or all of these steps to isolate the problem and identify obvious errors. The following checklist can be helpful.
- Is the code compiled and linked without errors? If the compiler does not accept a call to a database routine, check the documentation for that call to make sure you do not have any programming errors.
-
Have any run-time errors occurred, such as a bad ID return from a
dbOpenCellViewByTypecall? This can happen if you do not have write permission on a cellview and are trying to open it for writing or appending. -
Have you checked the log file for debugging and error messages? The log file (that is,
~/CDS.log) normally contains a complete log of run-time errors. - Have you used a symbolic debugger to trace the problem? With a symbolic debugger, you can stop your program and examine the variables examined in the middle of a run. This interactive querying is often helpful in determining the status of a program.
-
Is your storage allocation safe? Although this interface will probably change in the future, setting the shell environment variable
CDS_MEM_DEBUGto a value ofglobal:GET;PUT;PADcan help you spot this type of problem. Examine your code for reuse of storage that belongs to CDBA. The following code fragment overwrites the name string returned from CDBA:String name;
name = dbGetCellViewCellName(cellViewId);
printf(strcat(name, " opened."));
-
Are the proper actions being taken upon return from a database call? For instance, if the database call returns an error, does the program handle it properly, or does it continue running without checking for error conditions? In the previous example, the return value from
dbGetCellViewCellNamemust be compared todbcNullStringbefore use elsewhere.
Return to top