def test_pyha_to_python_value(self):
        class A(Hardware):
            def __init__(self):
                self.f = Sfix(0.5, 0, -5)
                self.fl = [Sfix(0.5, 0, -5)] * 2

        a = VHDLModule('name', A(), A())
        pyt = a._pyha_to_python_value()
        assert pyt.f == 0.5
        assert pyt.fl == [0.5] * 2
Exemple #2
0
    def __init__(self, red_node, parent=None):
        super().__init__(red_node, parent)

        # todo: remove me after refactorings
        try:
            self.data = VHDLModule('-', convert_obj)
        except AttributeError:
            self.data = None
        # collect multiline comment
        self.multiline_comment = ''
        if len(self.value) and isinstance(self.value[0], StringNodeVHDL):
            self.multiline_comment = str(self.value[0])
            del self.value[0]
    def test_pyha_is_equal(self):
        class A(Hardware):
            def __init__(self, v):
                self.f = v

        a = VHDLModule('name', A(False), A(True))
        b = VHDLModule('name', A(True), A(False))
        assert a._pyha_is_equal(a)
        assert not a._pyha_is_equal(b)

        a = VHDLModule('name', A([1, 2, 3]), A([1, 2, 3]))
        b = VHDLModule('name', A([3, 2, 1]), A([3, 2, 1]))
        assert a._pyha_is_equal(a)
        assert not a._pyha_is_equal(b)
    def setup(self):
        class T(Hardware):
            def __init__(self):
                self.a = 0
                self.b = Sfix(0, 0, -17)

        self.dut = VHDLModule('name', T(), T())
    def test_pyha_convert_from_stdlogic(self):
        class B(Hardware):
            def __init__(self):
                self.f = Sfix(0, 0, -17)

        class A(Hardware):
            def __init__(self):
                self.i = 1
                self.b = False
                self.sub = B()

        a = VHDLModule('name', A(), A())
        expect = 'var.i := to_integer(signed(in0(31 downto 0)));\n' \
                 'var.b := logic_to_bool(in0(32 downto 32));\n' \
                 'var.sub.f := Sfix(in0(50 downto 33), 0, -17);\n'

        assert expect == a._pyha_convert_from_stdlogic('var', 'in0')
    def test_pyha_convert_to_stdlogic(self):
        class B(Hardware):
            def __init__(self):
                self.f = Sfix(0, 0, -17)

        class A(Hardware):
            def __init__(self):
                self.i = 1
                self.b = False
                self.sub = B()

        a = VHDLModule('name', A(), A())

        expect = 'var(31 downto 0) <= std_logic_vector(to_signed(in0.i, 32));\n' \
                 'var(32 downto 32) <= bool_to_logic(in0.b);\n' \
                 'var(50 downto 33) <= to_slv(in0.sub.f);\n'

        assert expect == a._pyha_convert_to_stdlogic('var', 'in0')
Exemple #7
0
def transform_enum(red_node):
    """
    Converts 'EnumType.ENUMVALUE' to integer value , see #154
    """
    data = VHDLModule('-', convert_obj)
    enums = [x for x in data.elems if isinstance(x, VHDLEnum)]
    for x in enums:
        type_name = x._pyha_type()
        red_names = red_node.find_all('atomtrailers',
                                      value=lambda x: x[0].value == type_name)
        for i, node in enumerate(red_names):
            enum_obj = type(x.current)[str(node[1])]
            red_names[i].replace(str(enum_obj.value))
Exemple #8
0
def transform_dynamic_lists(red_node):
    data = VHDLModule('-', convert_obj)

    dynamic_lists = [
        x for x in data.elems
        if isinstance(x, VHDLList) and not x.elements_compatible_typed
    ]
    for x in dynamic_lists:
        name = x._name
        red_names = red_node.find_all('atomtrailers')
        for node in red_names:
            for i, part in enumerate(node):
                if str(part) == name and isinstance(part.next, GetitemNode):
                    try:
                        index = int(str(part.next.value))
                        part.replace(f'{name}_{index}')
                        del node[i + 1]
                    except ValueError:

                        line_node = node
                        while True:
                            if type(line_node.next) == EndlNode:
                                break
                            if hasattr(line_node.parent, 'value') and type(
                                    line_node.parent.value) == LineProxyList:
                                if not (
                                        hasattr(line_node.parent, 'test') and
                                    (line_node.parent.test ==
                                     node  # if WE are the if condition, skip
                                     or line_node.parent.test == node.parent)
                                ):  # if WE are the if condition (part of condition)
                                    break

                            line_node = line_node.parent

                        index = str(part.next.value)
                        node[i + 1].replace(
                            ' ')  # del node[i+1], crashes redbaron

                        correct_indentation = line_node.indentation
                        new = 'if True:\n'  # replace needs a BLOCK, so this is a dummy IF
                        for i in range(len(x.elems)):
                            part.replace(f'{name}_{i}')

                            head = 'if' if i == 0 else 'elif'
                            new += f'{correct_indentation}\t{head} {index} == {i}:\n{correct_indentation}\t\t{line_node}\n'

                        line_node.replace(new)
