Getting Started—A HelloWorld Example


Introduction

This document explains the development environment required to write OpenAccess applications; how you check, configure, and prepare the environment; and the elements you must incorporate to write a simple OpenAccess application. Information is provided for all supported UNIX and Windows platforms. Environment, configuration, and build information, which is unique to the Windows platform, is distinguished from information for other platforms by enclosing the Windows information in a separate panel.

The HelloWorld example is used as a programming model. The listing included with this document is based on the HelloWorld code that is provided with the OpenAccess installation. If you build and run HelloWorld, it does the following:

HelloWorld is a basic example that incorporates several important concepts for writing an application that uses an OpenAccess database. The main topics of this document are:

Getting Started

Before you can begin developing an OpenAccess application, you must install the Developer version of OpenAccess. Install the source files, include files, documentation, and examples.

You need to build OpenAccess as well. The OpenAccess shared libraries are required in order to build the examples.

Refer to the OpenAccess 2.2 Installation and Configuration Notes for more information about installing and building OpenAccess.

Checking Your Installation

Before you start, make sure your OpenAccess installation is complete by verifying that your installation hierarchy contains the following:

The documentation describes the OpenAccess API and is supplied in HTML format. On UNIX platforms, the documentation is located in your OpenAccess installation tree at <install_dir>/doc/html. You can begin browsing the documentation by opening index.html in the documentation directory.

On UNIX, the OpenAccess shared libraries are located at

    <install_dir>/lib/<platform_name>

The <platform_name> depends on your computer and operating system. A sysname script is provided in the <install_dir>/bin directory. Running the sysname script returns the <platform_name> for your computer and operating system.

The optimized versions of the shared libraries are found at:

    <install_dir>/lib/<platform_name>/opt 

The debug versions of the shared libraries are found at:

    <install_dir>/lib/<platform_name>/dbg

The debug versions of the shared libraries perform additional checking that is not available in optimized libraries. For more information, see OpenAccess Overview.

The <install_dir>/bin/<platform_name> directory contains the translator executables and utility scripts such as sysname. The opt subdirectory contains the optimized versions of the executables, and the dbg subdirectory contains the debug versions.

OpenAccess provides another script called oaGetLibPath that returns the path to the shared libraries for LD_LIBRARY_PATH, SHLIB_PATH, or LIB_PATH depending on which platform you use. Your application can use this script to set the library path for the OpenAccess libraries.

The script in available in <install_dir>/bin. The script has an optional mode, -numBits, that lets you override the bit mode specified by any environment variables.

If you install OpenAccess to the default location on Windows
  • Documentation is located at
    C:\Program Files\OpenAccess\doc\html
    You can open the documentation by choosing Start > Programs > OpenAccess > Documentation.
  • Libraries are located at
    C:\Program Files\OpenAccess\lib\win32\opt
    C:\Program Files\OpenAccess\lib\win32\dbg
  • Translator executables are located at
    C:\Program Files\OpenAccess\bin\opt
    C:\Program Files\OpenAccess\bin\dbg

For additional information about installing OpenAccess, see OpenAccess 2.2 Installation and Configuration Notes.

Preparing Your Development Environment

Your development environment must include a C++ compiler, and on UNIX, must also include the GNU make utility. A make file is provided at:

    <install_dir>/examples/oa

This file is named Makefile and builds all of the example applications including HelloWorld. A separate make file is provided in the HelloWorld directory and in each of the other example directories. All the example make files use the macro.defs file in the <install_dir>/examples/oa directory to determine several compiler and build configuration settings.

If you have a different version of the make utility installed in addition to the GNU version, you can rename the GNU version to gmake to avoid invoking the wrong make utility. For information about the required version of the GNU make utility, and for a list of the supported compilers for using the precompiled OpenAccess libraries, see the Configuration Information section of the Installation and Configuration Notes.

The example make files are intentionally simple and are provided to demonstrate the shared library and compiler options needed to build an application. These make files can provide a template for creating make files for your own applications.

Preparing your development environment on Windows
OpenAccess development on Windows requires the Microsoft Visual Studio .NET 2003 development environment.

Each example directory includes Visual Studio solution and project files to simplify building the examples. However, you cannot build an example by loading the solution from the example directory. Instead, you must load examples.sln from the <install_dir>\examples\oa directory and choose the example you want to build in the Visual Studio solution explorer.

If you use the OpenAccess default installation directory, the examples.sln solution file is located at:
    C:\Program Files\OpenAccess\examples\oa

