LUNAROPS · OPERATIONAL UPLINK 100% UPTIME 1,247d POSTS 893 JEFF.MOON@LUNAROPS.DEV UTC --:--:--

OpenAccess and OAScript: The Open EDA Database Standard

edaopenaccessoascripttclic-designsemiconductorcadencesi2layoutdesign-automation
Contents

If you work in IC design automation, physical design, or EDA tool development, you have almost certainly touched OpenAccess data — quite possibly without knowing it. Cadence Virtuoso, every major place-and-route tool, and dozens of commercial and open-source utilities either read from or write to OpenAccess databases. Understanding the database standard itself, and knowing how to drive it programmatically with OAScript, makes you significantly more effective at building flows, debugging data problems, and writing design automation.

This post covers everything from what OpenAccess actually is — the standard, the history, the licensing reality — through the object model, building from source, the OAScript Tcl shell, practical code examples, and how OpenAccess compares to the alternatives you will encounter in real flows.


What OpenAccess Is

OpenAccess is an open-standard C++ API and database format for integrated circuit design data. It provides a unified programmatic interface to IC design databases covering physical layout, schematics, netlists, and abstracts. The standard is maintained by SI2 (Silicon Integration Initiative), a non-profit semiconductor industry consortium whose membership includes most of the major EDA vendors and semiconductor companies.

The practical effect of the standard: a Cadence Virtuoso layout database, a Synopsys IC Compiler II design, and a standalone OAScript program all speak the same object model. The same API calls — same class names, same methods, same namespace — work across tools. That portability is the entire point.

History

OpenAccess originated inside Cadence Design Systems, where it was developed as the storage backend for Virtuoso. In 2004, Cadence donated the technology and source code to SI2 under an open-access license, making it available to the entire industry. This was a significant moment: Cadence was giving away the database that underpinned its flagship product so that the industry could standardize around a single format and reduce the integration friction between tools.

After donation, SI2 formed the OpenAccess Coalition to govern the standard. Synopsys, Mentor Graphics (now Siemens EDA), Magma Design Automation, and other EDA vendors joined as coalition members. The release that stabilized the public API and remains the reference today is OpenAccess 22 (also referred to as oa22 in filenames and directory structures). The version numbering reflects internal Cadence history, not the year — oa22 predates the SI2 donation.

Development activity on the SI2 OpenAccess codebase has slowed significantly since the mid-2010s. The standard is stable and mature; commercial tools have their own internally optimized implementations of the same API. But the reference source remains publicly available through SI2.

What OpenAccess Provides

OpenAccess is several things at once:

A database format. On disk, an OpenAccess library is a directory tree of binary .oa files — one per cell/cellview combination plus library and technology metadata. The format is documented and the reference implementation can read/write it.

A C++ class library. The primary interface to OpenAccess is a rich C++ API (roughly 300+ classes) covering every concept in IC design: libraries, cells, cellviews, instances, nets, terminals, shapes, layers, vias, design rules, and more. Commercial EDA tools typically embed this C++ library directly.

A Tcl scripting environment (OAScript). The oaScript executable is an interactive Tcl shell with all OpenAccess C++ objects wrapped as Tcl objects. It ships with the OpenAccess source distribution and is the most accessible way to drive OA databases without writing C++.

A technology database system. The technology database (tech.oa) stores layer definitions, purpose definitions, layer-purpose pair rules, via definitions, connectivity rules, and physical design rules — everything a tool needs to interpret the physical meaning of design data.

Who Uses It

Cadence Virtuoso is the most widely deployed OpenAccess consumer. The Virtuoso database is an OA database. When you open a cell in Virtuoso’s layout editor (Virtuoso Layout Suite, VLS), you are looking at an OpenAccess cellview. The SKILL scripting environment in Virtuoso exposes these same objects through SKILL bindings to the underlying OA API. When Virtuoso reads a cds.lib and opens cells, it is opening OA libraries from disk.

Synopsys tools including IC Compiler II and PrimeTime have OA database connectivity. IC Compiler II (ICC2) can work directly with OA databases, sharing data with Virtuoso without intermediate format translation.

Siemens EDA (formerly Mentor Graphics) tools including Calibre can be invoked against OA-native data through connectivity layers, though Calibre’s native input is typically GDSII or OASIS streams.

Ansys (formerly Apache) power analysis and signal integrity tools consume OA data directly.

Open-source tools: OpenROAD (the open-source RTL-to-GDSII flow) uses OpenDB, a separate database standard inspired by but not directly descended from OA. KLayout has partial OA reading capability in its open-source build and more complete OA support in its commercial edition.


The OpenAccess Object Model

Understanding the object model is the prerequisite for everything else. OpenAccess has a strict hierarchy, and every operation is anchored to a position in that hierarchy.

The Database Hierarchy

oaSession (the singleton session object)
└── oaLib (library — a collection of related cells)
    └── oaCell (a logical design unit — an AND gate, a memory, a full chip)
        └── oaCellView (one view of a cell — layout, schematic, netlist, abstract...)
            ├── oaBlock (the layout/netlist container within a cellview)
            │   ├── oaInst (instance of another cell placed in this design)
            │   ├── oaNet (a logical or physical wire)
            │   ├── oaTerm (a terminal — the port interface)
            │   ├── oaPin (physical pin shape attached to a terminal)
            │   └── oaShape (polygon, path, rect, label, etc.)
            └── oaTech (technology database, associated with a library)

Libraries

An oaLib represents a library — a directory on disk containing a set of related cells. Libraries come in two flavors:

Design libraries contain actual design content: schematics, layouts, netlists, abstracts. A PDK (Process Design Kit) ships as a collection of design libraries containing the standard cells, IO cells, and IP blocks available in that process.

Technology libraries contain the technology database (tech.oa) with all process-specific information — layers, purposes, design rules, via definitions. In practice, a technology library is typically associated with one or more design libraries through a library reference mechanism.

On disk, a library is a directory with a lib.defs-style registration mechanism. Virtuoso uses cds.lib to map library names to filesystem paths. The OA API uses oaLibDefList to read this mapping.

Cells and Cellviews

An oaCell is a named design unit within a library. It corresponds to a component: an inverter, a flip-flop, an SRAM block, an entire chip. The cell name is the identifier that other designs reference when they instantiate it.

An oaCellView is one representation (view) of a cell. A single cell will typically have multiple views:

