From 9b18da3e0a4e4e2c353fdb19516dbccac2c1aced Mon Sep 17 00:00:00 2001 From: Hippolyte Melica Date: Sun, 12 Apr 2026 12:57:18 +0200 Subject: [PATCH] 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) --- crlcore/meson.build | 6 +- crlcore/src/liberty/Group.cpp | 32 +- crlcore/src/liberty/LibertyLibProperty.cpp | 32 + crlcore/src/liberty/LibertyProperty.cpp | 28 + crlcore/src/liberty/Library.cpp | 67 ++- crlcore/src/liberty/Parser.cpp | 8 +- crlcore/src/liberty/SimpleGroup.cpp | 4 +- crlcore/src/liberty/crlcore/liberty/Group.h | 11 +- .../crlcore/liberty/LibertyLibProperty.h | 49 ++ .../liberty/crlcore/liberty/LibertyProperty.h | 54 ++ crlcore/src/liberty/crlcore/liberty/Library.h | 5 +- crlcore/src/liberty/meson.build | 6 +- crlcore/src/pyCRL/PyCRL.cpp | 31 +- crlcore/src/pyCRL/PyLiberty.cpp | 555 ++++++++++++++++++ crlcore/src/pyCRL/crlcore/PyLiberty.h | 123 ++++ crlcore/src/pyCRL/meson.build | 10 +- 16 files changed, 967 insertions(+), 54 deletions(-) create mode 100644 crlcore/src/liberty/LibertyLibProperty.cpp create mode 100644 crlcore/src/liberty/LibertyProperty.cpp create mode 100644 crlcore/src/liberty/crlcore/liberty/LibertyLibProperty.h create mode 100644 crlcore/src/liberty/crlcore/liberty/LibertyProperty.h create mode 100644 crlcore/src/pyCRL/PyLiberty.cpp create mode 100644 crlcore/src/pyCRL/crlcore/PyLiberty.h diff --git a/crlcore/meson.build b/crlcore/meson.build index 501caecca..1aa558687 100644 --- a/crlcore/meson.build +++ b/crlcore/meson.build @@ -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] ) diff --git a/crlcore/src/liberty/Group.cpp b/crlcore/src/liberty/Group.cpp index 69457b48e..60316123a 100644 --- a/crlcore/src/liberty/Group.cpp +++ b/crlcore/src/liberty/Group.cpp @@ -18,6 +18,7 @@ #include "crlcore/liberty/Library.h" #include "crlcore/liberty/Statement.h" #include +#include #include #include @@ -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(this); + _library = static_cast(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() diff --git a/crlcore/src/liberty/LibertyLibProperty.cpp b/crlcore/src/liberty/LibertyLibProperty.cpp new file mode 100644 index 000000000..e89ef8aac --- /dev/null +++ b/crlcore/src/liberty/LibertyLibProperty.cpp @@ -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; + } + +} diff --git a/crlcore/src/liberty/LibertyProperty.cpp b/crlcore/src/liberty/LibertyProperty.cpp new file mode 100644 index 000000000..4fd5a4cbc --- /dev/null +++ b/crlcore/src/liberty/LibertyProperty.cpp @@ -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() {} + +} diff --git a/crlcore/src/liberty/Library.cpp b/crlcore/src/liberty/Library.cpp index ad1b8f69d..60fa96d0c 100644 --- a/crlcore/src/liberty/Library.cpp +++ b/crlcore/src/liberty/Library.cpp @@ -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 #include #include #include @@ -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(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); + } } diff --git a/crlcore/src/liberty/Parser.cpp b/crlcore/src/liberty/Parser.cpp index 7acdc66e2..e75f1c462 100644 --- a/crlcore/src/liberty/Parser.cpp +++ b/crlcore/src/liberty/Parser.cpp @@ -40,6 +40,7 @@ namespace Liberty { return false; State state = Default; Group *current = dynamic_cast(lib); + bool CurrentIsLibrary = true; std::queue 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(current); + CurrentIsLibrary = false; + } else + sgroup = new SimpleGroup(current); sgroup->setName(waiting.front().str); waiting.pop(); sgroup->setGroupIdentifier(waiting.front().str); diff --git a/crlcore/src/liberty/SimpleGroup.cpp b/crlcore/src/liberty/SimpleGroup.cpp index 179d3db73..841128945 100644 --- a/crlcore/src/liberty/SimpleGroup.cpp +++ b/crlcore/src/liberty/SimpleGroup.cpp @@ -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); } diff --git a/crlcore/src/liberty/crlcore/liberty/Group.h b/crlcore/src/liberty/crlcore/liberty/Group.h index 9fc455abc..eabf307f5 100644 --- a/crlcore/src/liberty/crlcore/liberty/Group.h +++ b/crlcore/src/liberty/crlcore/liberty/Group.h @@ -15,7 +15,7 @@ #pragma once #include "Statement.h" -#include +#include "Attribute.h" #include #include #include @@ -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 &Group::getStatements() const { return _statements; diff --git a/crlcore/src/liberty/crlcore/liberty/LibertyLibProperty.h b/crlcore/src/liberty/crlcore/liberty/LibertyLibProperty.h new file mode 100644 index 000000000..13592547f --- /dev/null +++ b/crlcore/src/liberty/crlcore/liberty/LibertyLibProperty.h @@ -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 + +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"; + } +} diff --git a/crlcore/src/liberty/crlcore/liberty/LibertyProperty.h b/crlcore/src/liberty/crlcore/liberty/LibertyProperty.h new file mode 100644 index 000000000..7e5a03509 --- /dev/null +++ b/crlcore/src/liberty/crlcore/liberty/LibertyProperty.h @@ -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 + +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"; + } +} diff --git a/crlcore/src/liberty/crlcore/liberty/Library.h b/crlcore/src/liberty/crlcore/liberty/Library.h index 2206cf13b..09c972e14 100644 --- a/crlcore/src/liberty/crlcore/liberty/Library.h +++ b/crlcore/src/liberty/crlcore/liberty/Library.h @@ -17,10 +17,10 @@ #pragma once #include "SimpleGroup.h" #include "Statement.h" +#include "hurricane/Library.h" #include #include #include -#include 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. diff --git a/crlcore/src/liberty/meson.build b/crlcore/src/liberty/meson.build index b32980bb4..4196a92de 100644 --- a/crlcore/src/liberty/meson.build +++ b/crlcore/src/liberty/meson.build @@ -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, ) diff --git a/crlcore/src/pyCRL/PyCRL.cpp b/crlcore/src/pyCRL/PyCRL.cpp index 5f007e928..bb3f09040 100644 --- a/crlcore/src/pyCRL/PyCRL.cpp +++ b/crlcore/src/pyCRL/PyCRL.cpp @@ -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 ); diff --git a/crlcore/src/pyCRL/PyLiberty.cpp b/crlcore/src/pyCRL/PyLiberty.cpp new file mode 100644 index 000000000..c67b174be --- /dev/null +++ b/crlcore/src/pyCRL/PyLiberty.cpp @@ -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 +#include + + +namespace CRL { + + using std::cerr; + using std::endl; + using std::hex; + using std::string; + using std::ostringstream; + using Hurricane::tab; + using Hurricane::Exception; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Warning; + using Hurricane::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); + 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& 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(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. diff --git a/crlcore/src/pyCRL/crlcore/PyLiberty.h b/crlcore/src/pyCRL/crlcore/PyLiberty.h new file mode 100644 index 000000000..ed314aa0f --- /dev/null +++ b/crlcore/src/pyCRL/crlcore/PyLiberty.h @@ -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__ diff --git a/crlcore/src/pyCRL/meson.build b/crlcore/src/pyCRL/meson.build index 7c05f2fb8..e087242b2 100644 --- a/crlcore/src/pyCRL/meson.build +++ b/crlcore/src/pyCRL/meson.build @@ -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 )