How to Write a Pcell Evaluator Plug-in

OpenAccess supports parameterized cells (Pcells). Pcells are oaDesigns, which have content that is dynamically created based on a set of parameters. An application can provide different versions of Pcells by implementing a specialized Pcell evaluator; in this way, OpenAccess has the ability to support multiple Pcell evaluators at runtime. These evaluators can be statically bound to an application, but it is recommended that they be implemented as a plug-in. Some Pcell evaluators, such as the OpenAccess C++ Pcell evaluator, call functions written by a user in C++ in order to generate a database for a particular Pcell instance. Other possibilities are Pcell evaluators that can invoke engines such as Tcl or Skill to execute scripts stored in Pcell masters in order to generate the appropriate OpenAccess structures.

This document explains how to write a PCell evaluator plug-in. Additional information on writing a plug-in is available in the companion document How to Write a Plug-In.

Defining Pcells in OpenAccess

OpenAccess uses superMasters and subMasters to define and manage Pcells. A superMaster is an oaDesign that contains the information necessary to generate different variations of itself based on a set of parameters. A superMaster is created through the oaDesign::defineSuperMaster() API, where the Pcell evaluator and the set of parameters with default values are specified. An application can create an instance by specifying a superMaster as the master and additionally provide a set of parameters with values usually different from the superMaster defaults.

OpenAccess creates a subMaster as the master for this instance by using the Pcell evaluator specified in the superMaster and by using the parameters specified in the instances. A Pcell evaluator is typically implemented to create the subMasters on the fly in virtual memory. In this case, the application can access the subMaster as a regular oaDesign, except that it cannot be saved to disk persistently.

Alternatively, an application can save subMasters to a file using the PcellFile::append function. The subMasters can be read later by a Pcell evaluator.

Creating a Pcell Evaluator Plug-in

You can create a Pcell evaluator plug-in by creating a shared library that can be loaded by OpenAccess at runtime. The shared library must do the following:

After the shared library is created, you must write a plug-in registration file to register your plug-in.

Creating a Plug-in Factory and Implementing the Entry Point Function

OpenAccess provides the templated class oaCommon::Factory<T> for defining a factory object for a plug-in. The factory object is used to create instances of a plug-in. Each plug-in has a classID, which is put into a factory table. When OpenAccess needs to create an instance of a plug-in, it uses the classID to find the factory for the plug-in. For more information about creating a plug-in factory, see the Understanding the Plug-in Factory section of the companion document on writing a plug-in.

You must also implement the getClassObject entry point function. When called, this function returns a pointer to the plug-in factory. For more information about implementing the getClassObject entry point function, see the Implementing the Entry Point Function section of the companion document on writing a plug-in.

The plug-in registration file registers the plug-in shared library. When the plug-in shared library is installed, the registration file can be installed in $(OA_HOME)/data/plugins. Alternatively, the OA_PLUGIN_PATH environment variable can be used to reference a .plg file outside of $(OA_HOME)/data/plugins. Refer to Writing the Plug-In Registration File in How to Write a Plug-In for more information.

To create a Pcell evaluator plug-in, you must define a new class inherited from the IPcell class. This class implements the interfaces necessary to build and maintain Pcells in an OpenAccess database. The new class must implement all virtual functions of the IPcell class. Refer to the API documentation for IPcell for a detailed description about these virtual functions. OpenAccess uses the oaPcellLink class to form a runtime link to the application provided Pcell evaluator. There can only be one link per Pcell evaluator. In a statically linked Pcell evaluator, an application creates an instance of the evaluator class object and calls oaPcellLink::create() with the instance as the argument. An oaPcellLink is automatically created when a Pcell evaluator is requested by name using oaPcellLink::find() or oaPcellLink::getPcellDef(). The standard OpenAccess plug-in loading and class creation mechanism is used by oaPcellLink to get an instance of the Pcell evaluator class. A description of some of the IPcell virtual functions provides insight into how they interact:

Creating the Plug-in

A plug-in is a shared library that is installed in the OpenAccess installation hierarchy in the data/plugins directory, or in another location specified by the OA_PLUGIN_PATH environment variable. Applications load the plug-in at runtime to select a customized implementation. The following procedure describes the steps for creating an example plug-in. For additional guidance on writing a Pcell evaluator plug-in, see the code example in the $(OA_HOME)/examples/oa/PCells/opnPcell directory.