View name (by convention) Content
layout Physical layout — shapes on layers
schematic Schematic diagram — symbols, wires
symbol Symbol representation for placing in schematics
netlist Structural netlist (SPICE, Verilog, etc.)
abstract Abstract LEF-style view for P&R tools — pins, blockages, no internal detail
verilog RTL or gate-level Verilog
config Configuration view for running simulations

The view type is separate from the view name. OA tracks both: the name (a string like "layout") and the type (an enum value like oacMaskLayout). Most tools key on the name by convention, but some operations require the correct type.

The actual content of a cellview lives in an oaBlock. For layout, the block contains all the shapes, instances, nets, and terminals. For netlists, it contains instances and connectivity.

Instances and Masters

An oaInst is an instantiation of one cellview inside another. The master is the cell/cellview being referenced; the instance is the placed copy within a containing design.

Instance placement (in layout) is defined by a transformation: a translation (X, Y) and optional rotation/mirroring. OA represents this as an oaTransform, which combines an oaPoint for the origin and an oaOrient enum for orientation (R0, R90, R180, R270, MX, MY, MXR90, MYR90).

Instances can be fixed (fully placed) or unplaced (logical, no physical location). Mixed-signal flows often have unplaced instances at the schematic level that acquire physical placement later in the flow.

Nets, Terms, and Pins

These three objects represent connectivity and deserve careful distinction:

oaNet is a logical wire — a named signal node. In a netlist view, nets connect instances together. In a layout view, nets can also exist to carry connectivity annotations to shapes.

oaTerm (terminal) is a port on a cellview — the interface point through which the design communicates with the outside world. Terminals have a name (VDD, GND, A, B, OUT…) and a direction (input, output, inout, supply, ground, etc.). Terminals exist at the cellview boundary.

oaPin is the physical manifestation of a terminal — a shape (or set of shapes) on a specific layer that physically realizes where the terminal can be connected. A terminal can have multiple pins (e.g., power rails that appear on multiple metal layers). Pins reference both their parent terminal and their parent net.

The relationship: a net has terminals connected to it, and each terminal has one or more pins that define where on the layout the signal is accessible.

Shapes

oaShape is the base class for all geometric objects in a layout. The concrete subclasses are:

Class Description
oaRect Rectangle defined by lower-left and upper-right corners
oaPolygon Arbitrary polygon defined by a point array
oaPath Centerline path with a width and optional end styles
oaPathSeg Single segment of a path
oaEllipse Ellipse
oaArc Arc
oaText Text label
oaAttrDisplay Attribute display (used in schematics)
oaDot A dot

Every shape lives on a specific layer-purpose pair (LPP).

Layers, Purposes, and LPPs

The technology database defines all layers in the process. Layers correspond to physical manufacturing masks: metal layers (M1, M2, …), via layers (VIA1, VIA2, …), diffusion, polysilicon, well layers, etc. Each layer has a name and a numeric layer number.

Purposes add a second dimension to layer classification. A purpose describes the role a shape serves on its layer. Common purposes:

Purpose name Meaning
drawing The primary geometry — what gets manufactured
pin Pin shapes defining connectivity access points
net Net name labels
text Non-electrical annotations
boundary Cell boundary definition
blockage Routing blockage
fill Metal fill
outline Physical outline

A layer-purpose pair (LPP) is the combination of layer + purpose that fully identifies the “layer” a shape lives on. An oaLayerHeader on drawing is the actual metal geometry. An oaLayerHeader on pin is the pin access shape. When you query shapes on a layer, you typically need to specify both layer and purpose.

In the API, layers and purposes are referenced by integer numbers (from the tech database) for performance, not by name. The technology database provides the name-to-number mapping via oaLayer::find() and oaPurpose::find().

Coordinate System and DBU

All coordinates in OpenAccess are integers in database units (DBU). The technology database defines the DBU-to-micron conversion ratio (typically 1000 or 2000 DBU per micron, meaning 1 DBU = 1 nm or 0.5 nm respectively). This is the userunit and DBUPerUU relationship stored in the tech database.

The important implications:

  • You never use floating-point coordinates in OA. Everything is integer DBU.
  • To place a shape at (0.5 µm, 1.0 µm) with 1000 DBU/µm, you use coordinates (500, 1000).
  • Grid snapping is enforced by convention, not by the database, but DRC will catch off-grid shapes.

Coordinates are represented as oaPoint(x, y) where x and y are oaCoord (a typedef for int). Bounding boxes are oaBox(lowerLeftX, lowerLeftY, upperRightX, upperRightY).

Physical vs. Logical Views

OpenAccess cleanly separates physical views (layout) from logical views (schematic, netlist). The distinction matters for scripting:

Physical views (oacMaskLayout type, typically named layout) contain shapes, instances with physical placement, routing, and pins as geometric objects. The coordinate system and layers are meaningful.

Logical views (oacSchematic, oacNetlist, oacVerilog) contain instances, nets, and terminals but no physical geometry. Instances may have symbolic positions for display but no manufacturing-meaningful placement.

Abstract views (oacAbstract) are an interesting middle ground: they contain the bounding box and pin shapes of a cell (enough for a P&R tool to route to), but not the internal layout detail. LEF files are essentially abstract views in a different format.


Getting Access to OpenAccess

SI2 Membership and Access

The OpenAccess source code is available through SI2 (Silicon Integration Initiative) at si2.org. Access is tiered:

SI2 member companies get full access to the source repository, development mailing lists, and technical support. SI2 membership requires an annual fee based on company revenue tier. The membership roster includes the major EDA companies, semiconductor manufacturers, foundries, and many mid-sized design houses. For a company doing serious IC design work, SI2 membership is standard.

Non-members can access a publicly released snapshot of the source via the SI2 website, subject to signing the OpenAccess License Agreement (OALA). The OALA is a royalty-free license that allows use in commercial and academic work but includes attribution requirements and restricts redistribution of the source in modified form. It is considerably more permissive than commercial EDA licenses.

Academic access is available through a separate academic program with reduced fees and the same OALA terms. Many university EDA research programs use OpenAccess as their database substrate.

The honest state of things in 2026: the publicly available source is several years behind the internal versions used in commercial tools. Cadence’s internal OA implementation in Virtuoso, and Synopsys’s in ICC2, are both more recent than what SI2 distributes. The public source is sufficient for learning, tool development, and building standalone utilities, but you will not be programming the exact same binary that Cadence ships.

