CSharp Language Binding for OpenAccess

From oacwiki
Jump to: navigation, search

oasCSharp is the C# binding of the OpenAccess electronic design database API. Sponsored by [Texas Instruments], the OpenAccess C# binding was implemented by [John McGehee of Voom, Inc.]

The first practical programs came to life on April 5, 2011. oasCSharp is currently beta release quality—see the Prioritized List of oasCSharp Tasks for known missing features.




Format Meaning
Monospace font Command names, file names or other text designed to be entered literally, as-is, to a program input stream; or which is directed as-is to the output stream
Monospace font, with a colored background Computer language source code. All pages cannot be expected to adhere to the distinction between this and the command name formatting above.
Italic font Text that is a placeholder for a specific substitution that must be made to a program input stream
in a box
Console output, code examples, syntax prototypes (typically referenced by the preceding "normal style" paragraph)
[OPTION] Optional items in a syntax prototype are enclosed in square brackets

For guidelines on editing wiki pages yourself, see the Style Guide.

Set Up

Quick Start

The oaScript Quick Start Guides explain how to download, install and build oaScript:

The Main OpenAccess API Documentation

The excellent OpenAccess C++ API documentation serves as documentation for the classes in the oaScript API.

Most programmers use locally-installed documentation. Access it by pointing your web browser at doc/oa/html/index.html within your OpenAccess file hierarchy.

If your company is an OpenAccess coalition member, you can log in to si2.org and browse the OpenAccess C++ API documentation online.

Referencing the oasCSharp Managed Assembly

oasCSharp supports:

The OpenAccess API is in the OpenAccess_4 C# namespace. To use it, add

 using OpenAccess_4;

to your C# source file.

The C# code in oasCSharp is compiled into managed assembly oasCSharp.dll. You must compile your C# application with oasCSharp.dll defined as a reference. On Linux:

 gmcs /r:/path/to/oaScript/bin/win32/opt/oasCSharp.dll ...

On Windows:

 csc /r:C:\path\to\oaScript\bin\win32\opt\oasCSharp.dll ...

Finding the Unmanaged Libraries

The C++ code in oasCSharp is compiled into eight unmanaged (native C++) libraries corresponding to the OpenAccess libraries:

  • oasCSharpBase
  • oasCSharpCommon
  • oasCSharpdesign
  • oasCSharpDM
  • oasCSharpPlugIn
  • oasCSharpTech
  • oasCSharpUtil
  • oasCSharpWafer

These libraries are named according to the custom for your platform, like liboasCSharpBase.so on Linux, and oasCSharpBase.dll on Windows.

Your system must be able to find and load both the OpenAccess libraries as well as the oasCSharp libraries.

Linux Platforms

Your LD_LIBRARY_PATH environment variable must refer to the directory containing the libraries, such as amd-init/Release/lib/linux_rhel40_64/opt and /path/to/openaccess/lib/linux_rhel40_64/opt.

When you're just starting out, setting LD_LIBRARY_PATH is a fine way to get things going. However, setting LD_LIBRARY_PATH globally is evil. In your application release:

  • Set LD_LIBRARY_PATH in a wrapper script like those in /path/to/openaccess/bin, or
  • Use the $ORIGIN linker option

Windows Platforms

Your PATH environment variable must contain the directory containing the libraries, such as amd-init\Release\bin\win32\opt and C:\path\to\openaccess\bin\win32\opt. Ultimately, when you deploy your application, you will want to put the,

  • OpenAccess unmanaged libraries
  • oasCSharp unmanaged libraries
  • oasCSharp managed assembly
  • Your application assembly

all in the same folder. Alternatively, implement a side-by-side deployment.

Windows Debug Libraries Require Visual Studio 2005

In order to load the OpenAccess debug mode libraries in C:\path\to\openaccess\bin\win32\dbg, you must have Visual Studio 2005 installed. If not, the DLLs for your application will not load, and the reason why will be unapparent.

Cadence uses Visual Studio 2005 to compile OpenAccess. The debug mode libraries require library Microsoft.VC80.DebugCRT, which ships only with Visual Studio 2005. Therefore you have these alternatives:

  • The simplest is to use only the OpenAccess optimized libraries with your choice of Visual Studio versions. You just will not be able to step into OpenAccess with the debugger.
  • Install Visual Studio 2005 and use any of the pre-compiled libraries in the OpenAccess major release
  • Compile OpenAccess and your application all on your favorite version of Visual Studio and do whatever you like

Credit for finding the cause of this murky problem goes to Kyle Patterson of Texas Instruments.

Unit tests

Unit tests are in the release at csharp3.0/test directory. These tests are an excellent source of programming examples, particularly:

  • csharp3.0/test/TestDesigns.cs
  • csharp3.0/test/oasCSharpDesignTest.cs
  • csharp3.0/test/oasCSharpBaseTest.cs