Writing OpenAccess Applications

OpenAccess classes and functions are defined in header files that should be declared in your source files before you refer to the classes or functions. The OpenAccess header files are organized according to the types of databases an application might use, so you typically need only include one of the following header files:

Each of these header files includes all additional headers that are required, thereby explicitly managing the dependencies between those headers. You should not include any of the lower-level headers directly in your code.

oaDesignDB.h is the main header file that is required to create and interact with an OpenAccess design database. oaDesignDB.h includes oaBase.h, oaDM.h, and oaTechDB.h. oaDesignDB.h is used in the HelloWorld example.

oaTechDB.h is the main header file for the OpenAccess technology database. It includes oaBase.h and oaDM.h. If your application only accesses a technology database, include the oaTechDB.h header file.

oaWaferDB.h is the main header file for the OpenAccess wafer database. It includes oaBase.h, oaDM.h, oaTechDB.h, and oaDesignDB.h. If your application accesses wafer databases, include the oaWaferDB.h header file.

oaDM.h is the main header file for the oaDM library. It includes oaBase.h. If your application only uses routines to access design and reference libraries, and does not access the OpenAccess databases in those libraries, include the oaDM.h header file.

oaBase.h is the main header file for the oaBase library.

Initialization Calls

There are several initialization calls that applications can use to communicate with OpenAccess databases. The initialization routines automatically call any required lower-level routines. Each initialization routine can be called multiple times, but initialization is performed the first time only. Usually an application needs only one of the initialization calls described in the sections that follow.

Important: The initialization functions depend on static initializations and therefore cannot be called during static initialization.

oaDesign Initialization

The oaDesignInit function initializes the oaDesign package. This function is defined in oaDesignDB.h. It depends on the oaDM, oaTech, and oaBase packages, and therefore, it also initializes these.

The revision numbers compiled into an application’s initialization call will be compared to the revision numbers built into the OpenAccess runtime libraries when the call is made to check for compatibility. For more, refer to Compatibility for OpenAccess Applications and Data in the Programmers Guide.

The following oaDesignInit function prototype is provided for reference.

    void oaDesignInit(oaUInt4 apiMajorRev,
                      oaUInt4 apiMinorRev,
                      oaUInt4  dataModelRev
                      )

Applications should set the apiMajorRev and apiMinorRev so that they pick up the version numbers of the current OpenAccess software. The dataModelRev should be explicitly supplied to indicate the supported version of the OpenAccess information model. The following example shows an init function picking up the current OpenAccess major and minor version numbers and specifying a dataModelRev of 3.

oaDesignInit(oacAPIMajorRevNumber, oacAPIMinorRevNumber, 3);

Data model 3 is the first OpenAccess version to include the incremental technology database feature, which allows applications to incrementally assemble technology information by creating references from one oaTech database to other oaTech databases (known as creating a graph of technology databases). In order to support data model 3, the HelloWorld example must handle technology database object conflicts that might occur.

To learn more about using the dataModelRev argument to indicate the level of support that an application provides, refer to Compatibility for OpenAccess Applications and Data. Also, refer to the Features by Data Model for details about the features that are included in each dataModelRev.

Refer to the oaDesignInit implementation in the HelloWorld listing to see how this function is used.

oaTech Initialization

The oaTechInit function initializes the oaTech package. This function is defined in oaTechDB.h. It also initializes the oaBase package on which it depends. If your application only accesses the technology database, use the oaTechInit initialization call.

    void oaTechInit(oaUInt4  apiMajorRev,
                    oaUInt4  apiMinorRev,
                    oaUInt4  dataModelRev
                    )

oaDM Initialization

The oaDMInit function initializes the oaDM package. This function is defined in oaDM.h. It also calls oaBaseInit to initialize the oaBase package on which it depends. If your application only uses routines to access design and reference libraries, and does not access the OpenAccess databases in those libraries, use the oaDMInit initialization call.

    void oaDMInit(oaUInt4  apiMajorRev,
                  oaUInt4  apiMinorRev,
                  oaUInt4  dataModelRev
                  )

oaWafer Initialization

The oaWaferInit function initializes the oaWafer package. This function is defined in oaWaferDB.h. It also initializes the other OpenAccess packages that it depends on by calling oaDesignInit. oaDesignInit initializes the oaDM, oaTech, and oaBase packages. If your application accesses wafer databases, use the oaWaferInit initialization call.

    void oaWaferInit(oaUInt4  apiMajorRev,
                  oaUInt4  apiMinorRev,
                  oaUInt4  dataModelRev
                  )

