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:
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.
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
|
For additional information about installing OpenAccess, see OpenAccess 2.2 Installation and Configuration Notes.
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.
|
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.
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.
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.
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 )
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 )
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 )
Applications that use the OpenAccess design database must include the oaDesign::open() function. This is demonstrated in the HelloWorld code.
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.
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:
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); };
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); };
In summary, to write an OpenAccess application, you should:
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.
Use the GNU make file to build the HelloWorld example.
<install_dir>/examples/oa/common
directory, run the GNU make utility. gmakeThis builds common functions used by all the examples.
gmake
.<install_dir>/examples/oa/HelloWorld
directory, run the GNU make utility.
HelloWorld
at the shell prompt to run the HelloWorld example and verify that it built correctly.
Use the following steps to build the HelloWorld example on Windows:
|
The HelloWorld program is created in the examples\oa\HelloWorld
directory. Open a command shell and type the executable name (HelloWorld) to run it.
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.
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 // // 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 // // 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 // // // **************************************************************************** // 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 Programmers Guide topics
Copyright © 2001-2010 Cadence Design Systems, Inc.
All rights reserved.