From 2b3b847162d104e495b664880a73c7a70a74e7da Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Fri, 17 Nov 2017 11:48:20 +0100 Subject: [PATCH] New LEF importer for real technologies. * New: In CRL Core, added LEF importer for real technologies. This is still a work in progress. Exported in Python interface. * Bug: In CRL Core, CellGauge::getRecord() correctly display DbU attributes. * Change: In Unicorn, mofificate ImportCell and ImportCellDialog to support the LEF importer. Add a template layer so we can work with loaders returning Cell* or Library*. * Change: In Unicorn::UnicornGui::getCellFromDb(), in addition to the Alliance loader, uses the DataBase::getCell() too (for Cells that are *not* in Alliance). --- crlcore/src/ccore/CMakeLists.txt | 2 + crlcore/src/ccore/CellGauge.cpp | 10 +- crlcore/src/ccore/crlcore/LefImport.h | 40 ++ crlcore/src/ccore/crlcore/RoutingLayerGauge.h | 12 + crlcore/src/ccore/lefdef/LefImport.cpp | 619 ++++++++++++++++++ crlcore/src/pyCRL/CMakeLists.txt | 2 + crlcore/src/pyCRL/PyCRL.cpp | 5 + crlcore/src/pyCRL/PyLefImport.cpp | 121 ++++ crlcore/src/pyCRL/crlcore/PyLefImport.h | 55 ++ unicorn/src/ImportCell.cpp | 49 +- unicorn/src/ImportCellDialog.cpp | 9 +- unicorn/src/UnicornGui.cpp | 42 +- unicorn/src/cgt.py | 4 +- unicorn/src/unicorn/ImportCell.h | 90 ++- unicorn/src/unicorn/ImportCellDialog.h | 6 +- unicorn/src/unicorn/OpenCellDialog.h | 14 +- 16 files changed, 1005 insertions(+), 75 deletions(-) create mode 100644 crlcore/src/ccore/crlcore/LefImport.h create mode 100644 crlcore/src/ccore/lefdef/LefImport.cpp create mode 100644 crlcore/src/pyCRL/PyLefImport.cpp create mode 100644 crlcore/src/pyCRL/crlcore/PyLefImport.h diff --git a/crlcore/src/ccore/CMakeLists.txt b/crlcore/src/ccore/CMakeLists.txt index 8168ed74..1061dc64 100644 --- a/crlcore/src/ccore/CMakeLists.txt +++ b/crlcore/src/ccore/CMakeLists.txt @@ -61,6 +61,7 @@ crlcore/LefDefExtension.h crlcore/DefImport.h crlcore/DefExport.h + crlcore/LefImport.h crlcore/LefExport.h crlcore/Blif.h crlcore/AcmSigda.h @@ -157,6 +158,7 @@ # ) set ( lefdef_cpps lefdef/LefExport.cpp lefdef/DefExport.cpp + lefdef/LefImport.cpp lefdef/DefImport.cpp lefdef/LefDefExtension.cpp ) diff --git a/crlcore/src/ccore/CellGauge.cpp b/crlcore/src/ccore/CellGauge.cpp index 7d64ccd9..a78394d3 100644 --- a/crlcore/src/ccore/CellGauge.cpp +++ b/crlcore/src/ccore/CellGauge.cpp @@ -126,11 +126,11 @@ namespace CRL { Record* CellGauge::_getRecord () const { Record* record = new Record ( getString(this) ); - record->add ( getSlot ( "Name" , &_name ) ); - record->add ( getSlot ( "PinLayerName" , &_pinLayerName) ); - record->add ( getSlot ( "pitch" , _pitch ) ); - record->add ( getSlot ( "sliceHeight" , _sliceHeight ) ); - record->add ( getSlot ( "sliceStep" , _sliceStep ) ); + record->add( getSlot ( "Name" , &_name ) ); + record->add( getSlot ( "PinLayerName" , &_pinLayerName ) ); + record->add( DbU::getValueSlot( "pitch" , &_pitch ) ); + record->add( DbU::getValueSlot( "sliceHeight" , &_sliceHeight ) ); + record->add( DbU::getValueSlot( "sliceStep" , &_sliceStep ) ); return ( record ); } diff --git a/crlcore/src/ccore/crlcore/LefImport.h b/crlcore/src/ccore/crlcore/LefImport.h new file mode 100644 index 00000000..5a118efb --- /dev/null +++ b/crlcore/src/ccore/crlcore/LefImport.h @@ -0,0 +1,40 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2017-2017, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | C a d e n c e L E F I m p o r t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail :i Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/LefImport.h" | +// +-----------------------------------------------------------------+ + + +#ifndef CRL_LEF_IMPORT_H +#define CRL_LEF_IMPORT_H + +#include + +namespace Hurricane { + class Library; +} + + +namespace CRL { + + + class LefImport { + public: + static void reset (); + static Hurricane::Library* load ( std::string fileName ); + }; + + +} // CRL namespace. + + +#endif // CRL_DEF_IMPORT_H diff --git a/crlcore/src/ccore/crlcore/RoutingLayerGauge.h b/crlcore/src/ccore/crlcore/RoutingLayerGauge.h index 8287ec3f..d567588b 100644 --- a/crlcore/src/ccore/crlcore/RoutingLayerGauge.h +++ b/crlcore/src/ccore/crlcore/RoutingLayerGauge.h @@ -273,6 +273,12 @@ inline std::string getString } +template<> +inline std::string getString + ( Constant::LayerGaugeType* layerGaugeType ) +{ return getString(layerGaugeType); } + + template<> inline std::string getString ( const Constant::LayerGaugeType layerGaugeType ) @@ -285,6 +291,12 @@ inline std::string getString } +template<> +inline std::string getString + ( Constant::LayerGaugeType layerGaugeType ) +{ return getString(layerGaugeType); } + + IOSTREAM_POINTER_SUPPORT(Constant::LayerGaugeType); diff --git a/crlcore/src/ccore/lefdef/LefImport.cpp b/crlcore/src/ccore/lefdef/LefImport.cpp new file mode 100644 index 00000000..0f5fffe9 --- /dev/null +++ b/crlcore/src/ccore/lefdef/LefImport.cpp @@ -0,0 +1,619 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2017-2017, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | C a d e n c e L E F I m p o r t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./LefImport.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include +#include +#include +#if defined(HAVE_LEFDEF) +# include "lefrReader.hpp" +#endif +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/DataBase.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/Technology.h" +#include "hurricane/Net.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/Contact.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Cell.h" +#include "hurricane/Library.h" +#include "hurricane/UpdateSession.h" +#include "crlcore/Utilities.h" +#include "crlcore/ToolBox.h" +#include "crlcore/RoutingGauge.h" +#include "crlcore/CellGauge.h" +#include "crlcore/AllianceFramework.h" +#include "crlcore/LefImport.h" + + +#if defined(HAVE_LEFDEF) + +namespace { + + using namespace std; + using namespace Hurricane; + using namespace CRL; + + + void addSupplyNets ( Cell* cell ) + { + Net* vss = Net::create( cell, "vss" ); + vss->setExternal( true ); + vss->setGlobal ( true ); + vss->setType ( Net::Type::GROUND ); + + Net* vdd = Net::create( cell, "vdd" ); + vdd->setExternal( true ); + vdd->setGlobal ( true ); + vdd->setType ( Net::Type::POWER ); + } + + + class LefParser { + public: + static DbU::Unit fromLefUnits ( int ); + static Layer* getLayer ( string ); + static void addLayer ( string, Layer* ); + static void reset (); + static Library* parse ( string file ); + LefParser ( string file, string libraryName ); + ~LefParser (); + Library* createLibrary (); + inline string getLibraryName () const; + inline Library* getLibrary ( bool create=false ); + inline Cell* getCell () const; + inline void setCell ( Cell* ); + inline Net* getNet () const; + inline void setNet ( Net* ); + static void setCoreSite ( DbU::Unit x, DbU::Unit y ); + static DbU::Unit getCoreSiteX (); + static DbU::Unit getCoreSiteY (); + inline double getUnitsMicrons () const; + inline DbU::Unit fromUnitsMicrons ( double ) const; + inline void setUnitsMicrons ( double ); + inline bool hasErrors () const; + inline const vector& getErrors () const; + inline void pushError ( const string& ); + int flushErrors (); + inline void clearErrors (); + inline int getNthMetal () const; + inline void incNthMetal (); + inline int getNthCut () const; + inline void incNthCut (); + inline RoutingGauge* getRoutingGauge () const; + inline CellGauge* getCellGauge () const; + private: + static int _unitsCbk ( lefrCallbackType_e, lefiUnits* , lefiUserData ); + static int _layerCbk ( lefrCallbackType_e, lefiLayer* , lefiUserData ); + static int _siteCbk ( lefrCallbackType_e, lefiSite* , lefiUserData ); + static int _obstructionCbk ( lefrCallbackType_e, lefiObstruction*, lefiUserData ); + static int _macroCbk ( lefrCallbackType_e, lefiMacro* , lefiUserData ); + static int _pinCbk ( lefrCallbackType_e, lefiPin* , lefiUserData ); + private: + string _file; + string _libraryName; + Library* _library; + Cell* _cell; + Net* _net; + string _busBits; + double _unitsMicrons; + static map _layerLut; + vector _errors; + int _nthMetal; + int _nthCut; + RoutingGauge* _routingGauge; + CellGauge* _cellGauge; + static DbU::Unit _coreSiteX; + static DbU::Unit _coreSiteY; + }; + + + inline string LefParser::getLibraryName () const { return _libraryName; } + inline Library* LefParser::getLibrary ( bool create ) { if (not _library and create) createLibrary(); return _library; } + inline Cell* LefParser::getCell () const { return _cell; } + inline void LefParser::setCell ( Cell* cell ) { _cell=cell; } + inline Net* LefParser::getNet () const { return _net; } + inline void LefParser::setNet ( Net* net ) { _net=net; } + inline DbU::Unit LefParser::fromUnitsMicrons ( double d ) const { return DbU::fromPhysical(d,DbU::Micro); } + inline double LefParser::getUnitsMicrons () const { return _unitsMicrons; } + inline void LefParser::setUnitsMicrons ( double precision ) { _unitsMicrons=precision; } + inline int LefParser::getNthMetal () const { return _nthMetal; } + inline void LefParser::incNthMetal () { ++_nthMetal; } + inline int LefParser::getNthCut () const { return _nthCut; } + inline void LefParser::incNthCut () { ++_nthCut; } + inline RoutingGauge* LefParser::getRoutingGauge () const { return _routingGauge; } + inline CellGauge* LefParser::getCellGauge () const { return _cellGauge; } + inline void LefParser::setCoreSite ( DbU::Unit x, DbU::Unit y ) { _coreSiteX=x; _coreSiteY=y; } + inline DbU::Unit LefParser::getCoreSiteX () { return _coreSiteX; } + inline DbU::Unit LefParser::getCoreSiteY () { return _coreSiteY; } + inline bool LefParser::hasErrors () const { return not _errors.empty(); } + inline const vector& LefParser::getErrors () const { return _errors; } + inline void LefParser::pushError ( const string& error ) { _errors.push_back(error); } + inline void LefParser::clearErrors () { return _errors.clear(); } + + + map LefParser::_layerLut; + DbU::Unit LefParser::_coreSiteX = 0; + DbU::Unit LefParser::_coreSiteY = 0; + + + void LefParser::reset () + { + _layerLut.clear(); + _coreSiteX = 0; + _coreSiteY = 0; + } + + + Layer* LefParser::getLayer ( string layerName ) + { + auto item = _layerLut.find( layerName ); + if (item != _layerLut.end()) return (*item).second; + return NULL; + } + + + void LefParser::addLayer ( string layerName, Layer* layer ) + { + if (getLayer(layerName)) { + cerr << Warning( "LefParser::addLayer(): Duplicated layer name \"%s\" (ignored).", layerName.c_str() ); + return; + } + + _layerLut[ layerName ] = layer; + } + + + LefParser::LefParser ( string file, string libraryName ) + : _file (file) + , _libraryName (libraryName) + , _library (NULL) + , _cell (NULL) + , _net (NULL) + , _busBits ("()") + , _unitsMicrons(0.01) + , _errors () + , _nthMetal (0) + , _nthCut (0) + , _routingGauge(NULL) + , _cellGauge (NULL) + { + _routingGauge = AllianceFramework::get()->getRoutingGauge(); + _cellGauge = AllianceFramework::get()->getCellGauge(); + + lefrInit(); + lefrSetUnitsCbk ( _unitsCbk ); + lefrSetLayerCbk ( _layerCbk ); + lefrSetSiteCbk ( _siteCbk ); + lefrSetObstructionCbk( _obstructionCbk ); + lefrSetMacroCbk ( _macroCbk ); + lefrSetPinCbk ( _pinCbk ); + } + + + LefParser::~LefParser () + { + lefrReset(); + } + + + Library* LefParser::createLibrary () + { + DataBase* db = DataBase::getDB(); + Library* rootLibrary = db->getRootLibrary(); + if (not rootLibrary) rootLibrary = Library::create( db, "RootLibrary" ); + + Library* lefRootLibrary = rootLibrary->getLibrary( "LEF" ); + if (not lefRootLibrary) lefRootLibrary = Library::create( rootLibrary, "LEF" ); + + _library = lefRootLibrary->getLibrary( _libraryName ); + if (_library) + cerr << Error( "LefParser::createLibrary(): attempt to reload \"%s\"." + , _libraryName.c_str() ) << endl; + else + _library = Library::create( lefRootLibrary, _libraryName ); + + return _library; + } + + + int LefParser::_unitsCbk ( lefrCallbackType_e c, lefiUnits* units, lefiUserData ud ) + { + LefParser* parser = (LefParser*)ud; + + if (units->hasDatabase()) { + parser->_unitsMicrons = 1.0 / units->databaseNumber(); + cerr << " - Precision: " << parser->_unitsMicrons + << " (LEF MICRONS scale factor:" << units->databaseNumber() << ")" << endl; + } + return 0; + } + + + int LefParser::_layerCbk ( lefrCallbackType_e c, lefiLayer* lefLayer, lefiUserData ud ) + { + LefParser* parser = (LefParser*)ud; + + if (not lefLayer->hasType()) { + cerr << Warning( "LefParser::_layerCbk(): layer \"%s\" has no TYPE (ignored).", lefLayer->name() ); + return 0; + } + + Technology* techno = DataBase::getDB()->getTechnology(); + + string lefType = lefLayer->type(); + boost::to_upper( lefType ); + + if (lefType == "CUT") { + Layer* layer = techno->getNthCut( parser->getNthCut() ); + if (layer) { + parser->addLayer( lefLayer->name(), layer ); + parser->incNthCut(); + + cerr << " - \"" << lefLayer->name() << "\" map to \"" << layer->getName() << "\"" << endl; + } + } + + if (lefType == "ROUTING") { + Layer* layer = techno->getNthMetal( parser->getNthMetal() ); + if (layer) { + BasicLayer* basicLayer = layer->getBasicLayers().getFirst(); + parser->addLayer( lefLayer->name(), basicLayer ); + + cerr << " - \"" << lefLayer->name() << "\" map to \"" << basicLayer->getName() << "\"" << endl; + + RoutingLayerGauge* gauge = parser->getRoutingGauge()->getLayerGauge( parser->getNthMetal() ); + + if (gauge) { + if (lefLayer->hasPitch()) { + double lefPitch = lefLayer->pitch(); + double crlPitch = DbU::toPhysical(gauge->getPitch(),DbU::Micro); + if (lefPitch > crlPitch) + cerr << Warning( "LefParser::_layerCbk(): CRL Routing pitch for \"%s\" of %fum is less than %fum." + , getString( basicLayer->getName() ).c_str() , crlPitch , lefPitch ) << endl; + } + + if (lefLayer->hasWidth()) { + double lefWidth = lefLayer->width(); + double crlWidth = DbU::toPhysical(gauge->getWireWidth(),DbU::Micro); + if (lefWidth > crlWidth) + cerr << Warning( "LefParser::_layerCbk(): CRL Routing wire width for \"%s\" of %fum is less than %fum." + , getString( basicLayer->getName() ).c_str() , crlWidth , lefWidth ) << endl; + } + + if (lefLayer->hasDirection()) { + string lefDirection = lefLayer->direction(); + boost::to_upper( lefDirection ); + + if ( (lefDirection == "HORIZONTAL") and gauge->isVertical() ) + cerr << Warning( "LefParser::_layerCbk(): CRL Routing direction discrepency for \"%s\", LEF is HORIZONTAL." + , getString( basicLayer->getName() ).c_str() ) << endl; + + if ( (lefDirection == "VERTICAL") and gauge->isHorizontal() ) + cerr << Warning( "LefParser::_layerCbk(): CRL Routing direction discrepency for \"%s\", LEF is VERTICAL." + , getString( basicLayer->getName() ).c_str() ) << endl; + } + } else { + cerr << Warning( "LefParser::_layerCbk(): No CRL routing gauge defined for \"%s\"." + , getString( basicLayer->getName() ).c_str() + ) << endl; + } + + parser->incNthMetal(); + } + } + + return 0; + } + + + int LefParser::_siteCbk ( lefrCallbackType_e c, lefiSite* site, lefiUserData ud ) + { + LefParser* parser = (LefParser*)ud; + + if (site->hasClass()) { + string siteClass = site->siteClass(); + boost::to_upper( siteClass ); + + if (siteClass == "CORE") { + CellGauge* gauge = parser->getCellGauge(); + + DbU::Unit lefSliceStep = DbU::fromPhysical( site->sizeX(), DbU::Micro ); + DbU::Unit lefSliceHeight = DbU::fromPhysical( site->sizeY(), DbU::Micro ); + DbU::Unit crlSliceStep = gauge->getSliceStep (); + DbU::Unit crlSliceHeight = gauge->getSliceHeight(); + + if (not parser->getCoreSiteX() + or ((parser->getCoreSiteX() != crlSliceStep) and (parser->getCoreSiteY() != crlSliceHeight)) ) { + parser->setCoreSite( lefSliceStep, lefSliceHeight ); + + if ( (crlSliceStep == lefSliceStep) and (crlSliceHeight == lefSliceHeight) ) + cerr << " - Site \"" << site->name() << "\" of class CORE match the Coriolis Cell gauge." << endl; + } + } + } + + return 0; + } + + + int LefParser::_obstructionCbk ( lefrCallbackType_e c, lefiObstruction* obstruction, lefiUserData ud ) + { + LefParser* parser = (LefParser*)ud; + + const Layer* layer = NULL; + Cell* cell = parser->getCell(); + Net* blockageNet = cell->getNet( "blockage" ); + + if (not blockageNet) + blockageNet = Net::create( cell, "blockage" ); + + lefiGeometries* geoms = obstruction->geometries(); + for ( int igeom=0 ; igeom < geoms->numItems() ; ++ igeom ) { + if (geoms->itemType(igeom) == lefiGeomLayerE) { + layer = parser->getLayer( geoms->getLayer(igeom) )->getBlockageLayer(); + } + if (not layer) continue; + + if (geoms->itemType(igeom) == lefiGeomRectE) { + lefiGeomRect* r = geoms->getRect(igeom); + double w = r->xh - r->xl; + double h = r->yh - r->yl; + Component* component = NULL; + if (w >= h) { + component = Horizontal::create( blockageNet, layer + , parser->fromUnitsMicrons( (r->yl + r->yh)/2 ) + , parser->fromUnitsMicrons( h ) + , parser->fromUnitsMicrons( r->xl ) + , parser->fromUnitsMicrons( r->xh ) + ); + } else { + component = Vertical::create( blockageNet, layer + , parser->fromUnitsMicrons( (r->xl + r->xh)/2 ) + , parser->fromUnitsMicrons( w ) + , parser->fromUnitsMicrons( r->yl ) + , parser->fromUnitsMicrons( r->yh ) + ); + } + } + } + + return 0; + } + + + int LefParser::_macroCbk ( lefrCallbackType_e c, lefiMacro* macro, lefiUserData ud ) + { + LefParser* parser = (LefParser*)ud; + + string cellName = macro->name(); + DbU::Unit width = 0; + DbU::Unit height = 0; + Cell* cell = parser->getCell(); + + if (cell) { + cell->setName( cellName ); + } else { + cell = Cell::create( parser->getLibrary(true), cellName ); + parser->setCell( cell ); + } + + if (macro->hasSize()) { + width = parser->fromUnitsMicrons( macro->sizeX() ); + height = parser->fromUnitsMicrons( macro->sizeY() ); + cell->setAbutmentBox( Box( 0, 0, width, height ) ); + } + + cerr << " - " << cellName << " " << DbU::getValueString(width) << " " << DbU::getValueString(height) << endl; + parser->setCell( NULL ); + + return 0; + } + + + int LefParser::_pinCbk ( lefrCallbackType_e c, lefiPin* pin, lefiUserData ud ) + { + LefParser* parser = (LefParser*)ud; + + //cerr << " + _pinCbk: " << pin->name() << endl; + + if (not parser->getCell()) parser->setCell( Cell::create( parser->getLibrary(true), "LefImportTmpCell" ) ); + + Net* net = Net::create( parser->getCell(), pin->name() ); + net->setExternal( true ); + + if (pin->hasDirection()) { + string lefDir = pin->direction(); + boost::to_upper( lefDir ); + + if (lefDir == "INPUT" ) net->setDirection( Net::Direction::IN ); + if (lefDir == "OUTPUT" ) net->setDirection( Net::Direction::OUT ); + if (lefDir == "OUTPUT TRISTATE") net->setDirection( Net::Direction::TRISTATE ); + if (lefDir == "INOUT" ) net->setDirection( Net::Direction::INOUT ); + } + + if (pin->hasUse()) { + string lefUse = pin->use(); + boost::to_upper( lefUse ); + + if (lefUse == "SIGNAL") net->setType( Net::Type::LOGICAL ); + //if (lefUse == "ANALOG") net->setType( Net::Type::ANALOG ); + if (lefUse == "CLOCK" ) net->setType( Net::Type::CLOCK ); + if (lefUse == "POWER" ) net->setType( Net::Type::POWER ); + if (lefUse == "GROUND") net->setType( Net::Type::GROUND ); + } + + for ( int iport=0 ; iport < pin->numPorts() ; ++iport ) { + Layer* layer = NULL; + + lefiGeometries* geoms = pin->port( iport ); + for ( int igeom=0 ; igeom < geoms->numItems() ; ++igeom ) { + if (geoms->itemType(igeom) == lefiGeomLayerE) { + layer = parser->getLayer( geoms->getLayer(igeom) ); + continue; + } + if (geoms->itemType(igeom) == lefiGeomRectE) { + lefiGeomRect* r = geoms->getRect(igeom); + double w = r->xh - r->xl; + double h = r->yh - r->yl; + Component* component = NULL; + if (w >= h) { + component = Horizontal::create( net, layer + , parser->fromUnitsMicrons( (r->yl + r->yh)/2 ) + , parser->fromUnitsMicrons( h ) + , parser->fromUnitsMicrons( r->xl ) + , parser->fromUnitsMicrons( r->xh ) + ); + } else { + component = Vertical::create( net, layer + , parser->fromUnitsMicrons( (r->xl + r->xh)/2 ) + , parser->fromUnitsMicrons( w ) + , parser->fromUnitsMicrons( r->yl ) + , parser->fromUnitsMicrons( r->yh ) + ); + } + NetExternalComponents::setExternal( component ); + continue; + } + + string geomTypeName; + switch ( geoms->itemType(igeom) ) { + case lefiGeomUnknown: geomTypeName = "lefiGeomUnknown" ; break; + case lefiGeomLayerE: geomTypeName = "lefiGeomLayerE" ; break; + case lefiGeomLayerMinSpacingE: geomTypeName = "lefiGeomMinSpacingE" ; break; + case lefiGeomLayerRuleWidthE: geomTypeName = "lefiGeomRuleWidthE" ; break; + case lefiGeomWidthE: geomTypeName = "lefiGeomWidthE" ; break; + case lefiGeomPathE: geomTypeName = "lefiGeomPathE" ; break; + case lefiGeomPathIterE: geomTypeName = "lefiGeomPathIterE" ; break; + case lefiGeomRectE: geomTypeName = "lefiGeomRectE" ; break; + case lefiGeomRectIterE: geomTypeName = "lefiGeomRectIterE" ; break; + case lefiGeomPolygonE: geomTypeName = "lefiGeomPolygonE" ; break; + case lefiGeomPolygonIterE: geomTypeName = "lefiGeomPolygonIterE" ; break; + case lefiGeomViaE: geomTypeName = "lefiGeomViaE" ; break; + case lefiGeomViaIterE: geomTypeName = "lefiGeomViaIterE" ; break; + case lefiGeomClassE: geomTypeName = "lefiGeomClassE" ; break; + case lefiGeomLayerExceptPgNetE: geomTypeName = "lefiGeomLayerExceptPgNetE"; break; + case lefiGeomEnd: geomTypeName = "lefiGeomEnd" ; break; + } + + if (not geomTypeName.empty()) + cerr << Warning( "LefParser::_pinCkb(): In PIN \"%s\", unsupported geometry \"%s\"." + , pin->name(), geomTypeName.c_str() ) << endl; + } + } + + return 0; + } + + + int LefParser::flushErrors () + { + int code = (hasErrors()) ? 1 : 0; + + for ( size_t ierror=0 ; ierror < _errors.size() ; ++ierror ) { + string message = "LefImport::load(): " + _errors[ierror]; + cerr << Error(message.c_str(),getString(_library->getName()).c_str()) << endl; + } + clearErrors (); + + return code; + } + + + Library* LefParser::parse ( string file ) + { + cmess1 << " o LEF: <" << file << ">" << endl; + + DbU::setStringMode( DbU::Physical, DbU::Micro ); + + size_t iext = file.rfind( '.' ); + if (file.compare(iext,4,".lef") != 0) + throw Error( "LefImport::load(): DEF files must have \".lef\" extension <%s>.", file.c_str() ); + + size_t islash = file.rfind( '/' ); + islash = (islash == string::npos) ? 0 : islash+1; + + string libraryName = file.substr( islash, file.size()-4-islash ); + unique_ptr parser ( new LefParser(file,libraryName) ); + + FILE* lefStream = fopen( file.c_str(), "r" ); + if (not lefStream) + throw Error( "LefImport::load(): Cannot open LEF file \"%s\".", file.c_str() ); + + //parser->createLibrary( libraryName ); + lefrRead( lefStream, file.c_str(), (lefiUserData)parser.get() ); + + fclose( lefStream ); + + if (not parser->getCoreSiteX()) { + cerr << Warning( "LefParser::parse(): No CORE site found in library, unable to check the Cell gauge." ) << endl; + } else { + if (parser->getCoreSiteY() != parser->getCellGauge()->getSliceHeight()) + cerr << Warning( "LefParser::parse(): CRL slice height discrepency %s while LEF is %s." + , DbU::getValueString(parser->getCellGauge()->getSliceHeight()).c_str() + , DbU::getValueString(parser->getCoreSiteX()).c_str() ) << endl; + + if (parser->getCoreSiteX() != parser->getCellGauge()->getSliceStep()) + cerr << Warning( "LefParser::parse(): CRL slice step discrepency %s while LEF is %s." + , DbU::getValueString(parser->getCellGauge()->getSliceStep()).c_str() + , DbU::getValueString(parser->getCoreSiteY()).c_str() ) << endl; + } + + return parser->getLibrary(); + } + +} // Anonymous namespace. + +#endif // HAVE_LEFDEF + + +namespace CRL { + + using std::cerr; + using std::endl; + using std::string; + using Hurricane::UpdateSession; + + + Library* LefImport::load ( string fileName ) + { + UpdateSession::open (); + + Library* library = NULL; +#if defined(HAVE_LEFDEF) + library = LefParser::parse ( fileName ); +#else + cerr << "[ERROR] CRL::LefImport::load(): \n" + << " Coriolis2 hasn't been compiled with LEF/DEF support. To enable LEF/DEF\n" + << " support, you may obtain parser/driver from Si2 (www.si2.org) then recompile." + << endl; +#endif + + UpdateSession::close (); + + return library; + } + + + void LefImport::reset () + { LefParser::reset(); } + + +} // End of CRL namespace. diff --git a/crlcore/src/pyCRL/CMakeLists.txt b/crlcore/src/pyCRL/CMakeLists.txt index 002752b7..2ab73704 100644 --- a/crlcore/src/pyCRL/CMakeLists.txt +++ b/crlcore/src/pyCRL/CMakeLists.txt @@ -43,6 +43,7 @@ PyAcmSigda.cpp PyIspd05.cpp PyBlif.cpp + PyLefImport.cpp ) set( pyIncludes crlcore/PyBanner.h crlcore/PyCatalog.h @@ -60,6 +61,7 @@ crlcore/PyAcmSigda.h crlcore/PyIspd05.h crlcore/PyBlif.h + crlcore/PyLefImport.h ) set( depLibs crlcore ${HURRICANE_PYTHON_LIBRARIES} diff --git a/crlcore/src/pyCRL/PyCRL.cpp b/crlcore/src/pyCRL/PyCRL.cpp index 45298954..e3e49259 100644 --- a/crlcore/src/pyCRL/PyCRL.cpp +++ b/crlcore/src/pyCRL/PyCRL.cpp @@ -32,6 +32,7 @@ #include "crlcore/PyAcmSigda.h" #include "crlcore/PyIspd05.h" #include "crlcore/PyBlif.h" +#include "crlcore/PyLefImport.h" #include "crlcore/VhdlEntity.h" @@ -120,6 +121,7 @@ extern "C" { PyAcmSigda_LinkPyType (); PyIspd05_LinkPyType (); PyBlif_LinkPyType (); + PyLefImport_LinkPyType (); PYTYPE_READY ( Banner ); PYTYPE_READY ( CatalogState ); @@ -138,6 +140,7 @@ extern "C" { PYTYPE_READY ( AcmSigda ); PYTYPE_READY ( Ispd05 ); PYTYPE_READY ( Blif ); + PYTYPE_READY ( LefImport ); // Identifier string can take up to 10 characters. __cs.addType ( "alcLib" , &PyTypeAllianceLibrary , "" , false ); @@ -188,6 +191,8 @@ extern "C" { PyModule_AddObject ( module, "Ispd05", (PyObject*)&PyTypeIspd05 ); Py_INCREF ( &PyTypeBlif ); PyModule_AddObject ( module, "Blif", (PyObject*)&PyTypeBlif ); + Py_INCREF ( &PyTypeLefImport ); + PyModule_AddObject ( module, "LefImport", (PyObject*)&PyTypeLefImport ); PyCatalog_postModuleInit (); PyEnvironment_postModuleInit (); diff --git a/crlcore/src/pyCRL/PyLefImport.cpp b/crlcore/src/pyCRL/PyLefImport.cpp new file mode 100644 index 00000000..da7a34fb --- /dev/null +++ b/crlcore/src/pyCRL/PyLefImport.cpp @@ -0,0 +1,121 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2017-2017, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance / Hurricane Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyLefImport.cpp" | +// +-----------------------------------------------------------------+ + + +#include "crlcore/PyLefImport.h" +#include "hurricane/isobar/PyLibrary.h" +#include +#include + + +namespace CRL { + + using std::cerr; + using std::endl; + using std::hex; + using std::string; + using std::ostringstream; + using Hurricane::tab; + using Hurricane::Exception; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Warning; + using Hurricane::Library; + using Isobar::ProxyProperty; + using Isobar::ProxyError; + using Isobar::ConstructorError; + using Isobar::HurricaneError; + using Isobar::HurricaneWarning; + using Isobar::ParseOneArg; + using Isobar::ParseTwoArg; + using Isobar::__cs; + using Isobar::PyLibrary_Link; + + +extern "C" { + + +#if defined(__PYTHON_MODULE__) + +// +=================================================================+ +// | "PyLefImport" Python Module Code Part | +// +=================================================================+ + + + static PyObject* PyLefImport_load ( PyObject*, PyObject* args ) + { + cdebug_log(30,0) << "PyLefImport_load()" << endl; + + Library* library = NULL; + + HTRY + char* lefFile = NULL; + + if (PyArg_ParseTuple( args, "s:LefImport.load", &lefFile )) { + library = LefImport::load( lefFile ); + } else { + PyErr_SetString ( ConstructorError, "LefImport.load(): Bad type or bad number of parameters." ); + return NULL; + } + HCATCH + + return (PyObject*)PyLibrary_Link(library); + } + + + static PyObject* PyLefImport_reset ( PyObject*, PyObject* ) + { + cdebug_log(30,0) << "PyLefImport_reset()" << endl; + HTRY + LefImport::reset(); + HCATCH + Py_RETURN_NONE; + } + + + // Standart Destroy (Attribute). + + + PyMethodDef PyLefImport_Methods[] = + { { "load" , (PyCFunction)PyLefImport_load , METH_VARARGS|METH_STATIC + , "Load a complete Cadence LEF library." } + , { "reset" , (PyCFunction)PyLefImport_reset , METH_NOARGS|METH_STATIC + , "Reset the Cadence LEF parser (clear technology)." } + //, { "destroy" , (PyCFunction)PyLefImport_destroy , METH_VARARGS + // , "Destroy the associated hurricane object. The python object remains." } + , {NULL, NULL, 0, NULL} /* sentinel */ + }; + + + NoObjectDeleteMethod(LefImport) + PyTypeObjectLinkPyTypeWithoutObject(LefImport,LefImport) + + +#else // End of Python Module Code Part. + + +// +=================================================================+ +// | "PyLefImport" Shared Library Code Part | +// +=================================================================+ + + // Type Definition. + PyTypeObjectDefinitionsOfModule(CRL,LefImport) + + +#endif // End of Shared Library Code Part. + +} // extern "C". + +} // CRL namespace. diff --git a/crlcore/src/pyCRL/crlcore/PyLefImport.h b/crlcore/src/pyCRL/crlcore/PyLefImport.h new file mode 100644 index 00000000..fa8224a4 --- /dev/null +++ b/crlcore/src/pyCRL/crlcore/PyLefImport.h @@ -0,0 +1,55 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2017-2017, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | Alliance / Hurricane Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./crlcore/PyLefImport.h" | +// +-----------------------------------------------------------------+ + + +#ifndef CRL_PY_LEF_IMPORT_H +#define CRL_PY_LEF_IMPORT_H + +#include "hurricane/isobar/PyHurricane.h" +#include "crlcore/LefImport.h" + + +namespace CRL { + +extern "C" { + + +// ------------------------------------------------------------------- +// Python Object : "PyLefImport". + + typedef struct { + PyObject_HEAD + } PyLefImport; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyCRL.ccp". + + extern PyTypeObject PyTypeLefImport; + extern PyMethodDef PyLefImport_Methods[]; + + extern void PyLefImport_LinkPyType(); + + +#define IsPyLefImport(v) ( (v)->ob_type == &PyTypeLefImport ) +#define PY_LEFIMPORT(v) ( (PyLefImport*)(v) ) + + +} // extern "C". + +} // CRL namespace. + +#endif // CRL_PY_LEF_IMPORT_H diff --git a/unicorn/src/ImportCell.cpp b/unicorn/src/ImportCell.cpp index febd65ef..6a926406 100644 --- a/unicorn/src/ImportCell.cpp +++ b/unicorn/src/ImportCell.cpp @@ -15,9 +15,9 @@ #include +#include #include "hurricane/Error.h" #include "unicorn/ImportCell.h" -#include "unicorn/ImportCellDialog.h" namespace Unicorn { @@ -25,41 +25,54 @@ namespace Unicorn { using std::cerr; using std::endl; using std::string; + using std::function; using Hurricane::Error; using Hurricane::Cell; + using Hurricane::Library; + + + Importer:: Importer () : _rvalue() { } + Importer::~Importer () { } ImportCell::ImportCell () - : _count (0) - , _lut () - , _dialog(NULL) + : _importers() + , _dialog (NULL) + , _activeId (0) { } - void ImportCell::addImporter ( std::string menuName, std::function callback ) + ImportCell::~ImportCell () { - _lut.insert( make_pair( _count, make_pair(menuName,callback) ) ); - _dialog->addFormat( menuName.c_str(), _count++ ); + for ( Importer* importer : _importers ) delete importer; } - Cell* ImportCell::load ( const string& cellName, int format ) + bool ImportCell::load ( const string& cellName, int formatId ) { - Cell* cell = NULL; - - ImportLut::iterator iimport = _lut.find( format ); - if (iimport == _lut.end()) { - cerr << Error( "Importer id:%d for cell %s not found.", format, cellName.c_str() ) << endl; - return NULL; + if ( (formatId < 0) or ((size_t)formatId >= _importers.size()) ) { + cerr << Error( "Importer id:%d for library or cell %s not found.", formatId, cellName.c_str() ) << endl; + _activeId = _importers.size(); + return false; } + _activeId = (size_t)formatId; + + Importer* importer = _importers[ _activeId ]; + importer->load( cellName ); - cell = iimport->second.second( cellName ); - - if (not cell) { + if (importer->isA() and not importer->getAs()) { cerr << Error( "Cell not found: %s", cellName.c_str() ) << endl; + _activeId = _importers.size(); + return false; } - return cell; + if (importer->isA() and not importer->getAs()) { + cerr << Error( "Library not found: %s", cellName.c_str() ) << endl; + _activeId = _importers.size(); + return false; + } + + return true; } diff --git a/unicorn/src/ImportCellDialog.cpp b/unicorn/src/ImportCellDialog.cpp index d6bc3150..0216a36f 100644 --- a/unicorn/src/ImportCellDialog.cpp +++ b/unicorn/src/ImportCellDialog.cpp @@ -53,7 +53,7 @@ namespace Unicorn { label->setText ( tr("Enter Cell name (without extention)") ); label->setFont ( Graphics::getNormalFont(true) ); - _lineEdit->setMinimumWidth ( 400 ); + _lineEdit->setMinimumWidth ( Graphics::toHighDpi(400) ); _viewerCheckBox->setText ( tr("Import in new Viewer") ); QPushButton* okButton = new QPushButton (); @@ -81,13 +81,6 @@ namespace Unicorn { formatLabel->setFont ( Graphics::getNormalFont(true) ); hLayout2->addWidget ( formatLabel ); -#if 0 - _formatComboBox->addItem ( tr("ACM/SIGDA (aka MCNC, .bench)"), ImportCell::AcmSigda ); - _formatComboBox->addItem ( tr("ISPD'04 (Bookshelf)") , ImportCell::Ispd04 ); - _formatComboBox->addItem ( tr("ISPD'05 (Bookshelf)") , ImportCell::Ispd05 ); - _formatComboBox->addItem ( tr("ICCAD'04 (LEF/DEF)") , ImportCell::Iccad04 ); - _formatComboBox->addItem ( tr("Alliance compliant DEF") , ImportCell::AllianceDef ); -#endif hLayout2->addWidget ( _formatComboBox ); QVBoxLayout* vLayout = new QVBoxLayout (); diff --git a/unicorn/src/UnicornGui.cpp b/unicorn/src/UnicornGui.cpp index adbb3d3b..0459f0f9 100644 --- a/unicorn/src/UnicornGui.cpp +++ b/unicorn/src/UnicornGui.cpp @@ -19,6 +19,7 @@ #include #include "hurricane/DebugSession.h" #include "hurricane/Warning.h" +#include "hurricane/DataBase.h" #include "hurricane/viewer/Script.h" #include "hurricane/viewer/CellViewer.h" #include "hurricane/viewer/PyCellViewer.h" @@ -32,6 +33,7 @@ #include "crlcore/Ispd05Bookshelf.h" #include "crlcore/Blif.h" #include "crlcore/Iccad04Lefdef.h" +#include "crlcore/LefImport.h" #include "crlcore/DefImport.h" #include "crlcore/DefExport.h" #include "crlcore/GdsDriver.h" @@ -50,6 +52,8 @@ namespace Unicorn { using Hurricane::Warning; using Hurricane::PyCellViewer_Link; using Hurricane::jsonCellParse; + using Hurricane::DataBase; + using Hurricane::Library; using CRL::System; using CRL::Catalog; using CRL::AllianceFramework; @@ -59,6 +63,7 @@ namespace Unicorn { using CRL::Ispd05; using CRL::Blif; using CRL::Iccad04Lefdef; + using CRL::LefImport; using CRL::DefImport; using CRL::DefExport; using CRL::GdsDriver; @@ -92,13 +97,14 @@ namespace Unicorn { _runUnicornInit(); _importCell.setDialog( _importDialog ); - _importCell.addImporter( "JSON (experimental)" , std::bind( &Cell::fromJson , placeholders::_1 ) ); - _importCell.addImporter( "BLIF (Yosys/ABC)" , std::bind( &Blif::load , placeholders::_1 ) ); - _importCell.addImporter( "ACM/SIGDA (aka MCNC, .bench)", std::bind( &AcmSigda::load , placeholders::_1 ) ); - _importCell.addImporter( "ISPD'04 (Bookshelf)" , std::bind( &Ispd04::load , placeholders::_1 ) ); - _importCell.addImporter( "ISPD'05 (Bookshelf)" , std::bind( &Ispd05::load , placeholders::_1 ) ); - _importCell.addImporter( "ICCAD'04 (LEF/DEF)" , std::bind( &Iccad04Lefdef::load, placeholders::_1, 0 ) ); - _importCell.addImporter( "Alliance compliant DEF" , std::bind( &DefImport::load , placeholders::_1, DefImport::FitAbOnCells) ); + _importCell.addImporter ( "JSON (experimental)" , std::bind( &Cell::fromJson , placeholders::_1 ) ); + _importCell.addImporter ( "BLIF (Yosys/ABC)" , std::bind( &Blif::load , placeholders::_1 ) ); + _importCell.addImporter ( "ACM/SIGDA (aka MCNC, .bench)", std::bind( &AcmSigda::load , placeholders::_1 ) ); + _importCell.addImporter ( "ISPD'04 (Bookshelf)" , std::bind( &Ispd04::load , placeholders::_1 ) ); + _importCell.addImporter ( "ISPD'05 (Bookshelf)" , std::bind( &Ispd05::load , placeholders::_1 ) ); + _importCell.addImporter ( "ICCAD'04 (LEF/DEF)" , std::bind( &Iccad04Lefdef::load, placeholders::_1, 0 ) ); + _importCell.addImporter ( "Alliance compliant DEF" , std::bind( &DefImport::load , placeholders::_1, DefImport::FitAbOnCells) ); + _importCell.addImporter( "Cadence LEF" , std::bind( &LefImport::load , placeholders::_1 ) ); _libraryManager->setCellViewer( this ); } @@ -196,6 +202,9 @@ namespace Unicorn { Cell* UnicornGui::getCellFromDb ( const char* name ) { + Cell* cell = DataBase::getDB()->getCell( name ); + if (cell) return cell; + return AllianceFramework::get()->getCell ( name, Catalog::State::Views ); } @@ -253,16 +262,17 @@ namespace Unicorn { int format; if ( _importDialog->runDialog( cellName, format, newViewer ) ) { - Cell* cell = _importCell.load( cellName.toStdString(), format ); - - if (cell) { - UnicornGui* viewer = this; - if (newViewer) { - viewer = UnicornGui::create(); - viewer->show(); + if (_importCell.load( cellName.toStdString(), format )) { + Cell* cell = _importCell.getLoaded(); + if (cell) { + UnicornGui* viewer = this; + if (newViewer) { + viewer = UnicornGui::create(); + viewer->show(); + } + viewer->setCell( cell ); + emit cellLoadedFromDisk ( cell ); } - viewer->setCell( cell ); - emit cellLoadedFromDisk ( cell ); } } } diff --git a/unicorn/src/cgt.py b/unicorn/src/cgt.py index 73330b72..fd56ba18 100755 --- a/unicorn/src/cgt.py +++ b/unicorn/src/cgt.py @@ -22,7 +22,7 @@ except ImportError, e: module = serror.split()[-1] print '[ERROR] The <%s> python module or symbol cannot be loaded.' % module print ' Please check the integrity of the package.' - if str(e).find('cannot open shared object file'): + if serror.find('cannot open shared object file'): library = serror.split(':')[0] print '[ERROR] The <%s> shared library cannot be loaded.' % library print ' Under RHEL 6, you must be under devtoolset-2.' @@ -242,6 +242,6 @@ if __name__ == '__main__': sys.exit(not kiteSuccess) except Exception, e: - print e + showPythonTrace( sys.argv[0], e ) sys.exit(0) diff --git a/unicorn/src/unicorn/ImportCell.h b/unicorn/src/unicorn/ImportCell.h index e2b13661..7cd75910 100644 --- a/unicorn/src/unicorn/ImportCell.h +++ b/unicorn/src/unicorn/ImportCell.h @@ -1,16 +1,16 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2014-2016, All Rights Reserved +// Copyright (c) UPMC/LIP6 2014-2017, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | U n i c o r n - M a i n G U I | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | -// | C++ Header : "./ImportCell.h" | +// | C++ Header : "./unicorn/ImportCell.h" | // +-----------------------------------------------------------------+ @@ -18,36 +18,96 @@ #define UNICORN_IMPORT_CELL_H #include -#include +#include #include +#include "unicorn/ImportCellDialog.h" namespace Hurricane { class Cell; + class Library; } namespace Unicorn { - class ImportCellDialog; + + class Importer { + public: + Importer (); + virtual ~Importer (); + template< typename T > + inline bool isA () const; + template< typename T > + inline T getAs () const; + virtual void load ( std::string fileName ) = 0; + protected: + boost::any _rvalue; + }; + + template< typename T > + inline bool Importer::isA () const { return _rvalue.type() == typeid(T); } + + template< typename T > + inline T Importer::getAs () const { return boost::any_cast( _rvalue ); } + + + template< typename T > + class FileImporter : public Importer { + public: + FileImporter ( std::function& loader ); + virtual ~FileImporter (); + virtual void load ( std::string fileName ); + private: + std::function loader_; + }; + + + template< typename T > + FileImporter::FileImporter ( std::function& loader ) + : Importer(), loader_(loader) + { } + + template< typename T > + FileImporter::~FileImporter () { } + + template< typename T > + void FileImporter::load ( std::string fileName ) { _rvalue = loader_( fileName ); } class ImportCell { public: - typedef std::map< int, std::pair< std::string, std::function > > ImportLut; - public: - ImportCell (); - inline void setDialog ( ImportCellDialog* ); - Hurricane::Cell* load ( const std::string&, int format ); - void addImporter ( std::string, std::function ); + ImportCell (); + ~ImportCell (); + inline void setDialog ( ImportCellDialog* ); + bool load ( const std::string&, int formatId ); + template< typename T > + void addImporter ( std::string, std::function ); + inline bool succeeded () const; + template< typename T > + T getLoaded () const; private: - int _count; - ImportLut _lut; - ImportCellDialog* _dialog; + std::vector _importers; + ImportCellDialog* _dialog; + size_t _activeId; }; inline void ImportCell::setDialog ( ImportCellDialog* dialog ) { _dialog = dialog; } + inline bool ImportCell::succeeded () const { return _activeId < _importers.size(); } + + + template< typename T > + void ImportCell::addImporter ( std::string menuName, std::function callback ) + { + _dialog->addFormat( menuName.c_str(), _importers.size() ); + _importers.push_back( new FileImporter(callback) ); + } + + + template< typename T > + T ImportCell::getLoaded() const + { return (succeeded() and _importers[_activeId]->isA()) ? _importers[_activeId]->getAs() : NULL; } } // Unicorn namespace. -#endif +#endif // UNICORN_IMPORT_CELL_H diff --git a/unicorn/src/unicorn/ImportCellDialog.h b/unicorn/src/unicorn/ImportCellDialog.h index 51339217..3e4e2211 100644 --- a/unicorn/src/unicorn/ImportCellDialog.h +++ b/unicorn/src/unicorn/ImportCellDialog.h @@ -1,14 +1,14 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2016, All Rights Reserved +// Copyright (c) UPMC/LIP6 2008-2017, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | U n i c o r n - M a i n G U I | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./unicorn/ImportCellDialog.h" | // +-----------------------------------------------------------------+ @@ -44,7 +44,7 @@ namespace Unicorn { }; -} // End of Unicorn namespace. +} // Unicorn namespace. #endif // UNICORN_IMPORT_CELL_DIALOG_H diff --git a/unicorn/src/unicorn/OpenCellDialog.h b/unicorn/src/unicorn/OpenCellDialog.h index 620cfdfd..61d16d2d 100644 --- a/unicorn/src/unicorn/OpenCellDialog.h +++ b/unicorn/src/unicorn/OpenCellDialog.h @@ -2,21 +2,21 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved +// Copyright (c) UPMC/LIP6 2008-2017, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | U n i c o r n - M a i n G U I | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./unicorn/OpenCellDialog.h" | // +-----------------------------------------------------------------+ -#ifndef __UNICORN_OPEN_CELL_DIALOG_H__ -#define __UNICORN_OPEN_CELL_DIALOG_H__ +#ifndef UNICORN_OPEN_CELL_DIALOG_H +#define UNICORN_OPEN_CELL_DIALOG_H #include @@ -42,9 +42,7 @@ namespace Unicorn { }; +} // Unicorn namespace. -} // End of Unicorn namespace. - - -#endif +#endif // UNICORN_OPEN_CELL_DIALOG_H