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).
This commit is contained in:
Jean-Paul Chaput 2017-11-17 11:48:20 +01:00
parent 51b3a11739
commit 2b3b847162
16 changed files with 1005 additions and 75 deletions

View File

@ -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
)

View File

@ -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 );
}

View File

@ -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 <string>
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

View File

@ -273,6 +273,12 @@ inline std::string getString<const Constant::LayerGaugeType*>
}
template<>
inline std::string getString<Constant::LayerGaugeType*>
( Constant::LayerGaugeType* layerGaugeType )
{ return getString<const Constant::LayerGaugeType*>(layerGaugeType); }
template<>
inline std::string getString<const Constant::LayerGaugeType>
( const Constant::LayerGaugeType layerGaugeType )
@ -285,6 +291,12 @@ inline std::string getString<const Constant::LayerGaugeType>
}
template<>
inline std::string getString<Constant::LayerGaugeType>
( Constant::LayerGaugeType layerGaugeType )
{ return getString<const Constant::LayerGaugeType>(layerGaugeType); }
IOSTREAM_POINTER_SUPPORT(Constant::LayerGaugeType);

View File

@ -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 <cstdio>
#include <cstring>
#include <iostream>
#include <memory>
#include <boost/algorithm/string.hpp>
#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<string>& 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<string,Layer*> _layerLut;
vector<string> _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<string>& LefParser::getErrors () const { return _errors; }
inline void LefParser::pushError ( const string& error ) { _errors.push_back(error); }
inline void LefParser::clearErrors () { return _errors.clear(); }
map<string,Layer*> 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<LefParser> 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.

View File

@ -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}

View File

@ -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 , "<AllianceLibrary>" , 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 ();

View File

@ -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 <string>
#include <sstream>
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.

View File

@ -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

View File

@ -15,9 +15,9 @@
#include <iostream>
#include <boost/any.hpp>
#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<Cell*(std::string)> 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<Cell*>() and not importer->getAs<Cell*>()) {
cerr << Error( "Cell not found: %s", cellName.c_str() ) << endl;
_activeId = _importers.size();
return false;
}
return cell;
if (importer->isA<Library*>() and not importer->getAs<Library*>()) {
cerr << Error( "Library not found: %s", cellName.c_str() ) << endl;
_activeId = _importers.size();
return false;
}
return true;
}

View File

@ -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 ();

View File

@ -19,6 +19,7 @@
#include <QMenu>
#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<Cell*> ( "JSON (experimental)" , std::bind( &Cell::fromJson , placeholders::_1 ) );
_importCell.addImporter<Cell*> ( "BLIF (Yosys/ABC)" , std::bind( &Blif::load , placeholders::_1 ) );
_importCell.addImporter<Cell*> ( "ACM/SIGDA (aka MCNC, .bench)", std::bind( &AcmSigda::load , placeholders::_1 ) );
_importCell.addImporter<Cell*> ( "ISPD'04 (Bookshelf)" , std::bind( &Ispd04::load , placeholders::_1 ) );
_importCell.addImporter<Cell*> ( "ISPD'05 (Bookshelf)" , std::bind( &Ispd05::load , placeholders::_1 ) );
_importCell.addImporter<Cell*> ( "ICCAD'04 (LEF/DEF)" , std::bind( &Iccad04Lefdef::load, placeholders::_1, 0 ) );
_importCell.addImporter<Cell*> ( "Alliance compliant DEF" , std::bind( &DefImport::load , placeholders::_1, DefImport::FitAbOnCells) );
_importCell.addImporter<Library*>( "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<Cell*>();
if (cell) {
UnicornGui* viewer = this;
if (newViewer) {
viewer = UnicornGui::create();
viewer->show();
}
viewer->setCell( cell );
emit cellLoadedFromDisk ( cell );
}
viewer->setCell( cell );
emit cellLoadedFromDisk ( cell );
}
}
}

View File

@ -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 <coriolis> 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)

View File

@ -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 <string>
#include <map>
#include <vector>
#include <functional>
#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<T>( _rvalue ); }
template< typename T >
class FileImporter : public Importer {
public:
FileImporter ( std::function<T(std::string)>& loader );
virtual ~FileImporter ();
virtual void load ( std::string fileName );
private:
std::function<T(std::string)> loader_;
};
template< typename T >
FileImporter<T>::FileImporter ( std::function<T(std::string)>& loader )
: Importer(), loader_(loader)
{ }
template< typename T >
FileImporter<T>::~FileImporter () { }
template< typename T >
void FileImporter<T>::load ( std::string fileName ) { _rvalue = loader_( fileName ); }
class ImportCell {
public:
typedef std::map< int, std::pair< std::string, std::function<Hurricane::Cell*(std::string)> > > ImportLut;
public:
ImportCell ();
inline void setDialog ( ImportCellDialog* );
Hurricane::Cell* load ( const std::string&, int format );
void addImporter ( std::string, std::function<Hurricane::Cell*(std::string)> );
ImportCell ();
~ImportCell ();
inline void setDialog ( ImportCellDialog* );
bool load ( const std::string&, int formatId );
template< typename T >
void addImporter ( std::string, std::function<T(std::string)> );
inline bool succeeded () const;
template< typename T >
T getLoaded () const;
private:
int _count;
ImportLut _lut;
ImportCellDialog* _dialog;
std::vector<Importer*> _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<T(std::string)> callback )
{
_dialog->addFormat( menuName.c_str(), _importers.size() );
_importers.push_back( new FileImporter<T>(callback) );
}
template< typename T >
T ImportCell::getLoaded() const
{ return (succeeded() and _importers[_activeId]->isA<T>()) ? _importers[_activeId]->getAs<T>() : NULL; }
} // Unicorn namespace.
#endif
#endif // UNICORN_IMPORT_CELL_H

View File

@ -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

View File

@ -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 <QDialog>
@ -42,9 +42,7 @@ namespace Unicorn {
};
} // Unicorn namespace.
} // End of Unicorn namespace.
#endif
#endif // UNICORN_OPEN_CELL_DIALOG_H