Using oaDesign::open()

Applications that use the OpenAccess design database must include the oaDesign::open() function. This is demonstrated in the HelloWorld code.

Error Handling

In OpenAccess, there are no error code returns. All errors generate exceptions. It is good programming practice to add exception handling routines around all of the database calls. You can provide additional granularity by adding exception handlers deeper within the calling hierarchy.

In addition, it is useful to include code to catch any data compatibility errors.

Example

Try{ 			// Wrap a Try statement around code that performs database access calls.
….
    } catch (oaCompatibilityError &ex) {   // Capture information about data not compatible 
        handleFBCError(ex);                // with the current version of OpenAccess.
        exit(1);

    } catch (oaException    &excp) {                 // Capture exceptions thrown to the top level of your code,
        cout << "ERROR: " << excp.getMsg() << endl;  // and print any error messages.
        exit(1);
    }

}

Note: It is more efficient to catch an oaException by reference.

Applications can use the subclasses of oaException to catch exceptions specific to a particular database or level of severity.

Observer Notifications

Some error situations must communicate more information to the application than can be conveyed in an exception message. OpenAccess provides observer notifications for these situations. There are a number of observer classes that can be inherited by application code.

The HelloWorld example demonstrates two important observers:

oaObserver<oaTech>

Among other things, this observer provides notifications about conflicts in incremental technology databases. Conflicts occur when a technology database is edited outside the scope of a set of technology databases. For more information about the types of conflicts that can occur, refer to Conflicts in Incremental Technology Databases in the Programmers Guide.

An application can overload the onConflict virtual function to receive notification when there conflicting technology objects. In addition, the application can overload the following virtual functions to receive notification when there are conflicting user-specified  values for technology attributes:

An observer notification can be triggered when

If conflicts are detected, end users must resolve them. A technology hierarchy should not be used if conflicts are present.

The HelloWorld example includes the implementation of an oaTech conflict observer. Based on the error type, the list of conflicting objects or libraries is printed.

class opnTechConflictObserver : public oaObserver<oaTech> {
public:
                            opnTechConflictObserver(oaUInt4  priorityIn);

    virtual void            onConflict(oaTech                  *mostDerivedTech,
                                       oaTechConflictTypeEnum  conflictType,
                                       oaObjectArray           conflictingObjs);

    virtual void            onClearanceMeasureConflict(oaTechArray cTechs);

    virtual void            onDefaultManufacturingGridConflict(oaTechArray cTechs);

    virtual void            onGateGroundedConflict(oaTechArray cTechs);
	
    virtual void            onDBUPerUUConflict(oaTechArray  cTechs, 
                                               oaViewType   *viewType);

    virtual void            onUserUnitsConflict(oaTechArray cTechs, 
                                                oaViewType  *viewType);
												 
    virtual void            onProcessFamilyConflict(const oaTechArray &cTechs);

    virtual void            onExcludedLayerConflict(oaTech  *mostDerivedTech,
                                                    const oaPhysicalLayer *l1,
                                                    const oaLayer         *l2);

};

oaObserver<oaLibDefList>

This observer provides notifications about events related to library definition files (lib.defs). The onLoadWarnings( ) notification provides a message and error type if problems occur when reading a lib.defs file.

The notifications are triggered by oaLibDefList::openLibs(). Applications must derive an oaLibDefList observer in order to detect issues with library definitions files, such as missing, unreadable, or incorrectly formatted lib.defs files. The HelloWorld example includes an implementation of an oaLibDefList observer.

class opnLibDefListObserver : public oaObserver {
public:
                            opnLibDefListObserver(oaUInt4   priorityIn, 
                                                  oaBoolean enabledIn = true);

    oaBoolean               onLoadWarnings(oaLibDefList                 *obj,
                                           const oaString               &msg,
                                           oaLibDefListWarningTypeEnum  type);
};

Summary

In summary, to write an OpenAccess application, you should:

Building the HelloWorld Example

Now that OpenAccess is installed and your development environment is configured correctly, you are ready to build the HelloWorld example.

To run HelloWorld, or any OpenAccess application, you must ensure that the application can find the shared libraries with which it is linked. The directory and installation hierarchy where the libraries are located must be in your shared library path. Dependent on your platform, the shared library path is usually defined by the LD_LIBRARY_PATH, SHLIB_PATH, or LIBPATH environment variable.

Building HelloWorld on UNIX

