This document consists of five major sections:
The OpenAccess API is a C++ API to an IC design database. Although the OpenAccess reference implementation is implemented in C++, you can access the reference implementation from Tcl. This document describes the OpenAccess API in Tcl. If you prefer to script part or all of your database application in Tcl, you can access and use the OpenAccess reference implementation through the Tcl OpenAccess API.
The Tcl OpenAccess API resembles its C++ counterpart, but it is not identical. For example, some OpenAccess API C++ objects are not directly available in Tcl, such as the oaString class (Tcl provides built-in string support). More significantly, Tcl is a procedural language not an object-oriented language. Although Tcl calls to native OpenAccess functionality are designed to be as fast as possible, running Tcl is slower than running compiled C++ object code.
Tcl is a straightforward programming language and well documented in numerous books and publications. The main focus of this document is the OpenAccess API in Tcl, but it also introduces a few fundamental Tcl language concepts and practices for those who are new to Tcl.
The Tcl OpenAccess API is available in Tcl version 8.4.6. In order to use the Tcl OpenAccess API in Tcl, you must install Tcl 8.4.6 or later. You can obtain the most recent Tcl version from:
You must set the TCL_HOME
environment variable to the location of your Tcl installation.
This section describes basic features of the Tcl OpenAccess API in comparison to the OpenAccess C++ API. This information is helpful to C++ programmers who want to use the OpenAccess Tcl API for specific Tcl scripting tasks.
All OpenAccess Tcl commands involve either using or returning an instance of an OpenAccess class. Tcl variables are used to hold either a reference or a pointer to an instance of an OpenAccess class. From the OpenAccess C+++ API perspective, this is either a class reference or pointer to a class. The Tcl variable can then be used to access the non-static member functions for this class or used as an argument when a reference or pointer to the class is required. When used to access a non-static member function of the class, it must be passed as the first argument of the Tcl command for the member function.
All OpenAccess Tcl command names are defined in the Tcl namespace: oa. OpenAccess Tcl command names derive from their corresponding OpenAccess C++ class and member function names according to a set of rules. The rules for transforming non-static C++ function names to Tcl command names are different from those for transforming static C++ function names.
Tcl commands bound to a non-static C++ member function of an OpenAccess class
Tcl commands bound to a static C++ member function of an OpenAccess class
Examples:
Function Type | OA Class Name | Member Function Name | Tcl Command |
---|---|---|---|
Static | oaDesign | open() | oa::DesignOpen |
oaBlock | create() | oa::BlockCreate | |
Non-Static | oaDesign | save() | oa::save |
oaBlock | getDBUPerUU | oa::getDBUPerUU |
Example usage:
set design [oa::DesignOpen libName cellName viewName w] set block [oa::BlockCreate $design] set dbu [oa:getDBUPerUU $block] oa::save $design
See also the complete list of Tcl OpenAccess Commands.
Tcl has direct support for string, long, double and user defined values. Tcl command arguments map to OpenAccess C++ types according to the following table.
Open Access C++ Type |
Tcl Argument Type |
oaChar |
string |
oaByte |
int |
oaInt2 |
int |
oaInt4 |
int |
oaInt8 |
long long |
oaUInt2 |
int |
oaUInt4 |
int |
oaUInt8 |
long long |
oaFloat |
double |
oaDouble |
double |
oaBoolean |
string true or false (case insensitive), 1 or 0 |
enum |
string enum representation |
oaObject |
user defined type |
oaString |
Tcl string |
oaBox |
{{left bottom} {right top}} |
oaComplex |
{real imaginary} |
oaComplexArray |
{{r0 i0} {r1 i1} …} |
oaHashTable |
Excluded |
oaPoint |
{x y} |
oaPointArray |
{{x0 y0} {x1 y1} …} |
oaScalarName |
user defined type |
oaTransform |
user defined type |
Notes
""
. To provide a null pointer as a parameter value, the empty string, the string null, or the string NULL can be used.A number of parameters of the OpenAccess C++ API are output arguments in Tcl. Some examples of OpenAccess C++ APIs are:
void oaDesign::getLibName(oaScalarName &name) void oaPathSeg::getPoints(const oaPoint &beginPoint, const oaPoint &endPoint)
For member functions with void return values that have a single output parameter, the output parameter is converted to a Tcl return value. These functions may have additional input parameters. An example is:
set libName [oa::getLibName $design]
Commands with output arguments that do not satisfy these limitations are mapped directly. In other words, the arguments passed into the Tcl command are directly modified by the OpenAccess C++ implementation. These variables must first be initialized and be of the correct type. In the next example, $beginPt and $endPt are assigned by reference by oa::getPoints. Note that $beginPt and $endPt are first initialized to be oaPoint type variables.
set beginPt [oa::point [list 0 0]] set endPt [oa::point [list 0 0]] oa::getPoints $pathSeg $beginPt $endPt
As a consequence of the conventions for OpenAccess function names as described earlier, many of the OpenAccess C++ functions appear to be overloaded in Tcl. Because the Tcl interpreter does not handle command overloading, the resolution is handled by the Tcl binding.
The choice of the command based on the first arguments for mapped C++ member functions is the most common situation. The appropriate binding is first selected based on the class that this first argument represents, taking class derivation into account. For example, the Tcl function getBBox for an oaRect object selects the C++ getBBox member function of the oaFig class. Subsequently, the appropriate member function is selected if multiple functions by the same name, but with different argument types, exist for that class.
OpenAccess names are represented by strings and an OpenAccess namespace that defines the rules for the interpretation of the string. OpenAccess namespaces are objects and are different from Tcl or C++ namespaces. The OpenAccess namespaces can be created with the following Tcl commands:
oa::NativeNS
oa::CdbaNS
oa::LefNS
oa::SpefNS
oa::SpfNS
oa::UnixNS
oa::VerilogNS
oa::VhdlNS
oa::WinNS
The namespace can be used for creating names. For example,
set uns [oa::UnixNS]
set bc [oa::ScalarName $uns BigChip]
oa::get $bc [oa::WinNS]
The last command returns the string %Big%Chip, which is how the scalar name BigChip is represented in the Windows namespace. OpenAccess names can be handled automatically in Tcl. Names are represented in Tcl by the string that is obtained within the global namespace. It can be set globally with the following Tcl commands:
oa::pushNameSpace namespace
oa::popNameSpace
oa::getNameSpace
The native namespace is set as the global namespace on startup.
The global namespace is also used for the construction of command arguments. Arguments that are scalar names can be specified with simple strings, which are converted to scalar names using the global namespace. Therefore, you can create a library with
oa::LibCreate myLib myLib
instead of:
oa::LibCreate [oa::ScalarName [oa::NativeNS] myLib] myLib
Several command arguments take enumerated values.
For example, the oa::ViewTypeGet
command takes an oaReservedViewType
argument:
% oa::help ReservedViewType
ReservedViewType
valueIn
==> oaReservedViewType
ReservedViewType
name oaString
==> oaReservedViewType
Enumerated values and constants are Tcl variables in the oa namespace that start with “oac”. You can query all variables in Tcl with:
% info vars oa::oacMask*
oa::oacMaskLayout
You can use this variable directly.
% set oa::oacMaskLayout
0
%oa::ViewTypeGet [oa::ReservedViewType $oa::oacMaskLayout]
oa:0x029A0092
Alternatively, for enumerated values, you can use its string representation. The latter can be found with the getName function:
% oa::getName [oa::ReservedViewType $oa::oacMaskLayout]
maskLayout
The command to obtain the reserved view type can simply be:
% oa::ViewTypeGet maskLayout
oa:0x029A0092
A number of OpenAccess member functions return collection classes. These return values are represented by user-defined objects in Tcl just like regular objects. The collection can be traversed directly using the Tcl while
command:
set design [oa::DesignOpen $lib $cell $view r] set top [oa::getTopBlock $design] set shapes [oa::getShapes $top] while {[set shape [oa::getNext $shapes]] != ""} { set box [oa::getBBox $shape] puts "The bounding box is: $box" } set terms [oa::getTerms $top $oa::oacTermIterSingleBit]
while {[set term [oa::getNext $terms]] != ""} {
set termName [oa::getName $term [oa::NativeNS]]
puts "Term: $termName"
}
Note that the box and shape variables are unbound at the end of each iteration, and this code is therefore memory efficient.
In Tcl, coordinates, offsets, and distances are floating-point numbers specified in user units. For Tcl commands, these user units are converted to database units by the Tcl bindings. Any distance or coordinate results returned by Tcl commands are automatically converted from database units back to user units.
This affects the following C++ types directly:
Database units are converted to user units directly by the Tcl binding whenever possible. For example, when you call the getWidth command on a path object, the width return value is converted from database units to user units. This conversion is accomplished with oaTech conversion functions, as follows.
Type |
Database to user |
User to database |
oaCoord |
dbuToUU |
uuToDBU |
oaDist |
dbuToUUDistance |
uuToDBUDistance |
oaOffset |
dbuToUU |
uuToDBU |
These functions require the technology database and the view type. Tcl commands for C++ member functions that are derived from the oaDesignObject class obtain the technology database and the view type from their design. Because of this automatic conversion, a technology database must be available on the design before functions involving this conversion can be called. If a technology database is not available, a Tcl error results.
The procedure for converting command arguments from user units to database units is similar to that of converting return values from database units to user units.
In Tcl, a point is represented by a Tcl list of a double x value and a double y value. The values are in user units. Round-off precision must be taken into account by a script when the values of two points are compared.
A box object is represented in Tcl by a Tcl list of the lower left and the upper right points of the box. For example, the following command creates a rectangle with the lower left corner at (0,0) and the upper right at (100,400).
oa::RectCreate $block $layer $purpose [list [list 0 0] [list 100 400]]]
Similarly, functions that return boxes return a TCL list of two points. As a result, the following commands can be used to obtain the lower left corner of the bounding box of a shape.
set bbox [oa::getBBox $shape] set lowerLeft [lindex $bbox 0]
Important exceptions to this rule are the member functions of oaBox. The following example computes the center of the bounding box of a shape. The code illustrates how a bounding box obtained from an OA command can be used with an oaBox member function (oaBox::getCenter in this case).
set box [join [oa::getBBox $shape]] set boxObj [oa::Box [lindex $box 0] [lindex $box 1] [lindex $box 2] [lindex $box 3]] set center [oa::getCenter $boxObj]
The OpenAccess API in Tcl provides many commands. The info
command provides a means to simply list the OpenAccess commands. However, the command oa::help
provides additional, basic information on how to use an OpenAccess command. To create a library, you can use the LibOpen
command returned by the info query in the previous section. To obtain additional information on this command, use the help
command as follows:
% oa::help LibCreate
LibCreate name oaScalarName libPath oaString mode oaLibMode dmSystem oaString dmAttrList oaDMAttrArray ==> oaLib
For example, create a library as follows:
% oa::LibCreate myLib myLib
This returns an address such as:
oa:0x80013
When errors occur in the OpenAccess API, a Tcl error is thrown. These errors can be the result of an exception that is thrown by the C++ implementation. Errors also can be the result of the C++ Tcl binding code. The Tcl error can be caught in Tcl. For example, a second call to create a library results in a Tcl error. The following code shows how this type of error can be caught:
oa::LibCreate myLib myLib if [catch {oa::LibCreate myLib myLib} err] { puts "Error: $err" } puts “Successfully continued the script”
If the Tcl error is not caught as in the above example, Tcl aborts the execution of the script. In the example code, the error is caught and script execution continues.
This section provides information on using OpenAccess Tcl.
The Tcl bindings are packaged in a shared library that can be loaded by a standard Tcl shell, version 8.4.6 or later. This shared library path is shown in the table below and depends on the OpenAccess shared libraries that contain the reference implementation. To successfully load the Tcl library, you must set the library path environment variable to include the path to the directory of OpenAccess shared libraries. The following table provides sample commands to accomplish this.
Solaris |
setenv LD_LIBRARY_PATH /opt/oa2.2/lib/sunos_58_32/opt:/usr/lib |
HP |
setenv SHLIB_PATH /opt/oa2.2/lib/hpux_11_32/opt:/usr/lib |
Linux |
setenv LD_LIBRARY_PATH /opt/oa2.2/lib/linux_rhel21_32/opt:<gcc3.2.3_compliant_installDir>/lib |
AIX |
setenv LIBPATH /opt/oa2.2/lib/aix_51_32/opt:/usr/lib |
Windows XP |
set PATH = c:\oa2.2\bin\win32\opt;c:\window\system32 |
Note that the path on Windows should be modified through the Windows GUI.
If you want to run the Tcl bindings on a Linux platform, you must have a compliant version of the gcc runtime shared libraries in your LD_LIBRARY_PATH. In most cases on Linux, these are not the standard C++ runtime libraries supplied with the operating system.
setenv LD_LIBRARY_PATH /opt/oa2.2/lib/linux_rhel21_32/opt:<gcc3.2.3_compliant_installDir>/lib
If you do not have access to the libraries, for example, from your EDA vendor, you can build them. Refer to Notes on Compiling on Linux Platforms Without gcc 3.2.3 for build instructions.
You can start Tcl from the command line. For example, on UNIX platforms, enter:
> tclsh8.4
On Windows , enter:
> tclsh84.exe
Alternatively, you can launch the Tcl shell on Windows by double-clicking the Tcl shortcut.
This starts the Tcl shell from the Tcl distribution installed on your system. You can now enter Tcl commands. To see all available commands in the global Tcl namespace, use the info command:
% info commands *
This returns:
tell socket subst open eof pwd glob list exec pid auto_load_index time unknown eval lrange fblocked lsearch auto_import gets case lappend proc break variable llength auto_execok return linsert error catch clock info split array if fconfigure concat join lreplace source fcopy global switch auto_qualify update close cd for auto_load file append format read package set binary namespace scan trace seek while flush after vwait uplevel continue foreach lset rename fileevent regexp upvar unset encoding expr load regsub history interp exit puts incr lindex lsort tclLog string
All OpenAccess commands are provided in the Tcl namespace oa. To view commands in the oa namespace, enter:
% info commands oa::*
At this point, nothing is returned since there are no available OpenAccess commands because the oaTcl shared library is not loaded. The Tcl binding of OpenAccess supports the Tcl package command, which is preferred over the Tcl load command. The name of the OpenAccess package is “oa” and the version is 2.2. See the Tcl documentation for details on the package command. To use this Tcl command, the auto_path variable must include the directory of the oaTcl shared library. You can inspect the value of this variable with the Tcl command:
set auto_path
To add the directory that contains the oaTcl shared library, use a statement such as:
lappend auto_path /opt/oa2.2/lib/linux_rhel21_32/opt
The OpenAccess binding can be loaded with the package command as follows:
package require oa
This command should return the value "2.2".
The command info oa::*
now returns a long list of functions. To see just the commands for opening libraries, use:
% info commands oa::Lib*
This returns:
::oa::LibDefListGetDefaultPath ::oa::LibDefListOpenLibs ::oa::LibDefCreate
::oa::LibGetOpenLibs ::oa::LibDefListFind ::oa::LibDMDataDestroy::oa::LibMode
::oa::LibDefListGetLibDefLists ::oa::LibCreate ::oa::LibExists
::oa::LibDefListRefFind ::oa::LibDMDataOpen ::oa::LibDMDataFind
::oa::LibDefListRefCreate ::oa::LibAccess ::oa::LibAccessLevel
::oa::LibOpen ::oa::LibDefFind ::oa::LibFind ::oa::LibDefListGetTopList
::oa::LibDMDataExists ::oa::LibDataType ::oa::LibDefListGet
All Tcl OpenAccess commands can be used after the oaTcl shared library is loaded. The OpenAccess database is automatically initialized when the OpenAccess Tcl shared library is loaded into Tcl.
While OpenAccess Tcl does not support oaObserver notifications in general, however it does supply one internal observer for handling of the messages generated during loading of the library defintion files. This internal observer for oaLibDefListObserver::onLoad call backs will accumulate the warning messages that occur during loading of library definition files initiated by the Tcl call to oa::LibDefListOpenLibs. If warning messages occur oa::LibDefListOpenLibs will throw an exception with those warning messages. Users are expected to enclose any call to oa::LibDefListOpenLibs in a catch block to detect this error condition.
This behavior can be modifed via the oa::setLibDefListErrorLogging command. If oa::setLibDefListErrorLogging has not been called or has been called with the value true then the call back is enabled and the behavior of oa::LibDefListOpenLibs is as described above. If oa::setLibDefListErrorLogging has been called with the argument false then the observer will be disabled. oa::LibDefListOpenLibs will not print any warning messages and will return an ok status.
All commands defined in the oa
namespace are exported upon initialization of the OpenAccess Tcl API after all commands have been defined. OpenAccess commands can be imported to the global namespace with the common Tcl command namespace import. For example
namespace import oa::DesignOpen
Note that there are functions in the oa namespace that conflict with common Tcl functions, so you should not import all functions in the oa namespace to the global namespace.
There are two types of objects involved in the OpenAccess API: utility and managed. The utility type of objects have constructor commands. These commands are the name of the object type itself. For example, oa::Transform creates a transform object of the type Transform. These objects are created and, if assigned to a Tcl variable, remain in memory until no variables reference the object. When the reference count of the object becomes zero, the object is removed and the implemented C++ destructor for the object is called.
The managed type of objects do not have constructor commands, but instead have create commands. In Tcl, such commands are named according to the type of the object created, with “Create” appended to the command name. For example, the Tcl command oa::RectCreate is the name of the OpenAccess command to create a rectangle object. The lifetime of managed objects does not depend on Tcl variable references, but instead depends on the database the objects reside in. These objects remain valid as long as that database is opened. They become invalid as soon as the database is closed. For example, created rectangle objects are valid for as long as the design is open in which they reside. The validity of these objects is the responsibility of the Tcl programmer.
The following listing is a simple Tcl script that creates a net and adds two rectangles to it. The second half of this example outputs the bounding boxes of the two rectangles. The script assumes you have set the appropriate shared library path variable as explained previously.
# <---- Example Tcl Script: myExample.tcl ----> # A simple script to create a net and add two rectangles. proc openLib {name path} { set lib [oa::LibFind $name] if {$lib != ""} { return $lib } if {$lib != ""} { return $lib } if {[oa::LibExists $path]} { set lib [oa::LibOpen $name $path] return $lib } return [oa::LibCreate $name $path] } proc openTech {lib} { set tech [oa::TechFind $lib] if {$tech != ""} { return $tech } if {[oa::TechExists $lib]} { return [oa::TechOpen $lib] } return [oa::TechCreate $lib] } proc openLayer {{tech} {layerName} {layerNumber}} { set layer [oa::PhysicalLayerFind $tech $layerName] if {$layer != ""} { return $layer } return [oa::PhysicalLayerCreate $tech $layerName $layerNumber] } proc sample {} { # Load OA shared libraries set numBits [expr $::tcl_platform(wordSize) * 8] lappend auto_path [exec oaGetLibPath -numBits $numBits] package require oa 2.2 # Set the name space to oa::NativeNS oa::pushNameSpace [oa::NativeNS] # Create the lib if it does not already exist set lib [openLib "lib" "lib"] # Create a tech database if one does not already exists set tech [openTech $lib] # Create a new design in the library set master [oa::DesignOpen "lib" "cell" "view" [oa::ViewTypeGet maskLayout] w] set top [oa::BlockCreate $master] # Create the net "net1" in the design set net1 [oa::ScalarNetCreate $top "net1"] # Create the layer "Metal1" if it does not exist set layer [openLayer $tech "Metal1" 10] set metal1 [oa::getNumber $layer] # Get the "drawing" purpose from the tech database set purpose [oa::PurposeGet $tech [oa::PurposeType $oa::oacDrawingPurposeType]] set drawing [oa::getNumber $purpose] # Create 2 shapes on "net1" set rect1 [oa::RectCreate $top $metal1 $drawing [list [list 0 0] [list 100 400]]] set rect2 [oa::RectCreate $top $metal1 $drawing [list [list 0 0] [list 400 100]]] oa::addToNet $rect1 $net1 oa::addToNet $rect2 $net1 oa::save $master oa::close $master # Re-open the design and report the bounding boxes of the shapes on "net1" set master [oa::DesignOpen "lib" "cell" "view" r] set top [oa::getTopBlock $master] set net1 [oa::ScalarNetFind $top "net1"] set shapes [oa::getShapes $net1] while {[set shape [oa::getNext $shapes]] != ""} { set box [join [oa::getBBox $shape]] puts "The bounding box is: $box" set box [oa::Box [lindex $box 0] [lindex $box 1] [lindex $box 2] [lindex $box 3]] puts "The center is [oa::getCenter $box]\n" } } |
To load and run the script in the Tcl shell, enter:
>tclsh %source myExample.tcl %sample |
This sample .tclshrc file provides two procedures for initializing your Tcl environment. The procedure initoa
loads the oaTcl shared library and initializes the Tcl OpenAccess command interface. The setup
procedure calls the LibDefListOpenLibs command to open all your libraries defined by your lib.defs file. It uses the environment variables OA_HOME for your installation directory and OA_MODE for debuggable or optimized mode selection.
################################################################################ # oaInit.tcl# # This file is a Tcl package and is not intended to be executed as a standalone # script. This file provides Tcl functions to initialize the OpenAccess Tcl # binding and to perform some common setup tasks. This file also contains some # constants commonly used by OA Tcl scripts. ################################################################################ ################################################################################ package require Tcl 8.4.6 ################################################################################ # getOAInstDir # # This function returns the OpenAccess installation directory. ################################################################################ proc getOAInstDir {} { # Check first to see if it has been locally overridden if {[info exists ::OA_HOME] && [file exists $::OA_HOME]} { return $::OA_HOME } elseif {[info exists ::env(OA_HOME)]} { return $::env(OA_HOME) } set file [file join data plugins] set cwd [file split [pwd]] for {set i [llength $cwd]} {$i >= 0} {incr i -1} { set dir [eval file join [lrange $cwd 0 $i]] if [file exists [file join $dir $file]] { return $dir } } return "" } ################################################################################ # getSharedLibPath # # This function returns the path to the shared library directory of OpenAccess. ################################################################################ proc getSharedLibPath {{mode ""}} { set dir [getOAInstDir] if {$dir == ""} { return "" } set lib lib if {$::tcl_platform(platform) == "windows"} { set lib bin } return [file join $dir $lib [getSysName $dir] [getOAMode $mode]] } ################################################################################ # getSysName # # This function returns the OpenAccess system name, including the width which is # based on the tcl executable. ################################################################################ proc getSysName {dir} { if {$::tcl_platform(platform) == "windows"} { return win32 } set plaf [exec [file join $dir bin sysname]] set bits [expr $::tcl_platform(wordSize) * 8] return ${plaf}_${bits} } ################################################################################ # getOAMode # # This function returns the mode. The default is dbg on UNIX and dbgStatic on # Windows. ################################################################################ proc getOAMode {{mode ""}} { if {$mode != ""} { return $mode } if {[info exists ::env(OA_MODE)]} { return ${::env(OA_MODE)} } if {$::tcl_platform(platform) == "windows"} { return dbgStatic } return dbg } ################################################################################ # initoa # # This function initializes the Tcl OpenAccess binding. Call this function # with the mode argument. ################################################################################ proc initoa {{mode ""}} { global auto_path set mode [getOAMode $mode] set dir [getSharedLibPath $mode] if {$dir == ""} { puts "Cannot determine the OpenAccess installation directory. In order to initialize OpenAccess run the Tcl shell from a directory inside the installation hierarchy, or set the OA_HOME environment variable." return } lappend auto_path $dir if {[catch {set val [package require oa]}]} { puts "\nERROR: Cannot load the OA TCL shared libraries from $dir. Verify that the OA TCL shared libraries exist at that location. On Unix the global environment variable \$LD_LIBRARY_PATH must include $dir. Set its value using 'setenv' and rerun this program, since a TCL script cannot modify its own global environment variables.\n" return } puts "OpenAccess is loaded from $dir" return val } ################################################################################ # setup # # This function performs some setup tasks that are common to most OA Tcl # scripts. This function loads the default lib.defs file, and sets the global # OA namespace variable (ns) to oaNativeNS. ################################################################################ proc setup {{libDefs lib.defs}} { set retval [initoa] if {$retval != ""} { if [file exists $libDefs] { if {[catch {oa::LibDefListOpenLibs $libDefs} msg]} { puts "Problem loading lib.defs: $msg" } } } return $retval } |
The examples/oa/TCL directory in your OpenAccess installation hierarchy contains a number of example Tcl files, which are described in the following table.
Example Tcl Files Included With Your OpenAccess Installation | |
---|---|
sample.tcl | Excercises the findInst command implemented in C++ in findInst.cpp. Use "make" to compile the C++ code into "libfindInst.so". From the Tcl shell, enter:% oa::examples::demoSample
|
route.tcl | Tcl routines for creating and printing information on OpenAccess routes. From the Tcl shell, enter:% oa::examples::demoRoute
|
pcell.tcl | Demonstrates the Tcl PCell interface. From the Tcl shell, enter:% oa::examples::demoPcell
|
oa.tcl | Tcl routines for creating and printing information on shapes. From the Tcl shell, enter:% oa::examples::demoOa
|
ns.tcl | Demonstrates OA Namespaces in Tcl. From the Tcl shell, enter:% oa::examples::demoNS
|
libStructure.tcl | Prints the cells, views and DMFiles in an OA library. From the Tcl shell, enter:% oa::examples::demoInst
|
inst.tcl | Traverses an OA design and prints information about the instances it contains. From the Tcl shell, enter:% oa::examples::demoInst
|
hello.tcl | The Tcl implementation of the C++ HelloWorld example. From the Tcl shell, enter:% oa::examples::demoHello
|
contents.tcl | Prints statistical information about the contents of an OA design. From the Tcl shell, enter:% oa::examples::demoContents
|
This section addresses:
As an example, consider a C++ application function to get all instances in a design that match a given name pattern. The programmer wants to bind this function in Tcl so that it can be used in Tcl as in the following example:
set design [oa::DesignOpen lib cell view r] set instances [findInstance $design "I3.*" [oa::NativeNS]]
The Tcl command findInstance is bound to the implementation with the wrapper function:
extern "C" int wrap_findInstance (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
This function is usually registered by the Tcl initialization procedure of the shared library, as explained in the Tcl documentation of the load command. This is achieved with a call similar to:
Tcl_CreateObjCommand(interp, "findNearestRoute", wrap_findNearestRoute, NULL, NULL);
The second element of the objv argument refers to an OpenAccess object, in this case a design. The body of the binding function obtains the C++ OpenAccess object from the objv as explained below. The binding function also needs a way to create Tcl objects that are returned from the application wrapper, which in this example are objects that are stored in a Tcl list. These Tcl objects are used in a Tcl script and can be passed to an OpenAccess Tcl command. The TclCnv template class converts Tcl objects to OpenAccess C++ objects and converts OpenAccess C++ objects to Tcl objects. The oaTclArgException class is used to throw exceptions due to conversion errors. The TclCnv class is easily used in binding code.
extern "C" int wrap_findInstance(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { TclEnv env(interp, objc, objv); try { const TclParams params(env.params()); switch (params.size()) { case 3: { TclCnv<const oaDesign*> design(params[0]); TclCnv<const oaString&> pattern(params[1]); TclCnv<const oaNameSpace&> ns(params[2]); TclCnv<oaArray<oaInst*> > inst(findInstance(design, pattern, ns)); Tcl_Obj *result = createTclList(inst); Tcl_SetObjResult(interp, result); return TCL_OK; } default: throw oaTclArgException(oacBadParamCount); } } catch (oaTclException &ex) { return env.error(ex.getMsg()); } catch (oaException &ex) { Tcl_SetObjResult(interp, Tcl_NewStringObj(ex.getMsg(), -1)); return TCL_ERROR; } }
The TclParams class is a simple helper class to avoid array boundary violations. A complete code example is provided as wrapper.h and wrapper.cpp in the directory <install_directory>/examples/oa/Tcl.
There are six shared libraries needed for binding Tcl with the OpenAccess API. These are:
oaLangBase | Contains support classes to describe OpenAccess classes. |
oaLangInfo | Contains the description of OpenAccess classes and functions. |
oaTclCommon | Provides general support classes for Tcl bindings of C++ types. |
oaTclBase | Provides support classes for Tcl bindings to OpenAccess types. |
oaTclPlugIn | Provides support classes for the Tcl Script engine, which is used for Tcl Pcells. |
oaTclHelp | Provides the oa::help command bindings. |
Shared libraries for custom Tcl bindings must be linked to oaTclBase, oaLangInfo, oaTclCommon, oaLangBase, and oaTclPlugIn; and your header file must include oaTcl.h.
Some applications use a Tcl interpreter for other purposes besides OpenAccess. If a consistent interpreter is required in these situations, make the following call from the application:
oaTcl::oaTclEngineFactory::create(interp);
This call is necessary only in exceptional situations where the oaTcl shared library is not loaded from the interpreter. This call must be made before the call to Oa_Init.
The oaTcl dynamic libraries are not guaranteed to be drop-in compatible for applications that are compiled using the oaTcl header files. Drop-in compatibility is only guaranteed for the public C++ OpenAccess API. Applications that call the Tcl bindings from C++ must be recompiled for each release of OpenAccess. Note however that OpenAccess API compatibility means that Tcl scripts using the oaTcl command bindings will not require changes due to future releases.
Other limitations of the OpenAccess API in Tcl are:
Copyright © 2004-2010 Cadence Design Systems, Inc.
All rights reserved.