TestDesigns.cs is the most interesting because it shows start up, creating a library and creating designs.

For More Information

Differences Between the C# API and the C++ API

Inasmuch as possible, the C# API follows the C++ API so that you can use the C++ API documentation with any oaScript language. C# itself is very similar to C++, so the APIs are in many ways identical. Nonetheless, there are differences.

Native C# Numeric Types Replace C++ typedefs

For the sake of portability, the C++ API uses typedefs like oaInt4 and oaLayerNum for all numeric values. In C#, the width of value types is consistent across all platforms, so this is not a problem. Native C# types are used for numeric values, and the C++ API typedefs do not appear in the OpenAccess C# API:

C++ Type C# Type
oaCoord int
oaDist uint
oaOffset int
oaChar char
oaFloat float
oaDouble double
oaInt1 sbyte
oaUInt1 byte
oaInt2 short
oaUInt2 ushort
oaInt4 int
oaUInt4 uint
oaInt8 long
oaUInt8 ulong
oaLayerNum uint
oaPurposeNum uint

Native C# string Replaces oaString

The oaString class is entirely replaced with C# string. oaString does not appear in the OpenAccess C# API.

Native C# DateTime Replaces oaTime

The oaTime class is entirely replaced with C# System.DateTime. oaTime does not appear in the OpenAccess C# API.

uint Replaces oaTimeStamp

The oaTimeStamp class is entirely replaced with unsigned int in C#. oaTimeStamp does not appear in the OpenAccess C# API.

C++ Global Functions in C# Module Class

While OpenAccess is an object oriented API, there are a few global functions and constants. C# does not allow this, so the C++ global functions and constants become static members of the module classes in C#. The most useful are:

  • oasCSharpBase.oaBaseInit()
  • oasCSharpBase.oaRound()
  • oasCSharpBase.oacNullIndex
  • oasCSharpDesign.oaDesignInit()
  • oasCSharpTech.oaTechInit()
  • oasCSharpTech.oacAnyLayerNum
  • oasCSharpTech.oavPurposeNumberDrawing
  • oasCSharpTech.oavPurposeNumberFill
  • oasCSharpTech.oavPurposeNumberSlot
  • oasCSharpTech.oavPurposeNumberOPCSerif
  • oasCSharpTech.oavPurposeNumberOPCAntiSerif
  • oasCSharpTech.oavPurposeNumberAnnotation
  • oasCSharpTech.oavPurposeNumberGapFill
  • oasCSharpTech.oavPurposeNumberRedundant
  • oasCSharpTech.oavPurposeNumberAny
  • oasCSharpTech.oavPurposeNumberNo
  • oasCSharpTech.oavPurposeNumberFillOPC
  • oasCSharpWafer.oaWaferInit()

You will almost certainly be making use of the purpose numbers. You will rarely need to explicitly invoke the oa*Init() methods because they are invoked automatically upon initialization. You can examine the entire module classes in C# source code files:

  • csharp3.0/oasCSharpBase.cs
  • csharp3.0/oasCSharpCommon.cs
  • csharp3.0/oasCSharpDesign.cs
  • csharp3.0/oasCSharpDM.cs
  • csharp3.0/oasCSharpPlugIn.cs
  • csharp3.0/oasCSharpUtil.cs
  • csharp3.0/oasCSharpWafer.cs

Enumerated Types and Enum Wrappers

For many enums in C++, OpenAccess provides an enum wrapper class. The purpose of this wrapper class is to make up for the shortcoming of C++ enums—shortcomings that are not present in C#.

Therefore, in C# native enums have taken the place of the C++ enum wrapper classes. For example, consider the C# enum oaType. It expresses the type of an object descended from oaObject. For example,

 // C#
 // ...and so on

Note how the C# enum has taken the name of the C++ enum wrapper class oaType, and the values are those from the C++ enum oaTypeEnum. Enum oaTypeEnum is not present in C#.

For the sake of consistency, even the enums that have no corresponding enum wrapper also have the "Enum" suffix removed from their names.

The underlying type for most all enums is int. Only IDMObjectStatus::StatusEnum is uint.

Exceptions to the Rules About Enums and Enum Wrappers

oaManagedType and oaDesignAttrType remain enum wrapper classes because they simultaneously handle two different types of enums, which is beyond the scope of C# enums.

Further, oaDesignAttrTypeEnum cannot be renamed to oaDesignAttrType, because that name is already taken. Thus oaDesignAttrTypeEnum retains its "Enum" suffix.

English Nickname Functionality not Implemented

In the C++ API, enum wrapper classes can translate between the English name and the enum value. For instance, functions are provided to translate from the enum value oacTextType to the string Text and vice-versa.

