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 )