PySysC/pysysc/sccppyy.py

196 lines
6.3 KiB
Python
Raw Normal View History

2018-12-31 15:23:37 +01:00
import json
import cppyy
import os.path
import sys
import tempfile
import conans.client.conan_api as conan
from contextlib import (redirect_stdout, redirect_stderr)
import io
lang_symbols = {
3: '199711L',
11:'201103L',
14:'201402L',
17:'201703L'}
lang_level=11
'''
'''
sysIncludeDirs = set()
includeDirs = set()
class NullLogger(object):
def __init__(self):
self.terminal = sys.stdout
self.buffer=""
def __getattr__(self, attr):
return getattr(self.terminal, attr)
def write(self, message):
self.buffer+=message
2019-01-04 15:46:55 +01:00
def read_config_from_conan(conanfile, build_type='Release'):
2018-12-31 15:23:37 +01:00
global lang_level
sys.stdout = NullLogger()
#read conan configuration
with tempfile.TemporaryDirectory() as tmpdirname:
conan_api, client_cache, user_io = conan.Conan.factory()
install_info = conan_api.install(path=conanfile,
generators=['json'],
2019-01-04 15:46:55 +01:00
settings=['build_type=%s'%build_type],
2018-12-31 15:23:37 +01:00
install_folder=tmpdirname)
for e in install_info['installed']:
name = e['recipe']['name']
for p in e['packages']:
if name == 'SystemC' and p['cpp_info']['rootpath']:
os.environ['SYSTEMC_HOME']=p['cpp_info']['rootpath']
with open(os.path.join(tmpdirname, "conanbuildinfo.json")) as f:
data=json.load(f)
# set include pathes and load libraries
for d in data['dependencies']:
for p in d['include_paths']:
add_sys_include_path(p)
2018-12-31 15:23:37 +01:00
if d['name'] == 'SystemC':
for l in d['lib_paths']:
if os.path.exists(l+'/'+'libsystemc.so'):
cppyy.load_library(l+'/'+'libsystemc.so')
lang_level = int(data['options']['SystemC']['stdcxx'])
msg = sys.stdout.buffer
sys.stdout=sys.stdout.terminal
return msg
2019-01-04 15:46:55 +01:00
systemc_loaded=False
2018-12-31 15:23:37 +01:00
def load_systemc():
if 'SYSTEMC_HOME' in os.environ:
add_sys_include_path(os.path.join(os.environ['SYSTEMC_HOME'], 'include'))
for l in ['lib', 'lib64', 'lib-linux', 'lib-linux64']:
for f in ['libsystemc.so']:
if os.path.isfile(os.path.join(os.environ['SYSTEMC_HOME'], l, f)):
cppyy.load_library(os.path.join(os.environ['SYSTEMC_HOME'], l, f))
cppyy.cppdef("""
#define SC_CPLUSPLUS %s
#include "systemc"
#include "tlm"
2019-01-04 15:46:55 +01:00
"""
% lang_symbols[lang_level])
systemc_loaded=True
cppyy.gbl.sc_core.sc_in_action=True
2018-12-31 15:23:37 +01:00
return True
return False
def add_library(file, lib):
buf = io.StringIO()
with redirect_stdout(buf), redirect_stderr(buf):
cppyy.load_library(lib)
cppyy.include(file)
return buf.getvalue()
def add_include_path(incl):
includeDirs.add(incl)
cppyy.add_include_path(incl)
def add_sys_include_path(incl):
sysIncludeDirs.add(incl)
cppyy.add_include_path(incl)
# prepare a pythonizor
def _pythonizor(klass, name):
# A pythonizor receives the freshly prepared bound C++ class, and a name stripped down to
# the namespace the pythonizor is applied. Also accessible are klass.__name__ (for the
# Python name) and klass.__cppname__ (for the C++ name)
if name == 'sc_time':
klass.__repr__ = lambda self: repr(self.to_string())
klass.__str__ = lambda self: self.to_string()
elif name in ['sc_object', 'sc_module']:
klass.__repr__ = lambda self: repr(self.name())
elif len(name) > 8 and name[:7] == 'sc_port<':
klass.__repr__ = lambda self: repr(self.name())
elif len(name) > 10 and name[:9] == 'sc_export<':
klass.__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)
cppyy.py.add_pythonization(_pythonizor, 'sc_core')
2019-01-03 21:15:57 +01:00
2018-12-31 15:23:37 +01:00
# reflection methods
def get_members(sc_object):
2018-12-31 15:23:37 +01:00
def is_cpp_data_type(name, module):
matches = [x for x in ['int', 'char', 'float', 'double'] if name == x]
if len(matches) > 0 or module[:10] == "cppyy.gbl.":
return True
else:
return False
members = [(e, getattr(sc_object, e)) for e in dir(sc_object)]
2018-12-31 15:23:37 +01:00
return [(k,v) for k,v in members if is_cpp_data_type(type(v).__name__, type(v).__module__)]
def get_methods(sc_object):
members = [(e, getattr(sc_object, e)) for e in dir(sc_object)]
2018-12-31 15:23:37 +01:00
return [(k,v) for k,v in members if type(v).__name__=='CPPOverload']
def get_ports(module):
res = []
for elem in dir(module):
attr=getattr(module, elem)
if isinstance(attr, cppyy.gbl.sc_core.sc_port_base) and not isinstance(attr, cppyy.gbl.tlm.tlm_base_socket_if):
res.append(attr)
return res
def get_exports(module):
res = []
for elem in dir(module):
attr=getattr(module, elem)
if isinstance(attr, cppyy.gbl.sc_core.sc_export_base) and not isinstance(attr, cppyy.gbl.tlm.tlm_base_socket_if):
res.append(attr)
return res
def get_inititator_sockets(module):
res = []
for elem in dir(module):
attr=getattr(module, elem)
if isinstance(attr, cppyy.gbl.sc_core.sc_port_base) and isinstance(attr, cppyy.gbl.tlm.tlm_base_socket_if):
res.append(attr)
return res
def get_target_sockets(module):
res = []
for elem in dir(module):
attr=getattr(module, elem)
if isinstance(attr, cppyy.gbl.sc_core.sc_export_base) and isinstance(attr, cppyy.gbl.tlm.tlm_base_socket_if):
res.append(attr)
return res
def get_submodules(module):
res = []
for elem in dir(module):
attr=getattr(module, elem)
if isinstance(attr, cppyy.gbl.sc_core.sc_module):
res.append(attr)
return res
2019-01-04 15:46:55 +01:00
import time
class timewith():
def __init__(self, name=''):
self.name = name
self.start = time.time()
@property
def elapsed(self):
return time.time() - self.start
def checkpoint(self, name=''):
return '{timer} {checkpoint} took {elapsed} seconds'.format(timer=self.name, checkpoint=name, elapsed=self.elapsed).strip()
def __enter__(self):
return self
def __exit__(self, mytype, value, traceback):
print(self.checkpoint('finished'))
pass