Skip to content

Commit

Permalink
Merge pull request #895 from Thomasb81/python_wrapper
Browse files Browse the repository at this point in the history
Python wrapper
  • Loading branch information
alaindargelas authored Apr 1, 2023
2 parents f842443 + 49a2058 commit eef0530
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -386,3 +386,8 @@ install(
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/UHDM.pc
DESTINATION lib/pkgconfig)


if(BUILD_SHARED_LIBS)
add_subdirectory(python)
endif()
2 changes: 2 additions & 0 deletions include/vpi_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -966,11 +966,13 @@ XXTERN PLI_INT32 vpi_put_data PROTO_PARAMS((PLI_INT32 id,
XXTERN void *vpi_get_userdata PROTO_PARAMS((vpiHandle obj));
XXTERN PLI_INT32 vpi_put_userdata PROTO_PARAMS((vpiHandle obj,
void *userdata));
#ifndef SWIG
XXTERN PLI_INT32 vpi_vprintf PROTO_PARAMS((PLI_BYTE8 *format,
va_list ap));
XXTERN PLI_INT32 vpi_mcd_vprintf PROTO_PARAMS((PLI_UINT32 mcd,
PLI_BYTE8 *format,
va_list ap));
#endif
XXTERN PLI_INT32 vpi_flush PROTO_PARAMS((void));
XXTERN PLI_INT32 vpi_mcd_flush PROTO_PARAMS((PLI_UINT32 mcd));
XXTERN PLI_INT32 vpi_control PROTO_PARAMS((PLI_INT32 operation,
Expand Down
55 changes: 55 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Set up swig
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})

# Include python
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_PATH} ${GENDIR}/uhdm ${CMAKE_CURRENT_SOURCE_DIR})


set_source_files_properties(${PROJECT_NAME}.i
PROPERTIES CPLUSPLUS ON
INCLUDE_DIRECTORIES ${GENDIR}/uhdm
GENERATED_INCLUDE_DIRECTORIES ${GENDIR}/uhdm
DEPENDS uhdm
)

# Add swig module
swig_add_library(py_uhdm
TYPE MODULE
LANGUAGE python
SOURCES
${PROJECT_NAME}.i swig_test.cpp
)
target_link_libraries(py_uhdm
PRIVATE uhdm ${PYTHON_LIBRARIES}
)
set_target_properties(py_uhdm PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/
)

# this figures out where to install the Python modules
execute_process(
COMMAND ${Python3_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
OUTPUT_VARIABLE Python_site_packages
OUTPUT_STRIP_TRAILING_WHITESPACE
)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/uhdm.py
DESTINATION ${CMAKE_INSTALL_PREFIX}/${Python_site_packages}
)
install(
TARGETS ${SWIG_MODULE_py_udhm_REAL_NAME}
LIBRARY DESTINATION ${PYTHON_SITE_PACKAGES}
)

add_test(
NAME python-tests-import
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" "${Python3_EXECUTABLE}" -c "import uhdm"
)

add_test(
NAME python-tests-unit-module
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_module.py
)
30 changes: 30 additions & 0 deletions python/UHDM.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
%module uhdm
/*
Everithing in the %{ ... %} block is simply copied verbatim to the resulting wraper file created by swig.
It is not parsed or interpreted by swig
*/
%{
#include <stdarg.h>
#include "vpi_user.h"
#include "sv_vpi_user.h"
#include "Serializer.h"

#include "swig_test.h"

%}
%include "std_vector.i"
%include "std_string.i"

/* some api function using va_list are exclude using #ifndef SWIG/#endif */
%include "vpi_user.h"
%include "sv_vpi_user.h"

%include "Serializer.h"
%include "uhdm_types.h"
%include "swig_test.h"
%include stl.i

namespace std {
%template(vpiHandleVector) vector<vpiHandle>;
}

25 changes: 25 additions & 0 deletions python/swig_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "swig_test.h"
#include "uhdm.h"
using namespace UHDM;

std::vector<vpiHandle> buildTestDesign(Serializer* s) {
std::vector<vpiHandle> designs;

design* d = s->MakeDesign();
vpiHandle dh = s->MakeUhdmHandle(uhdmdesign,d);
designs.push_back(dh);

VectorOfmodule_inst* vm = s->MakeModule_instVec();
d->AllModules(vm);

module_inst* m1 = s->MakeModule_inst();
m1->VpiName("module1");
vm->push_back(m1);

module_inst* m2 = s->MakeModule_inst();
m2->VpiName("module2");
vm->push_back(m2);

return designs;
}

2 changes: 2 additions & 0 deletions python/swig_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "Serializer.h"
std::vector<vpiHandle> buildTestDesign(UHDM::Serializer* s);
23 changes: 23 additions & 0 deletions python/tests/test_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import unittest
import uhdm


class test_module(unittest.TestCase):

def test_module(self):
result = []

s = uhdm.Serializer()

data = uhdm.buildTestDesign(s)
modit = uhdm.vpi_iterate(uhdm.uhdmallModules,data[0])
while(True):
vpiObj = uhdm.vpi_scan(modit)
if vpiObj is None:
break
result.append(uhdm.vpi_get_str(uhdm.vpiName,vpiObj))

