Exemplo n.º 1
0
    def __check_vector_assignments__(self):
        """! @brief Checks the plausibility of the vector assignments.
        If assignments are overlapping or out of bounds, an AsConnectionError
        is raised."""
        if not self.data_width.is_resolved():
            raise AsConnectionError(
                self,
                ("Cannot partially assign to/from signal '{}' "
                 "with unresolved data width '{}' (generics present)!").format(
                     self, self.data_width),
            )
        bitwidth = self.data_width.get_bit_width()
        for vector_map in (self.vector_map_incoming, self.vector_map_outgoing):
            assignment_map = set()
            # Check plausibility of vector assignment (out of bounds, overlap, etc.)
            for assignment_id in vector_map:
                # Is bit position out of bounds?
                if assignment_id > bitwidth:
                    raise AsConnectionError(
                        self,
                        ("Vector assignment to/from signal '{}' at "
                         "bit index {} is out of bounds for signal type: {}"
                         ).format(
                             self,
                             assignment_id,
                             as_help.get_printable_datatype(self),
                         ),
                    )
                # Get source port/signal
                signal = vector_map[assignment_id]
                # Is its data width resolved?
                if not signal.data_width.is_resolved():
                    raise AsConnectionError(
                        signal,
                        ("Cannot assign {} to/from vector signal {}. "
                         "Data width '{}' is unresolved!").format(
                             signal, self,
                             as_help.get_printable_datatype(signal)),
                    )

                # Get bit width and a tuple with all bit positions to assign to
                signal_bit_width = signal.data_width.get_bit_width()
                new_map = tuple(
                    range(assignment_id, assignment_id + signal_bit_width))
                # Does the new assignment overlap with previous assignments?
                if assignment_map.intersection_update(new_map):
                    raise AsConnectionError(
                        signal,
                        ("Vector assignment to/from signal '{}' from '{}' "
                         "overlaps with previous assignments! List: {}"
                         ).format(self, signal, vector_map),
                    )
Exemplo n.º 2
0
 def list_constant(self):
     """Prints a complete list of information available for this constant"""
     print(
         "{name}: {data_type}-constant with value: {value}".format(
             name=self.code_name,
             data_type=get_printable_datatype(self),
             value=self.value,
         )
     )
Exemplo n.º 3
0
 def __str__(self) -> str:
     """! @brief Print the configuration of this port instance."""
     return ("{name}('{code}'): {necessity}, {direction} as "
             "{data_type}, type: {port_type}").format(
                 name=self.name,
                 necessity=("optional" if self.optional else "mandatory"),
                 direction=self.direction,
                 data_type=get_printable_datatype(self),
                 port_type=self.port_type,
                 code=self.code_name,
             )
Exemplo n.º 4
0
    def _generate_module_group_architecture(self, group_module: AsModuleGroup,
                                            file) -> list:

        # Add static code
        self.signal_list.extend(group_module.static_code["signals"])
        self.arch_body.extend(group_module.static_code["body"])

        # Generate constant declaration strings
        constant_list = []
        for con in group_module.constants:
            constant_list.append("  constant {} : {} := {};".format(
                con.code_name,
                as_help.get_printable_datatype(con),
                con.value,
            ))

        # Run dynamic code generation functions of the group module
        code_dict = {"signals": [], "body": []}
        for gen in group_module.dynamic_code_generators:
            gen(self.chain, code_dict)
        self.signal_list.extend(code_dict["signals"])
        self.arch_body.extend(code_dict["body"])

        if not isinstance(group_module, AsModuleWrapper):
            self._architecture_port_assignements(group_module)
            self._architecture_port_bundles(group_module)
        self._architecture_signal_assignements(group_module)

        self.arch_body.extend(["  ", "  -- Components:"])

        for mod in group_module.modules:
            # Generate VHDL instantiation
            ret = self._instantiate_module(mod)
            if not ret:
                raise Exception("Problem instantiating module {}!".format(
                    mod.name))
            self.arch_body.append(ret)  # And add to the architecture body

        out_list = []

        out_list.append("\narchitecture RTL of {} is".format(
            group_module.entity_name))
        if constant_list:
            out_list.append("  -- Constant declarations:")
            out_list.extend(constant_list)
        if self.signal_list:
            out_list.append("\n  -- Signal declarations:")
            out_list.extend(self.signal_list)
        out_list.append("\nbegin")
        out_list.extend(self.arch_body)
        out_list.append("\nend architecture RTL;\n")
        return out_list
