SWIG Wrappers for OpenAccess

A while ago, I needed to use the OpenAccess SDK to write some code to do some physical design. I tried to get the much touted Python wrappers to work, but they were for OA2.1, while I was using OA2.1.1. The OA API changed just enough to foil any attempts at compilation. Since those wrappers were a big monolith of generated code, I figured I'd probably be better off writing my own.

I chose SWIG over Boost.Python because of the more advanced typemaps. I actually like Boost.Python better, because it avoids shadow classes, but SWIG's typemaps seemed like the right thing for wrapping someone else's code. Not all of the API is wrapped, because I didn't need all of the API. (Finishing it is left as an exercise to the reader.)

Download:
pyoa.tar.gz (for OpenAccess 2.1)
pyoa-2.2.tar.gz (for OpenAccess 2.2)

Why Python

In case you haven't used Python, Ruby, (or even Perl,) here's my motivation for using wrappers:

I'm lazy and impatient.

Compilation just takes too much time.

Programmers in the 1950s needed to meticulously check that their FORTRAN (as it was spelled in those days) code would compile cleanly and work correctly, as computer time was expensive. Nowadays, I'm sometimes too lazy to check that the syntax is okay, and let the compiler tell me about it.

In the case of EDA, lots of code is written to do very simple things, like perhaps rename blocks. Back in the days of human readable design files, sed/awk were sufficient. With OpenAccess, however, you need to write C++ code to do that, and compile and link it with all the right options. Not fun.

I'm primarily a printf sort of debugger, also, so not having to recompile is a big plus when adding new features.

I'm feeble-minded.

Most programming tasks actually consist of reading code, not writing code. (Which is a big reason why Python is whitespace sensitive.) When maintaining code, I'd much rather have to keep 1,000 lines of code in my head than 10,000 lines of code in my head.

I hate programming.

I don't actually hate programming, I just hate writing boilerplate code, and some APIs are rather unfun to use. Get/set methods to use structs, when a struct is just a struct, are not fun. Using arguments to return values is not fun. Manipulating fancy names when all you need are strings is not fun.

Example

The following code opens design foo/bar/baz, and prints out, in sorted order, the affinely transformed coordinates of each instance along with the instance name.

Python

cv       = oaCellView.open('foo', 'bar', 'baz', 'r')
insts    = cv.getTopBlock().getInsts()
instList = [(i.getBBox().getCenter().transform(t), i) for i in insts]
instList.sort(lambda a,b : cmp(a[0].y, b[0].y))
for (p, i) in instList:
    print p, i.getName()

C++

bool
cmpy(const pair<oaPoint,oaInst*> &a, const pair<oaPoint,oaInst*> &b)
{
    return a.first.y() < b.first.y();
}

oaNativeNS   ns;
oaScalarName libName(ns, "foo");
oaScalarName cellName(ns, "bar");
oaScalarName viewName(ns, "baz");

oaCellView                      *cv = oaCellView::open(libName, cellName, viewName, 'r');
oaIter<oaInst>                  it(cv->getTopBlock()->getInsts());
oaInst                          *i;
vector<pair<oaPoint, oaInst*> > sorted;
while ((i = it.getNext())) {
    oaBox                       bbox;
    oaPoint                     point;
    i->getBBox(bbox);
    bbox.getCenter(point);
    point.transform(t);
    sorted.push_back(std::make_pair(point, i));
}
std::sort(sorted.begin(), sorted.end(), cmpy);
for (vector<pair<oaPoint, oaInst*> >::iterator it = sorted.begin();
        it != sorted.end();
        ++it) {
    oaString instName;
    it->second->getName(ns, instName);
    std::cout << it->first << ' ' << instName << std::endl;
}