示例#1
0
    def generate_consumer(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection, consumer_instance_name,
                          attributes):
        caller_fn = context.get_port(connection.provider).functions['run']
        fn_to_call = context.get_port(consumer_instance_name).functions['run']

        manual_args = {}
        consumer_instance = context.get_component_instance(
            consumer_instance_name)
        provider_instance = context.get_component_instance(connection.provider)

        callee_instance_arg_name = get_instance_argument(
            list(fn_to_call.arguments.keys()), consumer_instance)
        if callee_instance_arg_name:
            manual_args[
                callee_instance_arg_name] = '&' + consumer_instance.instance_var_name

        caller_args = caller_fn.arguments.copy()
        passed_arguments = collect_arguments(attributes,
                                             consumer_instance_name,
                                             fn_to_call.arguments, caller_args,
                                             manual_args)

        provider_port_name = context.get_component_ref(connection.provider)
        body = fn_to_call.generate_call(passed_arguments) + ';'

        used_args = list(passed_arguments.keys())

        instance_arg_name = get_instance_argument(list(caller_args.keys()),
                                                  provider_instance)
        if instance_arg_name:
            used_args.append(instance_arg_name)
            body = add_instance_check(body,
                                      provider_instance,
                                      instance_arg_name=instance_arg_name)

        return {
            provider_port_name: {
                'run': {
                    'body': body,
                    'used_arguments': used_args
                },
                'write': {
                    'body': body,
                    'used_arguments': used_args
                }
            }
        }
示例#2
0
    def generate_consumer(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection, consumer_instance_name,
                          attributes):
        provider_port_data = context.get_port(connection.provider)
        consumer_port_data = context.get_port(consumer_instance_name)
        consumer_port_name = context.get_component_ref(consumer_instance_name)

        member_accessor, data_type = process_member_access(
            context.types, attributes, provider_port_data['data_type'],
            consumer_port_data['data_type'])

        function = context.functions[consumer_port_name]['read']
        argument_names = list(function.arguments.keys())

        consumer_instance = context.get_component_instance(
            consumer_instance_name)
        instance_argument = get_instance_argument(argument_names,
                                                  consumer_instance)

        used_args = []
        return_statement = None
        if 'count' not in consumer_port_data:
            # single read, index should be next to consumer name
            try:
                index = attributes['index']
            except KeyError as e:
                raise Exception(
                    f'{consumer_instance_name} tries to read from an '
                    f'array without specifying the element') from e
        else:
            if consumer_port_data['count'] > provider_port_data['count']:
                raise Exception(
                    f'{consumer_instance_name} signal count ({consumer_port_data["count"]}) '
                    f'is incompatible with {connection.provider} ({provider_port_data["count"]})'
                )

            index = argument_names.pop(0)
            used_args.append(index)

        if data_type.passed_by() == TypeCollection.PASS_BY_VALUE:
            read = f'return {connection.name}[{index}]{member_accessor};'
            if instance_argument is not None:
                return_statement = data_type.render_value(None)
        else:
            out_name = argument_names[0]
            used_args.append(out_name)

            read = f'*{out_name} = {connection.name}[{index}]{member_accessor};'

        if instance_argument is not None:
            used_args.append(instance_argument)
            read = add_instance_check(read,
                                      consumer_instance,
                                      instance_arg_name=instance_argument)

        mods = {'body': read, 'used_arguments': used_args}
        if return_statement:
            mods['return_statement'] = return_statement

        return {consumer_port_name: {'read': mods}}
示例#3
0
    def generate_provider(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection,
                          provider_instance_name):
        provider_port_data = context.get_port(provider_instance_name)
        provider_port_name = context.get_component_ref(provider_instance_name)
        data_type = context.types.get(provider_port_data['data_type'])

        function = context.functions[provider_port_name]['write']
        argument_names = list(function.arguments.keys())

        provider_instance = context.get_component_instance(
            provider_instance_name)
        instance_argument = get_instance_argument(argument_names,
                                                  provider_instance)

        index, value = argument_names
        used_args = [index, value]

        if data_type.passed_by() == TypeCollection.PASS_BY_VALUE:
            body = f'{connection.name}[{index}] = {value};'
        else:
            body = f'{connection.name}[{index}] = *{value};'

        if instance_argument is not None:
            used_args.append(instance_argument)
            body = add_instance_check(body, provider_instance)

        return {
            provider_port_name: {
                'write': {
                    'used_arguments': used_args,
                    'body': body
                }
            }
        }