Use the GNU make file to build the HelloWorld example.

  1. From the <install_dir>/examples/oa/common directory, run the GNU make utility.

    For example, enter:
        gmake
    This builds common functions used by all the examples.

    Note
    This step assumes you renamed your GNU make utility to gmake.

  2. From the <install_dir>/examples/oa/HelloWorld directory, run the GNU make utility.

  3. Enter HelloWorld at the shell prompt to run the HelloWorld example and verify that it built correctly.

  4. If the HelloWorld build fails, refer to Troubleshooting to determine the possible causes.

Building HelloWorld on Windows

Use the following steps to build the HelloWorld example on Windows:
  1. Start Visual Studio and open the examples.sln (for Visual Studio .NET 2003) or or examples_vc8.sln (for Visual Studio 2005) solution file from <install_dir>\examples\oa.
  2. In the Solution Explorer window, right-click HelloWorld and choose Project Only > Build Only HelloWorld. The HelloWorld executable is built in the <install_dir>\examples\oa\optDLL or <install_dir>\examples\oa\HelloWorld directory.
  3. If the HelloWorld build fails, refer to Troubleshooting to determine the possible causes.

Running the Example

The HelloWorld program is created in the examples\oa\HelloWorld directory. Open a command shell and type the executable name (HelloWorld) to run it.

Troubleshooting

If you use Makefile in the HelloWorld directory, and the example fails to build, the possible reasons are:

If HelloWorld fails to build, you might need to edit Makefile in the HelloWorld directory or the macro.defs file in the <install_dir>/examples/oa directory. The variables in macro.defs that might require revision are:

For optimized builds, or for builds that do not require debugging into the OpenAccess code, use the optimized shared libraries. For builds that require debugging into the shared libraries in order to find bugs in your application code, use the debug version of the shared libraries. Always use one of these versions of the shared libraries for developing OpenAccess applications.


HelloWorld Code Files

The HelloWorld example uses observers that are used by other examples shipped with OpenAccess. These observers are stored in a common folder with other code that is shared by the various examples.

The code for the HelloWorld example is in the following files.

Content
Files
HelloWorld example <install_dir>/examples/oa/HelloWorld/HelloWorld.cpp
Conflict Observer <install_dir>/examples/oa/common/commonTechObserver.cpp
oaLibDef Observer <install_dir>/examples/oa/common/commonLibDefListObserver.cpp
openLibrary and handleFBCError functions <install_dir>/examples/oa/common/commonFunctions.cpp

HelloWorld.cpp

// *****************************************************************************
// HelloWorld.cpp
//
// The following tasks are performed by this program
//  1. Derive an oaTech observer to handle conflicts in the technology hierarchy
//  2. Derive an oaLibDefsList observer to handle warnings related to lib.defs
//  3. Open the design
//  4. Print the library name
//  5. Print the cell name
//  6. Print the view name
//  7. Create nets with the names "Hello" and "World"
//  8. Save these nets
//  9. Run the net iterator and print the existing nets in the design
//
// ****************************************************************************
// Except as specified in the OpenAccess terms of use of Cadence or Silicon
// Integration Initiative, this material may not be copied, modified,
// re-published, uploaded, executed, or distributed in any way, in any medium,
// in whole or in part, without prior written permission from Cadence.
//
//                Copyright 2002-2005 Cadence Design Systems, Inc.
//                           All Rights Reserved.
//
// To distribute any derivative work based upon this file you must first contact
// Si2 @ contracts@si2.org.
//
// *****************************************************************************
// *****************************************************************************

#include <iostream>
#include "oaDesignDB.h"

#include "../common/commonTechObserver.h"
#include "../common/commonLibDefListObserver.h"
#include "../common/commonFunctions.h"


using namespace oa;
using namespace std;

static oaNativeNS   ns;




// ****************************************************************************
// printDesignNames()
//
// This function gets the library, cell and view names associated with the open
// design and prints them.
// ****************************************************************************
void
printDesignNames(oaDesign   *design)
{
    oaString        libName;
    oaString        cellName;
    oaString        viewName;

    // Library, cell and view names are obtained.
    design->getLibName(ns, libName);
    design->getCellName(ns, cellName);
    design->getViewName(ns, viewName);

    // Library, cell and view names are printed.
    cout << "\tThe library name for this design is : " << libName << endl;
    cout << "\tThe cell name for this design is : " << cellName << endl;
    cout << "\tThe view name for this design is : " << viewName << endl;
}