License Agreement Reality

The OALA is not open source in the OSI sense. Key points:

  • Free to use in any product, commercial or academic.
  • Source redistribution requires attribution and SI2 notification.
  • You cannot sublicense the source under a different license.
  • Binary redistribution (shipping an OA-based tool) is allowed.

This licensing model is why OpenAccess is not packaged in Linux distributions and why you will not find it in package managers. Every consumer has to build from source or link against a pre-built binary from their EDA vendor.

Build Requirements

OpenAccess builds on Linux. In practice, Linux is the only supported platform — specifically RHEL/CentOS-family and derivatives. MacOS and Windows builds are not supported by SI2 and are not a practical option for production use.

The build requires specific tool versions that track the toolchain assumptions baked into the OA source. As of the oa22 reference release:

  • GCC: the supported version is older than current GCC. The codebase was developed and tested against GCC 4.x–6.x. Building with GCC 9+ requires pragmas to suppress deprecated-copy warnings and may require patching. If your distribution ships GCC 11+, you will need either a compatibility GCC installation or a patch set.
  • Tcl/Tk: version 8.4 or 8.5. OAScript was written against the Tcl 8.x C API. Tcl 8.6 works but has subtle differences; Tcl 9.x is not supported.
  • OpenSSL: required for certificate-based licensing features in some builds. Version 1.x; OpenSSL 3.x has API changes that require patching.
  • Doxygen: needed only for building the HTML API documentation from source.
  • GNU Make: the build system is pure Makefile, no CMake or autoconf.
  • Python 2.x: some build scripts use Python 2 syntax. Python 3-only environments need to adjust shebang lines.

The dependency on older toolchain versions is the single biggest practical challenge when building OA on a modern Linux system (RHEL 9, Ubuntu 22.04+). The recommended approach for a modern host is to use a Docker container or Podman container with RHEL 8 / CentOS Stream 8 and the appropriate GCC version from devtoolset.


Building OpenAccess from Source

Source Layout

After unpacking the OA source tarball, the top-level directory structure is:

oa/
├── src/          # C++ source for all OA libraries
│   ├── oa/       # Core database implementation
│   ├── oaBase/   # Base types and utilities
│   ├── oaDM/     # Design management (library/cell/cellview CRUD)
│   ├── oaCommon/ # Shared infrastructure
│   ├── oaTech/   # Technology database
│   └── oaScript/ # OAScript Tcl interpreter
├── include/      # Public C++ headers
│   └── oa/       # All oa*.h headers live here
├── lib/          # Output directory for compiled shared libraries
├── bin/          # Output directory for executables including oaScript
├── data/         # Tech database templates, built-in layer definitions
├── doc/          # Documentation source (Doxygen markup)
└── Makefile      # Top-level build entry point

Environment Variables

Before building, set the following environment variables:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# Root of the OA installation/build tree
export OA_HOME=/opt/oa22

# Compiler family. Options: linux_rhel40_gcc44x, linux_rhel50_gcc44x,
# linux_rhel60_gcc44x, etc. The string encodes both OS and GCC version.
# For a modern RHEL 8 build with devtoolset GCC 4.x compatibility:
export OA_COMPILER=linux_rhel60_gcc44x

# Toolkit selection. Options: 32bit, 64bit
export OA_TOOLKIT=64bit

# Tcl installation root (needed for OAScript)
export TCL_ROOT=/usr

# Optional: OpenSSL location if not in system default paths
export OPENSSL_ROOT=/usr

# Add OA libraries and binaries to search paths
export LD_LIBRARY_PATH=${OA_HOME}/lib/${OA_COMPILER}/${OA_TOOLKIT}:${LD_LIBRARY_PATH}
export PATH=${OA_HOME}/bin/${OA_COMPILER}/${OA_TOOLKIT}:${PATH}

The OA_COMPILER variable is critical. The build system uses it as a directory component for all output — compiled objects go into subdirectories keyed by this string, which allows multiple compiler/OS combinations to coexist in one source tree.

Build Steps

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
cd /path/to/oa

# Build everything: libraries + oaScript executable + utilities
make

# Build only the core libraries (faster for development iterations)
make oa

# Build oaScript specifically
make oaScript

# Build the HTML documentation (requires Doxygen)
make doc

# Install to OA_HOME
make install

A full build takes 15-30 minutes on a modern workstation. The output libraries are shared objects (libOA*.so) in lib/${OA_COMPILER}/${OA_TOOLKIT}/ and the oaScript binary in bin/${OA_COMPILER}/${OA_TOOLKIT}/.

Common Build Errors and Fixes

error: implicitly-declared ... is deprecated (GCC 9+)

The OA codebase has classes where copy constructors/assignment operators are implicitly deprecated under newer C++ standards. Fix by adding to the relevant Makefile fragment:

1
CXXFLAGS += -Wno-deprecated-copy

openssl/md5.h: No such file or directory

OpenSSL 3.x moved the legacy MD5 header. Install openssl-devel (or libssl-dev) for your distribution, or patch the include path:

1
2
# On RHEL/Rocky 9 with OpenSSL 3
dnf install openssl-devel compat-openssl11-devel

Or, in the source, find the #include <openssl/md5.h> references and add a compatibility shim.

Tcl header not found

1
2
3
export TCL_INCLUDE=/usr/include/tcl8.5
# or wherever your distribution installs Tcl headers
export TCL_LIB=/usr/lib64/libtcl8.5.so

undefined reference to link errors

The link order in the OA Makefiles assumes the GNU linker’s behavior for shared library resolution. If you get undefined reference errors at link time, ensure the OA_COMPILER string exactly matches a known configuration and that the .so files from a previous partial build are not stale. make clean && make from scratch resolves most linker issues.

Post-Build Verification

After a successful build, verify the OAScript binary exists and starts:

1
2
3
4
5
6
${OA_HOME}/bin/${OA_COMPILER}/${OA_TOOLKIT}/oaScript

# Expected output:
# oaScript version 22.x.x
# Copyright (c) 1996-200x Silicon Integration Initiative, Inc.
# %

The % prompt indicates a live OAScript session.


OAScript: The Tcl Shell for OpenAccess

What OAScript Is