示例#4
0
    def generate_provider(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection,
                          provider_instance_name):
        provider_port_data = context.get_port(provider_instance_name)
        provider_port_name = context.get_component_ref(provider_instance_name)
        data_type = context.types.get(provider_port_data['data_type'])

        if connection.attributes['queue_length'] == 1:
            template = \
                "{{ signal_name }}_overflow = {{ signal_name }}_data_valid;\n" \
                "{{ signal_name }} = {{ value }};\n" \
                "{{ signal_name }}_data_valid = true;"
        else:
            template = \
                "if ({{ signal_name }}_count < {{ queue_length }}u)\n" \
                "{\n" \
                "    ++{{ signal_name }}_count;\n" \
                "}\n" \
                "else\n" \
                "{\n" \
                "    {{ signal_name }}_overflow = true;\n" \
                "}\n" \
                "size_t {{ signal_name }}_idx = {{ signal_name }}_write_index;\n" \
                "{{ signal_name }}_write_index = ({{ signal_name }}_write_index + 1u) % {{ queue_length }}u;\n" \
                "{{ signal_name }}[{{ signal_name }}_idx] = {{ value }};"

        function = context.functions[provider_port_name]['write']
        argument_names = list(function.arguments.keys())

        provider_instance = context.get_component_instance(
            provider_instance_name)
        instance_arg_name = get_instance_argument(argument_names,
                                                  provider_instance)

        passed_by_value = data_type.passed_by() == TypeCollection.PASS_BY_VALUE
        value_arg = argument_names[0]
        used_args = [value_arg]

        body = chevron.render(
            template, {
                'queue_length': connection.attributes['queue_length'],
                'signal_name': connection.name,
                'value': value_arg if passed_by_value else '*' + value_arg
            })

        if instance_arg_name:
            used_args.append(instance_arg_name)
            body = add_instance_check(body,
                                      provider_instance,
                                      instance_arg_name=instance_arg_name)

        return {
            provider_port_name: {
                'write': {
                    'used_arguments': used_args,
                    'body': body
                }
            }
        }
示例#5
0
    def generate_consumer(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection, consumer_instance_name,
                          attributes):
        provider_port_data = context.get_port(connection.provider)
        consumer_port_data = context.get_port(consumer_instance_name)
        consumer_port_name = context.get_component_ref(consumer_instance_name)

        member_accessor, data_type = process_member_access(
            context.types, attributes, provider_port_data['data_type'],
            consumer_port_data['data_type'])

        function = context.functions[consumer_port_name]['read']
        argument_names = list(function.arguments.keys())

        consumer_instance = context.get_component_instance(
            consumer_instance_name)
        instance_argument = get_instance_argument(argument_names,
                                                  consumer_instance)

        used_args = []
        return_statement = None
        if data_type.passed_by() == TypeCollection.PASS_BY_VALUE:
            read = f'return {connection.name}{member_accessor};'

            if instance_argument is not None:
                return_statement = data_type.render_value(None)
        else:
            out_name = argument_names[0]
            read = f'*{out_name} = {connection.name}{member_accessor};'
            used_args.append(out_name)

        if instance_argument is not None:
            used_args.append(instance_argument)
            read = add_instance_check(read,
                                      consumer_instance,
                                      instance_arg_name=instance_argument)

        mods = {'body': read, 'used_arguments': used_args}
        if return_statement:
            mods['return_statement'] = return_statement

        return {consumer_port_name: {'read': mods}}