Exemplo n.º 5
0
 def generate_glue_signal_strings(self, signals: Sequence[GenericSignal]):
     """! @brief Convert a list of glue signal objects to a string representation
     in the format for VHDL signals in an architecture section."""
     for glue in signals:
         # We only process GlueSignals here...
         if not isinstance(glue, GlueSignal):
             continue
         # Insert values to format string
         glue_signal_str = "  signal {} : {};".format(
             glue.code_name, as_help.get_printable_datatype(glue))
         # Filter duplicate signals
         if glue_signal_str not in self.signal_list:
             self.signal_list.append(glue_signal_str)
    def __convert_port_entity_list__(ports: Sequence[Port]):
        """Convert a list of port objects to the string representation
        in the format for a VHDL entity."""
        out = []
        in_entity = []
        for port in ports:
            # Skip specifically excluded ports
            if not port.in_entity:
                continue
            # Skip ports of excluded interfaces
            if port.port_type == "interface" and (
                (port.parent.to_external or port.parent.instantiate_in_top)
                and port.parent.in_entity
            ):
                pass
            # inlcude only external type single ports
            elif port.port_type == "external":
                pass
            else:
                continue
            in_entity.append(port)

        for port in in_entity:
            # Generate string parts of the entity port declaration
            port_data = as_help.get_printable_datatype(port)
            port_dir = port.get_direction_normalized()
            # Generate and add string for entity
            if in_entity.index(port) == len(in_entity) - 1:
                out.append(
                    "    {} : {} {}\n  );\n".format(
                        port.get_print_name(), port_dir, port_data
                    )
                )
            else:
                out.append(
                    "    {} : {} {};\n".format(
                        port.get_print_name(), port_dir, port_data
                    )
                )
        return out
def convert_port_entity_list(ports: Sequence[Port]):
    """! @brief Convert a list of port objects to the string representation
    in the format for a VHDL entity."""
    out = []
    in_entity = []
    for port in ports:
        # Skip specifically excluded ports
        if not port.in_entity:
            continue
        # Skip ports of excluded interfaces
        if port.port_type == "interface":
            if (port.parent.to_external or
                    port.parent.instantiate_in_top) and port.parent.in_entity:
                # For external interfaces
                pass
            elif port.parent.parent.modlevel > 2 and port.parent.in_entity:
                # For interfaces of module groups within as_main
                pass
        # inlcude only external type single ports
        elif port.port_type in ("external", "single"):
            pass
        else:
            continue
        in_entity.append(port)

    for port in in_entity:
        # Generate string parts of the entity port declaration
        port_data = get_printable_datatype(port)
        port_dir = port.get_direction_normalized()
        # Generate and add string for entity
        if in_entity.index(port) == len(in_entity) - 1:
            out.append("    {} : {} {}\n  );".format(port.get_print_name(),
                                                     port_dir, port_data))
        else:
            out.append("    {} : {} {};".format(port.get_print_name(),
                                                port_dir, port_data))
    return out