OAScript is an interactive Tcl interpreter that has the entire OpenAccess C++ API exposed as Tcl commands. Every OA C++ class becomes a Tcl command prefix; every method becomes a subcommand. The C++ objects are wrapped as opaque Tcl handles — you manipulate them by passing the handles to the appropriate commands.

The wrapping is mechanical but complete: if the C++ API has oaLib::open(libName, mode), OAScript has oa::Lib open libName mode. If the C++ class has a getCell() method returning an iterator, the Tcl equivalent returns a list.

The oa Namespace

All OAScript commands live in the oa:: namespace. You reference them as oa::ClassName for constructors/static methods and pass object handles to commands for instance methods. The namespace approach avoids collision with standard Tcl commands and with any other Tcl packages you might load.

1
2
3
4
5
# Static/constructor-style call
set lib [oa::Lib open "myLib" oaLibOpenMode_read]

# Instance method on the returned handle
set cells [$lib getCells]

The handle returned by oa::Lib open is a Tcl value that represents the C++ oaLib* pointer. You cannot inspect it directly — it is opaque. You use it only as an argument to subsequent oa:: commands.

Starting OAScript

Standalone interactive session:

1
oaScript

This drops you into the % prompt. Standard Tcl constructs work normally: variables, lists, dicts, procs, if, for, foreach, while, puts, file I/O — all of standard Tcl is available alongside the oa:: commands.

Running a script file non-interactively:

1
oaScript -replay my_script.tcl

Sourcing a script from within an interactive session:

1
source /path/to/my_script.tcl

In Cadence Virtuoso’s CIW (Command Interpreter Window):

Virtuoso embeds OAScript semantics through its SKILL environment. You cannot run raw OAScript commands in the CIW — you use SKILL functions that internally call the OA C++ API. However, you can load OAScript-style Tcl inside Virtuoso using the Virtuoso Tcl integration:

1
2
# In CIW, load a Tcl file via Virtuoso's Tcl bridge
hiSetBindKey "Layout" "<Ctrl>t" "load(\"/path/to/script.tcl\")"

For batch automation outside Virtuoso, the standalone oaScript binary is the right tool. For automation inside Virtuoso, SKILL (or the hiXxx API) is more natural, though the underlying objects are the same OA objects.

Loading OA Plugin Libraries

OAScript needs to know about any plugin libraries (translators, PDK-specific functionality) you want to use. The oaLibDefList mechanism handles library discovery:

1
2
# Load the library definition list (analogous to cds.lib)
oa::LibDefList openLibs "/path/to/lib.defs"

For standalone work, you create a minimal lib.defs file:

DEFINE myDesignLib /path/to/myDesignLib
DEFINE myTechLib   /path/to/myTechLib

OAScript API Reference and Usage Patterns

Session and Library Management

The session is a singleton — you do not create it; it exists as soon as oaScript starts. Library operations are the entry point to everything:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Open an existing library for reading
set lib [oa::Lib open "myLib" oaLibOpenMode_read]

# Open an existing library for read/write
set lib [oa::Lib open "myLib" oaLibOpenMode_readWrite]

# Create a new library
# Arguments: libName, libPath, techLibName (or "" for no tech), DMSystem
set lib [oa::Lib create "newLib" "/disk/newLib" "myTechLib" "oaDMFileSys"]

# Check if a library exists
if {[oa::Lib exists "myLib"]} {
    puts "Library found"
}

# Get a list of all open libraries
set libList [oa::Lib getLibs]
foreach lib $libList {
    puts "Library: [$lib getName]"
}

# Close a library
$lib close

Iterating Over Cells and Cellviews

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Open the library
set lib [oa::Lib open "myDesignLib" oaLibOpenMode_read]

# Get all cells in the library
set cellIter [$lib getCells]
foreach cell $cellIter {
    set cellName [$cell getName]
    puts "Cell: $cellName"

    # Get all cellviews for this cell
    set cvIter [$cell getCellViews]
    foreach cv $cvIter {
        set viewName [$cv getName]
        puts "  Cellview: $viewName"
    }
}

The iterators in OAScript are returned as Tcl lists you can iterate with foreach. In the C++ API, these are oaIter<> objects; in Tcl, they are already materialized as lists.

Opening a Cellview

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# Open a specific cellview for reading
# Arguments: libName, cellName, viewName, mode
set cv [oa::DesignOpen "myLib" "inv_x1" "layout" oaViewOpenMode_read]

# Or navigate via the hierarchy:
set lib  [oa::Lib open "myLib" oaLibOpenMode_read]
set cell [oa::Cell find $lib "inv_x1"]
set cv   [oa::CellView find $cell "layout"]
set des  [oa::Design open $cv oaViewOpenMode_read]

# Get the top-level block
set block [$des getTopBlock]

# Get the bounding box of the design
set bbox [$block getBBox]
puts "Bounding box: [$bbox lowerLeft] to [$bbox upperRight]"

# Save and close
$des save
$des close

Note: oa::DesignOpen is the convenience entry point; it takes library/cell/view strings directly. It is equivalent to the longer navigate-and-open sequence. Both are common in practice.

Accessing Instances

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
set cv  [oa::DesignOpen "topChip" "core" "layout" oaViewOpenMode_read]
set blk [$cv getTopBlock]

# Iterate over all instances
set instIter [$blk getInsts]
foreach inst $instIter {
    set instName  [$inst getName]
    set masterLib [$inst getMasterLibName]
    set masterCell [$inst getMasterCellName]
    set masterView [$inst getMasterViewName]

    # Get placement transformation
    set xform  [$inst getTransform]
    set origin [$xform getOffset]
    set orient [$xform getOrient]

    puts "Instance: $instName -> $masterLib/$masterCell/$masterView"
    puts "  Origin: ([$origin x], [$origin y])  Orient: $orient"
}

$cv close

Iterating Over Shapes in a Layout

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
set cv  [oa::DesignOpen "myLib" "metal_test" "layout" oaViewOpenMode_read]
set blk [$cv getTopBlock]

# Get the technology database for layer name lookups
set tech [$cv getTech]