// ****************************************************************************
//  void printNets()
//  
//  This function invokes the net iterator for the design and prints the names
//  of the nets one by one.
// ****************************************************************************
void
printNets(oaDesign  *design)
{
    // Get the TopBlock of the current design
    oaBlock *block = design->getTopBlock();

    if (block) {
        oaString        netName;

        cout << "The following nets exist in this design." << endl;

        // Iterate over all nets in the design
        oaIter<oaNet>   netIterator(block->getNets());
        while (oaNet *net = netIterator.getNext()) {
            net->getName(ns, netName);
            cout << "\t" << netName << endl;
        }
    } else {
        cout << "There is no block in this design" << endl;
    }
}






// ****************************************************************************
// main()
//
// This is the top level function that opens the design, prints library, cell,
// and view names, creates nets, and iterates the design to print the net 
// names.
// ****************************************************************************
int
main(int    argc,
     char   *argv[])
{
    try {
        // Initialize OA with data model 3, since incremental technology
        // databases are supported by this application.
        oaDesignInit(oacAPIMajorRevNumber, oacAPIMinorRevNumber, 3);

        oaString        libPath("./DesignLib"); 
        oaString        library("DesignLib");
        oaString        cell("And");
        oaString        view("view");

        oaScalarName    libName(ns, library);
        oaScalarName    cellName(ns, cell);
        oaScalarName    viewName(ns, view);

        // Setup an instance of the oaTech conflict observer.
        opnTechConflictObserver myTechConflictObserver(1);

        // Setup an instance of the oaLibDefList observer.
        opnLibDefListObserver myLibDefListObserver(1);

        // Read in the lib.defs file.
        oaLibDefList::openLibs();

        // Try to get a pointer to the library. If it does not exist yet,
        // it will be created and added to the lib.defs file.
        oaLib  *lib = openLibrary(libName, libPath);

        // Create the design with the specified viewType,
        // Opening it for a 'write' operation.
        cout << "The design is created and opened in 'write' mode." << endl;

        oaViewType  *vt  = oaViewType::get(oacSchematic);
        oaDesign *design = oaDesign::open(libName, cellName, viewName, vt, 'w');

        // The library, cell, and view names are printed.
        printDesignNames(design);

        // Create the TopBlock for this design.
        oaBlock *block = oaBlock::create(design);

        // The nets "Hello" and "World are created.
        oaString        net1("Hello");
        oaString        net2("World");
        oaScalarName    hNet(ns, net1);
        oaScalarName    wNet(ns, net2);

        oaScalarNet     *helloNet = oaScalarNet::create(block, hNet);
        oaScalarNet     *worldNet = oaScalarNet::create(block, wNet);

        // The design is saved.
        design->save();

        // The nets in this design are printed.
        printNets(design);

        // The design is closed.   
        design->close();

        // The library is closed.   
        lib->close();

    } catch (oaCompatibilityError &ex) {
        handleFBCError(ex);
        exit(1);

    } catch (oaException    &excp) {
        cout << "ERROR: " << excp.getMsg() << endl;
        exit(1);
    }

    return 0;
}
 

commonTechObserver.cpp

// *****************************************************************************
// commonTechObserver.cpp
//
// This file contains the implementation of an oaTech observer for technology
// conflict notifications.
//
// This code is used in all examples to alert the users of technology conflicts.
//
// ****************************************************************************
// Except as specified in the OpenAccess terms of use of Cadence or Silicon
// Integration Initiative, this material may not be copied, modified,
// re-published, uploaded, executed, or distributed in any way, in any medium,
// in whole or in part, without prior written permission from Cadence.
//
//                Copyright 2002-2005 Cadence Design Systems, Inc.
//                           All Rights Reserved.
//
// To distribute any derivative work based upon this file you must first contact
// Si2 @ contracts@si2.org.
//
// *****************************************************************************
// *****************************************************************************


#include "commonTechObserver.h"



// *****************************************************************************
// Global Instantiation
// *****************************************************************************
oaString    opnTechConflictObserver::format
                   ("ERROR: A %s conflict has been detected in the technology "
                    "hierarchy. It is caused by the following list of %s: %s");

oaNativeNS  opnTechConflictObserver::ns;



// *****************************************************************************
// opnTechConflictObserver::opnTechConflictObserver()
//
// This is the default constructor for the opnTechConflictObserver class.
// *****************************************************************************
opnTechConflictObserver::opnTechConflictObserver(oaUInt4 priorityIn)
:   oaObserver<oaTech>(priorityIn)
{
}