To Create a Plug-in Pcell Evaluator Named myPcell

  1. Create a factory for the myPcell plug-in, and construct a static member of myPcell. Use:
     
        oaCommon::Factory<myPcell>	myFactory;
    
        oaCommon::Factory<myPcell>	myPcell::myFactory("myPcell");
    
  2. Define the entry point function getClassObject(). Use:
        extern "C" long getClassObject(const char *classID,
                                       const Guid &interfaceID,
                                       void **ptr);
    
  3. Implement the entry point function as:
        long
        getClassObject(const char *classID,
                       const Guid &interfaceID,
                       void **ptr)
        {
            return FactoryBase::getClassObject(classId, interfaceID, ptr);
        }
    
  4. Define a new class inherited from IPcell, and implement the required functions. For example:
        class myPcell : public PlugInBase<IPcell> {
          public:
            virtual oaPcellDef	      *getPcellDef();
            virtual void		getName(oaString &name) {name = "myPcell";}
    
            virtual void		onBind(oaDesign	*design,
                                            oaPcellDef *pcellDef) {}
            virtual void		onUnbind(oaDesign *design,
                                              oaPcellDef	*pcellDef);
            virtual void		onEval(oaDesign	*design,
                                             oaPcellDef	*pcellDef);
            virtual void		onRead(oaDesign	    *design,
                                            oaMapFileWindow  &mapWindow,
                                            oaUInt4	    &loc,
                                            oaPcellDef	    *def) {}
            virtual void		onWrite(oaDesign	    *design,
                                             oaMapFileWindow &mapWindow,
                                             oaUInt4	    &loc,
                                             oaPcellDef	    *def) {}
    
            virtual oaUInt4		calcDiskSize(oaPcellDef *pcellDef) const;
    
          private:
            static Factory<myPcell>  factory;
        };
  5. Optionally implement an ICompatibility::validate function to verify whether or not the version of OpenAccess is compatible with the plug-in. The validate() function should check the OpenAccess API version and either throw an exception with a description of the requirements or simply return false. REVIEWERS: Need to describe how an app might check if an interface has an ICompatibility component and if so, how to use it.
    virtual bool                validate()
  6. Write the plug-in registration file myPcell.plg. Use:
        <?xml version="1.0" encoding="utf-8" ?>
        <plugIn lib="myAppPcell"/>
      
    Note: The registration file can be installed in $(OA_HOME)/data/plugins when the plug-in shared library is installed. Alternatively, the OA_PLUGIN_PATH environment variable can be used to reference a .plg file outside of $(OA_HOME)/data/plugins. Refer to Writing the Plug-In Registration File in How to Write a Plug-In for more information.

Once the evaluator plug-in is done, an application must be written to create the corresponding Pcell superMasters. You can refer to the PCells.cpp code in $(OA_HOME)/examples/oa/PCells for an example of how you might write an application to create Pcells. The following steps include portions of the PCells.cpp code:

  1. Get the plug-in's PcellDef by calling oaPcellLink::getPcellDef(pluginname). For example:
        oaPcellDef	*def = oaPcellLink::getPcellDef("myPcell");
    
  2. Define an oaDesign. For example:
        oaDesignInit();
        oaLibDefList::openLibs();
    
  3. Define the array of parameters to be associated with this pCell, along with their default values. For example:
        oaParam p1;
            p1.setName("width");
            p1.setDoubleVal(3.0);
    
        oaParam p2;
            p2.setName("length");
            p2.setDoubleVal(1.0);
    
        oaParamArray    paramArray(2);
            paramArray.append(p1);
            paramArray.append(p2);
    
  4. Make the design a superMaster by calling oaDesign::defineSuperMaster(pcelldef, paramarray). For example:
        oaScalarName    viewName(ns, "layout");
        oaScalarName    sCellName(ns, "pcell_master");
        oaViewType      *viewType = oaViewType::get(oacMaskLayout);
        oaDesign        *superMaster = oaDesign::open(libName, sCellName,
                                                      viewName, viewType, 'w');
    
        superMaster->defineSuperMaster(def, paramArray);
    
  5. Save the design.

After these steps are completed, when the application needs to create an instance of a Pcell, it simply uses the following call:

    Scalarinst = oaScalarInst::create(ptrParentBlock, ptrSuperMaster, xform, paramarray);

Where ptrSuperMaster is a pointer to the oaDesign, which is the superMaster for the Pcell, and the paramArray is the array of the non-default parameters for the instance. An application that is only going to traverse the hierarchy only needs to call getMaster() on the instance, which returns the oaDesign that is the subMaster for that instance. The application can traverse the data on that oaDesign without taking into consideration that it is a Pcell that was generated on the fly.

Storing and Retrieving subMasters

An application can store multiple Pcell subMasters to a cache file using the PcellFile interface. An application first uses the PcellFile constructor to get a handle to a cache file. The application must call PcellFile::open before appending subMasters to the cache file. The append function returns an offset that indicates the location in the file for that particular subMaster. PcellFile::close() should be called to release the resources associated with the cache file before calling the destructor on the handle.

An application that writes Pcell subMasters to a file is responsible for:

A different application can read a particular cached subMaster from a file. In order to do this, the application needs:

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