# Iterate over all shapes
set shapeIter [$blk getShapes]
foreach shape $shapeIter {
    set className [$shape getClassName]

    # Get layer and purpose numbers
    set layerNum   [$shape getLayerNum]
    set purposeNum [$shape getPurposeNum]

    # Convert numbers back to names via the tech DB
    set layer   [oa::Layer find $tech $layerNum]
    set purpose [oa::Purpose find $tech $purposeNum]
    set layName   [$layer getName]
    set purpName  [$purpose getName]

    puts "Shape: $className on $layName/$purpName"

    # For rectangles, get the bounding box
    if {$className eq "oaRect"} {
        set bbox [$shape getBBox]
        puts "  BBox: ([$bbox lowerLeft x], [$bbox lowerLeft y]) - \
               ([$bbox upperRight x], [$bbox upperRight y])"
    }

    # For paths, get the centerline points and width
    if {$className eq "oaPath"} {
        set width  [$shape getWidth]
        set points [$shape getPoints]
        puts "  Width: $width  Points: $points"
    }
}

$cv close

Creating Layout Programmatically

This example creates a new cellview with a rectangle, a path, and an instance:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Open libraries
oa::LibDefList openLibs "/my/project/lib.defs"

# Open tech library first — required for any layout creation
set techLib  [oa::Lib open "myTechLib" oaLibOpenMode_read]
set tech     [$techLib getTech]

# Look up layer and purpose numbers from names
set m1Layer  [oa::Layer find $tech "M1"]
set m1Num    [$m1Layer getNumber]

set drawPurp [oa::Purpose find $tech "drawing"]
set drawNum  [$drawPurp getNumber]

set pinPurp  [oa::Purpose find $tech "pin"]
set pinNum   [$pinPurp getNumber]

# DBU per micron for coordinate math
set dbuPerUU [$tech getDBUPerUU]

# Open (or create) the target design library
set desLib [oa::Lib open "myDesignLib" oaLibOpenMode_readWrite]

# Create a new cellview (layout)
set cv [oa::DesignOpen "myDesignLib" "test_cell" "layout" oaViewOpenMode_readWrite]
set blk [$cv getTopBlock]

# Shorthand: 1 micron in DBU
proc um {x} {
    global dbuPerUU
    return [expr {int($x * $dbuPerUU)}]
}

# Create a rectangle: M1/drawing, BBox = (0,0) to (2µm, 1µm)
set rect [oa::Rect create $blk $m1Num $drawNum \
    [oa::Box create [um 0] [um 0] [um 2] [um 1]]]
puts "Created rect: $rect"

# Create a path: M1/drawing, width = 0.2µm, points along X axis
set pathPoints [list \
    [oa::Point create [um 0]   [um 0.5]] \
    [oa::Point create [um 5]   [um 0.5]] \
    [oa::Point create [um 5]   [um 3.0]]]

set path [oa::Path create $blk $m1Num $drawNum [um 0.2] $pathPoints \
    oaPathStyle_truncate oaPathStyle_truncate]
puts "Created path: $path"

# Place an instance of an existing cell
# oaTransform: origin point, orientation
set xform   [oa::Transform create [oa::Point create [um 10] [um 0]] oaOrient_R0]
set inst    [oa::ScalarInst create $blk \
    "myTechLib" "nand2_x1" "layout" \
    "U1" $xform oaPlacementStatus_placed]
puts "Created instance: $inst"

# Set a bounding box on the block (required for many tools)
$blk setBBox [oa::Box create [um -0.5] [um -0.5] [um 20] [um 5]]

# Save and close
$cv save
$cv close
puts "Layout created successfully"

Working with Nets and Connectivity

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
set cv  [oa::DesignOpen "myLib" "alu_core" "schematic" oaViewOpenMode_read]
set blk [$cv getTopBlock]

# Iterate over all nets
set netIter [$blk getNets]
foreach net $netIter {
    set netName [$net getName]
    set netType [$net getSigType]   ;# signal, power, ground, clock, etc.
    puts "Net: $netName (type: $netType)"

    # Get all instTerms connected to this net
    # instTerms are the connection points where an instance terminal meets a net
    set itIter [$net getInstTerms]
    foreach it $itIter {
        set instName [$it getInst getName]
        set termName [$it getTerm getName]
        puts "  -> $instName / $termName"
    }
}

# Find a specific net by name
set clkNet [oa::Net find $blk "clk"]
if {$clkNet ne ""} {
    puts "Found clock net: [$clkNet getName]"
    set fanout [llength [$clkNet getInstTerms]]
    puts "Clock fanout: $fanout"
}

$cv close

Technology Database Access

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
set lib  [oa::Lib open "myTechLib" oaLibOpenMode_read]
set tech [$lib getTech]

# List all layers
set layerIter [oa::Layer getLayersInTech $tech]
foreach layer $layerIter {
    set name   [$layer getName]
    set number [$layer getNumber]
    set type   [$layer getType]   ;# routing, masterslice, well, implant, cut...
    puts "Layer: $name  Number: $number  Type: $type"
}

# List all purposes
set purposeIter [oa::Purpose getPurposesInTech $tech]
foreach purp $purposeIter {
    puts "Purpose: [$purp getName]  Number: [$purp getNumber]"
}

# Access design rules
# Via definitions
set viaIter [oa::Via getViasInTech $tech]
foreach via $viaIter {
    puts "Via: [$via getName]  Layer1: [$via getLayer1Name]  Layer2: [$via getLayer2Name]"
}

# Spacing rules for a layer (example — exact API varies by rule type)
set m1Layer [oa::Layer find $tech "M1"]
set m1Num   [$m1Layer getNumber]
set rules   [oa::Constraint getConstraints $tech $m1Num]
foreach rule $rules {
    puts "Constraint: [$rule getConstraintType] = [$rule getValue]"
}

$lib close

Saving and Closing

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Save a design (writes changes to disk)
$cv save

# Save to a different location (save-as)
$cv saveAs "newLib" "new_cell" "layout"

# Close without saving (discard changes)
$cv close

# Purge (close and remove from memory — for large batch scripts)
$cv purge

# Close all open libraries at the end of a batch script
foreach lib [oa::Lib getLibs] {
    $lib close
}

Common Scripting Patterns for Design Automation

Batch Script Template

A well-structured OAScript batch script follows this pattern:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/env oaScript
# batch_example.tcl — list all cells in a library
# Usage: oaScript -replay batch_example.tcl

# Error handling: exit on any uncaught error
proc errorHandler {msg} {
    puts stderr "ERROR: $msg"
    exit 1
}