Exemple #9
0
    def __init__(self, simulated_object):
        self.simulated_object = simulated_object
        self.simulated_object_vhdl = VHDLModule('-', self.simulated_object)

        # 0 or 1 calls wont propagate register outputs
        if self.simulated_object.main.calls == 0:
            raise NotTrainedError(
                'Top level object must be trained (executed) > 1 times.')

        if len(self.get_object_inputs()) == 0:
            raise NoInputsError(
                'Top level "main" has no inputs (arguments to main).')

        if len(self.get_object_return()) == 0:
            raise NoOutputsError(
                'Top level "main" has no outputs (return values).')
    def test_pyha_type_is_compatible(self):
        class A(Hardware):
            def __init__(self, init):
                self.REG = init

        class B(Hardware):
            def __init__(self):
                self.REG = 1
                self.lol = False

        class C(Hardware):
            def __init__(self):
                self.a = A(1)
                self.b = B()

        a = VHDLModule('name', A(1), A(2))
        b = VHDLModule('name', B(), B())
        c = VHDLModule('name', C(), C())
        assert a._pyha_type_is_compatible(a)
        assert not a._pyha_type_is_compatible(b)
        assert c._pyha_type_is_compatible(c)
        assert not c._pyha_type_is_compatible(a)
        assert not c._pyha_type_is_compatible(b)
Exemple #11
0
    def __init__(self, obj, datamodel=None):
        """ Convert object and all childs to VHDL """
        with RecursiveConverter.in_progress:
            self.obj = obj
            self.class_name = obj.__class__.__name__
            self.datamodel = datamodel
            self.is_root = datamodel is None
            if self.is_root:
                RecursiveConverter.converted_modules = {}
                RecursiveConverter.typedefs = []
                self.datamodel = VHDLModule('-', obj)

            # recursively convert all child modules
            self.childs = []

            def conv(self, node):
                if isinstance(node, VHDLList):
                    if node.elements_compatible_typed:
                        if isinstance(node.elems[0], VHDLModule):
                            if self.is_compatible_with_converted_module(
                                    node.elems[0]):
                                return
                            self.childs.append(
                                RecursiveConverter(node.elems[0].current,
                                                   node.elems[0]))

                    else:
                        # dynamic list..need to convert all modules
                        for x in node.elems:
                            if isinstance(x, VHDLModule):
                                if self.is_compatible_with_converted_module(x):
                                    return
                                self.childs.append(
                                    RecursiveConverter(x.current, x))
                elif isinstance(node, VHDLModule):
                    if self.is_compatible_with_converted_module(node):
                        return
                    self.childs.append(RecursiveConverter(node.current, node))

            if self.is_root:
                logger.info(f'Creating top.vhd ...')
                self.top_vhdl = TopGenerator(obj)

                # maybe some input/output is a convertible module?
                for node in self.inputs:
                    conv(self, node)

                for node in self.outputs:
                    conv(self, node)

            # iterate all functions and discover local variables that may need to be converted
            for x in self.obj.__dict__.values():
                if isinstance(x, PyhaFunc):
                    for key, val in x.get_local_types().items():
                        if isinstance(val, Hardware):
                            node = init_vhdl_type(key, val)
                            conv(self, node)

            # convert instance elements before the instance itself, recursive
            for node in self.datamodel.elems:
                conv(self, node)

            self.red_node = get_objects_rednode(obj)
            logger.info(f'{self.class_name} to VHDL ...')
            self.conv = convert(self.red_node,
                                obj)  # actual conversion happens here

            self.vhdl_conversion = str(self.conv)
            RecursiveConverter.converted_modules[
                self.get_module_converted_name(
                    self.datamodel)] = (self.datamodel, self.vhdl_conversion)
            RecursiveConverter.typedefs.extend(self.conv.build_typedefs())