Exemplo n.º 8
0
    def _instantiate_module(self, module: AsModule) -> str:
        """! @brief Generate VHDL code as a list of strings to instantiate 'module'.
        Handles generic assignment and port mapping."""

        # -> Generating the generic map <-
        gen_str = []
        if module.generics:
            gen_str.append("  generic map(")
            for tgen in module.generics:
                # If the generic was set by the user in the generator,
                # use that value
                if isinstance(tgen.value, Generic):
                    ret = tgen.value.code_name
                else:
                    ret = tgen.get_value()
                    # Skip generics that use the default value
                    if ret == tgen.default_value:
                        continue
                gen_str.append("    {} => {},".format(tgen.code_name, ret))
        if len(gen_str) > 1:
            # Remove the last comma "," and add a closing bracket
            gen_str[-1] = gen_str[-1].strip(",")
            gen_str.append("  )\n")
            gen_str = "\n".join(gen_str)
        else:
            gen_str = ""

        # -> Generating the port map <-
        port_str = ["  port map("]
        full_port_list = module.get_full_port_list(include_signals=False)
        # For every port of this module:
        for port in full_port_list:
            # Target of the port map
            target = None

            # Determine the format for this ports port map line
            if full_port_list.index(port) < len(full_port_list) - 1:
                templ_str = "    {} => {},"
            else:
                templ_str = "    {} => {}\n  );"

            # -> Has glue signal <-
            # Port mapping target is the port's glue signal
            if port.glue_signal:
                glue = port.glue_signal
                try:
                    target = glue if isinstance(glue, str) else glue.code_name
                except AttributeError:
                    raise AsConnectionError(
                        port,
                        "Unsuitable object assigned as glue signal of port! "
                        "'{}: {}'".format(type(glue), str(glue)),
                    )
                # If this glue signal should be included in the signal list
                if isinstance(glue, GlueSignal) and glue.is_signal:
                    # Add the glue signal to the signal list
                    # Assemble vhdl signal declaration string
                    glue_signal_str = "  signal {} : {};".format(
                        glue.code_name, as_help.get_printable_datatype(glue))
                    # Make sure the same glue signal is not declared twice
                    if glue_signal_str not in self.signal_list:
                        self.signal_list.append(glue_signal_str)

            else:  # -> No glue signal present <-
                # Port mapping target is one of the connected ports,
                # depending on port direction
                target = (port.incoming
                          if port.get_direction_normalized() == "in" else
                          port.outgoing[0] if port.outgoing else None)
                # If the target is a Port object: use the code_name as target
                if isinstance(target, Port):
                    target = target.code_name
                # For strings: use the string as is (eg. for static values)
                elif isinstance(target, str):
                    target = target
                else:
                    target = None

                if not target:  # -> No target <-
                    # If the target is 'None': get neutral value
                    if port.get_direction_normalized() == "in":
                        target = port.get_neutral_value()
                    else:
                        target = "open"
                    # And warn the user of an unconnected port
                    if port.optional:
                        LOG.debug(
                            ("Optional port '%s' of module '%s' was "
                             "left unconnected, automatically set to [%s]!"),
                            port.code_name,
                            get_parent_module(port).name,
                            target,
                        )
                    else:
                        LOG.info(
                            ("Port '%s' of module '%s' was left "
                             "unconnected, automatically set to [%s]!"),
                            port.code_name,
                            get_parent_module(port).name,
                            target,
                        )
            # Insert the values in the format string and add to the return list
            port_str.append(templ_str.format(port.code_name, target))
        port_str = "\n".join(port_str)

        # --> OUT
        entity_keyword_str = ("" if isinstance(module, AsModuleWrapper) else
                              " entity")
        out_str = as_static.MODULE_INSTANTIATION_TEMPLATE.format(
            module_name=module.name,
            entity_name=module.entity_name,
            entity_keyword=entity_keyword_str,
            port_map=port_str,
            generic_map=gen_str,
        )
        return out_str