// *****************************************************************************
// opnTechConflictObserver::onConflict()
//
// This is the observer function definition for tech conflict. It handles
// conflicts by calling oaIncTechConflictTest::handleConflicts().
// *****************************************************************************
void
opnTechConflictObserver::onConflict(oaTech                  *mostDerivedTech,
                                    oaTechConflictTypeEnum  conflictType,
                                    oaObjectArray           conflictingObjs)
{
    oaString            str;
    oaString            type;
    oaString            elements;
    oaString            list;    
    oaLayer             *layer;
    oaDerivedLayer      *derivedLay;
    oaPurpose           *purpose;
    oaSiteDef           *siteDef;
    oaViaDef            *viaDef;
    oaViaSpec           *viaSpec;
    oaAnalysisLib       *analysisLib;
    oaConstraint        *constraint;
    oaConstraintGroup   *constraintGroup;

    for (oaUInt4 i = 0; i < conflictingObjs.getNumElements(); i++) {
        oaObject    *obj = conflictingObjs[i];

        switch (conflictType) {
        case oacLayerNameTechConflictType:
        case oacLayerNumTechConflictType:
            layer = (oaLayer*) obj;
            list += (getObjectLibName(obj, str), str) + "/";
            list += (layer->getName(str), str);
            list += (str.format(" (#%d); ", layer->getNumber()), str);
            break;

        case oacDerivedLayerTechConflictType:
            derivedLay = (oaDerivedLayer*) obj;
            list += (getObjectLibName(obj, str), str) + "/";
            list += (derivedLay->getName(str), str) + " (";
            
            if (layer = derivedLay->getLayer1()) {
                list += (layer->getName(str), str) + ", ";
            } else {
                list += (str.format("#%d, ", derivedLay->getLayer1Num()), str);
            }
            
            if (layer = derivedLay->getLayer2()) {
                list += (layer->getName(str), str) + "); ";
            } else {
                list += (str.format("#%d); ", derivedLay->getLayer2Num()), str);
            }

            break;

        case oacPurposeNameTechConflictType:
        case oacPurposeNumTechConflictType:
            purpose = (oaPurpose*) obj;
            list += (getObjectLibName(obj, str), str) + "/";
            list += (purpose->getName(str),str);
            list += (str.format(" (#%d); ", purpose->getNumber()), str);
            break;

        case oacSiteDefNameTechConflictType:
            siteDef = (oaSiteDef*) obj;
            list += (getObjectLibName(obj, str), str) + "/";
            list += (siteDef->getName(str), str) + "; ";
            break;

        case oacViaDefNameTechConflictType:
            viaDef = (oaViaDef*) obj;
            list += (getObjectLibName(obj, str), str) + "/";
            list += (viaDef->getName(str), str) + "; ";
            break;

        case oacViaSpecTechConflictType:
            viaSpec = (oaViaSpec*) obj;
            list += (getObjectLibName(obj, str), str) + "/(";

            if (layer = viaSpec->getLayer1()) {
                list += (layer->getName(str), str) + ", ";
            } else {
                list += (str.format("#%d, ", viaSpec->getLayer1Num()), str);
            }

            if (layer = viaSpec->getLayer2()) {
                list += (layer->getName(str), str) + "); ";
            } else {
                list += (str.format("#%d); ", viaSpec->getLayer2Num()), str);
            }

            break;

        case oacAnalysisLibNameTechConflictType:
            analysisLib = (oaAnalysisLib*) obj;
            list += (getObjectLibName(obj, str), str) + "/";
            list += (analysisLib->getName(str), str) + "; ";
            break;

        case oacConstraintNameTechConflictType:
            constraint = (oaConstraint*) obj;
            list += (getObjectLibName(obj, str), str) + "/";
            list += (constraint->getName(str), str) + "; ";
            break;

        case oacConstraintGroupNameTechConflictType:
            constraintGroup = (oaConstraintGroup*) obj;
            list += (getObjectLibName(obj, str), str) + "/";
            list += (constraintGroup->getName(str), str) + "; ";
            break;

        default:
            break;
        }
    }

    switch (conflictType) {
    case oacLayerNameTechConflictType:
        type = "Layer Name"; 
        elements = "layers";
        break;

    case oacLayerNumTechConflictType:
        type = "Layer Number"; 
        elements = "layers";
        break;

    case oacDerivedLayerTechConflictType:
        type = "Derived Layer"; 
        elements = "derived layers";
        break;

    case oacPurposeNameTechConflictType:
        type = "Layer Purpose Name"; 
        elements = "purposes";
        break;

    case oacPurposeNumTechConflictType:
        type = "Layer Purpose Number"; 
        elements = "purposes";
        break;

    case oacSiteDefNameTechConflictType:
        type = "Site Definition"; 
        elements = "sites";
        break;
    
    case oacViaDefNameTechConflictType:
        type = "Via Def Name"; 
        elements = "via definitions";
        break;

    case oacViaSpecTechConflictType:
        type = "Via Spec"; 
        elements = "via specifications";
        break;

    case oacAnalysisLibNameTechConflictType:
        type = "Analysis Library Name"; 
        elements = "analysis libraries";
        break;

    case oacConstraintNameTechConflictType:
        type = "Constraint Name"; 
        elements = "constraints";
        break;

    case oacConstraintGroupNameTechConflictType:
        type = "Constraint Group Name"; 
        elements = "constraint groups";
        break;

    default:
        type = "Unknown"; 
        elements = "Unknown";
        break;
    }

    printErrorMsg(type, elements, list);
}