示例#6
0
    def generate_consumer(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection, consumer_instance_name,
                          attributes):
        consumer_port_data = context.get_port(consumer_instance_name)
        caller_fn = consumer_port_data.functions['run']
        fn_to_call = context.get_port(connection.provider).functions['run']

        manual_args = {}
        consumer_instance = context.get_component_instance(
            consumer_instance_name)
        provider_instance = context.get_component_instance(connection.provider)

        instance_arg_name = get_instance_argument(
            list(caller_fn.arguments.keys()), consumer_instance)

        provider_instance_arg_name = get_instance_argument(
            list(fn_to_call.arguments.keys()), provider_instance)
        if provider_instance_arg_name:
            manual_args[
                provider_instance_arg_name] = '&' + provider_instance.instance_var_name

        passed_arguments = collect_arguments(attributes,
                                             consumer_instance_name,
                                             fn_to_call.arguments,
                                             caller_fn.arguments, manual_args)

        consumer_port_name = context.get_component_ref(consumer_instance_name)

        return_statement = None
        if caller_fn.return_type != 'void':
            if caller_fn.return_type != fn_to_call.return_type:
                raise Exception(
                    f'Callee return type is incompatible ({consumer_port_data["return_type"]} '
                    f'instead of {caller_fn.return_type})')

            body = f"return {fn_to_call.generate_call(passed_arguments)};"
            if provider_instance_arg_name:
                return_statement = context.types.get(
                    caller_fn.return_type).render_value(None)
        else:
            body = fn_to_call.generate_call(passed_arguments) + ';'

        if attributes['conditions']:
            used_args = [
                *passed_arguments.keys(), *attributes['conditions'].keys()
            ]
            conditions = (f'{arg} == {value}'
                          for arg, value in attributes['conditions'].items())
            body = f'if ({" && ".join(conditions)})\n' \
                   f'{{\n' \
                   f'{indent(body)}\n' \
                   f'}}'
        else:
            used_args = passed_arguments.keys()

        if instance_arg_name:
            body = add_instance_check(body,
                                      consumer_instance,
                                      instance_arg_name=instance_arg_name)

        mod = {'body': body, 'used_arguments': used_args}
        if return_statement:
            mod['return_statement'] = return_statement

        return {consumer_port_name: {'run': mod}}
示例#7
0
    def generate_consumer(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection, consumer_instance_name,
                          attributes):
        provider_port_data = context.get_port(connection.provider)
        consumer_port_data = context.get_port(consumer_instance_name)
        consumer_port_name = context.get_component_ref(consumer_instance_name)

        member_accessor, data_type = process_member_access(
            context.types, attributes, provider_port_data['data_type'],
            consumer_port_data['data_type'])

        consumer_instance = context.get_component_instance(
            consumer_instance_name)
        provider_instance = context.get_component_instance(connection.provider)

        function = context.functions[consumer_port_name]['read']
        argument_names = list(function.arguments.keys())

        constant_provider = provider_port_data.functions['constant']
        provider_argument_names = list(constant_provider.arguments.keys())

        call_args = {}
        instance_arg_name = get_instance_argument(argument_names,
                                                  consumer_instance)
        provider_instance_arg_name = get_instance_argument(
            provider_argument_names, provider_instance)
        if instance_arg_name:
            call_args[
                instance_arg_name] = '&' + consumer_instance.instance_var_name

        used_args = []
        if 'count' not in consumer_port_data:
            # single read, index should be next to consumer name
            try:
                index = attributes['index']
            except KeyError as e:
                raise Exception(
                    f'{consumer_instance_name} tries to read from a constant '
                    f'array without specifying the element') from e
        else:
            if consumer_port_data['count'] > provider_port_data['count']:
                raise Exception(
                    f'{consumer_instance_name} signal count ({consumer_port_data["count"]}) '
                    f'is incompatible with {connection.provider} ({provider_port_data["count"]})'
                )
            index = argument_names.pop(0)
            used_args.append(index)

        call_args['index'] = index

        return_statement = None
        if data_type.passed_by() == TypeCollection.PASS_BY_VALUE:
            call = constant_provider.generate_call(call_args)
            body = f'return {call}{member_accessor};'
            if provider_instance_arg_name:
                return_statement = data_type.render_value(None)
        else:
            out_name = argument_names[0]
            used_args.append(out_name)

            if member_accessor:
                call_args['value'] = '&tmp'
                call = constant_provider.generate_call(call_args)
                body = f'{data_type.name} tmp;\n' \
                       f'{call};\n' \
                       f'{out_name} = tmp{member_accessor};'
            else:
                call_args['value'] = out_name
                body = constant_provider.generate_call(call_args) + ';'

        if provider_instance_arg_name:
            used_args.append(provider_instance_arg_name)
            body = add_instance_check(
                body,
                consumer_instance,
                instance_arg_name=provider_instance_arg_name)

        mods = {'body': body, 'used_arguments': used_args}
        if return_statement:
            mods['return_statement'] = return_statement

        return {consumer_port_name: {'read': mods}}
