Added PyScModule to forward simulation phase callbacks

This commit is contained in:
Eyck Jentzsch 2019-06-08 14:31:23 +00:00
parent b1334a0689
commit 4381c9be32
5 changed files with 120 additions and 9 deletions

57
PyScModule.cpp Normal file
View File

@ -0,0 +1,57 @@
/*
* PyScModule.cpp
*
* Created on: 08.06.2019
* Author: eyck
*/
#include "PyScModule.h"
#define PY_SSIZE_T_CLEAN
#include <python3.6/Python.h>
class TPyScriptThreadLocker {
PyGILState_STATE m_state;
public:
TPyScriptThreadLocker(): m_state(PyGILState_Ensure()) {}
~TPyScriptThreadLocker() { PyGILState_Release(m_state); }
};
scc::PyScModule::PyScModule(PyObject* self, const sc_core::sc_module_name& nm)
: sc_core::sc_module(nm)
, self(self)
{
if (! PyEval_ThreadsInitialized())
PyEval_InitThreads();
Py_INCREF(self);
}
scc::PyScModule::~PyScModule() {
Py_DECREF(self);
}
void scc::PyScModule::before_end_of_elaboration(){
invoke_callback("BeforeEndOfElaboration");
}
void scc::PyScModule::end_of_elaboration(){
invoke_callback("EndOfElaboration");
}
void scc::PyScModule::start_of_simulation(){
invoke_callback("StartOfSimulation");
}
void scc::PyScModule::end_of_simulation(){
invoke_callback("EndOfSimulation");
}
void scc::PyScModule::invoke_callback(const char* callback_name) {
// acquiring the GIL
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
if(PyObject_HasAttrString(self, callback_name)){
auto* func = PyObject_GetAttrString(self, callback_name);
PyObject_CallFunctionObjArgs(func, nullptr);
}
// Release the thread. No Python API allowed beyond this point.
PyGILState_Release(gstate);
}

33
PyScModule.h Normal file
View File

@ -0,0 +1,33 @@
/*
* PyScModule.h
*
* Created on: 08.06.2019
* Author: eyck
*/
#ifndef COMPONENTS_PYSCMODULE_H_
#define COMPONENTS_PYSCMODULE_H_
#include <systemc>
#include <unordered_map>
#include <tuple>
typedef struct _object PyObject;
namespace scc {
class PyScModule: public sc_core::sc_module {
public:
PyScModule(PyObject* self, const sc_core::sc_module_name& nm);
virtual ~PyScModule();
protected:
void before_end_of_elaboration() override;
void end_of_elaboration() override;
void start_of_simulation() override;
void end_of_simulation() override;
private:
void invoke_callback(const char*);
PyObject* self{nullptr};
};
}
#endif /* COMPONENTS_PYSCMODULE_H_ */

View File

@ -1,6 +1,7 @@
import json import json
import cppyy import cppyy
import os.path import os.path
from pathlib import Path
import sys import sys
import tempfile import tempfile
import conans.client.conan_api as conan import conans.client.conan_api as conan
@ -13,8 +14,6 @@ lang_symbols = {
14:'201402L', 14:'201402L',
17:'201703L'} 17:'201703L'}
lang_level=11 lang_level=11
'''
'''
sysIncludeDirs = set() sysIncludeDirs = set()
@ -92,6 +91,7 @@ namespace sc_core { extern void pln(); }
if systemc_loaded: break; if systemc_loaded: break;
if not interactive: cppyy.gbl.sc_core.pln() if not interactive: cppyy.gbl.sc_core.pln()
cppyy.gbl.sc_core.sc_in_action=True cppyy.gbl.sc_core.sc_in_action=True
_load_pythonization_lib()
return True return True
return False return False
@ -121,6 +121,16 @@ def _load_systemc_cci():
return True return True
return False return False
def _load_pythonization_lib():
import pysysc
path = os.path.dirname(os.path.dirname(pysysc.__file__))
for file in os.listdir(path):
if file.endswith(".so"):
cppyy.load_library(os.path.join(path, file))
cppyy.include(os.path.join(path, "PyScModule.h"))
return
def add_library(file, lib): def add_library(file, lib):
buf = io.StringIO() buf = io.StringIO()
with redirect_stdout(buf), redirect_stderr(buf): with redirect_stdout(buf), redirect_stderr(buf):
@ -150,8 +160,6 @@ def _pythonizor(clazz, name):
clazz.__repr__ = lambda self: repr(self.name()) clazz.__repr__ = lambda self: repr(self.name())
elif len(name) > 10 and name[:9] == 'sc_export<': elif len(name) > 10 and name[:9] == 'sc_export<':
clazz.__repr__ = lambda self: repr(self.name()) clazz.__repr__ = lambda self: repr(self.name())
# else:
# print('not pythonizing', name)
# install the pythonizor as a callback on namespace 'Math' (default is the global namespace) # install the pythonizor as a callback on namespace 'Math' (default is the global namespace)
cppyy.py.add_pythonization(_pythonizor, 'sc_core') cppyy.py.add_pythonization(_pythonizor, 'sc_core')

View File

@ -8,7 +8,6 @@ from builtins import getattr
import re import re
from enum import Enum from enum import Enum
import logging import logging
import pysysc
class Mode(Enum): class Mode(Enum):
SIM = 1 SIM = 1
@ -21,6 +20,8 @@ class Simulation(object):
@staticmethod @staticmethod
def run(): def run():
cpp.sc_core.sc_start() cpp.sc_core.sc_start()
if not cpp.sc_core.sc_end_of_simulation_invoked():
cpp.sc_core.sc_stop()
@staticmethod @staticmethod
def setup(log_level = logging.WARNING): def setup(log_level = logging.WARNING):

View File

@ -1,15 +1,26 @@
from setuptools import setup from setuptools import setup, Extension
import os
def readme(): def readme():
with open('README.md') as f: with open('README.md') as f:
return f.read() return f.read()
sysc_home = os.environ['SYSTEMC_HOME']
pysyscsc = Extension('pysyscsc',
define_macros = [('MAJOR_VERSION', '1'), ('MINOR_VERSION', '0')],
extra_compile_args = ['-std=c++11'],
include_dirs = [sysc_home+'/include'],
libraries = ['systemc'],
library_dirs = [sysc_home+'/lib'],
sources = ['PyScModule.cpp'])
setup(name='PySysC', setup(name='PySysC',
version='0.1', version='0.1',
description='Python SystemC binding', description='Python SystemC binding',
long_description=readme(), long_description=readme(),
ext_modules = [pysyscsc],
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'License :: OSI Approved :: Apache Software License', 'License :: OSI Approved :: Apache Software License',
@ -22,11 +33,12 @@ setup(name='PySysC',
author_email='info@minres.com', author_email='info@minres.com',
license='Apache-2.0', license='Apache-2.0',
packages=['pysysc'], packages=['pysysc'],
data_files=[('.',['PyScModule.h'])],
include_package_data=True,
install_requires=[ install_requires=[
'cppyy', 'cppyy',
'conan' 'conan'
], ],
include_package_data=True,
test_suite='nose.collector', test_suite='nose.collector',
tests_require=['nose'], tests_require=['nose'],
) )