// *****************************************************************************
// opnTechConflictObserver::onClearanceMeasureConflict()
//
// This function handles clearance measure conflict between tech libs.
// *****************************************************************************
void    
opnTechConflictObserver::onClearanceMeasureConflict(oaTechArray cTechs)
{
    oaString list;
    oaString str;

    oaUInt4 i;
    for (i = 0; i<cTechs.getNumElements(); i++) {        
        list += (getObjectLibName(cTechs[i], str), str) + " (";
        list += cTechs[i]->getClearanceMeasure(true).getName() + "); ";  
    }

    printErrorMsg("Clearance Measure", "Libraries", list);
}



// *****************************************************************************
// opnTechConflictObserver::onDefaultManufacturingGridConflict()
//
// This function handles manufacturing grid conflicts.
// *****************************************************************************
void    
opnTechConflictObserver::onDefaultManufacturingGridConflict(oaTechArray cTechs)
{
    oaString list;
    oaString str;    

    oaUInt4 i;
    for (i = 0; i<cTechs.getNumElements(); i++) {
        list += (getObjectLibName(cTechs[i], str), str) + " (";
        str.format("%d); ", cTechs[i]->getDefaultManufacturingGrid(true));
        list += str;
    }

    printErrorMsg("Default Manufacturing Grid", "Libraries", list);
}



// *****************************************************************************
// opnTechConflictObserver::onGateGroundedConflict()
//
// This function handles conflicts between tech libs related to gate grounding.
// *****************************************************************************
void    
opnTechConflictObserver::onGateGroundedConflict(oaTechArray cTechs)
{
    oaString list;
    oaString str;    

    oaUInt4 i;
    for (i = 0; i<cTechs.getNumElements(); i++) {
        list += (getObjectLibName(cTechs[i], str), str) + " (";

        if (cTechs[i]->isGateGrounded(true)) {
            list += "grounded); ";
        } else {
            list += "not grounded); ";
        }
    }

    printErrorMsg("Gate Grounded", "Libraries", list);
}



// *****************************************************************************
// opnTechConflictObserver::onDBUPerUUConflict()
//
// This function handles conflicts between tech libs related to DBU per UU.
// *****************************************************************************
void
opnTechConflictObserver::onDBUPerUUConflict(oaTechArray cTechs, 
                                            oaViewType  *viewType)
{
    oaString list;
    oaString viewTypeName;
    oaString str;    

    oaUInt4 i;
    for (i = 0; i<cTechs.getNumElements(); i++) {
        list += (getObjectLibName(cTechs[i], str), str) + " (";
        str.format("%d); ", cTechs[i]->getDBUPerUU(viewType, true));
        list += str;
    }

    viewType->getName(viewTypeName);
    printErrorMsg("DBU per UU ("+viewTypeName+")", "Libraries", list);
}



// *****************************************************************************
// opnTechConflictObserver::onUserUnitsConflict()
//
// This function handles conflicts between tech libs related to user units.
// *****************************************************************************
void
opnTechConflictObserver::onUserUnitsConflict(oaTechArray cTechs, 
                                             oaViewType  *viewType)
{
    oaString list;
    oaString viewTypeName;
    oaString str;

    oaUInt4 i;
    for (i = 0; i<cTechs.getNumElements(); i++) {
        list += (getObjectLibName(cTechs[i], str), str) + " (";
        list += cTechs[i]->getUserUnits(viewType, true).getName() + "); ";  
    }

    viewType->getName(viewTypeName);
    printErrorMsg("User Units ("+viewTypeName+")", "Libraries", list);
}



