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:
parent
51b3a11739
commit
2b3b847162
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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.
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue