The Cadence ITK C API and the OpenAccess C++ API can be used together in the same program.
Cadence ITK (Integrator’s Tool Kit) enables C programs to directly manipulate the database for Virtuoso IC layout software. For new code, you will want to use the more modern OpenAccess C++ API, but if you also have legacy ITK code, you will need to link both APIs into the same program. This post tells you how.
Advantages and Disadvantages of ITK
For those who are thinking about developing new client code using ITK, first consider its advantages and disadvantages.
Advantages
- ITK works with both CDB and OpenAccess design databases
- ITK is the only C/C++ API that can evaluate Cadence SKILL PCells
Disadvantages
- ITK is a decades old C API that is inferior to the modern OpenAccess C++ API
- ITK consumes an inordinate number of Virtuoso license tokens
- ITK is a static library that must be linked to your application, not a loadable library or plugin
- ITK is a proprietary, legacy product of Cadence, whereas OpenAccess is open and has become a mainstay of the entire EDA industry
My opinion is that ITK should be used only for existing legacy code, and the portions of your code that simply must evaluate SKILL PCells.
Linking ITK and OpenAccess Into the Same Program
You can link both APIs into the same program if you obey a few simple rules:
- Use the same OpenAccess version that ITK uses
- Initialize ITK with
dbInit()first, and initialize OpenAccess withoaDesignInit()second - ITK functions automatically get access to OpenAccess libraries as needed, while OpenAccess clients are expected to explicitly get library read or write access using
oaLib::getAccess(). The symptom of library access trouble is that OpenAccess throws an exception when you fail to get proper access. - ITK handles names in the CDBA namespace. Therefore, use the
oaCdbaNSnamespace in the OpenAccess API when passing name strings to or from ITK.
I did not try casting between OpenAccess pointers and ITK database IDs. If you succeed at this, let me know how it goes.

{ 3 comments… read them below or add one }
Dear M. McGehee,
Currently, I am a severely stuck with a practical issue trying to get an OpenAccess plugin working from Cadence Virtuoso.
From the point of view of OpenAccess, everything is very well documented and clear. However, it is not from the point of Cadence. It is also not clear if we maybe need the Cadence Integrator’s Toolkit (ITK), or not.
-We have an Openaccess plugin file (.plg extension, see opnPCell.plg herunder) which was placed in the path /Cadence/IC6.1/oa_v22.04.028/data/plugins/
-We have the C++ code “opnPcell.cpp” (see below) which was compiled into a shared library “libopnPcell.so” and placed in the path /Cadence/IC6.1/oa_v22.04.028/lib/linux_rhel30_gcc411_32/opt
These come from the standard OpenAccess 2.2 release.
Now my question is : how do I tell Cadence Virtuoso (6.1.3) to “start up” the
plugin when instantiating a PCell, i.e. to call the getClassObject method of “libopnPcell.so” and instantiate an object of class “opnPcell” ?
Do we need the Cadence ITK ?
I cannot find any documentation about this on Sourcelink or newsgroups.
Could you give us a hint on how to proceed?
Best regards.
————————– file opnPCell.plg ————–
—————————file opnPcell.cpp —————-
#include “opnPcell.h”
Factory opnPcell::factory(“opnPcell”);
const oaString opnPcellMsgs[] = {
“Invalid value for the ‘%s’ parameter supplied.”
};
long
getClassObject(const char *classID,
const Guid &interfaceID,
void **ptr)
{
return FactoryBase::getClassObject(classID, interfaceID, ptr);
}
oaPcellDef *
opnPcell::getPcellDef()
{
return new opnPcellDef(this);
}
void
opnPcell::onUnbind(oaDesign *design,
oaPcellDef *pcellDef)
{
delete pcellDef;
}
void
opnPcell::onEval(oaDesign *design,
oaPcellDef *pcellDef)
{
oaParam param;
oaParamArray params;
design->getParams(params);
oaUInt4 dbu = 1000;
oaInt4 w;
oaInt4 l;
if (params.find(“width”, param)) {
if (param.getType() == oacDoubleParamType) {
w = oaInt4(param.getDoubleVal() * dbu);
}
}
if (w < 1) {
throw opnError(opnParamInvalid, (const char *) "width");
};
if (params.find("length", param)) {
if (param.getType() == oacDoubleParamType) {
l = oaInt4(param.getDoubleVal() * dbu);
}
}
if (l getTopBlock();
if (!bk) {
bk = oaBlock::create(design);
}
oaRect *box1 = oaRect::create(bk, 2, 1, oaBox(-l, -w, l, w));
// Double w,l and swap
w *= 2;
l *= 2;
oaRect *box2 = oaRect::create(bk, 3, 1, oaBox(-w, -l, w, l));
}
oaUInt4
opnPcell::calcDiskSize(oaPcellDef *pcellDef) const
{
return 0;
}
opnPcellDef::opnPcellDef(IPcell *pcell)
: oaPcellDef(pcell)
{
data = “MyopnPcellData”;
}
inline
opnException::opnException(oaUInt4 msgIdIn)
: oaException(msgIdIn)
{
}
const oaString &
opnException::getFormatString() const
{
return opnPcellMsgs[msgId];
}
opnError::opnError(oaUInt4 msgIdIn,
…)
: opnException(msgIdIn)
{
va_list args;
va_start(args, msgIdIn);
format(args);
va_end(args);
}
Thank you for your interest.
I have no experience with C++ PCells. C++ PCells are not at all popular. In fact, you are the first person I have heard of who has tried them.
I have two suggestions for you. Get the Ciranova PyCells, and write your PCells in Python. You could also try Tcl PCells. Synopsys Custom Designer is using them.
If you still want to use C++ PCells, have a look at the CiraNova PyCell documentation. You can download it for free. It might give you a clue that will help you get your C++ PCells running.
Keep me posted. I am interested to hear what happens.
Emmanuel,
- there is an example C++ Pcell in the OpenAccess tutorial package, at ./labs/pccpp
- there is an example of Pcell registration in the plugin mechanism at ./labs/pcplugin
- -
John,
using the same version as VXL may give “surprises”. For instance the latest 6.1.4 will ignore the “lib.defs” files, as it reads a “cds.lib” by default.
regarding the pros&cons of OA/ITK. For Pcells, it is possible with OA to get the PCells that have been cached using both CDNS or CNI formats, even if actual evaluation is not possible.
k.r.
–