// *****************************************************************************
// opnTechConflictObserver::onProcessFamilyConflict()
//
// This function handles conflicting process family attributes.
// *****************************************************************************
void
opnTechConflictObserver::onProcessFamilyConflict(const oaTechArray &cTechs)
{
    oaString list;
    oaString str;

    oaUInt4 i;
    for (i = 0; i<cTechs.getNumElements(); i++) {
        list += (getObjectLibName(cTechs[i], str), str) + " (";
        list += (cTechs[i]->getProcessFamily(str, true), str) + "); ";        
    }

    printErrorMsg("Process Family", "Libraries", list);
}



// *****************************************************************************
// opnTechConflictObserver::onExcludedLayerConflict()
//
// This function handles conflicting layer definitions.
// *****************************************************************************
void
opnTechConflictObserver::onExcludedLayerConflict(oaTech                  *tech,
                                                 const oaPhysicalLayer   *l1,
                                                 const oaLayer           *l2)
{
    oaString str;
    oaString list;
    
    list += (getObjectLibName(l1, str), str) + "/";
    list += (l1->getName(str), str) + " is mutually exclusive with ";
    list += (getObjectLibName(l2, str), str) + "/";
    list += (l2->getName(str), str) + "; ";

    printErrorMsg("Excluded Layer", "Layers", list);
}



// *****************************************************************************
// opnTechConflictObserver::getObjectLibName()
//
// This function returns the name of the library a certain object resides in.
// *****************************************************************************
void
opnTechConflictObserver::getObjectLibName(const oaObject *obj, 
                                          oaString       &str) const
{
    oaTech *tech;

    tech = (oaTech*) obj->getDatabase();
    
    // Return the name of the library that contains the techDB.
    // Alternatively, the full path to the library could be found as follows:
    //  tech->getLib()->getFullPath(str);
    //
    tech->getLibName(ns, str);
}



// *****************************************************************************
// opnTechConflictObserver::printErrorMsg()
//
// This function populates a format string for a tech conflict error message
// and prints it to stdout.
// *****************************************************************************
void
opnTechConflictObserver::printErrorMsg(const char    *type, 
                                       const char    *elements, 
                                       const char    *list) const
{
    oaString str;

    str.format(format, type, elements, list);
    cout << endl << str << endl;
}

commonLibDefListObserver.cpp

// *****************************************************************************
// commonLibDefListObserver.cpp
//
//
// ****************************************************************************
// Except as specified in the OpenAccess terms of use of Cadence or Silicon
// Integration Initiative, this material may not be copied, modified,
// re-published, uploaded, executed, or distributed in any way, in any medium,
// in whole or in part, without prior written permission from Cadence.
//
//                Copyright 2002-2005 Cadence Design Systems, Inc.
//                           All Rights Reserved.
//
// To distribute any derivative work based upon this file you must first contact
// Si2 @ contracts@si2.org.
//
// *****************************************************************************
// *****************************************************************************


#include "commonLibDefListObserver.h"



// *****************************************************************************
// opnLibDefListObserver::opnLibDefListObserver()
// 
// Constructor which passes the priority argument to its inherited constructor.
// *****************************************************************************
opnLibDefListObserver::opnLibDefListObserver(oaUInt4    priorityIn,
                                             oaBoolean  enabledIn)
:oaObserver<oaLibDefList>(priorityIn, enabledIn)
{
}



// *****************************************************************************
// opnLibDefListObserver::onLoadWarnings()
// 
// This overloaded member function of the opnLibDefListObserver class, prints
// out either a syntax error or any warning which are issued by the oaLibDefList
// object management.
// *****************************************************************************
oaBoolean
opnLibDefListObserver::onLoadWarnings(oaLibDefList                  *list,
                                      const oaString                &msg,
                                      oaLibDefListWarningTypeEnum   type)
{
    if (type == oacNoDefaultLibDefListWarning) {
        // No warning if there is no lib.defs file found
        return true;
    } else {
        oaString libDefPath;

	if (list) {
	  list->getPath(libDefPath);
	}

	cout << "ERROR: While loading the library definitions file ";
	cout << libDefPath;
	cout << ", OpenAccess generated the message:\n";
	cout << msg << endl;

	exit(1);
    }
    return true;
}



Return to top of page

Return to Programmers Guide topics

Copyright © 2001-2010 Cadence Design Systems, Inc.
All rights reserved.