# Load library definitions
if {[catch {oa::LibDefList openLibs $env(OA_LIB_DEFS)} err]} {
    errorHandler "Failed to open lib.defs: $err"
}

# Process arguments (passed via environment variables or hardcoded for batch)
set libName   $env(OA_LIB_NAME)
set viewName  "layout"

# Open library
if {[catch {set lib [oa::Lib open $libName oaLibOpenMode_read]} err]} {
    errorHandler "Cannot open library $libName: $err"
}

# Process all cells
set cellIter [$lib getCells]
foreach cell $cellIter {
    set cellName [$cell getName]

    # Check for the desired view
    set cv [oa::CellView find [oa::Cell find $lib $cellName] $viewName]
    if {$cv eq ""} {
        puts "SKIP $cellName — no $viewName view"
        continue
    }

    # Open and process
    set des [oa::Design open $cv oaViewOpenMode_read]
    set blk [$des getTopBlock]

    set instCount  [llength [$blk getInsts]]
    set shapeCount [llength [$blk getShapes]]
    puts "CELL $cellName: $instCount instances, $shapeCount shapes"

    $des close
}

$lib close
puts "Done."

Running as Part of a Makefile Flow

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Makefile excerpt for OA-based design automation

OA_HOME    ?= /opt/oa22
OA_COMPILER ?= linux_rhel60_gcc44x
OA_TOOLKIT  ?= 64bit
OASCRIPT    := $(OA_HOME)/bin/$(OA_COMPILER)/$(OA_TOOLKIT)/oaScript

export LD_LIBRARY_PATH := $(OA_HOME)/lib/$(OA_COMPILER)/$(OA_TOOLKIT):$(LD_LIBRARY_PATH)
export OA_LIB_DEFS     := $(PWD)/lib.defs
export OA_LIB_NAME     := myDesignLib

.PHONY: check_layout extract_nets

check_layout:
    $(OASCRIPT) -replay scripts/check_layout.tcl | tee reports/layout_check.log

extract_nets:
    $(OASCRIPT) -replay scripts/extract_nets.tcl | tee reports/nets.rpt

Hierarchical Traversal

A common pattern is hierarchical traversal — processing not just a top-level design but all cells it instantiates:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
proc processHierarchy {libName cellName viewName visited} {
    # Avoid processing the same cell twice
    set key "${libName}/${cellName}/${viewName}"
    if {[dict exists $visited $key]} {
        return $visited
    }
    dict set visited $key 1

    set lib [oa::Lib open $libName oaLibOpenMode_read]
    set cv  [oa::DesignOpen $libName $cellName $viewName oaViewOpenMode_read]

    if {$cv eq ""} {
        puts "Cannot open $key — skipping"
        return $visited
    }

    set blk [$cv getTopBlock]

    # Process this level
    puts "Processing: $key"
    puts "  Shapes: [llength [$blk getShapes]]"
    puts "  Insts:  [llength [$blk getInsts]]"

    # Recurse into sub-instances
    foreach inst [$blk getInsts] {
        set subLib  [$inst getMasterLibName]
        set subCell [$inst getMasterCellName]
        set subView [$inst getMasterViewName]

        # Only recurse into non-primitive cells
        if {![isPrimitive $subLib $subCell]} {
            set visited [processHierarchy $subLib $subCell $subView $visited]
        }
    }

    $cv close
    return $visited
}

# Kick off from top level
set visited [dict create]
set visited [processHierarchy "chipLib" "topLevel" "layout" $visited]
puts "Total unique cells processed: [dict size $visited]"

Integration with EDA Flows

Inside Cadence Virtuoso

Within Virtuoso, you do not run oaScript directly — you use the SKILL programming environment. SKILL is a Lisp dialect that exposes the same OA object model through a different syntax and naming convention. The underlying objects are the same OA C++ objects.

However, Virtuoso does expose a Tcl bridge. You can call Tcl/OAScript code from within Virtuoso using the built-in Tcl interpreter:

1
2
3
4
5
6
; SKILL code in Virtuoso CIW
; Load and run a Tcl script via Virtuoso's Tcl integration
(hiLoadFile "/path/to/script.tcl")

; Or run a Tcl expression inline
(evalTcl "oa::Lib open myLib oaLibOpenMode_read")

The typical integration pattern for teams using both SKILL and standalone OAScript:

  • Interactive, session-based design editing: SKILL or the Virtuoso GUI
  • Batch processing, reporting, cross-tool data exchange: standalone oaScript scripts called from a Makefile or LSF/Slurm job

Running Standalone Batch Jobs

For batch automation, the full invocation pattern in a cluster environment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/bash
# run_oa_job.sh

source /opt/oa22/setup.sh   # Sets OA_HOME, OA_COMPILER, LD_LIBRARY_PATH, PATH

# Pass parameters via environment
export OA_LIB_DEFS=/proj/chip/lib.defs
export OA_LIB_NAME=myBlock
export OA_CELL_NAME=alu_core
export OA_VIEW_NAME=layout

# Run the script
oaScript -replay /proj/scripts/check_drc_annotations.tcl \
    2>&1 | tee /proj/logs/alu_core_check_$(date +%Y%m%d_%H%M%S).log

exit $?

Submit to a cluster:

1
2
bsub -J oa_check -q eda -n 1 -R "rusage[mem=4096]" \
    /proj/scripts/run_oa_job.sh

Scripting Cadence OCEAN with OA Backends

OCEAN (Open Command Environment for Analysis) is Cadence’s simulation scripting language, sitting on top of SKILL/OA. OA data flows through OCEAN scripts transparently. If you are writing OCEAN scripts and need to access the OA database directly, you can drop into the OA layer:

1
2
3
4
5
6
7
; OCEAN script: access OA data directly
let( (lib cell cv blk)
    lib  = oa_LibOpen("myLib" oaLibOpenMode_read)
    cell = oa_CellFind(lib "myCell")
    cv   = oa_CellViewFind(cell "schematic")
    ; ... OA operations through SKILL/OA bridge
)

The oa_ prefix functions in SKILL map directly to OA C++ calls.


Comparison to Alternatives

SKILL vs. OAScript

SKILL (Simulation Knowledge Interpretation Language) is Cadence’s proprietary Lisp-based scripting language embedded in Virtuoso. It is not the same as OAScript, though both can manipulate OA data.

