diff --git a/crlcore/src/ccore/openaccess/OpenAccessCommon.h b/crlcore/src/ccore/openaccess/OpenAccessCommon.h index ef02d4b3..a4d03a65 100644 --- a/crlcore/src/ccore/openaccess/OpenAccessCommon.h +++ b/crlcore/src/ccore/openaccess/OpenAccessCommon.h @@ -1,5 +1,5 @@ // -*-compile-command:"cd ../../../../.. && make"-*- -// Time-stamp: "2010-07-26 16:09:36" - OpenAccessCommon.h +// Time-stamp: "2010-07-30 16:48:54" - OpenAccessCommon.h // x-----------------------------------------------------------------x // | This file is part of the hurricaneAMS Software. | // | Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved | @@ -28,14 +28,13 @@ using namespace oa; #define assert(cond) if (! (cond) ) throw Error("assertion failed : " + string( #cond ) ) //#define assert(cond) -namespace { +namespace { /** giving a oaDesign pointer that should be not NULL return the oaString representing its name */ inline oaString getDesignName(oaDesign* design) { - cerr << "getDesignName" << endl; assert(design); oaNativeNS ns; oaString libName, cellName, viewName; @@ -52,7 +51,6 @@ namespace { @todo remove when not needed anymore */ inline void printBlockTerms(oaBlock* block) { - cerr << "printBlockTerms" << endl; assert(block); oaNativeNS ns; oaDesign* design = block->getDesign(); @@ -71,7 +69,6 @@ namespace { @todo verify */ inline oaMaterial getOAMaterial(const BasicLayer::Material& material) { - cerr << "getOAMaterial" << endl; switch ( material.getCode() ) { case BasicLayer::Material::nWell: return oacNWellMaterial; case BasicLayer::Material::pWell: return oacPWellMaterial; @@ -81,7 +78,7 @@ namespace { case BasicLayer::Material::poly: return oacPolyMaterial; case BasicLayer::Material::cut: return oacCutMaterial; case BasicLayer::Material::metal: return oacMetalMaterial; - case BasicLayer::Material::blockage: + case BasicLayer::Material::blockage: //there is no blockage type but a specific oaLayerBlockage class return oacOtherMaterial; case BasicLayer::Material::other: return oacOtherMaterial; @@ -90,12 +87,36 @@ namespace { } } + /** + @todo complete,verify ... + */ + inline BasicLayer::Material::Code oaMaterialToBasicLayerType(const oaMaterial& material) { + switch(material) { + case oacNWellMaterial: + return BasicLayer::Material::nWell; + case oacPWellMaterial: + return BasicLayer::Material::pWell; + case oacNImplantMaterial: + return BasicLayer::Material::nImplant; + case oacPImplantMaterial: + return BasicLayer::Material::pImplant; + case oacPolyMaterial: + return BasicLayer::Material::poly; + case oacCutMaterial: + return BasicLayer::Material::cut; + case oacMetalMaterial: + case oacContactlessMetalMaterial: + return BasicLayer::Material::metal; + default: + return BasicLayer::Material::other; + } + } + /** Convertion helper for Net convertion ... @todo verify */ inline oaTermType getOATermType(const Net::Direction& direction) { - cerr << "getOATermType" << endl; switch (direction) { case Net::Direction::IN: return oacInputTermType; @@ -117,7 +138,6 @@ namespace { @todo verify */ inline oaSigType getOASigType(const Net::Type& type) { - cerr << "getOASigType" << endl; switch (type.getCode()) { case Net::Type::LOGICAL: return oacSignalSigType; @@ -136,9 +156,8 @@ namespace { /** Convertion helper ... - */ + */ inline oaOrient getOAOrientFromOrientation(const Transformation::Orientation& orientation) { - cerr << "getOAOrientFromOrientation" << endl; switch (orientation) { case Transformation::Orientation::ID: return oacR0; @@ -163,9 +182,8 @@ namespace { /** Convertion helper ... - */ + */ inline void getOATransformFromTransformation(oaTransform& transform, const Transformation& transformation) { - cerr << "getOATransformFromTransformation" << endl; transform.set(transformation.getTx(), transformation.getTy(), getOAOrientFromOrientation(transformation.getOrientation())); @@ -173,18 +191,17 @@ namespace { /** Convertion helper ... - */ + */ inline void getOABoxForBox(oaBox& box, const Box& hbox) { cerr << "getOABoxForBox" << endl; box.set(hbox.getXMin(), hbox.getYMin(), hbox.getXMax(), hbox.getYMax()); } /** - Create InstTerm representing connection of nets ... + Create InstTerm representing connection of nets between instance always return a non NULL value */ inline oaInstTerm* getInstTerm(oaInst* inst, Plug* plug,oaNet* net) { - cerr << "getInstTerm" << endl; assert(inst); assert(plug); oaNativeNS ns; @@ -225,7 +242,6 @@ namespace { print the oaLayera in a oaTech ... */ inline void printOALayers(oaTech* theOATech){ - cerr << "printOALayers" << endl; assert(theOATech); oaIter lIter(theOATech->getLayers()); while(oaLayer* l = lIter.getNext()){ @@ -235,34 +251,9 @@ namespace { } } - /** - @todo complete,verify ... - */ - inline BasicLayer::Material::Code oaMaterialToBasicLayerType(const oaMaterial& material) { - switch(material) { - case oacNWellMaterial: - return BasicLayer::Material::nWell; - case oacPWellMaterial: - return BasicLayer::Material::pWell; - case oacNImplantMaterial: - return BasicLayer::Material::nImplant; - case oacPImplantMaterial: - return BasicLayer::Material::pImplant; - case oacPolyMaterial: - return BasicLayer::Material::poly; - case oacCutMaterial: - return BasicLayer::Material::cut; - case oacMetalMaterial: - case oacContactlessMetalMaterial: - return BasicLayer::Material::metal; - default: - return BasicLayer::Material::other; - } - } - /** generate info from library name - */ + */ inline pair libInfos(const string& path, const string& libName){ oaNativeNS ns; @@ -274,7 +265,7 @@ namespace { /** open oaLib with the info gathered by libPath function - */ + */ inline oaLib* openOALib(const pair& infos){ oaLib *lib = oaLib::find(infos.first); const char* pathLib = infos.second.c_str(); @@ -292,19 +283,19 @@ namespace { return lib; } - inline void createCDS(const pair& infos){ + inline void createCDS(const pair& infos,const string& path){ try{ - cerr << "Overwriting cds.lib file begin" << endl; - string cdsPath = infos.second + "/cds.lib"; + cerr << "Overwriting cds.lib file begin " << endl; + string cdsPath = path + "/cds.lib"; oaLibDefList* ldl = oaLibDefList::get( cdsPath.c_str(), 'a'); assert(ldl); - assert(ldl->isValid()); - if(!oaLibDef::find(ldl, infos.first)) - oaLibDef::create(ldl, infos.first, infos.second.c_str()); - ldl->save(); - ldl->destroy();//claim memory - ldl = NULL; - cerr << "Overwrited cds.lib file end" << endl; + assert(ldl->isValid()); + if(!oaLibDef::find(ldl, infos.first)) + oaLibDef::create(ldl, infos.first, infos.second.c_str()); + ldl->save(); + ldl->destroy();//claim memory + ldl = NULL; + cerr << "Overwrited cds.lib file end" << endl; }catch(oaException& e){ cerr << "ERROR cds: " << e.getMsg() << endl; exit(-2); @@ -352,7 +343,7 @@ namespace { } return findLibraryByNameInLibrary(rootLibrary, libraryName); } - + inline void getAllCells(Library* rootLibrary, set& cellSet) { for_each_cell(cell, rootLibrary->getCells()) { cellSet.insert(cell); @@ -391,7 +382,7 @@ namespace { /** function helper - */ + */ inline Library* getOACellLibraries() { Library* rootLibrary = getRootLibrary(); if (!rootLibrary) { @@ -408,7 +399,7 @@ namespace { /** helper function - */ + */ inline Library* getOADesignLibraries() { Library* rootLibrary = getRootLibrary(); if (!rootLibrary) { @@ -425,7 +416,7 @@ namespace { /** utility to open a design by name - */ + */ inline oaView* pickView(oaCell* oa_Cell) { //oacMaskLayout Type is first oaView* toReturnView = NULL; @@ -452,7 +443,7 @@ namespace { /** utility to open a design by name - */ + */ inline oaDesign* openDesign(const oaNameSpace& oaNS, oaCell* oa_Cell) { oaView* view = pickView(oa_Cell); if (view != NULL) { @@ -567,25 +558,25 @@ namespace { if (instance) { //cerr << "found " << instance << endl; oaPlacementStatus placementStatus= oa_Inst->getPlacementStatus(); - //switch (placementStatus) { - // case oacNonePlacementStatus : - // cerr << " none" << endl; - // break; - // case oacUnplacedPlacementStatus : - // cerr << " unplaced" << endl; - // break; - // case oacPlacedPlacementStatus : - // cerr << " placed" << endl; - // break; - // case oacFixedPlacementStatus : - // cerr << " fixed" << endl; - // break; - // default : - // cerr << "other" << endl; - //} + switch (placementStatus) { + case oacNonePlacementStatus : + cerr << " none" << endl; + break; + case oacUnplacedPlacementStatus : + cerr << " unplaced" << endl; + break; + case oacPlacedPlacementStatus : + cerr << " placed" << endl; + break; + case oacFixedPlacementStatus : + cerr << " fixed" << endl; + break; + default : + cerr << "other" << endl; + } oaPoint instOrigin; oa_Inst->getOrigin(instOrigin); - //cerr << instOrigin.x() << " " << instOrigin.y() << endl; + cerr << instOrigin.x() << " " << instOrigin.y() << endl; } else { cerr << "cannot find " << oaInstStr << endl; } @@ -617,6 +608,188 @@ namespace { } }//end if (cellDesign != NULL) } + + inline oaRect* MakeRect(oaBlock *block, + oaTransform &xform, + oaInt4 xformXoffset, + oaLayer* layerPin){ + xform.xOffset() += xformXoffset; + const oaUInt4 lengthPin(3); + const oaUInt4 widthPin(2); + const oaBox boxPin(0, -static_cast(widthPin/2), + lengthPin, static_cast(widthPin/2)); + return oaRect::create(block, + layerPin->getNumber(), + oacDrawingPurposeType, + oaBox(boxPin, xform)); + } + + inline void MakeStub(oaBlock *block, + oaPointArray &pa, + oaInt4 endPointXoffset, + oaLayer* layerPin){ + pa[1].x() += endPointXoffset; + oaLine::create(block, layerPin->getNumber(), oacDrawingPurposeType, pa); + } + + oaString MakeLabel(oaBlock* block, + oaTransform& xform, + const char* label, + oaLayer* layerText){ + oaString str; + const oaUInt4 widthPin(2); + xform.yOffset() += 1 + widthPin/2; + oaText* text = oaText::create(block, + layerText->getNumber(), + oacDrawingPurposeType, + label, + xform.offset(), + oacLowerLeftTextAlign, + oacR0, + oacFixedFont, + 3); + text->getText(str); + return str; + } + + /** + Make a rectangular Pin shape for a Term on a block's symbol. + For the purpose of the schematicSymbol, this pin shape will + be attached to a line "stub extension" sticking out from the + basic symbol shape to represents block's internal Net. + */ + oaPin* MakePinSymbol(oaBlock* block, + oaPoint location, + const char* strNameTerm, + oaInt4 stubLength, + oaOrient rotation, + oaLayer* layerPin, + oaLayer* layerText){ + const oaUInt4 lengthPin(3); + const oaUInt4 widthPin(2); + const oaBox boxPin( 0, -static_cast(widthPin/2), + lengthPin, static_cast(widthPin/2)); + + // boxPin is represented here + // Y-axis + // | + // | lengthPin --> + // |_________ + // | | + // ----|---------|-------- X-axis + // |_________| + // | + // | + // Assume the location argument is the point on the main symbol + // against which the Pin is to be located, centered vertically (Y-axis) + // on that point, left of the point if it is an INPUT pin and right + // of that point if an OUTPUT pin, moved orthogonally away from the + // edge of the gate symbol by a stub of length stubLength representing + // part of the internal net of the gate to which a Term's Pin is attached. + // + // | | + // | OUT | Y__ + // | point o---------|__| + // | | / + // | | / + // | GATE | stubLength + // | | + // A__ | | + // |__|---------o point | + // / | IN | + // / | | + // stubLength | | + + + // Define oaTransform xform to be the location argument (no rotation) + // begin_skel + oaTransform xform( location, rotation ); + // end_skel + + static oaPointArray pa(2); + + // Set both points in pa[] to the value of the location arg. + // (HINT: The allocation size and number of points attributes are DIFFERENT.) + // + // begin_skel + pa.setNumElements(2); + pa[0] = location; + pa[1] = location; + // end_skel + + // Find the term by name (the strNameTerm arg) and set to the term variable + // for reuse later when the Pin is created for that Term. + oaTerm* term = oaTerm::find(block, oaScalarName(oaNativeNS(),strNameTerm)); + + // Create for the Term: + // + // 1. A "stub" Line from the symbol shape to the Pin shape + // (representing a connection to the Block's internal Net) + // + // The pa[] PointArray has already been set up for this Line with the start + // and end Points both set to the proper location on the edge of the symbol + // Shape. Only the second (endPoint) X value must be moved to the LEFT + // or RIGHT (for Input or Output Pins, respectively). Call MakeStub() passing + // in the block to the right edge of the Pin. + // + // 2. A rectangular Shape to represent the Pin itself + // + // Use the MakeRect() utility function to create the Shape of the Pin + // passing to it the template boxPin from the globals singleton, and the + // Transform declared and initialized above. That Transform will move the + // base boxPin from its 0,0 location to the location point on the edge of the + // symbol shape. Also pass in an X offset from that location that moves + // the pinBox to the left or right, depending on whether it's an Input or + // Output Pin. + // + // 3. The Pin itself using the rectangle just created with the same name + // as the Term (arg passed in). Set the access direction for the Pin to + // enable connections from all directions except that on the "stub side". + // The rectangle must be explicitly added to the Pin. + // + // 4. A Text label for the Pin whose text value is the name of the Term. + // Use the MakeLabel() utility function passing in the strNameTerm and + // Transform (which now represents the left edge of the Pin shape properly located. + oaPin* pin = NULL; + switch (term->getTermType()) { + + // If the Pin is an Output type, assume it is on the RIGHT side. + // + // 1. Call MakeStub() with endPointXoffset to the RIGHT by the stubLength. + // 2. Call MakeRect() with an X offset that moves RIGHT by stubLength. + // 3. Construct the oaPin allowing access from top, bottom and right. + // 4. Call MakeLabel(). + // + case oacOutputTermType: + case oacInputOutputTermType: + MakeStub(block, pa, stubLength,layerPin); + pin = oaPin::create(term, oacTop|oacBottom|oacRight); + MakeRect(block, xform, stubLength,layerPin)->addToPin(pin); + MakeLabel(block, xform, strNameTerm,layerText); + break; + + // If the Pin is an Input type, assume it is on the LEFT side. + // + // 1. Call MakeStub() with endPointXoffset to the LEFT by the stubLength. + // 2. Call MakeRect() with an X offset that moves LEFT by + // (stubLength + lengthPin) if the rotation is oacR0. + // 3. Construct the oaPin allowing access from top, bottom, and left. + // 4. Call MakeLabel(). + case oacInputTermType: + default: + MakeStub(block, pa, -stubLength,layerPin); + pin = oaPin::create(term, oacTop|oacBottom|oacLeft); + MakeRect(block,xform, + -stubLength - (rotation == oacR0 + ? lengthPin : 0 ), + layerPin)->addToPin(pin); + MakeLabel(block, xform, strNameTerm,layerText); + break; + } + return pin; + }//MakePinSymbol + + }//end anonymous namespace #endif//HAVE_OPENACCESS diff --git a/crlcore/src/ccore/openaccess/OpenAccessDriver.cpp b/crlcore/src/ccore/openaccess/OpenAccessDriver.cpp new file mode 100644 index 00000000..8da9b80e --- /dev/null +++ b/crlcore/src/ccore/openaccess/OpenAccessDriver.cpp @@ -0,0 +1,662 @@ +// -*-compile-command:"cd ../../../../.. && make"-*- +// Time-stamp: "2010-07-30 16:44:00" - OpenAccessDriver.cpp +// x-----------------------------------------------------------------x +// | This file is part of the hurricaneAMS Software. | +// | Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved | +// | =============================================================== | +// | Author : Chistophe Alexandre | +// | E-mail : Christophe.Alexandre@asim.lip6.fr | +// x-----------------------------------------------------------------x +// | Author : Jean-Manuel Caba | +// | E-mail : Jean-Manuel.Caba@asim.lip6.fr | +// x-----------------------------------------------------------------x + + +#include +#include +#include +using namespace std; + +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Library.h" +#include "hurricane/Cell.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/Segment.h" +#include "hurricane/Pad.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/Slice.h" +using namespace Hurricane; + +#include "OpenAccess.h" +#include "OpenAccessCommon.h" + +namespace { + +#ifdef HAVE_OPENACCESS + + /** + Class to drive OA to Hurricane + */ + class OADriver { + private: + typedef map Library2OALibMap; + typedef map Cell2OADesignMap; + typedef map Instance2OAInstsMap; + typedef map Layer2OAPhysicalLayerMap; + + string _path; + oaTech* _oaTech; + Library2OALibMap _library2OALib; + Cell2OADesignMap _cell2OADesign4Netlist; + Cell2OADesignMap _cell2OADesign4Schematic; + Cell2OADesignMap _cell2OADesign4Symbolic; + Cell2OADesignMap _cell2OADesign4Layout; + Instance2OAInstsMap _instance2OAInst; + Layer2OAPhysicalLayerMap _layer2OAPhysicalLayer; + DataBase* _db; + Technology* _technology; + int _layerID; + oaLayer* layerDev; + oaLayer* layerPin; + oaLayer* layerText; + oaLayer* layerWire; + public: + OADriver(const string& path): + _path(path), + _oaTech(NULL), + _library2OALib(), + _cell2OADesign4Netlist(), + _cell2OADesign4Schematic(), + _cell2OADesign4Symbolic(), + _cell2OADesign4Layout(), + _instance2OAInst(), + _layer2OAPhysicalLayer(), + _db(NULL), + _technology(NULL), + _layerID(0) { + _db = DataBase::getDB(); + if (!_db) { + throw Error("no database"); + } + _technology = _db->getTechnology(); + if (!_technology) { + throw Error("no technology"); + } + } + + ~OADriver() { + cerr << "SAVING ALL" << endl; + _oaTech->save(); + _oaTech->close(); + saveDesignsInMap(_cell2OADesign4Netlist); + saveDesignsInMap(_cell2OADesign4Schematic); + saveDesignsInMap(_cell2OADesign4Symbolic); + saveDesignsInMap(_cell2OADesign4Layout); + for (Library2OALibMap::iterator it = _library2OALib.begin(); + it != _library2OALib.end(); + ++it) { + oaLib* lib = it->second; + lib->close(); + } + cerr << "ALL SAVED" << endl; + } + + /** + Create an empty oaLib from a Library + no cells are added in this oaLib + all sub Library are also converted. + */ + oaLib* getOALibForLibrary(const Library* library) { + cerr << "getOALibForLibrary" << endl; + assert(library); + Library2OALibMap::iterator it = _library2OALib.find(library); + if (it != _library2OALib.end()) { + return it->second; + } + + // 1) create or open library + pair infos=libInfos(_path, + getString(library->getName())); + oaLib *lib = openOALib(infos); + _library2OALib[library] = lib; + +#if 0 + // 2) for each cell convert them too : if it's a standard cell library for example + for_each_cell(c ,library->getCells()){ + getOADesignForCell(c); + end_for; + } + + // 3) also convert each contained library if any + for_each_library(l ,library->getLibraries()){ + getOALibForLibrary(l); + end_for; + } +#endif + // 4) create, update library list file + createCDS(infos,_path); + + return lib; + } + + /** + convert oaLayer from a Layer ... + */ + oaLayer* getOALayerFromLayer(Layer* layer,oaTech* theOATech) { + assert(layer); + Layer2OAPhysicalLayerMap::iterator it = _layer2OAPhysicalLayer.find(layer); + if (it != _layer2OAPhysicalLayer.end()) { + return it->second; + } + assert(theOATech); + + // 1) get or create layer + oaString layerName = getString(layer->getName()).c_str(); + oaPhysicalLayer* aOALayer = NULL; + aOALayer = oaPhysicalLayer::find(theOATech, layerName, true); + if(aOALayer){ + _layer2OAPhysicalLayer[layer] = aOALayer; + return aOALayer; + } + BasicLayer* bLayer = dynamic_cast(layer); + if(bLayer) + aOALayer = oaPhysicalLayer::create(theOATech, layerName, _layerID++,getOAMaterial(bLayer->getMaterial())); + else + aOALayer = oaPhysicalLayer::create(theOATech, layerName, _layerID++); + assert(aOALayer); + + _layer2OAPhysicalLayer[layer] = aOALayer; + + //create and add layer constraint for Layer specific manufacturing rules + cerr << " o get value for constraint" << endl; + long minSize = Hurricane::DbU::getDb(layer->getMinimalSize()); + long minSpace = Hurricane::DbU::getDb(layer->getMinimalSpacing()); + long pitch = Hurricane::DbU::getDb(layer->getPitch()); + +#if 0 + cerr << " o create constraint for min size : " << pitch << endl; + oaLayerConstraint* cMinSize = NULL; + try{ + cMinSize = oaLayerConstraint::create(aOALayer->getNumber(), + oaLayerConstraintDef::get(oacMinSize), + oaIntValue::create(theOATech,500)) + }catch(oaException& e){ + cerr << "ERROR oaLayer: " << e.getMsg() << endl; + exit(-2); + }catch(...){ + cerr << "ERROR oaLayer: [UNKNOWN]" << endl; + exit(-1); + } + assert(cMinSize); + cerr << " o create constraint for min space" << endl; + oaLayerConstraint* cMinSpace = oaLayerConstraint::create(aOALayer->getNumber(), + oaLayerConstraintDef::get(oacMinSpacing), + oaIntValue::create(theOATech->getLib(),minSpace)); + assert(cMinSpace); + cerr << " o create constraint for pitchH" << endl; + oaLayerConstraint* cPitchH = oaLayerConstraint::create(aOALayer->getNumber(), + oaLayerConstraintDef::get(oacHorizontalRouteGridPitch), + oaIntValue::create(theOATech->getLib(),pitch)); + assert(cPitchH); + + cerr << " o create constraint for pitchV" << endl; + oaLayerConstraint* cPitchV = oaLayerConstraint::create(aOALayer->getNumber(), + oaLayerConstraintDef::get(oacVerticalRouteGridPitch), + oaIntValue::create(theOATech->getLib(),pitch)); + assert(cPitchV); +#endif + if(bLayer){ + unsigned gdsIInumber = bLayer->getExtractNumber(); + } + return aOALayer; + } + + /** + create a oaTech from a Hurricane::Technology in it's Library + also create the oaLib corresponding to the Hurricane::Library + containing the Hurricane::Technology + @todo complete with technology info for layers + @see getOALibForLibrary + */ + oaTech* getOATechForTechnology(const Technology* technology,const Library* lib) { + cerr << "createOATechForTechnology" << endl; + assert(technology); + + // 1) get or create Library for the techno + assert(lib); + oaLib* techOAlib = getOALibForLibrary(lib); + assert(techOAlib); + + // 2) get or create oaTech container + bool created = false; + cerr << "oaTech::find" << endl; + oaTech* theOATech = oaTech::find(techOAlib); + if(!theOATech){ + if (oaTech::exists(techOAlib)){ + cerr << "oaTech::open" << endl; + theOATech = oaTech::open(techOAlib,'a'); + } + if(!theOATech){ + cerr << "oaTech::create" << endl; + theOATech = oaTech::create(techOAlib); + created = true; + } + } + assert(techOAlib); + if(created){ + theOATech->setDefaultManufacturingGrid(10); + theOATech->setDBUPerUU(oaViewType::get(oacMaskLayout), 2000); + + //create and add foundry constraint group for General manufacturing rules + //and add oaSimpleConstraintType too + oaConstraintGroup *cgFoundry = theOATech->getFoundryRules(); + + /* + add the constraint group LEFDefaultRouteSpec for oa2lef + */ + + //first create "utility" layers following : + layerDev = oaPhysicalLayer::create(theOATech, "device", _layerID++); + layerText = oaPhysicalLayer::create(theOATech, "text", _layerID++); + layerPin = oaPhysicalLayer::create(theOATech, "pin", _layerID++); + layerWire = oaPhysicalLayer::create(theOATech, "wire", _layerID++); + } + + // get or create physical layer + + for_each_layer(layer, technology->getLayers()) { + getOALayerFromLayer(layer,theOATech); + end_for; + } + printOALayers(theOATech); + + return theOATech; + } + + /** + convert Hurricane::Instance to oaInst ... + */ + oaInst* getOAInstForInstance(Instance* instance,oaBlock* topBlock) { + cerr << "getOAInstForInstance " << instance << endl; + assert(instance); + Instance2OAInstsMap::iterator it = _instance2OAInst.find(instance); + if (it != _instance2OAInst.end()) { + return it->second; + } + assert(topBlock); + + // 1) get the master cell for the instance + Cell* masterCell = instance->getMasterCell(); + assert(masterCell); + oaDesign* masterDesign = getOADesignForCell(masterCell); + assert(masterDesign); + + oaNativeNS ns; + oaScalarName scMasterName; + masterDesign->getCellName(scMasterName); + oaString strMasterName; + scMasterName.get(strMasterName); + oaScalarName scInstName(ns, getString(instance->getName()).c_str()); + + + oaScalarInst* blockInst = oaScalarInst::find(topBlock, + scInstName); + if(!blockInst){ + oaTransform transform; + getOATransformFromTransformation(transform, instance->getTransformation()); + blockInst = oaScalarInst::create(topBlock, masterDesign, scInstName, transform); + } + _instance2OAInst[instance] = blockInst; + return blockInst; + } + + /** + convert Hurricane::plug to oaInstTerm + and add it to if connected. + always return a non NULL value + */ + oaInstTerm* getOAInstTermFromPlug(Plug* plug,oaNet* net){ + cerr << "getOAInstTermFromPlug " << plug << endl; + assert(plug); + Instance* instance = plug->getInstance(); + Instance2OAInstsMap::iterator it = _instance2OAInst.find(instance); + assert(it != _instance2OAInst.end()); + oaInst* blockInst = it->second; + oaInstTerm* instTerm = getInstTerm(blockInst, plug,net); + assert(instTerm); + return instTerm; + } + + oaPin* getOAPinFromNet(Net* net,oaNet* blockNet){ + cerr << "getOAPinFromNet" << endl; + assert(net); + assert(net->isExternal()); + assert(blockNet); + oaNativeNS ns; + oaScalarName scNetName(ns, getString(net->getName()).c_str()); + oaTerm* term = oaTerm::find(blockNet->getBlock(), scNetName); + assert(term); + + oaPin* pin = oaPin::create(term); + + return pin; + } + + oaRect* getOARectFromComponent(Component* component,oaBlock* topBlock){ + cerr << "getOARectFromComponent" << endl; + assert(component); + assert(topBlock); + oaBox box; + getOABoxForBox(box, component->getBoundingBox()); + Layer* layer = (Layer*) component->getLayer(); + assert(layer); + oaPhysicalLayer* physLayer = NULL; + Layer2OAPhysicalLayerMap::iterator it = _layer2OAPhysicalLayer.find(layer); + if (it != _layer2OAPhysicalLayer.end()) { + physLayer = it->second; + } + assert(physLayer); + oaLayerNum layerNum = physLayer->getNumber(); + oaRect* rect = oaRect::create(topBlock, + layerNum, + oacDrawingPurposeType, + box); + return rect; + } + + /** + convert Hurricane::Net to oaNet + always return a non NULL value + */ + oaNet* getOANetFromNet(Net* net,oaBlock* topBlock) { + cerr << "getOANetFromNet " << net << endl; + assert(net); + oaNativeNS ns; + oaScalarName scNetName(ns, getString(net->getName()).c_str()); + oaScalarNet* blockNet = NULL; + blockNet = oaScalarNet::find(topBlock, scNetName); + if(blockNet) + return blockNet; + assert(!blockNet); + blockNet = oaScalarNet::create(topBlock, scNetName, getOASigType(net->getType())); + assert(blockNet); + oaScalarTerm::create(blockNet, scNetName, getOATermType(net->getDirection())); + if (net->isExternal()) { + oaPin* pin = getOAPinFromNet(net,blockNet); + Components externalComponents = NetExternalComponents::get(net); + for_each_component(component, externalComponents) { + oaRect* rect = getOARectFromComponent(component,topBlock); +// rect->addToPin(pin); + end_for; + } + } + cerr << " o transformation of plugs" << endl; + for_each_plug(plug, net->getPlugs()) { + getOAInstTermFromPlug(plug,blockNet); + end_for; + } + blockNet->scalarize(); + return blockNet; + } + + /** + create oaRect for slice ... + */ + void getOARectFromSlice(Slice* slice,oaBlock* topBlock){ + cerr << "getOARectFromSlice" << endl; + assert(slice); + assert(topBlock); + for_each_component(component, slice->getComponents()) { + oaRect* rect = getOARectFromComponent(component,topBlock); + end_for; + } + } + + /** + Create initial oaDesign from the cell and save it as a netlist view + */ + oaDesign* createOAasNetlist(const Cell* cell) { + cerr << "createNetlist " << cell << endl; + assert(cell); + Cell2OADesignMap::iterator it = _cell2OADesign4Netlist.find(cell); + if (it != _cell2OADesign4Netlist.end()) { + return it->second; + } + + // 1) get the lib containing the cell + oaNativeNS ns; + oaLib* lib = getOALibForLibrary(cell->getLibrary()); + assert(lib); + + // 2) create a netlist CellView of the cell + oaScalarName scNameDesign(ns, getString(cell->getName()).c_str()); + oaScalarName scNameView(ns, "netlist"); + oaScalarName scNameLib; + lib->getName(scNameLib); + cerr << "oaDesign::open for netlist view" << endl; + oaDesign* designCellView = oaDesign::open(scNameLib, scNameDesign, scNameView, oaViewType::get(oacNetlist), 'a'); + _cell2OADesign4Netlist[cell] = designCellView; + + // 3) create oaBlock singleton where we will do all the work + oaBlock* topBlock = designCellView->getTopBlock(); + if(!topBlock){ + cerr << "oaBlock::create for netlist view" << endl; + topBlock = oaBlock::create(designCellView); + } + assert(topBlock); + + // 4) convert each OA object + cerr << "transformation of instances" << endl; + for_each_instance(instance, cell->getInstances()){ + getOAInstForInstance(instance,topBlock); + end_for; + } + cerr << "transformation of nets" << endl; + for_each_net(net, cell->getNets()){ + getOANetFromNet(net,topBlock); + end_for; + } + return designCellView; + } + + /** + Add symbol view to previous view ... + */ + oaDesign* addSymbol(const Cell* cell,oaDesign* previous) { + cerr << "addSymbol" << cell << endl; + assert(cell); + assert(previous); + Cell2OADesignMap::iterator it = _cell2OADesign4Symbolic.find(cell); + if (it != _cell2OADesign4Symbolic.end()) { + return it->second; + } + oaNativeNS ns; + oaLib* lib = getOALibForLibrary(cell->getLibrary()); + assert(lib); + oaScalarName scNameDesign(ns, getString(cell->getName()).c_str()); + oaScalarName scNameView(ns, "symbolic"); + oaScalarName scNameLib; + lib->getName(scNameLib); + + // create a symbolic CellView of the cell + oaViewType* vType = oaViewType::get(oacSchematicSymbol); + cerr << "oaDesign::open for symbolic view" << endl; + oaDesign* designCellView = oaDesign::open(scNameLib, scNameDesign, scNameView, vType, 'a'); + _cell2OADesign4Symbolic[cell] = designCellView; + + // get module or embed previous module + oaModule* topMod = NULL; + topMod = designCellView->getTopModule(); + if(!topMod){ + topMod = oaModule::embed(designCellView, previous); + designCellView->setTopModule(topMod); + } + oaBlock *topBlock = designCellView->getTopBlock(); + assert(topBlock); + + + return designCellView; + } + + /** + Add schematic view to previous view ... + */ + oaDesign* addSchematic(const Cell* cell,oaDesign* previous) { + cerr << "addSchematic" << cell << endl; + assert(cell); + assert(previous); + Cell2OADesignMap::iterator it = _cell2OADesign4Schematic.find(cell); + if (it != _cell2OADesign4Schematic.end()) { + return it->second; + } + + oaNativeNS ns; + oaLib* lib = getOALibForLibrary(cell->getLibrary()); + assert(lib); + oaScalarName scNameDesign(ns, getString(cell->getName()).c_str()); + oaScalarName scNameView(ns, "schematic"); + oaScalarName scNameLib; + lib->getName(scNameLib); + + // create a schematic CellView of the cell + oaViewType* vType = oaViewType::get(oacSchematic); + cerr << "oaDesign::open for schematic view" << endl; + oaDesign* designCellView = oaDesign::open(scNameLib, scNameDesign, scNameView, vType, 'a'); + _cell2OADesign4Schematic[cell] = designCellView; + + // get module or embed previous module + oaModule* topMod = NULL; + topMod = designCellView->getTopModule(); + if(!topMod){ + topMod = oaModule::embed(designCellView, previous); + designCellView->setTopModule(topMod); + } + oaBlock *topBlock = designCellView->getTopBlock(); + assert(topBlock); + + return designCellView; + } + + /** + Add layout view to previous view ... + */ + oaDesign* addLayout(const Cell* cell,oaDesign* previous) { + cerr << "addLayout" << cell << endl; + assert(cell); + assert(previous); + Cell2OADesignMap::iterator it = _cell2OADesign4Layout.find(cell); + if (it != _cell2OADesign4Layout.end()) { + return it->second; + } + + oaNativeNS ns; + oaLib* lib = getOALibForLibrary(cell->getLibrary()); + assert(lib); + oaScalarName scNameDesign(ns, getString(cell->getName()).c_str()); + oaScalarName scNameView(ns, "layout"); + oaScalarName scNameLib; + lib->getName(scNameLib); + + // create a layout CellView of the cell + oaViewType* vType = oaViewType::get(oacMaskLayout); + cerr << "oaDesign::open for layout view" << endl; + oaDesign* designCellView = oaDesign::open(scNameLib, scNameDesign, scNameView, vType, 'a'); + _cell2OADesign4Layout[cell] = designCellView; + + // get module or embed previous module + oaModule* topMod = NULL; + topMod = designCellView->getTopModule(); + if(!topMod){ + topMod = oaModule::embed(designCellView, previous); + designCellView->setTopModule(topMod); + } + oaBlock *topBlock = designCellView->getTopBlock(); + assert(topBlock); + + cerr << "transformation of slices" << endl; + for_each_slice(slice, cell->getSlices()){ + getOARectFromSlice(slice,topBlock); + end_for; + } + + return designCellView; + } + + /** + Convert a Cell to OA designs ... + */ + oaDesign* getOADesignForCell(const Cell* cell) { + cerr << "getOADesignForCell " << cell << endl; + assert(cell); + + // 1) get technology + if(!_oaTech) + _oaTech = getOATechForTechnology(_technology,cell->getLibrary()); + + // 2) create OA structure ... + oaDesign* netlistView = createOAasNetlist(cell); + assert(netlistView); + + oaCell* c1 = OADesignToOACell(netlistView); + assert(c1); + + oaDesign* symbolicView = addSymbol(cell,netlistView); + assert(symbolicView); + + oaCell* c2 = OADesignToOACell(symbolicView); + assert(c2); + + oaDesign* schematicView = addSchematic(cell,symbolicView); + assert(schematicView); + + oaCell* c3 = OADesignToOACell(schematicView); + assert(c3); + + oaDesign* layoutView = addLayout(cell,schematicView); + assert(layoutView); + + oaCell* c4 = OADesignToOACell(layoutView); + assert(c4); + + //3) we check it's the same oaCell for all designs + assert(c1 == c2 && c2 == c3 && c3 == c4); + + return netlistView; + } + + oaCell* getOACellForCell(const Cell* cell) { + return OADesignToOACell( getOADesignForCell(cell) ); + } + };//OADriver class +#endif +}//namespace + +namespace CRL { + oaCell* OpenAccess::oaDriver(const string& path, Cell* cell) { +#ifdef HAVE_OPENACCESS + //for the moment a driver for hurricaneAMS + //save the Cell only and all used Cell + oaCell* convertedCell = NULL; + cerr << "Saving " << cell << " in " << path << endl; + try { + oaDesignInit(oacAPIMajorRevNumber, + oacAPIMinorRevNumber, + oacDataModelRevNumber); + + OADriver oaDriver(path); + convertedCell = oaDriver.getOACellForCell(cell); + }catch (oaException &e) { + cerr << "OA::ERROR => " << e.getMsg() << endl; + exit(1); + }catch(std::exception& e){ + cerr << "STD::ERROR => " << e.what() << endl; + exit(2); + } + return convertedCell; +#else + cerr << "\nDummy OpenAccess driver call for " << path << endl; + return NULL; +#endif + } +} diff --git a/crlcore/src/ccore/openaccess/OpenAccessParser.cpp b/crlcore/src/ccore/openaccess/OpenAccessParser.cpp index bf6b36fb..f6cb1310 100644 --- a/crlcore/src/ccore/openaccess/OpenAccessParser.cpp +++ b/crlcore/src/ccore/openaccess/OpenAccessParser.cpp @@ -1,5 +1,5 @@ // -*-compile-command:"cd ../../../../.. && make"-*- -// Time-stamp: "2010-07-26 16:16:18" - OpenAccessParser.cpp +// Time-stamp: "2010-07-28 15:44:58" - OpenAccessParser.cpp // x-----------------------------------------------------------------x // | This file is part of the hurricaneAMS Software. | // | Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved | @@ -344,7 +344,6 @@ namespace { cout << "ERROR: " << excp.getMsg() << endl; exit(1); } - } void getDesigns(set& designCellSet) { diff --git a/crlcore/src/ccore/openaccess/test/Makefile b/crlcore/src/ccore/openaccess/test/Makefile index a13a34c1..2be11892 100644 --- a/crlcore/src/ccore/openaccess/test/Makefile +++ b/crlcore/src/ccore/openaccess/test/Makefile @@ -1,16 +1,15 @@ - all: ./compile.sh -run: - cd x86_64/usr/local/bin && ./testOAWrapper /asim/chams/etc/chams/config.freePDK45.xml /tmp/testOA +run: + ./x86_64/usr/local/bin/testOAWrapper /asim/chams/etc/chams/config.freePDK45.xml /tmp/testOA 2>&1 | tee err.log -debug: - cd x86_64/usr/local/bin && gdb -args ./testOAWrapper /asim/chams/etc/chams/config.freePDK45.xml /tmp/testOA +debug: + gdb -args ./x86_64/usr/local/bin/testOAWrapper /asim/chams/etc/chams/config.freePDK45.xml /tmp/testOA -ddd: - cd x86_64/usr/local/bin && ddd -args ./testOAWrapper /asim/chams/etc/chams/config.freePDK45.xml /tmp/testOA +ddd: + ddd -args ./x86_64/usr/local/bin/testOAWrapper /asim/chams/etc/chams/config.freePDK45.xml /tmp/testOA rmtmp: rm -rf /tmp/* diff --git a/crlcore/src/ccore/openaccess/test/src/main.cpp b/crlcore/src/ccore/openaccess/test/src/main.cpp index dfd2ce79..fbc868e9 100755 --- a/crlcore/src/ccore/openaccess/test/src/main.cpp +++ b/crlcore/src/ccore/openaccess/test/src/main.cpp @@ -29,6 +29,7 @@ using namespace CRL; #include "hurricaneAMS/devices/SimpleCurrentMirror.h" #include "crlcore/GdsDriver.h" +#include "crlcore/CifDriver.h" #include "crlcore/OADriver.h" namespace { @@ -44,9 +45,13 @@ void testCell(Cell* dev,char* pathToTest){ return; } system((string("mkdir -p ") + string(pathToTest)).c_str()); + cerr << "driving GDS" << endl; GdsDriver(dev).save(string(pathToTest) + "/" + getString(dev->getName()) + ".gds"); + cerr << "driving CIF" << endl; + CifDriver(dev).save(string(pathToTest) + "/" + getString(dev->getName()) + ".cif"); + cerr << "driving OA" << endl; OADriver(dev).save(string(pathToTest) + "/OAdrive"); }