Exemple #12
0
class ClassNodeVHDL(NodeVHDL):
    def __init__(self, red_node, parent=None):
        super().__init__(red_node, parent)

        # todo: remove me after refactorings
        try:
            self.data = VHDLModule('-', convert_obj)
        except AttributeError:
            self.data = None
        # collect multiline comment
        self.multiline_comment = ''
        if len(self.value) and isinstance(self.value[0], StringNodeVHDL):
            self.multiline_comment = str(self.value[0])
            del self.value[0]

    def get_function(self, name):
        f = [x for x in self.value if str(x.name) == name]
        assert len(f)
        return f[0]

    def build_imports(self):
        template = textwrap.dedent("""\
            library ieee;
                use ieee.std_logic_1164.all;
                use ieee.numeric_std.all;
                use ieee.fixed_float_types.all;
                use ieee.fixed_pkg.all;
                use ieee.math_real.all;

            library work;
                use work.complex_pkg.all;
                use work.PyhaUtil.all;
                use work.Typedefs.all;
                use work.all;
            {IMPORTS}""")

        # add all converted classes to imports
        # look: https://github.com/tgingold/ghdl/issues/209
        from pyha.conversion.conversion import RecursiveConverter
        imports = [
            f'use work.{x}.all;'
            for x in RecursiveConverter.converted_modules.keys()
        ]
        return template.format(IMPORTS=formatter(imports))

    def build_constructor(self, prototype_only=False):
        template = textwrap.dedent("""\
            function {NAME}{ARGS} return self_t is
                -- constructor
                variable self: self_t;
            begin
            {DATA}
                return self;
            end function;""")

        data = [x._pyha_constructor() for x in self.data.elems]
        args = '; '.join([
            x._pyha_constructor_arg() for x in self.data.elems
            if x._pyha_constructor_arg() != ''
        ])
        if args != '':
            args = f'({args[:-2]})' if args[-2:] == '; ' else f'({args})'
        ret = template.format(NAME=escape_reserved_vhdl(self.name),
                              ARGS=args,
                              DATA=formatter(data))

        if prototype_only:
            return ret.splitlines()[0][:-3] + ';'
        return ret

    def build_data_structs(self):
        template = textwrap.dedent("""\
            type self_t is record
            {DATA}
            end record;""")

        data = [
            x._pyha_definition() for x in self.data.elems
            if not is_constant(x._name)
        ]
        if not data:
            data = ['dummy: integer;']
        return template.format(DATA=formatter(data))

    def build_constants(self):
        template = textwrap.dedent("""\
            type self_t_const is record
            {DATA}
            end record;""")

        data = [
            x._pyha_definition() for x in self.data.elems if const_filter(x)
        ]

        if not data:
            data = ['DUMMY: integer;']
        return template.format(DATA=formatter(data))

    def build_typedefs(self):
        # self typedefs
        typedefs = [
            x._pyha_typedef() for x in self.data.elems
            if x._pyha_typedef() is not None
        ]

        # local vars
        for function in self.value:
            if not isinstance(function, DefNodeVHDL):
                continue
            variables = [
                init_vhdl_type(name, val, val)
                for name, val in function.data.get_local_types().items()
            ]
            typedefs += [
                x._pyha_typedef() for x in variables
                if x is not None and x._pyha_typedef() is not None
            ]
        typedefs = list(dict.fromkeys(typedefs))  # get rid of duplicates
        return typedefs

    def build_package_header(self):
        template = textwrap.dedent("""\
            {MULTILINE_COMMENT}
            package {NAME} is
            {SELF_T}
            {SELF_ARRAY_TYPEDEF}
            
            {CONST_SELF_T}
            {CONST_SELF_ARRAY_TYPEDEF}

            {FUNC_HEADERS}
            end package;""")

        sockets = {}
        sockets['MULTILINE_COMMENT'] = self.multiline_comment
        sockets['NAME'] = self.data._pyha_module_name()

        # data-structure without constants ie. registers
        sockets['SELF_T'] = tabber(self.build_data_structs())
        sockets[
            'SELF_ARRAY_TYPEDEF'] = f'    type {self.data._pyha_arr_type_name()} is array (natural range <>) of {self.data._pyha_type()};'

        # only constants
        with TypeAppendHack('_const'):
            sockets['CONST_SELF_T'] = tabber(self.build_constants())
            sockets[
                'CONST_SELF_ARRAY_TYPEDEF'] = f'    type {self.data._pyha_arr_type_name()} is array (natural range <>) of {self.data._pyha_type()};'

        proto = '\n'.join(
            x.build_function(prototype_only=True) for x in self.value
            if isinstance(x, DefNodeVHDL))
        proto += '\n' + self.build_constructor(prototype_only=True) + '\n'
        sockets['FUNC_HEADERS'] = tabber(proto)

        return template.format(**sockets)

    def build_package_body(self):
        template = textwrap.dedent("""\
            package body {NAME} is
            {USER_FUNCTIONS}
            
            {CONSTRUCTOR}
            end package body;""")

        sockets = {}
        sockets['NAME'] = self.data._pyha_module_name()

        sockets['CONSTRUCTOR'] = tabber(self.build_constructor())
        # sockets['INIT_SELF'] = tabber(self.build_init())
        # sockets['CONSTANT_SELF'] = tabber(self.build_reset_constants())
        # sockets['RESET_SELF'] = tabber(self.build_reset())
        # sockets['UPDATE_SELF'] = tabber(self.build_update_registers())
        sockets['USER_FUNCTIONS'] = '\n\n'.join(
            tabber(str(x)) for x in self.value if isinstance(x, DefNodeVHDL))

        return template.format(**sockets)

    def __str__(self):
        template = textwrap.dedent("""\
            {FILE_HEADER}
            {IMPORTS}

            {PACKAGE_HEADER}

            {PACKAGE_BODY}
            """)

        sockets = {}
        sockets['FILE_HEADER'] = file_header()
        sockets['IMPORTS'] = self.build_imports()
        sockets['PACKAGE_HEADER'] = self.build_package_header()
        sockets['PACKAGE_BODY'] = self.build_package_body()
        return template.format(**sockets)
Exemple #13
0
 def object_class_name(self) -> str:
     # make sure we escape reserved names
     mod = VHDLModule('-', self.simulated_object)
     return mod._pyha_module_name()