CSharp Language Binding for OpenAccess
From oacwiki
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.
1 Conventions
1.1 Typography
| 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 |
Monospace 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.
2 Set Up
2.1 Quick Start
The oaScript Quick Start Guides explain how to download, install and build oaScript:
- For Perl, Python, Ruby and Tcl, use the OaScript Quick Start Guide
- For C#, use the OaScript CMake Quick Start Guide
2.2 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.
2.3 Referencing the oasCSharp Managed Assembly
oasCSharp supports:
- C# version 3.0
- .NET 3.5 on Windows
- Mono 2.6 on Linux
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 ...
2.4 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.
2.4.1 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_PATHin a wrapper script like those in /path/to/openaccess/bin, or - Use the
$ORIGINlinker option
2.4.2 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.
2.4.3 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.
2.5 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.
2.6 For More Information
- See the Prioritized List of oasCSharp Tasks for known missing features.
- Ask a question on the oaScript Discussion Forum (also functions as FAQ)
- Report a problem using the oaScript Bug Tracker
- Request a new feature using the oaScript Feature Request Tracker
- Read oaScript News
- Download oaScript
3 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.
3.1 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 |
3.2 Native C# string Replaces oaString
The oaString class is entirely replaced with C# string. oaString does not appear in the OpenAccess C# API.
3.3 Native C# DateTime Replaces oaTime
The oaTime class is entirely replaced with C# System.DateTime.
oaTime does not appear in the OpenAccess C# API.
3.4 uint Replaces oaTimeStamp
The oaTimeStamp class is entirely replaced with unsigned int in C#.
oaTimeStamp does not appear in the OpenAccess C# API.
3.5 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
3.6 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# oaType.oacTextType oaType.oacRectType oaType.oScalarInstType oaType.oaScalarNetType // ...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.
3.6.1 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.
3.6.2 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.
3.7 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:
-
oaAntennaAreaarea,layerNum -
oaBoxlowerLeft,upperRight,left,bottom,right,top -
oaComplex_float(oaComplex<oaFloat>in C++)real,imag -
oaDMObjectStatusRefobj,status -
oaDMObjectVersionRefobj,version -
oaLayerMapdesignLayer,waferLayer -
oaOccTraverserflags -
oaPointx,y -
oaSegmenthead,tail,x1,y1,x2,y2 -
oaSiteRefsiteName,transform -
oaTransformoffset,xOffset,yOffset,orient -
oaVectorx,y
Get/set properties for all single argument getXXX()/setXXX() pairs has
been requested, and it appears in the Prioritized List of oasCSharp Tasks.
3.8 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
}
3.9 oaArrays
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);
}
Console.WriteLine("");
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.
3.10 oaExceptions
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 likeoaException.Message -
oaException.getMsgId(), which always returns the invalid message IDoasCSharpBase.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.
3.11 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.
3.12 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.
3.13 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.
4 Enhancements to the OpenAccess C++ API for C#
oaScript offers some features beyond what is offered in the C++ API.
4.1 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.
4.1.1 Inhibiting Automatic Initialization
Set environment variable OASCRIPT_USE_INIT to "0" (zero) to skip automatic initialization. Then you
are responsible for initializing OpenAccess explicitly.
4.1.2 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().
4.2 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#.
4.3 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_
oaNameSpace.push(ns_);
// Create the library
LibMgrOptions libMgrOptions = new LibMgrOptions();
libMgrOptions.setDMSystem("oaDMFileSys");
libMgrOptions.setShared(true);
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));
...
oaNameSpace.pop();
See oaScript Default Namespace Extensions for a detailed discussion of this important feature.
4.4 Two Corner Methods Added to oaBox
For convenience, two more methods to get the corners of an oaBox are provided:
oaBox.upperLeft() oaBox.lowerRight()
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.
5 Identical in OpenAccess C++ API and C#
Some things are identical in both languages, but still bear mention.
5.1 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);
5.2 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
rectangleAandrectangleBrefer to a single rectangle in the OpenAccess database, even whenrectangleAandrectangleBare 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().