In C# this English nickname functionality is missing. Again using enum oaType.oacTextType as an example, the C# oaType.oacTextType.ToString() function returns oacTextType, not Text. The OpenAccess C# API provides no particular functionality to translate from a string to an enum.

Get/Set Properties

Certain OpenAccess methods have been converted to use C# properties. For example, the C++ methods oaPoint.x() and oaPoint.y() have been converted to C# members oaPoint.x and oaPoint.y:

 oaPoint p0 = new oaPoint(100, 200);
 Debug.Assert(100,  p0.x);
 Debug.Assert(200,  p0.y);

oaTransform has C# members offset, xOffset, yOffset and orient:

 oaTransform t0 = new oaTransform(new oaPoint(100,200), oaOrient.oacR180);
 Debug.Assert(new oaPoint(100, 200), t0.offset);
 Debug.Assert(100,  t0.xOffset);
 Debug.Assert(200,  t0.yOffset);
 Debug.Assert(oaOrient.oacR180,  t0.orient);

The following is a complete list of classes and methods that have been converted to use C# properties:

  • oaAntennaArea area, layerNum
  • oaBox lowerLeft, upperRight, left, bottom, right, top
  • oaComplex_float (oaComplex<oaFloat> in C++) real, imag
  • oaDMObjectStatusRef obj, status
  • oaDMObjectVersionRef obj, version
  • oaLayerMap designLayer, waferLayer
  • oaOccTraverser flags
  • oaPoint x, y
  • oaSegment head, tail, x1, y1, x2, y2
  • oaSiteRef siteName, transform
  • oaTransform offset, xOffset, yOffset, orient
  • oaVector x, y

Get/set properties for all single argument getXXX()/setXXX() pairs has been requested, and it appears in the Prioritized List of oasCSharp Tasks.

oaCollection and oaIter

All oaCollections implement the ICollection<> interface. All oaCollections are read-only, so the IsReadOnly method always returns true, and the Add(), Clear() and Remove() methods always throw System.NotSupportedException.

Template oaCollection<obj,container> appears in C# as oaCollection_obj_container, but is rarely instantiated explicitly. It is almost always more convenient to use the return value of a method directly. For example, instead of instantiating a oaCollection_oaTerm_oaBlock, just use:

 Console.WriteLine("Examining a total of {0} terminals", block.getTerms().Count);

oaIters also exist in C#, but are not used directly. Instead, oaCollection objects are iterable in C#:

 foreach (oaNet net in block.getNets())
   // Do something netistic


oaArray is a misnomer in C# because oaArrays can change size, while C# arrays have a fixed capacity. Thus in C# the oaArray classes implement the C# IList interface. For example:

 // oaLine line = ...;
 oaPointArray points;
 line.getPoints(out points);
 Console.Write("Found line with {0} points", points.Count);
 foreach (oaPoint point in points)
   Console.Write(" {0}", point);

Due to a number of factors, not all oaArrays are currently implemented. See the oaScript Typed oaArray Specification for a list of the unimplemented arrays and a detailed discussion of why this is a problem and how it will be addressed.


Exceptions thrown by the OpenAccess C# API can be caught using oaException, which is derived from System.ApplicationException.

The OpenAccess exception message string can be obtained from the oaException.Message property.

C++ oaExceptions also have an associated message ID number which is not available in C#. This is not an overwhelming problem because the message string alone uniquely identifies the error; there is one-to-one correspondence between message strings and message ID numbers.

For compatibility with the C++ API, C# oaException has:

  • oaException.getMsg(), which returns the OpenAccess exception message, just like oaException.Message
  • oaException.getMsgId(), which always returns the invalid message ID oasCSharpBase.oacNullIndex (0xFFFFFFFF)

However, C# clients should favor oaException.Message over these methods.

OpenAccess does not throw plugin exception IException nor its derived exceptions IPlugInException and ExceptionBase. Therefore nothing has been done to enable client applications to catch these exceptions.

Collisions with C# Keywords lock, object, and override

A few OpenAccess methods have the same name as C# keywords and had to be renamed:

OpenAccess C++ oasCSharp C#
ILocking::lock() ILocking::latch()
oaConstraintGroup::override() oaConstraintGroup::overule()

Fortunately, object only appears as the name of an argument. It has been changed to obj, but this makes no difference to the client programmer.

oaAppDefs, oaOccTraverser and oaObservers not Implemented

oaAppDefs are not implemented in oasCSharp. oaAppDefs are database objects that can be defined by the application. You can add custom attributes to existing OpenAccess objects, or even define entirely new types of objects.

oaOccTraverser and oaObservers require cross language polymorphism, which is possible, but not working yet.

File Manipulation Classes Not Included

The OpenAccess C++ API includes file manipulation classes that provide cross-platform file system support:

  • oaFile, file object
  • oaDir, directory object
  • oaDirIter, iterator for items in a directory
  • oaFSComponent, base class with predicates for testing file system objects

Scripting languages already contain good cross-platform file system support, so in oaScript these classes have been removed.

Enhancements to the OpenAccess C++ API for C#

oaScript offers some features beyond what is offered in the C++ API.

OpenAccess Initializes Automatically

To eliminate confusion, oaScript automatically initializes the OpenAccess session. This is different from the C++ API, where the client application must explicitly initialize OpenAccess session with methods like oaDesignInit() or sometimes oaTechInit(). oaScript performs the initialization:

  • In the module initialization for scripting languages
  • Upon static initialization of the respective oasCSharp library in C#

Note that this automatic initialization of OpenAccess does not include reading a preexisting library definition list. Read the library definition list file using oaLibDefList.openLibs() before you try to access any preexisting library.

Inhibiting Automatic Initialization

Set environment variable OASCRIPT_USE_INIT to "0" (zero) to skip automatic initialization. Then you are responsible for initializing OpenAccess explicitly.

Initialization Methods

If you decide to skip automatic initialization, you must initialize OpenAccess yourself using one of the initialization functions:

  • oasCSharpBase.oaBaseInit()
  • oasCSharpDesign.oaDesignInit()
  • oasCSharpTech.oaTechInit()
  • oasCSharpWafer.oaWaferInit()

The initialization method most commonly used is oasCSharpDesign.oaDesignInit().

Library Definition List Errors Detected

In C++, it is good practice to derive an oaObserver<oaLibDefList> to catch errors in the library definition (lib.defs) file. The OpenAccess documentation describes this in doc/oa/html/guide/helloworld.html.

Since oaScript does not support observers, oaObserver<oaLibDefList> is built in to oaScript. When oaLibDefList::openLibs() or oaLibDefList::open() detect an issue such as a missing, unreadable, or incorrectly formatted library definition file, an oaException is thrown in C#.

OpenAccess Names and the Default Namespace

The oaScript scripting language bindings support a default namespace that allows you to define an oaNameSpace to be used everywhere, so you can specify names as ordinary C# strings. Note how strings are used directly in place of oaScalarNames in this example:

 // From unit test file csharp3.0/test/TestDesign.cs
 using OpenAccess_4;
 static protected oaNameSpace ns_ = new oaVerilogNS();
 // Interpret all strings as being in namespace ns_
 // Create the library
 LibMgrOptions libMgrOptions = new LibMgrOptions();
 oaLib lib = LibMgr.create("testLib", "testLib", libMgrOptions);
 oaDesign MidSchematicDesign = oaDesign.open("testLib", "mid", "schematic",
 oaViewType.get(oaReservedViewType.oacSchematic), 'w');
 oaBlock block = oaBlock.create(MidSchematicDesign);
 oaScalarInst i0 = oaScalarInst.create(block, InvDesign, "i0",
     new oaTransform(2000, 3000, oaOrient.oacR0));

See oaScript Default Namespace Extensions for a detailed discussion of this important feature.

Two Corner Methods Added to oaBox

For convenience, two more methods to get the corners of an oaBox are provided:


These compliment the native OpenAccess methods oaBox.lowerLeft() and oaBox.upperRight(). All four return an oaPoint.

The native methods that take an output argument, oaBox.getUpperLeft(oaPoint) and oaBox.getLowerRight(oaPoint), are also present.

Identical in OpenAccess C++ API and C#

Some things are identical in both languages, but still bear mention.

oaBox, oaPoint, oaTransform

As in the C++ API, coordinates are always integer values in database units.

oaPoint, oaBox, and oaTransform are used as they are in C++. All operators are implemented. For example, you can add oaPoints:

 oaPoint p0 = new oaPoint(1000, 2000);
 oaPoint p1 = new oaPoint(100, 200);
 Debug.Assert(new oaPoint(1100, 2200) == p0 + p1);

Equality Operator for oaObject and Its Derived Classes

oaObject is the abstract base class for all persistent database objects managed by OpenAccess. In C#, the oaObject equality operator == and oaObject.Equals() compare the underlying C++ pointer value of the underlying oaObject. Thus,

 oaRect rectangleA = // Somehow get a rectangle from the OpenAccess database
 oaRect rectangleB = // Somehow once again get a rectangle from the OpenAccess database
 return rectangleA == rectangleB

will return:

  • True if rectangleA and rectangleB refer to a single rectangle in the OpenAccess database, even when rectangleA and rectangleB are two different C# references
  • False if they are separate rectangles, no matter how similar

Therefore this is reference equality with respect to the C++ oaObject* pointer, not with respect to the C# references.

You can still test the C# references for equality using System.Object.ReferenceEquals().

Personal tools