Exemplo n.º 9
0
    def _handle_module_group_signal(self, group_module: AsModuleGroup,
                                    signal: GenericSignal):
        self.signal_list.append("  signal {} : {};".format(
            signal.code_name, as_help.get_printable_datatype(signal)))
        in_done = False
        try:
            # If the signal has a vector map with content, generate
            # the vector assignment string stored in a glue signal

            if signal.vector_map_incoming:
                self.arch_body.extend(
                    vhdl_write.generate_vector_assignments(signal))
                in_done = True
            if signal.vector_map_outgoing:
                self.arch_body.extend(
                    vhdl_write.generate_from_vector_assignment_strings(signal))
                return None
        except AttributeError:
            pass
        for target in signal.outgoing:
            try:
                if signal in target.vector_map_incoming.values():
                    continue
            except AttributeError:
                pass
            # If target
            if (not isinstance(target, GenericSignal)
                    and get_parent_module(target) is not group_module):
                continue
            try:
                target_str = target.code_name
            except AttributeError:
                target_str = str(target)
            if target_str == signal.code_name:
                continue
            add_str = as_static.ASSIGNMENT_TEMPL.format(
                target_str, signal.code_name)
            if add_str not in self.arch_body:
                self.arch_body.append(add_str)
        for source in signal.incoming:
            if in_done:
                break
            try:
                # If the signal was already assigned to
                # in a vector map of the source,
                # this would generate a wrong assignment
                if signal in source.vector_map_outgoing.values():
                    break
            except AttributeError:
                # If the source doesn't have a vector map
                pass
            # If the signal was already assigned to in a port map,
            # this would generate a wrong assignment
            if get_parent_module(source) in group_module.modules:
                break
            try:
                source_str = source.code_name
            except AttributeError:
                source_str = str(source)
            if source_str == signal.code_name:
                continue
            add_str = as_static.ASSIGNMENT_TEMPL.format(
                signal.code_name, source_str)
            if add_str not in self.arch_body:
                self.arch_body.append(add_str)
    def __instantiate_module__(self, module: AsModule) -> Sequence[str]:
        """Generate VHDL code as a list of strings to instantiate 'module'.
        Handles generic assignment and port mapping."""
        out = [
            "\n  -- Instantiate module {}:\n".format(module.name),
            "  {} : entity {}\n".format(
                "as_main_impl" if module.name == "as_main" else module.name,
                module.entity_name,
            ),
        ]
        gen_str = []
        if module.generics:
            gen_str.append("  generic map(\n")
            for tgen in module.generics:
                # If the generic was set by the user in the generator,
                # use that value
                if isinstance(tgen.value, Generic):
                    ret = tgen.value.code_name
                else:
                    ret = self.__get_printable_generic_value__(tgen)
                    # Skip generics that use the default value
                    if ret == tgen.default_value:
                        continue
                gen_str.append("    {} => {},\n".format(tgen.code_name, ret))
        if len(gen_str) > 1:
            # Replace the comma in the last generic mapping with a brace ')'
            gen_str[-1] = ")".join(gen_str[-1].rsplit(",", maxsplit=1))
            out.extend(gen_str)
        out.append("  port map(\n")

        full_port_list = module.get_full_port_list(include_signals=False)
        # For every port of this module:
        for port in full_port_list:
            # Target of the port map
            target = None

            # Determine the format for this ports port map line
            if full_port_list.index(port) < len(full_port_list) - 1:
                templ_str = "    {} => {},\n"
            else:
                templ_str = "    {} => {});\n"

            # Port mapping target is the port's glue signal
            if port.glue_signal and isinstance(port.glue_signal, GlueSignal):
                glue = port.glue_signal
                target = glue.code_name

                # If this glue signal should be included in the signal list
                if glue.is_signal:
                    # Add the glue signal to the signal list
                    # Assemble vhdl signal declaration string
                    glue_signal_str = "  signal {} : {};\n".format(
                        glue.code_name, as_help.get_printable_datatype(glue)
                    )
                    # Make sure the same glue signal is not declared twice
                    if glue_signal_str not in self.signal_list:
                        self.signal_list.append(glue_signal_str)
            else:  # If no glue signal present:
                # Port mapping target is one of the connected ports,
                # depending on port direction
                target = (
                    port.incoming
                    if port.get_direction_normalized() == "in"
                    else port.outgoing[0]
                    if port.outgoing
                    else None
                )
                # If the target is a Port object: use the code_name as target
                if isinstance(target, Port):
                    target = target.code_name
                # For strings: use the string as is (eg. for static values)
                elif isinstance(target, str):
                    target = target
                else:
                    target = None

                if not target:
                    # If the target is 'None': get neutral value
                    if port.get_direction_normalized() == "in":
                        target = port.get_neutral_value()
                    else:
                        target = "open"
                    # And warn the user of an unconnected port
                    if port.optional:
                        LOG.debug(
                            (
                                "Optional port '%s' of module '%s' was "
                                "left unconnected, automatically set to [%s]!"
                            ),
                            port.code_name,
                            AsModule.get_parent_module(port).name,
                            target,
                        )
                    else:
                        LOG.info(
                            (
                                "Port '%s' of module '%s' was left "
                                "unconnected, automatically set to [%s]!"
                            ),
                            port.code_name,
                            AsModule.get_parent_module(port).name,
                            target,
                        )
            # Insert the values in the format string and add to the return list
            out.append(templ_str.format(port.code_name, target))
        return out
    def __write_module_group_architecture__(self, group_module: AsModuleGroup, file):

        self.signal_list.extend(group_module.static_code["signals"])
        self.arch_body.extend(group_module.static_code["body"])
        code_dict = {"signals": [], "body": []}
        if group_module.dynamic_code_generator:
            group_module.dynamic_code_generator(self.chain, code_dict)
            self.signal_list.extend(code_dict["signals"])
            self.arch_body.extend(code_dict["body"])

        self.arch_body.extend(["  \n", "  -- Port assignments:\n"])
        for port in group_module.ports:
            if port.port_type == "external" and port.glue_signal is not None:
                try:
                    target = port.glue_signal.code_name
                except AttributeError:
                    target = port.glue_signal
                if str(target) == port.code_name:
                    continue
                self.arch_body.append(
                    as_static.ASSIGNMENT_TEMPL.format(port.code_name, target)
                )

        # Add signal assignments to the architecture body
        self.arch_body.extend(["  \n", "  -- Signal assignments:\n"])
        for signal in group_module.signals:
            if signal.port_type == "signal":
                self.signal_list.append(
                    "  signal {} : {};\n".format(
                        signal.code_name, as_help.get_printable_datatype(signal)
                    )
                )
                if signal.glue_signal:
                    try:
                        target_str = signal.glue_signal.code_name
                    except AttributeError:
                        target_str = str(signal.glue_signal)
                    self.arch_body.append(
                        as_static.ASSIGNMENT_TEMPL.format(signal.code_name, target_str)
                    )
                    continue
                for target in signal.outgoing:
                    try:
                        target_str = target.code_name
                    except AttributeError:
                        target_str = str(target)
                    self.arch_body.append(
                        as_static.ASSIGNMENT_TEMPL.format(target_str, signal.code_name)
                    )
                for source in signal.incoming:
                    try:
                        source_str = source.code_name
                    except AttributeError:
                        source_str = str(source)
                    self.arch_body.append(
                        as_static.ASSIGNMENT_TEMPL.format(signal.code_name, source_str)
                    )

        self.arch_body.extend(["  \n", "  -- Components:\n"])

        for mod in group_module.modules:
            # Generate VHDL instantiation
            ret = self.__instantiate_module__(mod)
            if not ret:
                raise Exception("Problem instantiating module {}!".format(mod.name))
            self.arch_body.extend(ret)  # And add to the architecture body

        # Write to the output file
        file.write("\narchitecture RTL of {} is\n".format(group_module.entity_name))
        self.__write_list_to_file__(self.signal_list, file, "  -- Glue signals:\n")
        file.write("\nbegin\n")
        self.__write_list_to_file__(self.arch_body, file, "\n")
        file.write("end architecture RTL;\n")