Adding Liberty to Hurricane bridge + python wrapper

Adding Python wrappers, fixes accross liberty lib
Fixing infinite loop
Tested and fixed Liberty to Hurricane bridge

Setting proper ownership of liberty library.

Changing name of LibertyToDb (because name was nonsense)
This commit is contained in:
Hippolyte Melica
2026-04-12 12:57:18 +02:00
committed by Jean-Paul Chaput
parent efd64d35c6
commit 9b18da3e0a
16 changed files with 967 additions and 54 deletions

View File

@@ -1,14 +1,14 @@
subdir('src/ccore')
subdir('src/liberty')
subdir('src/LibraryManager')
subdir('src/cyclop')
subdir('src/pyCRL')
subdir('src/liberty')
subdir('python')
subdir('doc/crlcore')
CrlCore = declare_dependency(
link_with: [crlcore, librarymanager, pycrlcore],
include_directories: [crlcore_includes, pyCRL_includes, librarymanager_includes],
link_with: [crlcore, librarymanager, pycrlcore, liberty],
include_directories: [crlcore_includes, pyCRL_includes, librarymanager_includes,liberty_includes],
dependencies: [qt_deps, py_deps, boost, rapidjson, Hurricane]
)

View File

@@ -18,6 +18,7 @@
#include "crlcore/liberty/Library.h"
#include "crlcore/liberty/Statement.h"
#include <algorithm>
#include <iostream>
#include <string>
#include <string_view>
@@ -25,10 +26,12 @@ namespace Liberty {
Group::Group(Group *parent) : Statement(parent)
{
if (parent)
if (parent and parent != this)
_library = parent->getLibrary();
else
_library = dynamic_cast<Library*>(this);
_library = static_cast<Library*>(this);
// this is a static_cast because Library is a child of Group
// dynamic_case would not work.
}
Group::~Group()
@@ -37,11 +40,28 @@ namespace Liberty {
delete statement;
}
void Group::addStatement(Statement *statement)
{
if (statement->isAttribute()) {
auto it = _attributes.find(statement->getName());
if (it != _attributes.end()) {
std::cout << (getParent() ? "[WARNING]" : "[INFO]") << " Attribute " << statement->getName()
<< " twice in group " << getName()
<< (getParent() ? ", getAttribute() will return incoherent results.":".") << std::endl;
it->second = statement->getAsAttribute();
} else
_attributes.insert({statement->getName(), statement->getAsAttribute()});
}
if (statement == this)
return; // not adding library to its own statements.
_statements.push_back(statement);
}
Group *Group::getGroup(const std::string &group_name) const
{
Statement *ret;
ret = *std::find_if(_statements.begin(), _statements.end(), [&](Statement *item){
if (item->isGroup())
if (not item->isGroup())
return false;
Group *g = item->getAsGroup();
return g->getName() == group_name;
@@ -51,7 +71,11 @@ namespace Liberty {
Attribute *Group::getAttribute(const std::string &attribute_name) const
{
return _attributes.at(attribute_name);
auto it = _attributes.find(attribute_name);
if (it != _attributes.end()) {
return it->second;
}
return nullptr;
}
Library *Group::getLibrary()

View File

@@ -0,0 +1,32 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Uiversité 2013-2026, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | V L S I B a c k e n d D a t a - B a s e |
// | |
// | Author : Hippolyte MELICA |
// | E-mail : hippolyte.melica@etu.sorbonne-universite.fr |
// | =============================================================== |
// | C++ Module : "./LibertyLibProperty.cpp" |
// +-----------------------------------------------------------------+
#include "crlcore/liberty/LibertyLibProperty.h"
#include "crlcore/liberty/Group.h"
#include "hurricane/Property.h"
namespace Liberty {
using Hurricane::PrivateProperty;
LibertyLibProperty::LibertyLibProperty(Library *library) : PrivateProperty(), _library(library) {}
LibertyLibProperty::LibertyLibProperty(const Library *library) : PrivateProperty(), _library(library) {}
LibertyLibProperty::~LibertyLibProperty() {
delete _library;
}
}

View File

@@ -0,0 +1,28 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Uiversité 2013-2026, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | V L S I B a c k e n d D a t a - B a s e |
// | |
// | Author : Hippolyte MELICA |
// | E-mail : hippolyte.melica@etu.sorbonne-universite.fr |
// | =============================================================== |
// | C++ Module : "./LibertyProperty.cpp" |
// +-----------------------------------------------------------------+
#include "crlcore/liberty/LibertyProperty.h"
#include "crlcore/liberty/Group.h"
#include "hurricane/Property.h"
namespace Liberty {
using Hurricane::PrivateProperty;
LibertyProperty::LibertyProperty(Group *cell) : PrivateProperty(), _cell(cell) {}
LibertyProperty::~LibertyProperty() {}
}

View File

@@ -15,9 +15,15 @@
#include "crlcore/liberty/Library.h"
#include "crlcore/liberty/LibertyLibProperty.h"
#include "crlcore/liberty/LibertyProperty.h"
#include "crlcore/liberty/Parser.h"
#include "crlcore/liberty/SimpleGroup.h"
#include "crlcore/liberty/Statement.h"
#include "hurricane/Cells.h"
#include "hurricane/Library.h"
#include "hurricane/DataBase.h"
#include <cstddef>
#include <filesystem>
#include <iostream>
#include <string>
@@ -33,26 +39,16 @@ namespace Liberty {
bool Library::load() {
Parser parser(_path.string());
if (not parser.parse(this))
return false;
// we need to make library top level.
SimpleGroup *actual = dynamic_cast<SimpleGroup*>(this->_statements.front()->getAsGroup());
if (!actual)
return false;
_statements.clear();
_statements = actual->getStatements();
this->setName(actual->getName());
this->setGroupIdentifier(actual->getGroupIdentifier());
actual->clear_statements();
delete actual;
return true;
return parser.parse(this);
}
Group *Library::getCellGroup(const std::string &cell_name) const
{
if (_cells.find(cell_name) == _cells.end())
return nullptr;
return _cells.at(cell_name);
auto it = _cells.find(cell_name);
if (it != _cells.end()) {
return it->second;
}
return nullptr;
}
void Library::_include(const std::string &filename) {
@@ -62,13 +58,40 @@ namespace Liberty {
}
void Library::addCellGroup(const std::string &cell_name, Group *group) {
std::cout << "Adding cell '" << cell_name << "'" << std::endl;
if (_cells.find(cell_name) != _cells.end()) {
if (_cells.at(cell_name))
delete _cells.at(cell_name);
_cells[cell_name] = nullptr;
auto it = _cells.find(cell_name);
if (it != _cells.end()) {
if (it->second)
delete it->second;
it->second = group;
return;
}
_cells[cell_name] = group;
_cells.insert({cell_name, group});
}
void Library::mapLibertyToDb(Hurricane::DataBase *db) const
{
using Hurricane::Cell;
Hurricane::Library* root = db->getRootLibrary();
size_t count = 0;
for (Hurricane::Library * lib : root->getLibraries()) {
for (Cell *cell : lib->getCells()) {
Group *liberty_cell = getCellGroup(cell->getName()._getString());
if (!liberty_cell) {
std::cerr << "[WARNING] Cell " << cell->getName()._getString()<< " is not found in Liberty library "
<< _path.filename()<< std::endl;
continue;
}
LibertyProperty *property = new LibertyProperty(liberty_cell);
cell->put(property);
count++;
}
}
std::cout << "[INFO] Matched " << count << " cells of library. Added Liberty infos." << std::endl;
// Make db own Liberty::Library to free it properly (at this point python won't do it).
LibertyLibProperty *library_prop = new LibertyLibProperty(this);
db->put(library_prop);
}
}

View File

@@ -40,6 +40,7 @@ namespace Liberty {
return false;
State state = Default;
Group *current = dynamic_cast<Group*>(lib);
bool CurrentIsLibrary = true;
std::queue<Token> waiting;
while (1) {
@@ -181,7 +182,12 @@ namespace Liberty {
// if (waiting.size() != 2 or waiting.front().type == Coma)
// return _print_error(t);
if (waiting.size() == 2) {
SimpleGroup *sgroup = new SimpleGroup(current);
SimpleGroup *sgroup;
if (CurrentIsLibrary) {
sgroup = dynamic_cast<SimpleGroup*>(current);
CurrentIsLibrary = false;
} else
sgroup = new SimpleGroup(current);
sgroup->setName(waiting.front().str);
waiting.pop();
sgroup->setGroupIdentifier(waiting.front().str);

View File

@@ -28,14 +28,14 @@ namespace Liberty {
void SimpleGroup::setGroupIdentifier(const std::string &group_id)
{
_group_identifier = group_id;
if (_group_identifier == "cell")
if (getName() == "cell")
getLibrary()->addCellGroup(_group_identifier, this);
}
void SimpleGroup::setGroupIdentifier(const std::string_view &group_id)
{
_group_identifier = group_id;
if (_group_identifier == "cell")
if (getName() == "cell")
getLibrary()->addCellGroup(_group_identifier, this);
}

View File

@@ -15,7 +15,7 @@
#pragma once
#include "Statement.h"
#include <istream>
#include "Attribute.h"
#include <map>
#include <string>
#include <string_view>
@@ -42,7 +42,7 @@ namespace Liberty {
~Group();
inline bool isGroup () const override;
inline void addStatement (Statement *statement) ;
void addStatement (Statement *statement) ;
Library *getLibrary () ;
inline void clear_statements () ;
@@ -67,13 +67,6 @@ namespace Liberty {
return true;
}
inline void Group::addStatement(Statement *statement)
{
_statements.push_back(statement);
if (statement->isAttribute())
_attributes.at(statement->getName()) = statement->getAsAttribute();
}
inline const std::vector<Statement*> &Group::getStatements() const
{
return _statements;

View File

@@ -0,0 +1,49 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Uiversité 2013-2026, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | V L S I B a c k e n d D a t a - B a s e |
// | |
// | Author : Hippolyte MELICA |
// | E-mail : hippolyte.melica@etu.sorbonne-universite.fr |
// | =============================================================== |
// | C++ Module : "./LibertyLibProperty.h" |
// +-----------------------------------------------------------------+
#pragma once
#include "Group.h"
#include "crlcore/liberty/Library.h"
#include "hurricane/Name.h"
#include "hurricane/Property.h"
#include <string>
namespace Liberty {
using Hurricane::PrivateProperty;
class LibertyLibProperty: public PrivateProperty {
public:
LibertyLibProperty( Library *library);
LibertyLibProperty(const Library *library);
~LibertyLibProperty();
inline Hurricane::Name getName() const override;
inline std::string _getTypeName() const override;
protected:
const Library *_library;
};
inline Hurricane::Name LibertyLibProperty::getName() const
{
return Hurricane::Name("Liberty Cell Library");
}
inline std::string LibertyLibProperty::_getTypeName() const
{
return "LibertyLibProperty";
}
}

View File

@@ -0,0 +1,54 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Uiversité 2013-2026, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | V L S I B a c k e n d D a t a - B a s e |
// | |
// | Author : Hippolyte MELICA |
// | E-mail : hippolyte.melica@etu.sorbonne-universite.fr |
// | =============================================================== |
// | C++ Module : "./LibertyProperty.h" |
// +-----------------------------------------------------------------+
#pragma once
#include "Group.h"
#include "hurricane/Name.h"
#include "hurricane/Property.h"
#include <string>
namespace Liberty {
using Hurricane::PrivateProperty;
class LibertyProperty: public PrivateProperty {
public:
LibertyProperty(Group *cell);
~LibertyProperty();
inline Group *getLibCell() const;
inline Hurricane::Name getName() const override;
inline std::string _getTypeName() const override;
protected:
Group *_cell;
};
inline Group *LibertyProperty::getLibCell() const
{
return _cell;
}
inline Hurricane::Name LibertyProperty::getName() const
{
return Hurricane::Name("Liberty Cell Informations");
}
inline std::string LibertyProperty::_getTypeName() const
{
return "LibertyProperty";
}
}

View File

@@ -17,10 +17,10 @@
#pragma once
#include "SimpleGroup.h"
#include "Statement.h"
#include "hurricane/Library.h"
#include <filesystem>
#include <map>
#include <string>
#include <vector>
namespace Liberty {
@@ -29,11 +29,12 @@ namespace Liberty {
* */
class Library: public SimpleGroup {
public:
Library (const std::string &filepath); // TODO: find a way to fiter stuff
Library (const std::string &filepath);
~Library ();
Group *getCellGroup(const std::string &cell_name ) const ;
void addCellGroup(const std::string &cell_name, Group *group ) ;
void mapLibertyToDb (Hurricane::DataBase *db) const ;
inline std::string getFilePath () const ;
bool load(); /// Process the actual loading of library.

View File

@@ -7,6 +7,8 @@ liberty = shared_library (
'Define.cpp',
'Group.cpp',
'Library.cpp',
'LibertyLibProperty.cpp',
'LibertyProperty.cpp',
'Parser.cpp',
'Reader.cpp',
'SimpleGroup.cpp',
@@ -14,6 +16,8 @@ liberty = shared_library (
'Tokenizer.cpp',
'Value.cpp',
'ValueString.cpp',
link_with: hurricane,
include_directories: crlcore_includes,
link_with: [crlcore,hurricane],
dependencies: Hurricane,
install: true,
)

View File

@@ -25,6 +25,7 @@
#include "crlcore/PyAllianceFramework.h"
#include "crlcore/PyEnvironment.h"
#include "crlcore/PyAllianceLibrary.h"
#include "crlcore/PyLiberty.h"
#include "crlcore/PyCellGauge.h"
#include "crlcore/PyRoutingGauge.h"
#include "crlcore/PyRoutingLayerGauge.h"
@@ -97,12 +98,14 @@ extern "C" {
// x-------------------------------------------------------------x
static PyMethodDef PyCRL_Methods[] =
{ { "createPartRing" , (PyCFunction)PyToolBox_createPartRing , METH_VARARGS
, "Partial build of a ring" }
, { "restoreNetsDirection", (PyCFunction)PyToolBox_restoreNetsDirection, METH_VARARGS
, "Compute and set nets direction of a complete cell hierarchy." }
, { "destroyAllVHDL" , (PyCFunction)PyVhdl_destroyAllVHDL , METH_NOARGS
, "Clear all VHDL informations on all cells." }
{ { "createPartRing" , (PyCFunction)PyToolBox_createPartRing , METH_VARARGS
, "Partial build of a ring" }
, { "restoreNetsDirection" , (PyCFunction)PyToolBox_restoreNetsDirection , METH_VARARGS
, "Compute and set nets direction of a complete cell hierarchy." }
, { "destroyAllVHDL" , (PyCFunction)PyVhdl_destroyAllVHDL , METH_NOARGS
, "Clear all VHDL informations on all cells." }
, { "getLibertyGroupFromCell" , (PyCFunction)PyCRL_getLibertyGroupFromCell , METH_VARARGS
, "Get the Liberty Group attached to a Hurricane Cell." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
@@ -120,6 +123,10 @@ extern "C" {
PyCatalog_LinkPyType ();
PyEnvironment_LinkPyType ();
PyAllianceLibrary_LinkPyType ();
PyLibertyLibrary_LinkPyType ();
PyLibertyGroup_LinkPyType ();
PyLibertyAttribute_LinkPyType ();
PyLibertyValue_LinkPyType ();
PyCellGauge_LinkPyType ();
PyRoutingGauge_LinkPyType ();
PyRoutingLayerGauge_LinkPyType ();
@@ -144,6 +151,10 @@ extern "C" {
PYTYPE_READY_NEW ( Catalog );
PYTYPE_READY_NEW ( Environment );
PYTYPE_READY_NEW ( AllianceLibrary );
PYTYPE_READY_NEW ( LibertyLibrary );
PYTYPE_READY ( LibertyGroup );
PYTYPE_READY ( LibertyAttribute );
PYTYPE_READY ( LibertyValue );
PYTYPE_READY_NEW ( CellGauge );
PYTYPE_READY_NEW ( RoutingGauge );
PYTYPE_READY_NEW ( RoutingLayerGaugeVector );
@@ -182,6 +193,14 @@ extern "C" {
PyModule_AddObject ( module, "Catalog", (PyObject*)&PyTypeCatalog );
Py_INCREF ( &PyTypeAllianceLibrary );
PyModule_AddObject ( module, "AllianceLibrary", (PyObject*)&PyTypeAllianceLibrary );
Py_INCREF ( &PyTypeLibertyLibrary );
PyModule_AddObject ( module, "LibertyLibrary", (PyObject*)&PyTypeLibertyLibrary );
Py_INCREF ( &PyTypeLibertyGroup );
PyModule_AddObject ( module, "LibertyGroup", (PyObject*)&PyTypeLibertyGroup );
Py_INCREF ( &PyTypeLibertyAttribute );
PyModule_AddObject ( module, "LibertyAttribute", (PyObject*)&PyTypeLibertyAttribute );
Py_INCREF ( &PyTypeLibertyValue );
PyModule_AddObject ( module, "LibertyValue", (PyObject*)&PyTypeLibertyValue );
Py_INCREF ( &PyTypeEnvironment );
PyModule_AddObject ( module, "Environment", (PyObject*)&PyTypeEnvironment );
Py_INCREF ( &PyTypeCellGauge );

View File

@@ -0,0 +1,555 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2013-2026, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | Alliance / Hurricane Interface |
// | |
// | Author : Hippolyte MELICA |
// | E-mail : hippolyte.melica@etu.sorbonne-universite.fr |
// | =============================================================== |
// | C++ Module : "./PyLiberty.cpp" |
// +-----------------------------------------------------------------+
#include "crlcore/PyLiberty.h"
#include "hurricane/isobar/PyDataBase.h"
#include "hurricane/isobar/PyCell.h"
#include "hurricane/DataBase.h"
#include "hurricane/Property.h"
#include "Library.h"
#include "Group.h"
#include "Attribute.h"
#include "Value.h"
#include "LibertyProperty.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::DataBase;
using Hurricane::Cell;
using Isobar::PyTypeDataBase;
using Isobar::PyDataBase;
using Isobar::PyTypeCell;
using Isobar::PyCell;
using Isobar::ProxyProperty;
using Isobar::ProxyError;
using Isobar::ConstructorError;
using Isobar::HurricaneError;
using Isobar::HurricaneWarning;
using Isobar::getPyHash;
using Isobar::ParseOneArg;
using Isobar::ParseTwoArg;
using Isobar::__cs;
typedef Liberty::Library LibertyLibrary;
typedef Liberty::Group LibertyGroup;
typedef Liberty::Attribute LibertyAttribute;
typedef Liberty::Value LibertyValue;
extern "C" {
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(LibertyLibrary,liberty,function)
#define METHOD_HEAD_GROUP(function) GENERIC_METHOD_HEAD(LibertyGroup,group,function)
#define METHOD_HEAD_ATTRIBUTE(function) GENERIC_METHOD_HEAD(LibertyAttribute,attribute,function)
#define METHOD_HEAD_VALUE(function) GENERIC_METHOD_HEAD(LibertyValue,value,function)
#if defined(__PYTHON_MODULE__)
// +=================================================================+
// | "PyLiberty" Python Module Code Part |
// +=================================================================+
static PyObject* PyLibertyLibrary_NEW ( PyTypeObject* type, PyObject* args, PyObject* kwArgs )
{
cdebug_log(30,0) << "PyLibertyLibrary_NEW()" << endl;
Liberty::Library* liberty = NULL;
HTRY
char* filepath = NULL;
static char* keywords[] = { (char*)"filepath", NULL };
if (not PyArg_ParseTupleAndKeywords( args
, kwArgs
, "s:LibertyLibrary.__new__"
, keywords
, &filepath )) {
PyErr_SetString ( ConstructorError, "LibertyLibrary(): Invalid number or type of parameters." );
return NULL;
}
liberty = new Liberty::Library( filepath );
HCATCH
return PyLibertyLibrary_Link( liberty );
}
static int PyLibertyLibrary_Init ( PyLibertyLibrary*, PyObject*, PyObject* )
{
cdebug_log(30,0) << "PyLibertyLibrary_Init()" << endl;
return 0;
}
static PyObject* PyLibertyLibrary_getName ( PyLibertyLibrary* self )
{
cdebug_log(30,0) << "PyLibertyLibrary_getName()" << endl;
HTRY
METHOD_HEAD("LibertyLibrary.getName()")
return PyString_FromString( liberty->getName().c_str() );
HCATCH
return NULL;
}
static PyObject* PyLibertyLibrary_getFilePath ( PyLibertyLibrary* self )
{
cdebug_log(30,0) << "PyLibertyLibrary_getFilePath()" << endl;
HTRY
METHOD_HEAD("LibertyLibrary.getFilePath()")
return PyString_FromString( liberty->getFilePath().c_str() );
HCATCH
return NULL;
}
static PyObject* PyLibertyLibrary_getGroupIdentifier ( PyLibertyLibrary* self )
{
cdebug_log(30,0) << "PyLibertyLibrary_getGroupIdentifier()" << endl;
HTRY
METHOD_HEAD("LibertyLibrary.getGroupIdentifier()")
return PyString_FromString( liberty->getGroupIdentifier().c_str() );
HCATCH
return NULL;
}
static PyObject* PyLibertyLibrary_setGroupIdentifier ( PyLibertyLibrary* self, PyObject* args )
{
cdebug_log(30,0) << "PyLibertyLibrary_setGroupIdentifier()" << endl;
HTRY
METHOD_HEAD("LibertyLibrary.setGroupIdentifier()")
char* groupId = NULL;
if ( not PyArg_ParseTuple( args, "s:LibertyLibrary.setGroupIdentifier", &groupId ) ) {
PyErr_SetString( ConstructorError, "LibertyLibrary.setGroupIdentifier(): Invalid number or type of parameters." );
return NULL;
}
liberty->setGroupIdentifier( std::string(groupId) );
HCATCH
Py_RETURN_NONE;
}
static PyObject* PyLibertyLibrary_load ( PyLibertyLibrary* self )
{
cdebug_log(30,0) << "PyLibertyLibrary_load()" << endl;
bool loaded = false;
HTRY
METHOD_HEAD("LibertyLibrary.load()")
loaded = liberty->load();
HCATCH
if (loaded) Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
static PyObject* PyLibertyLibrary_mapLibertyToDb ( PyLibertyLibrary* self, PyObject* args )
{
cdebug_log(30,0) << "PyLibertyLibrary_mapLibertyToDb()" << endl;
HTRY
METHOD_HEAD("LibertyLibrary.mapLibertyToDb()")
PyObject* pyDataBase = NULL;
// Make db argument optional - if not provided, use DataBase::getDB()
if ( not PyArg_ParseTuple( args, "|O:LibertyLibrary.mapLibertyToDb", &pyDataBase ) ) {
PyErr_SetString ( ConstructorError, "LibertyLibrary.mapLibertyToDb(): Invalid arguments." );
return NULL;
}
Hurricane::DataBase* db = NULL;
if ( pyDataBase ) {
// Use provided DataBase argument
if ( not IsPyDataBase(pyDataBase) ) {
PyErr_SetString ( ConstructorError, "LibertyLibrary.mapLibertyToDb(): Argument is not of type DataBase." );
return NULL;
}
db = PYDATABASE_O(pyDataBase);
} else {
// Get current DataBase automatically
db = DataBase::getDB();
if ( not db ) {
PyErr_SetString ( ConstructorError, "LibertyLibrary.mapLibertyToDb(): No DataBase created (call DataBase.getDB() first)." );
return NULL;
}
}
liberty->mapLibertyToDb( db );
// Ownership is now held by the C++ DataBase side.
// Detach from Python wrapper so tp_dealloc won't delete it.
self->_object = NULL;
HCATCH
Py_RETURN_NONE;
}
static PyObject* PyLibertyLibrary_getRootGroup ( PyLibertyLibrary* self )
{
cdebug_log(30,0) << "PyLibertyLibrary_getRootGroup()" << endl;
HTRY
METHOD_HEAD("LibertyLibrary.getRootGroup()")
// Library extends SimpleGroup which extends Group, so we can cast it
Liberty::Group* group = static_cast<Liberty::Group*>(liberty);
return PyLibertyGroup_Link( group );
HCATCH
return NULL;
}
static PyObject* PyLibertyLibrary_getCellGroup ( PyLibertyLibrary* self, PyObject* args )
{
cdebug_log(30,0) << "PyLibertyLibrary_getCellGroup()" << endl;
HTRY
METHOD_HEAD("LibertyLibrary.getCellGroup()")
char* cellName = NULL;
if ( not PyArg_ParseTuple( args, "s:LibertyLibrary.getCellGroup", &cellName ) ) {
PyErr_SetString( ConstructorError, "LibertyLibrary.getCellGroup(): Invalid arguments." );
return NULL;
}
Liberty::Group* group = liberty->getCellGroup( cellName );
if ( group ) return PyLibertyGroup_Link( group );
Py_RETURN_NONE;
HCATCH
return NULL;
}
PyMethodDef PyLibertyLibrary_Methods[] =
{ { "getName" , (PyCFunction)PyLibertyLibrary_getName , METH_NOARGS
, "Return the name of the Liberty library." }
, { "getFilePath" , (PyCFunction)PyLibertyLibrary_getFilePath , METH_NOARGS
, "Return the Liberty file path." }
, { "getGroupIdentifier" , (PyCFunction)PyLibertyLibrary_getGroupIdentifier, METH_NOARGS
, "Return the top-level group identifier." }
, { "setGroupIdentifier" , (PyCFunction)PyLibertyLibrary_setGroupIdentifier, METH_VARARGS
, "Set the top-level group identifier." }
, { "load" , (PyCFunction)PyLibertyLibrary_load , METH_NOARGS
, "Parse the Liberty file." }
, { "mapLibertyToDb" , (PyCFunction)PyLibertyLibrary_mapLibertyToDb , METH_VARARGS
, "Map Liberty cells onto the Hurricane database (db=DataBase.getDB() by default). After success, ownership is transferred to C++." }
, { "getRootGroup" , (PyCFunction)PyLibertyLibrary_getRootGroup , METH_NOARGS
, "Get the root Group of the library." }
, { "getCellGroup" , (PyCFunction)PyLibertyLibrary_getCellGroup , METH_VARARGS
, "Get a cell group by name." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
DirectDeleteMethod(PyLibertyLibrary_DeAlloc,PyLibertyLibrary)
PyTypeObjectLinkPyTypeNewInit(LibertyLibrary)
// +=================================================================+
// | "PyLibertyGroup" Python Module Code Part |
// +=================================================================+
static PyObject* PyLibertyGroup_getName ( PyLibertyGroup* self )
{
cdebug_log(30,0) << "PyLibertyGroup_getName()" << endl;
HTRY
METHOD_HEAD_GROUP("LibertyGroup.getName()")
return PyString_FromString( group->getName().c_str() );
HCATCH
return NULL;
}
static PyObject* PyLibertyGroup_getStatements ( PyLibertyGroup* self )
{
cdebug_log(30,0) << "PyLibertyGroup_getStatements()" << endl;
HTRY
METHOD_HEAD_GROUP("LibertyGroup.getStatements()")
const std::vector<Liberty::Statement*>& stmts = group->getStatements();
PyObject* list = PyList_New( stmts.size() );
for ( size_t i = 0; i < stmts.size(); ++i ) {
Liberty::Statement* stmt = stmts[i];
PyObject* pyStmt = NULL;
if ( stmt->isGroup() ) {
pyStmt = PyLibertyGroup_Link( stmt->getAsGroup() );
} else if ( stmt->isAttribute() ) {
pyStmt = PyLibertyAttribute_Link( stmt->getAsAttribute() );
}
if ( pyStmt ) {
PyList_SetItem( list, i, pyStmt );
}
}
return list;
HCATCH
return NULL;
}
static PyObject* PyLibertyGroup_getGroup ( PyLibertyGroup* self, PyObject* args )
{
cdebug_log(30,0) << "PyLibertyGroup_getGroup()" << endl;
HTRY
METHOD_HEAD_GROUP("LibertyGroup.getGroup()")
char* groupName = NULL;
if ( not PyArg_ParseTuple( args, "s:LibertyGroup.getGroup", &groupName ) ) {
PyErr_SetString( ConstructorError, "LibertyGroup.getGroup(): Invalid arguments." );
return NULL;
}
Liberty::Group* subGroup = group->getGroup( groupName );
if ( subGroup ) return PyLibertyGroup_Link( subGroup );
Py_RETURN_NONE;
HCATCH
return NULL;
}
static PyObject* PyLibertyGroup_getAttribute ( PyLibertyGroup* self, PyObject* args )
{
cdebug_log(30,0) << "PyLibertyGroup_getAttribute()" << endl;
HTRY
METHOD_HEAD_GROUP("LibertyGroup.getAttribute()")
char* attrName = NULL;
if ( not PyArg_ParseTuple( args, "s:LibertyGroup.getAttribute", &attrName ) ) {
PyErr_SetString( ConstructorError, "LibertyGroup.getAttribute(): Invalid arguments." );
return NULL;
}
Liberty::Attribute* attr = group->getAttribute( attrName );
if ( attr ) return PyLibertyAttribute_Link( attr );
Py_RETURN_NONE;
HCATCH
return NULL;
}
PyMethodDef PyLibertyGroup_Methods[] =
{ { "getName" , (PyCFunction)PyLibertyGroup_getName , METH_NOARGS
, "Return the name of the group." }
, { "getStatements" , (PyCFunction)PyLibertyGroup_getStatements , METH_NOARGS
, "Return list of statements (Groups and Attributes) in this group." }
, { "getGroup" , (PyCFunction)PyLibertyGroup_getGroup , METH_VARARGS
, "Get a sub-group by name." }
, { "getAttribute" , (PyCFunction)PyLibertyGroup_getAttribute , METH_VARARGS
, "Get an attribute by name." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
PythonOnlyDeleteMethod(LibertyGroup)
PyTypeObjectLinkPyType(LibertyGroup)
// +=================================================================+
// | "PyLibertyAttribute" Python Module Code Part |
// +=================================================================+
static PyObject* PyLibertyAttribute_getName ( PyLibertyAttribute* self )
{
cdebug_log(30,0) << "PyLibertyAttribute_getName()" << endl;
HTRY
METHOD_HEAD_ATTRIBUTE("LibertyAttribute.getName()")
return PyString_FromString( attribute->getName().c_str() );
HCATCH
return NULL;
}
static PyObject* PyLibertyAttribute_getValue ( PyLibertyAttribute* self )
{
cdebug_log(30,0) << "PyLibertyAttribute_getValue()" << endl;
HTRY
METHOD_HEAD_ATTRIBUTE("LibertyAttribute.getValue()")
Liberty::Value* value = attribute->getValue();
if ( value ) return PyString_FromString( value->getAsString().c_str() );
Py_RETURN_NONE;
HCATCH
return NULL;
}
PyMethodDef PyLibertyAttribute_Methods[] =
{ { "getName" , (PyCFunction)PyLibertyAttribute_getName , METH_NOARGS
, "Return the name of the attribute." }
, { "getValue" , (PyCFunction)PyLibertyAttribute_getValue , METH_NOARGS
, "Return the attribute value as a string." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
PythonOnlyDeleteMethod(LibertyAttribute)
PyTypeObjectLinkPyType(LibertyAttribute)
// +=================================================================+
// | "PyLibertyValue" Python Module Code Part |
// +=================================================================+
static PyObject* PyLibertyValue_getAsString ( PyLibertyValue* self )
{
cdebug_log(30,0) << "PyLibertyValue_getAsString()" << endl;
HTRY
METHOD_HEAD_VALUE("LibertyValue.getAsString()")
return PyString_FromString( value->getAsString().c_str() );
HCATCH
return NULL;
}
PyMethodDef PyLibertyValue_Methods[] =
{ { "getAsString" , (PyCFunction)PyLibertyValue_getAsString , METH_NOARGS
, "Return the value as a string." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
PythonOnlyDeleteMethod(LibertyValue)
PyTypeObjectLinkPyType(LibertyValue)
// +=================================================================+
// | "PyLibertyHelper" Functions |
// +=================================================================+
PyObject* PyCRL_getLibertyGroupFromCell ( PyObject* self, PyObject* args )
{
cdebug_log(30,0) << "PyCRL_getLibertyGroupFromCell()" << endl;
HTRY
PyObject* pyCell = NULL;
if ( not PyArg_ParseTuple( args, "O:CRL.getLibertyGroupFromCell", &pyCell ) ) {
PyErr_SetString( ConstructorError, "getLibertyGroupFromCell(): Argument must be a Cell." );
return NULL;
}
if ( not IsPyCell(pyCell) ) {
PyErr_SetString( ConstructorError, "getLibertyGroupFromCell(): Argument is not of type Cell." );
return NULL;
}
Cell* cell = PYCELL_O(pyCell);
Hurricane::Property* property = cell->getProperty( Hurricane::Name("Liberty Cell Informations") );
if ( not property ) {
Py_RETURN_NONE;
}
// Avoid RTTI cross-DSO dependency on Liberty::LibertyProperty typeinfo.
Liberty::LibertyProperty* prop = static_cast<Liberty::LibertyProperty*>(property);
if (not prop) {
Py_RETURN_NONE;
}
Liberty::Group* group = prop->getLibCell();
if ( group ) return PyLibertyGroup_Link( group );
Py_RETURN_NONE;
HCATCH
return NULL;
}
#else // End of Python Module Code Part.
// +=================================================================+
// | "PyLiberty" Shared Library Code Part |
// +=================================================================+
PyObject* PyLibertyLibrary_Link ( Liberty::Library* object )
{
if ( object == NULL ) {
Py_RETURN_NONE;
}
PyLibertyLibrary* pyObject = NULL;
HTRY
pyObject = PyObject_NEW( PyLibertyLibrary, &PyTypeLibertyLibrary );
if ( pyObject == NULL ) return NULL;
pyObject->ACCESS_OBJECT = object;
HCATCH
return (PyObject*)pyObject;
}
PyObject* PyLibertyGroup_Link ( Liberty::Group* object )
{
if ( object == NULL ) {
Py_RETURN_NONE;
}
PyLibertyGroup* pyObject = NULL;
HTRY
pyObject = PyObject_NEW( PyLibertyGroup, &PyTypeLibertyGroup );
if ( pyObject == NULL ) return NULL;
pyObject->ACCESS_OBJECT = object;
HCATCH
return (PyObject*)pyObject;
}
PyObject* PyLibertyAttribute_Link ( Liberty::Attribute* object )
{
if ( object == NULL ) {
Py_RETURN_NONE;
}
PyLibertyAttribute* pyObject = NULL;
HTRY
pyObject = PyObject_NEW( PyLibertyAttribute, &PyTypeLibertyAttribute );
if ( pyObject == NULL ) return NULL;
pyObject->ACCESS_OBJECT = object;
HCATCH
return (PyObject*)pyObject;
}
PyObject* PyLibertyValue_Link ( Liberty::Value* object )
{
if ( object == NULL ) {
Py_RETURN_NONE;
}
PyLibertyValue* pyObject = NULL;
HTRY
pyObject = PyObject_NEW( PyLibertyValue, &PyTypeLibertyValue );
if ( pyObject == NULL ) return NULL;
pyObject->ACCESS_OBJECT = object;
HCATCH
return (PyObject*)pyObject;
}
PyTypeObjectDefinitionsOfModule(CRL,LibertyLibrary)
PyTypeObjectDefinitionsOfModule(CRL,LibertyGroup)
PyTypeObjectDefinitionsOfModule(CRL,LibertyAttribute)
PyTypeObjectDefinitionsOfModule(CRL,LibertyValue)
#endif // End of Shared Library Code Part.
} // extern "C".
} // CRL namespace.

View File

@@ -0,0 +1,123 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2013-2026, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | Alliance / Hurricane Interface |
// | |
// | Author : Hippolyte MELICA |
// | E-mail : hippolyte.melica@etu.sorbonne-universite.fr |
// | =============================================================== |
// | C++ Header : "./crlcore/PyLiberty.h" |
// +-----------------------------------------------------------------+
#ifndef __CRL_PY_LIBERTY__
#define __CRL_PY_LIBERTY__
#include "hurricane/isobar/PyHurricane.h"
// Forward declarations - avoid circular includes
namespace Liberty {
class Library;
class Group;
class Attribute;
class Value;
}
namespace CRL {
extern "C" {
// -------------------------------------------------------------------
// Python Object : "PyLibertyLibrary".
typedef struct {
PyObject_HEAD
Liberty::Library* _object;
} PyLibertyLibrary;
// -------------------------------------------------------------------
// Python Object : "PyLibertyGroup".
typedef struct {
PyObject_HEAD
Liberty::Group* _object;
} PyLibertyGroup;
// -------------------------------------------------------------------
// Python Object : "PyLibertyAttribute".
typedef struct {
PyObject_HEAD
Liberty::Attribute* _object;
} PyLibertyAttribute;
// -------------------------------------------------------------------
// Python Object : "PyLibertyValue".
typedef struct {
PyObject_HEAD
Liberty::Value* _object;
} PyLibertyValue;
// -------------------------------------------------------------------
// Functions & Types exported to "PyCRL.cpp".
extern PyTypeObject PyTypeLibertyLibrary;
extern PyTypeObject PyTypeLibertyGroup;
extern PyTypeObject PyTypeLibertyAttribute;
extern PyTypeObject PyTypeLibertyValue;
extern PyMethodDef PyLibertyLibrary_Methods[];
extern PyMethodDef PyLibertyGroup_Methods[];
extern PyMethodDef PyLibertyAttribute_Methods[];
extern PyMethodDef PyLibertyValue_Methods[];
extern PyObject* PyLibertyLibrary_Link ( Liberty::Library* );
extern void PyLibertyLibrary_LinkPyType ();
extern PyObject* PyLibertyGroup_Link ( Liberty::Group* );
extern void PyLibertyGroup_LinkPyType ();
extern PyObject* PyLibertyAttribute_Link ( Liberty::Attribute* );
extern void PyLibertyAttribute_LinkPyType ();
extern PyObject* PyLibertyValue_Link ( Liberty::Value* );
extern void PyLibertyValue_LinkPyType ();
extern PyObject* PyCRL_getLibertyGroupFromCell ( PyObject*, PyObject* );
#define IsPyLibertyLibrary(v) ( (v)->ob_type == &PyTypeLibertyLibrary )
#define PYLIBERTY_LIBRARY(v) ( (PyLibertyLibrary*)(v) )
#define PYLIBERTY_LIBRARY_O(v) ( PYLIBERTY_LIBRARY(v)->_object )
#define IsPyLibertyGroup(v) ( (v)->ob_type == &PyTypeLibertyGroup )
#define PYLIBERTY_GROUP(v) ( (PyLibertyGroup*)(v) )
#define PYLIBERTY_GROUP_O(v) ( PYLIBERTY_GROUP(v)->_object )
#define IsPyLibertyAttribute(v) ( (v)->ob_type == &PyTypeLibertyAttribute )
#define PYLIBERTY_ATTRIBUTE(v) ( (PyLibertyAttribute*)(v) )
#define PYLIBERTY_ATTRIBUTE_O(v) ( PYLIBERTY_ATTRIBUTE(v)->_object )
#define IsPyLibertyValue(v) ( (v)->ob_type == &PyTypeLibertyValue )
#define PYLIBERTY_VALUE(v) ( (PyLibertyValue*)(v) )
#define PYLIBERTY_VALUE_O(v) ( PYLIBERTY_VALUE(v)->_object )
} // extern "C".
} // namespace CRL.
#endif // __CRL_PY_LIBERTY__

View File

@@ -1,4 +1,5 @@
pyCRL_includes = include_directories('.')
liberty_includes = include_directories('../liberty/crlcore/liberty')
pyCRL_files = files([
'PyCRL.cpp',
@@ -8,6 +9,7 @@ pyCRL_files = files([
'PyCatalogState.cpp',
'PyEnvironment.cpp',
'PyAllianceLibrary.cpp',
'PyLiberty.cpp',
'PyCellGauge.cpp',
'PyRoutingGauge.cpp',
'PyRoutingLayerGauge.cpp',
@@ -39,9 +41,9 @@ py.extension_module(
pycrlcore = shared_library(
'pycrlcore',
pyCRL_files,
link_with: crlcore,
link_with: [crlcore, liberty],
dependencies: [qt_deps, boost, Hurricane],
include_directories: crlcore_includes,
include_directories: [crlcore_includes, liberty_includes],
install: true,
)
@@ -49,9 +51,9 @@ pycrlcore = shared_library(
py.extension_module(
'CRL',
pyCRL_files,
link_with: pycrlcore,
link_with: [pycrlcore, liberty],
dependencies: [qt_deps, py_mod_deps, boost, Hurricane],
include_directories: crlcore_includes,
include_directories: [crlcore_includes, liberty_includes],
subdir: 'coriolis',
install: true
)