Aspect SKILL OAScript
Language base Lisp (with unique Cadence extensions) Tcl (standard)
Availability Cadence Virtuoso only Standalone, any OA-capable tool
Object names dbOpenCellViewByType, geCreateRect oa::DesignOpen, oa::Rect create
Documentation Cadence SKILL Language Reference (CDNS subscription) SI2 OA API docs (SI2 member access)
Community Large — decades of SKILL scripts in industry Smaller but exists
Portability None (Cadence only) Any OA implementation
Interactive Yes (CIW in Virtuoso) Yes (oaScript prompt)
Maturity Very mature Mature (development slowed)

For work that only ever runs inside Virtuoso, SKILL is more natural — the function names map more directly to Virtuoso UI concepts, the documentation is more complete, and there are more code examples. For cross-tool automation, batch processing outside Virtuoso, or writing tools that need to run on multiple EDA platforms, OAScript is the portable choice.

A common real-world pattern: use SKILL for interactive Virtuoso automation and use OAScript for batch flows that run on farm machines without a Virtuoso license.

Python and OA

There is no official Python binding for OpenAccess in the SI2 distribution. Unofficial Python wrappers exist in some academic and internal tool distributions, typically implemented as SWIG-generated wrappers around the C++ API, but these are not part of any standard release.

KLayout (the widely used open-source/commercial layout viewer and editor) has a Python API (klayout.db) that can read and write GDSII, OASIS, DXF, and has partial OA reading capability. KLayout’s OA support is more complete in the commercial edition and reads OA data by embedding the OA C++ library. You can drive KLayout’s OA-aware operations from Python through the KLayout Python API, but you are going through KLayout’s abstraction, not talking to OA directly.

For Python-native IC design database access, the OpenROAD project’s OpenDB (now maintained as part of OpenROAD and accessible via its Python bindings) is the most actively developed open option, though OpenDB targets the P&R domain rather than the full OA scope.

OA vs. GDSII/OASIS

GDSII (Graphic Design System II, now officially called DFII) and OASIS (Open Artwork System Interchange Standard) are streaming formats — they represent a flat or hierarchical snapshot of physical layout at tape-out time. They are not databases you work in; they are interchange formats you export from and import to.

OpenAccess GDSII / OASIS
Primary use Working database during design Tape-out stream, tool exchange
Format Directory of binary .oa files Single binary stream file
Incremental edit Yes No (stream in/stream out)
Schematic/netlist Yes No (layout only)
Technology data Yes (in tech.oa) Partial (layer map only)
Hierarchy First-class (instances reference cells) Cell references in the stream
Design rules Yes No
Version control Via library management Whole-file versioning
Open standard Yes (SI2) Yes (Semiconductor Equipment and Materials International)

In practice, GDSII or OASIS is what you hand to a foundry or a mask shop. OA is what you work in during design. A final step in the tape-out flow converts OA to GDS/OASIS for delivery.

OA vs. LEF/DEF

LEF (Library Exchange Format) and DEF (Design Exchange Format) are ASCII text formats used by place-and-route tools.

  • LEF encodes the technology (layers, vias, grid rules) and cell abstracts (bounding boxes, pin shapes, obstruction geometry). It is approximately equivalent to the technology database + abstract views in OA.
  • DEF encodes a placed-and-routed design: the netlist, the placed component locations, the routing geometry. It is approximately equivalent to a placed OA layout cellview.

The P&R flow from a tool like Synopsys DC + Synopsys ICC2 or Cadence Innovus traditionally used LEF/DEF for tool interoperability. Modern flows (especially ICC2 working with Virtuoso) increasingly use OA natively, with LEF/DEF available as an interchange format for tools that do not support OA directly.

OA vs. OpenDB

OpenDB is the database used by OpenROAD, the open-source RTL-to-GDSII flow. It was originally developed at Silicon Intelligence and is now maintained by the OpenROAD project. OpenDB has Python bindings and is actively developed.

OpenAccess OpenDB
Governance SI2 (industry consortium) OpenROAD project (UCB ORFS)
Language bindings C++, Tcl (OAScript) C++, Python, Tcl
Scope Full IC design (layout, schematic, netlist) P&R focused (netlist, placement, routing)
Schematic support Yes No
Technology DB Full OA tech Simplified (from LEF)
Activity level (2026) Maintenance mode Actively developed
License OALA (SI2) BSD-3
Availability SI2 member portal GitHub (The-OpenROAD-Project/OpenROAD)

If you are working in open-source EDA flows with OpenROAD, OpenDB + Python is the practical choice. If you are working in a commercial EDA environment with Virtuoso or ICC2, OpenAccess is the standard you are working against.


Common Pitfalls and Gotchas

Database Locking

OpenAccess uses file-system-level locking for write access. When you open a cellview with oaViewOpenMode_readWrite, OA creates a lock file in the library directory. If your script crashes or exits uncleanly, the lock file may be left behind, preventing any other tool from opening that cellview for writing.

Lock files are named <cellName>.<viewName>.oa.lck and live alongside the .oa data files. They contain the hostname and PID of the locking process. If the lock is genuinely stale (the process is dead), you can delete the .lck file manually. Never delete a lock file for a process that might still be running — you will corrupt the database.

In scripts, always close cellviews in a catch/cleanup block:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if {[catch {
    set cv [oa::DesignOpen "myLib" "myCell" "layout" oaViewOpenMode_readWrite]
    # ... operations ...
    $cv save
} err]} {
    puts stderr "Error: $err"
} finally {
    # Always close, even on error
    if {[info exists cv] && $cv ne ""} {
        catch { $cv close }
    }
}

Tcl’s finally clause is available in Tcl 8.6+. For older Tcl, use nested catch blocks.

The Transaction Model

OpenAccess has a transaction model for write operations, but it is not exposed through OAScript in the way database transactions are. In the C++ API, you call oaDesign::beginAccess() and oaDesign::endAccess() around write operations. In OAScript, this is implicit — opening a design in read-write mode begins a transaction, and saving commits it.

The implication: partial writes are possible if your script crashes between shape creation and $cv save. There is no rollback mechanism in OAScript. Design the script so that all modifications are in-memory until a single $cv save at the end.

Reference Counting and Memory

In the C++ API, many OA objects are reference counted and can be explicitly destroyed. In OAScript, object lifetimes are managed by the Tcl interpreter’s garbage collection, but this does not map cleanly to OA’s own reference counting. In long-running scripts that process thousands of cellviews, you can accumulate memory from OA objects that Tcl has not yet GC’d.