self.assertEqual(set(result),set(["module2","module1"]))

if __name__ == '__main__':
unittest.main()
11 changes: 8 additions & 3 deletions templates/Serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ enum ErrorType {
UHDM_INVALID_CASE_STMT_VALUE = 727
};

#ifndef SWIG
typedef std::function<void(ErrorType errType, const std::string&,
const any* object1, const any* object2)>
ErrorHandler;
Expand All @@ -74,6 +75,7 @@ void DefaultErrorHandler(ErrorType errType, const std::string& errorMsg,

template <typename T>
class FactoryT;
#endif

class Serializer {
public:
Expand All @@ -82,29 +84,31 @@ class Serializer {
Serializer() : incrId_(0), objId_(0), errorHandler(DefaultErrorHandler) {}
~Serializer();

#ifndef SWIG
void Save(const std::filesystem::path& filepath);
void Save(const std::string& filepath);
void Purge();
void SetErrorHandler(ErrorHandler handler) { errorHandler = handler; }
ErrorHandler GetErrorHandler() { return errorHandler; }
#endif
const std::vector<vpiHandle> Restore(const std::filesystem::path& filepath);
const std::vector<vpiHandle> Restore(const std::string& filepath);
std::map<std::string, unsigned long, std::less<>> ObjectStats() const;
void PrintStats(std::ostream& strm, std::string_view infoText) const;

#ifndef SWIG
private:
template <typename T>
T* Make(FactoryT<T>* const factory);

template <typename T>
std::vector<T*>* Make(FactoryT<std::vector<T*>>* const factory);

public:
<FACTORY_FUNCTION_DECLARATIONS>
std::vector<any*>* MakeAnyVec() { return anyVectMaker.Make(); }

vpiHandle MakeUhdmHandle(UHDM_OBJECT_TYPE type, const void* object) {
return uhdm_handleMaker.Make(type, object);
}

VectorOfanyFactory anyVectMaker;
SymbolFactory symbolMaker;
uhdm_handleFactory uhdm_handleMaker;
Expand Down Expand Up @@ -138,6 +142,7 @@ class Serializer {
unsigned long objId_; // ID for property annotations

ErrorHandler errorHandler;
#endif
};
}; // namespace UHDM

Expand Down
5 changes: 4 additions & 1 deletion templates/Serializer_restore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,12 @@ struct Serializer::RestoreAdapter {
};

const std::vector<vpiHandle> Serializer::Restore(const std::filesystem::path& filepath) {
return Restore( filepath.string());
}
const std::vector<vpiHandle> Serializer::Restore(const std::string& filepath) {
Purge();
std::vector<vpiHandle> designs;
const std::string file = filepath.string();
const std::string file = filepath;
int fileid = open(file.c_str(), O_RDONLY | O_BINARY);
::capnp::ReaderOptions options;
options.traversalLimitInWords = ULLONG_MAX;
Expand Down
5 changes: 4 additions & 1 deletion templates/Serializer_save.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,14 @@ struct Serializer::SaveAdapter {
};

void Serializer::Save(const std::filesystem::path& filepath) {
Save(filepath.string());
}
void Serializer::Save(const std::string& filepath) {
unsigned long index = 0;

<CAPNP_ID>

const std::string file = filepath.string();
const std::string file = filepath;
const int fileid = open(file.c_str(), O_CREAT | O_WRONLY | O_BINARY, S_IRWXU);
::capnp::MallocMessageBuilder message;
UhdmRoot::Builder cap_root = message.initRoot<UhdmRoot>();
Expand Down
67 changes: 67 additions & 0 deletions templates/vpi_user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,70 @@ vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index,
PLI_INT32* index_array) {
return 0;
}


vpiHandle vpi_register_assertion_cb( vpiHandle assertion, PLI_INT32 reason, vpi_assertion_callback_func *cb_rtn, PLI_BYTE8 *user_data) {
return 0;
}


PLI_INT32 vpi_printf(PLI_BYTE8 *format, ...){
return 0;
};

/* callback related */
vpiHandle vpi_register_cb(p_cb_data cb_data_p){
return 0;
}

PLI_INT32 vpi_remove_cb(vpiHandle cb_obj){
return 0;
}

void vpi_get_cb_info(vpiHandle object, p_cb_data cb_data_p){
}

vpiHandle vpi_register_systf(p_vpi_systf_data systf_data_p){
return 0;
}

void vpi_get_systf_info(vpiHandle object, p_vpi_systf_data systf_data_p){
}

PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *fileName){
return 0;
}
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd){
return 0;
}
PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 cd){
return 0;
}
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd,PLI_BYTE8 *format, ...){
return 0;
}

PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p){
return 0;
}
PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p){
return 0;
}

PLI_INT32 vpi_flush(void) {
return 0;
}
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd){
return 0;
}
PLI_INT32 vpi_control(PLI_INT32 operation, ...){
return 0;
}

/*
* 38.37.1 System task and system function callbacks
* Global variable
*/
void (*vlog_startup_routines[]) () = {
0
};

0 comments on commit eef0530

Please sign in to comment.