示例#8
0
    def generate_consumer(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection, consumer_instance_name,
                          attributes):
        provider_port_data = context.get_port(connection.provider)
        consumer_port_data = context.get_port(consumer_instance_name)
        consumer_port_name = context.get_component_ref(consumer_instance_name)

        member_accessor, data_type = process_member_access(
            context.types, attributes, provider_port_data['data_type'],
            consumer_port_data['data_type'])

        consumer_instance = context.get_component_instance(
            consumer_instance_name)
        provider_instance = context.get_component_instance(connection.provider)

        function = context.functions[consumer_port_name]['read']
        argument_names = list(function.arguments.keys())

        constant_provider = provider_port_data.functions['constant']
        provider_argument_names = list(constant_provider.arguments.keys())

        call_args = {}
        instance_arg_name = get_instance_argument(argument_names,
                                                  consumer_instance)
        provider_instance_arg_name = get_instance_argument(
            provider_argument_names, provider_instance)
        if instance_arg_name:
            call_args[
                instance_arg_name] = '&' + consumer_instance.instance_var_name

        used_args = []
        return_statement = None
        if data_type.passed_by() == TypeCollection.PASS_BY_VALUE:
            call = constant_provider.generate_call(call_args)
            body = f'return {call}{member_accessor};'
            if provider_instance_arg_name:
                return_statement = data_type.render_value(None)
        else:
            out_arg_name = argument_names[0]
            used_args.append(out_arg_name)
            if member_accessor:
                call_args['value'] = '&tmp'
                body = f"{data_type.name} tmp;\n" \
                       f"{constant_provider.generate_call(call_args)};\n" \
                       f"{out_arg_name} = tmp{member_accessor};"
            else:
                call_args['value'] = out_arg_name
                body = constant_provider.generate_call(call_args) + ';'

        if provider_instance_arg_name:
            used_args.append(provider_instance_arg_name)
            body = add_instance_check(
                body,
                consumer_instance,
                instance_arg_name=provider_instance_arg_name)

        mods = {'used_arguments': used_args, 'body': body}
        if return_statement:
            mods['return_statement'] = return_statement

        return {consumer_port_name: {'read': mods}}
示例#9
0
    def generate_consumer(self, context: RuntimeGeneratorContext,
                          connection: SignalConnection, consumer_instance_name,
                          attributes):
        provider_port_data = context.get_port(connection.provider)
        consumer_port_data = context.get_port(consumer_instance_name)
        consumer_port_name = context.get_component_ref(consumer_instance_name)

        member_accessor, data_type = process_member_access(
            context.types, attributes, provider_port_data['data_type'],
            consumer_port_data['data_type'])

        if connection.attributes['queue_length'] == 1:
            template = \
                "bool was_overflow = {{ signal_name }}_overflow;\n" \
                "if ({{ signal_name }}_data_valid)\n" \
                "{\n" \
                "    {{ signal_name }}_overflow = false;\n" \
                "    {{ out_name }} = {{ signal_name }}{{ member_accessor }};\n" \
                "    {{ signal_name }}_data_valid = false;\n" \
                "    if (was_overflow)\n" \
                "    {\n" \
                "        return QueueStatus_Overflow;\n" \
                "    }\n" \
                "    else\n" \
                "    {\n" \
                "        return QueueStatus_Ok;\n" \
                "    }\n" \
                "}"
        else:
            template = \
                "if ({{ signal_name }}_count > 0u)\n" \
                "{\n" \
                "    size_t idx = ({{ signal_name }}_write_index - {{ signal_name }}_count) % {{ queue_length }}u;\n" \
                "    --{{ signal_name }}_count;\n" \
                "    {{ out_name }} = {{ signal_name }}[idx]{{ member_accessor }};\n" \
                "    \n" \
                "    if ({{ signal_name }}_overflow)\n" \
                "    {\n" \
                "        {{ signal_name }}_overflow = false;\n" \
                "        return QueueStatus_Overflow;\n" \
                "    }\n" \
                "    else\n" \
                "    {\n" \
                "        return QueueStatus_Ok;\n" \
                "    }\n" \
                "}"

        function = context.functions[consumer_port_name]['read']
        argument_names = list(function.arguments.keys())

        consumer_instance = context.get_component_instance(
            consumer_instance_name)
        instance_arg_name = get_instance_argument(argument_names,
                                                  consumer_instance)

        value_arg = argument_names[0]
        data = {
            'queue_length': connection.attributes['queue_length'],
            'signal_name': connection.name,
            'out_name': '*' + value_arg,
            'member_accessor': member_accessor
        }

        read = chevron.render(template, data)
        used_args = [value_arg]
        if instance_arg_name:
            used_args.append(instance_arg_name)
            read = add_instance_check(read,
                                      consumer_instance,
                                      instance_arg_name=instance_arg_name)

        return {
            consumer_port_name: {
                'read': {
                    'used_arguments': used_args,
                    'body': read,
                    'return_statement': 'QueueStatus_Empty'
                }
            }
        }