Mitigation: explicitly close designs when you are done with them ($cv close or $cv purge). The purge variant is stronger — it removes the design from OA’s internal cache, freeing more memory. For batch scripts processing hundreds of designs in a loop, close and purge after each iteration.

1
2
3
4
5
foreach cellName $cellList {
    set cv [oa::DesignOpen $libName $cellName "layout" oaViewOpenMode_read]
    # ... process ...
    $cv purge    ;# stronger than close for memory management
}

Platform Compatibility

OpenAccess .oa files include a version marker. A database written by a newer OA version may not be readable by an older OA version. In practice:

  • Files written by Virtuoso (using Cadence’s internal OA implementation) are generally readable by the SI2 reference implementation at the same major API revision.
  • Files written with Virtuoso 22.x features may use OA schema extensions not in the public oa22 source.
  • Mixing OA versions in a multi-tool flow (e.g., Virtuoso 22.x writes, standalone oa22.04 reads) requires testing. Minor version differences are usually fine; major OA API version differences can cause read errors.

The version of the .oa files can be inspected with the oaDesign::getRevision() call or by looking at the binary header of the file (not recommended directly).

OAScript vs. the OA API Inside a Commercial Tool

When you write OAScript code and run it with the standalone oaScript binary, you are using the SI2 reference implementation of OA. When Cadence Virtuoso or Synopsys ICC2 opens the same OA database, it is using that tool’s internal OA implementation (which is based on the same standard but may have internal optimizations, extensions, and different performance characteristics).

The observable differences:

  • Performance: Commercial tool implementations are typically faster for large databases.
  • Extensions: Cadence has OA schema extensions used by Virtuoso for schematic-specific metadata that are not in the public OA specification. Reading these extended attributes from standalone oaScript returns default/empty values.
  • Licensing metadata: Some tools embed license-check objects in OA databases (for IP protection). The reference implementation reads these as generic properties.
  • Error handling: Error messages and error codes differ between the reference implementation and commercial implementations.

The API — class names, method signatures, behavior for standard operations — is the same. If your oaScript code correctly opens a library, reads instances, and prints net names, it will produce the same results as equivalent C++ code in a commercial tool against the same database.

Documentation Gaps

Be aware that documentation availability varies significantly by what you are trying to do:

Well-documented (SI2 public docs):

  • The C++ class reference (accessible after SI2 registration)
  • OAScript command syntax (mirrors the C++ API 1:1)
  • The OA schema: what objects exist and what they contain

Sparsely documented or tool-specific:

  • Technology database constraint APIs (spacing rules, antenna rules) — the public docs cover the framework but not every constraint type
  • Cadence Virtuoso-specific OA extensions (pcell parameterized cells, the cellview config view, connectivity rules used by Spectre)
  • The exact format of .oa binary files on disk (not publicly documented; OA is API-access only)
  • OA event/callback infrastructure (used by tools for incremental update)

Not in public docs — requires working code:

  • PCell (parameterized cell) evaluation. PCells are OA cellviews with embedded code that generates geometry on-the-fly. The public OA API has a PCell framework, but actual PCell compilation is handled by Cadence’s Virtuoso with SKILL callbacks. Understanding how PCells work requires Virtuoso documentation (Cadence support portal).
  • The DM (Design Management) plugin system used to integrate OA with version control systems like DesignSync.

A Note on Current State (2026)

The SI2 OpenAccess reference implementation has been in maintenance mode for several years. Active development has shifted to commercial tool vendors’ internal forks and to newer open-source alternatives like OpenDB.

For learning OA and writing portable design automation tools, the reference implementation and OAScript are still the right starting point — the standard is stable, the object model is well understood, and any knowledge you build transfers directly to working with Virtuoso’s OA layer through SKILL or to commercial OA C++ plugin development.

For greenfield open-source EDA tool development in 2026, evaluate OpenROAD/OpenDB alongside the OA reference — OpenDB has active development, good Python bindings, and permissive licensing. If your flow is entirely within the Cadence ecosystem, invest in SKILL proficiency alongside OAScript; both operate on the same underlying objects.

The EDA database landscape is one of the most balkanized areas in engineering tooling. OpenAccess remains the most successful attempt at a true open standard for IC design data — imperfect, showing its age, but widely deployed and worth understanding deeply.


Quick Reference

Key Environment Variables

1
2
3
4
OA_HOME          # Root of OA installation
OA_COMPILER      # Platform/compiler string (e.g., linux_rhel60_gcc44x)
OA_TOOLKIT       # 32bit or 64bit
LD_LIBRARY_PATH  # Must include ${OA_HOME}/lib/${OA_COMPILER}/${OA_TOOLKIT}

Common OAScript Commands

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Library operations
oa::Lib open $name $mode
oa::Lib create $name $path $techLib $dmSystem
oa::Lib exists $name
oa::Lib getLibs

# Design operations
oa::DesignOpen $lib $cell $view $mode
oa::Design open $cv $mode
$cv save
$cv close
$cv purge

# Block access
$cv getTopBlock
$blk getInsts
$blk getNets
$blk getShapes
$blk getTerms

# Instance access
$inst getName
$inst getMasterLibName / getMasterCellName / getMasterViewName
$inst getTransform

# Technology access
$lib getTech
oa::Layer find $tech $nameOrNumber
oa::Purpose find $tech $nameOrNumber
$layer getNumber / getName

# Shapes
$shape getLayerNum / getPurposeNum / getClassName
$rect getBBox
$path getWidth / getPoints
oa::Rect create $blk $layNum $purpNum $bbox
oa::Path create $blk $layNum $purpNum $width $points $startStyle $endStyle
oa::ScalarInst create $blk $lib $cell $view $name $xform $status

Open Mode Constants

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
oaLibOpenMode_read
oaLibOpenMode_readWrite
oaViewOpenMode_read
oaViewOpenMode_readWrite
oaPlacementStatus_placed
oaPlacementStatus_unplaced
oaOrient_R0    # No rotation
oaOrient_R90   # 90 degrees counterclockwise
oaOrient_R180  # 180 degrees
oaOrient_R270  # 270 degrees counterclockwise
oaOrient_MX    # Mirror about X axis
oaOrient_MY    # Mirror about Y axis

Comments