예제 #1
0
    def __init__(self):
        super().__init__("simple_ram_interface")

        self.add_port(Port("wr_en"))
        self.add_port(Port("wr_addr",
                           data_type="std_logic_vector",
                           data_width=Port.DataWidth(a="ADDR_WIDTH - 1",
                                                     sep="downto",
                                                     b=0)))
        self.add_port(Port("rd_addr",
                           data_type="std_logic_vector",
                           data_width=Port.DataWidth(a="ADDR_WIDTH - 1",
                                                     sep="downto",
                                                     b=0)))
        self.add_port(Port("din",
                           data_type="std_logic_vector",
                           data_width=Port.DataWidth(a="DATA_WIDTH - 1",
                                                     sep="downto",
                                                     b=0)))
        self.add_port(Port("dout",
                           direction="out",
                           data_type="std_logic_vector",
                           data_width=Port.DataWidth(a="DATA_WIDTH - 1",
                                                     sep="downto",
                                                     b=0)))
 def define_signal(
     self,
     name: str,
     data_type: str = "std_logic",
     data_width: tuple = None,
     fixed_value=None,
 ) -> GenericSignal:
     """! @brief Define, create and add a signal object to this module group.
     @param name  The name for the signal to create
     @param data_type  The data type to set for the signal
     @param data_width  The data width to define for the data type (optional)
     @param fixed_value  (optional) Set a fixed value to assign to the signal
     """
     if data_width:
         data_width = Port.DataWidth(*data_width)
     else:
         data_width = Port.DataWidth(1, None, None)
     signal = GenericSignal(name, data_type=data_type, data_width=data_width)
     if fixed_value:
         glue = GlueSignal(
             name=fixed_value,
             code_name=fixed_value,
             port_type=signal.port_type,
             data_width=signal.data_width,
             optional=False,
         )
         glue.is_signal = False
         signal.glue_signal = glue
         signal.incoming.append(glue)
         glue.set_connected()
         signal.set_connected()
     # Assign signal to this module group and return it
     if self.add_signal(signal):
         return signal
     return None
예제 #3
0
 def __init__(self):
     super().__init__(self.INTERFACE_TYPE_NAME)
     self.add_port(
         Port(
             "write_data",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_DATA_WIDTH - 1", "downto", 0
             ),
         )
     )
     self.add_port(
         Port(
             "read_data",
             data_type="std_logic_vector",
             direction="out",
             data_width=Port.DataWidth(
                 "C_S_AXI_DATA_WIDTH - 1", "downto", 0
             ),
         )
     )
     self.add_port(Port("write_enable"))
     self.add_port(Port("read_enable"))
     self.add_port(
         Port(
             "write_address",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_ADDR_WIDTH - 1", "downto", 0
             ),
         )
     )
     self.add_port(
         Port(
             "read_address",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_ADDR_WIDTH - 1", "downto", 0
             ),
         )
     )
     self.add_port(
         Port(
             "write_byte_strobe",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_DATA_WIDTH / 8 - 1", "downto", 0
             ),
         )
     )
     self.set_prefix_suffix("axi_slv_reg_", "")
    def _add_register_interface(self):
        """! @brief Add a register interface to this module group.
        This method defines and adds the necessary signals to this module group
        comrising an ASTERICS slave register interface.
        This method is called by methods adding port-register connections."""
        # Slave register interface:
        # Create ports for the slave register interface

        ctrl_reg = Port(
            "slv_ctrl_reg",
            data_type="slv_reg_data",
            data_width=Port.DataWidth(0, "to", 0),
        )
        status_reg = Port(
            "slv_status_reg",
            direction="out",
            data_type="slv_reg_data",
            data_width=Port.DataWidth(0, "to", 0),
        )
        mod_reg = Port(
            "slv_reg_modify",
            direction="out",
            data_type="std_logic_vector",
            data_width=Port.DataWidth(0, "to", 0),
        )
        config_reg = Port(
            "slv_reg_config",
            direction="out",
            data_type="slv_reg_config_table",
            data_width=Port.DataWidth(0, "to", 0),
        )
        config_const = Constant(
            "slave_register_configuration",
            data_type="slv_reg_config_table",
            data_width=Port.DataWidth(0, "to", 0),
            value="()",
        )
        self.entity_ports = [config_reg, ctrl_reg, status_reg, mod_reg]
        self.entity_constants = [config_const]
        self.constants = [config_const]

        self.__assign_interfaces__()

        reginter = self.get_slave_register_interface()
        self.register_if = reginter
        self.regmod = self.define_signal("reg_modify_vect", "std_logic_vector")
        # Hack to suppress neutral value assignment; Assigned object is not used
        config_reg.incoming = config_const
        status_reg.incoming = config_const

        mod_reg.connect(self.regmod)
 def test_get_ports(self):
     LOG.debug("*UNITTEST* <running test_get_ports>")
     # Get the port list
     ports = self.mut.get_port_list()
     # Checks for the found ports:
     # Check the number of ports, name, direction, data type and data width
     self.assertEqual(len(ports), 7)
     self.assertEqual(
         [port.code_name for port in ports],
         [
             "clk",
             "reset",
             "ready",
             "mem_out_data",
             "wideport",
             "invwideport",
             "expdatatest",
         ],
     )
     self.assertEqual(
         [port.direction for port in ports],
         ["in", "inout", "out", "out", "out", "in", "out"],
     )
     self.assertEqual(
         [port.data_type for port in ports],
         [
             "std_logic",
             "std_logic",
             "std_logic",
             "std_logic_vector",
             "bitvector",
             "vector",
             "anothervector",
         ],
     )
     sdwtemp = Port.DataWidth(1, None, None)
     self.assertEqual(
         [port.data_width for port in ports],
         [
             sdwtemp,
             sdwtemp,
             sdwtemp,
             Port.DataWidth("MEMORY_DATA_WIDTH - 1", "downto", 0),
             Port.DataWidth(1023, "downto", 0),
             Port.DataWidth(0, "to", "24 * 11 - 9 + MAX_REGS_PER_MODULE"),
             Port.DataWidth(65535, "downto", 0),
         ],
     )
예제 #6
0
def parse_gwindow_type(width_str: str, generics: list) -> list:
    """Parse the generic_window custom VHDL data type."""
    gendict = {}
    for gen in generics:
        gendict[gen.code_name] = gen.get_value()

    out = []
    parens = width_str.lower().split(",")
    for par in parens:
        dt_pos = par.find(" downto ")
        to_pos = par.find(" to ")
        if dt_pos > -1:
            spliton = "downto"
        elif to_pos > -1:
            spliton = "to"
        else:
            continue

        values = par.split(spliton, 1)
        value0 = eval_vhdl_expr(values[0].strip().upper(), "data width",
                                gendict)
        value1 = eval_vhdl_expr(values[1].strip().upper(), "data width",
                                gendict)
        out.append(Port.DataWidth(a=value0, sep=spliton, b=value1))
    return out
예제 #7
0
 def __init__(self):
     super().__init__(self.INTERFACE_TYPE_NAME)
     self.add_port(Port("strobe"))
     self.add_port(
         Port(
             "data",
             data_type="std_logic_vector",
             data_width=Port.DataWidth("DATA_WIDTH - 1", "downto", 0),
         )
     )
     self.add_port(Port("data_error", optional=True))
     self.add_port(Port("stall", direction="out", optional=True))
     self.add_port(Port("vsync", optional=True))
     vcomplete = Port("vcomplete", optional=True)
     vcomplete.add_rule("sink_missing", "fallback_port(vsync)", False)
     vcomplete.add_rule(
         "sink_missing", "fallback_port(data_unit_complete)", False
     )
     self.add_port(vcomplete)
     hcomplete = Port("hcomplete", optional=True)
     self.add_port(Port("hsync", optional=True))
     hcomplete.add_rule("sink_missing", "fallback_port(hsync)", False)
     self.add_port(hcomplete)
     self.add_port(Port("xres", data_type="std_logic_vector", optional=True))
     self.add_port(Port("yres", data_type="std_logic_vector", optional=True))
     self.add_port(Port("data_unit_complete", optional=True))
예제 #8
0
    def __get_constant__(self, file_obj) -> str:
        # Make sure the current line is the complete constant definition
        if ";" not in self.line:
            self.line = self.line.strip(" \n") + self.__next_clean_statement__(
                file_obj)
        # Clean current line, remove the 'constant' keyword and split on ':'
        words = self.line.replace("constant", "", 1).strip(" \n").split(":", 1)
        if len(words) > 1:  # Was there a ':' in this line?
            # If so, we can extract the constant's name
            name = words[0].strip()
            # Split on value assignment
            words = words[1].strip().split(":=", 1)
            if len(words) > 1:  # Was there a ':=' in this line?
                # If so, we can extract both the data type and value.
                data_type = words[0].strip()
                value = words[1].strip(" ;").upper()
                data_width = Port.DataWidth(1, None, None)
                # If the data type is a vector (contains a "(a to/downto b)")
                if "(" in data_type:
                    words = data_type.strip().split("(", maxsplit=1)
                    data_type = words[0].strip()
                    # Get the data width (remove closing bracket)
                    data_width = self.__get_data_width__(words[1][:-1])

                # That's all infos for this constant! Create and add it:
                self.found_constants.append(
                    Constant(
                        code_name=name,
                        data_type=data_type,
                        value=value,
                        data_width=data_width,
                    ))
                LOG.debug(
                    "Found constant '%s' of type '%s' with value '%s'",
                    name,
                    data_type,
                    value,
                )
                return ""

            LOG.error(
                ("Malformed 'constant' declaration: '%s' in '%s': "
                 "Missing ':='!"),
                self.line,
                file_obj.name,
            )
            return "malformed constant declaration"

        LOG.error(
            ("Malformed 'constant' declaration: '%s' in '%s': "
             "Missing ':'!"),
            self.line,
            file_obj.name,
        )
        return "malformed constant declaration"
예제 #9
0
 def __init__(
         self,
         name: str = "",
         code_name: str = "",
         port_type: str = "glue_signal",
         data_type: str = "std_logic",
         optional: bool = False,
         data_width=Port.DataWidth(1, None, None),
 ):
     super().__init__(name, code_name, port_type, data_type, optional,
                      data_width)
예제 #10
0
 def define_port(
     self,
     name: str,
     code_name: str = "",
     direction: str = "in",
     data_type: str = "std_logic",
     data_width: tuple = None,
     fixed_value: str = "",
 ) -> Port:
     """! @brief Add a port to this module group.
     @param name: The ports base name (without pre- or suffixes)
     @param code_name: The ports name as it appears in VHDL code. [name]
     @param direction: Direction or data ['in'], 'out' or 'inout'.
     @param data_type: The ports VHDL data type. [std_logic]
     @param data_width: The width of vector data types. Use a tuple to define.
                        Example: (7, 'downto', 0); [None]
     @param fixed_value: Optionally set a fixed value for the port. The value of
                         this parameter is directly copied into code!
     @return  The created GenericSignal object."""
     if not code_name:
         code_name = name
     if data_width:
         data_width = Port.DataWidth(*data_width)
     else:
         data_width = Port.DataWidth(1, None, None)
     port = Port(
         name,
         code_name,
         direction,
         port_type="external",
         data_type=data_type,
         optional=False,
         data_width=data_width,
     )
     if fixed_value:
         self.__port_set_value__(port, fixed_value)
     self.add_port(port)
     return port
예제 #11
0
    def _update_register_params(self):
        # Update config constant value
        self.register_if.config.value = (
            as_help.generate_register_config_value_string(self.register_config)
        )
        # Update register interface port's data width
        for port in ittls.chain(
            self.register_if.ports, [self.regmod, self.register_if.config]
        ):
            port.data_width = Port.DataWidth(0, "to", self.register_count - 1)

        # Update register interface parameters
        self.register_if.config_applied = False
        self.register_if.__decode_slvreg_table__()
예제 #12
0
def resolve_data_width(data_width: Port.DataWidth, generics: list) -> list:
    """! @brief Resolve data_width using a list of generics."""
    if data_width.is_resolved():
        return data_width

    gendict = {}
    for gen in generics:
        gendict[gen.code_name] = gen.get_value()

    spliton = data_width.sep
    value0 = eval_vhdl_expr(
        str(data_width.a).strip().upper(), "data width", gendict)
    value1 = eval_vhdl_expr(
        str(data_width.b).strip().upper(), "data width", gendict)
    return Port.DataWidth(a=value0, sep=spliton, b=value1)
예제 #13
0
 def __init__(self):
     super().__init__(self.INTERFACE_TYPE_NAME)
     self.add_port(Port("reset_n", direction="out"))
     self.add_port(Port("powerdown", direction="out"))
     self.add_port(Port("pixclk"))
     self.add_port(Port("frame_valid"))
     self.add_port(Port("line_valid"))
     self.add_port(
         Port(
             "data",
             data_type="std_logic_vector",
             data_width=Port.DataWidth("SENSOR_DATA_WIDTH - 1", "downto", 0),
         )
     )
     self.set_prefix_suffix("sensor_", "")
     self.to_external = True
예제 #14
0
 def __init__(
         self,
         name: str = "",
         code_name: str = "",
         port_type: str = "signal",
         data_type: str = "std_logic",
         optional: bool = False,
         data_width=Port.DataWidth(1, None, None),
 ):
     super().__init__(name, code_name, "inout", port_type, data_type,
                      optional, data_width)
     self.incoming = []
     self.is_signal = True
     self.vector_map_incoming = dict()
     self.vector_map_outgoing = dict()
     self.vector_assignment_tasks = []
예제 #15
0
    def __get_data_width__(parens: str) -> str:
        parens = parens[1:-1]
        # Determine the "direction" of the data width assignment
        dt_pos = parens.find(" downto ")
        to_pos = parens.find(" to ")
        if dt_pos > -1:
            spliton = "downto"
        elif to_pos > -1:
            spliton = "to"
        else:
            return ""

        values = parens.split(spliton, 1)
        value0 = eval_vhdl_expr(values[0].strip().upper(), "data width")
        value1 = eval_vhdl_expr(values[1].strip().upper(), "data width")
        return Port.DataWidth(a=value0, sep=spliton, b=value1)
    def build_inout_vectors(self) -> GenericSignal:
        # Get module ports
        mod_in_port = self.module.get_port("buff_in")
        mod_out_port = self.module.get_port("data_out")
        mod_line_port = self.module.get_port("line_out")

        foreach(self.module.get_full_port_list(), resolve_generic)

        # Create intermediate vector signals
        sig_name = self.name + "_data_"
        self.in_signal = self.pipe.define_signal(
            sig_name + "in",
            data_type="std_logic_vector",
            data_width=(self.bit_width_in - 1, "downto", 0),
        )
        self.out_signal = self.pipe.define_signal(
            sig_name + "out",
            data_type="std_logic_vector",
            data_width=(self.bit_width_in - 1, "downto", 0),
        )
        # Connect them to the buffers input and output
        self.pipe.chain.__connect__(self.in_signal, mod_in_port, top=self.pipe)
        self.pipe.chain.__connect__(mod_out_port,
                                    self.out_signal,
                                    top=self.pipe)
        # Define vector signal connections
        for source in self.inputs:
            self.in_signal.assign_to_this_vector(source.port,
                                                 source.start_index)
        for target in self.outputs:
            self.out_signal.assign_from_this_vector(target.port,
                                                    target.start_index)
        # Create line port signal
        self.line_signal = self.pipe.define_signal(
            self.name + "_line_data",
            data_type="t_generic_line",
            data_width=(self.bit_width_in - 1, "downto", 0),
        )
        setattr(
            self.line_signal,
            "line_width",
            Port.DataWidth(0, "to", self.window_width - 1),
        )
        # Connect to buffer module line port
        self.pipe.__connect__(self.line_signal, mod_line_port)
        return self.line_signal
예제 #17
0
 def convert_window_port_to_vector(self) -> list:
     """! @brief Convert as_window to only use standard data types.
     If this module wrapper contains a window module, the window port's
     data type must be converted from t_generic_window to std_logic_vector.
     Generates the conversion code and adds the necessary signals within
     the wrapper VHDL file (conversion from vector to window type) and
     converts the port data type."""
     # If we wrap a window module, we need to convert t
     if not isinstance(self.modules[0], AsWindowModule):
         return None
     mod = self.modules[0]
     window_ports = []
     conversion_template = (
         "f_convert_vector_to_generic_window({vector_name}, {x}, {y})")
     # Xilinx Vivado OOC Synthesis can't deal with custom data types
     # For all window interfaces, take the window port using the
     # t_generic_window data type and convert it to a std_logic_vector
     # Within this wrapper, take the vectorized port and convert it back
     # to a t_generic_window port to pass to the filter module.
     # The conversion from window to vector is done in the 2D Pipeline class
     for winter in getattr(self, "window_interfaces"):
         wport = winter.window_port
         window_dims = winter.window
         window_elements = window_dims.x * window_dims.y
         new_vector_width = (window_elements *
                             wport.data_width.get_bit_width())
         wport.data_type = "std_logic_vector"
         wport.data_width = Port.DataWidth(new_vector_width - 1, "downto",
                                           0)
         mport = mod.get_port(wport.code_name, suppress_error=True)
         sig = self.define_signal(
             mport.code_name + "_reconv",
             data_type=mport.data_type,
             data_width=mport.data_width,
             fixed_value=conversion_template.format(
                 vector_name=wport.code_name,
                 x=window_dims.x,
                 y=window_dims.y,
             ),
         )
         sig.window_config = wport.window_config
         wport.window_config = None
         mport.incoming = sig
         window_ports.append(wport)
     return window_ports
예제 #18
0
    def assign_port_to_register(
        self, register_num: int, port: Port, to_bit_index: int
    ) -> bool:
        """! @brief Assign a Port as a part of a register as a data sink.
        @param register_num  Define the number of the register to assign to
        @param port  The Port to assign to the register
        @param to_bit_index  The bit offset to assign to.
                             register bit map: (31 downto 0)
        """
        if to_bit_index > 31 or to_bit_index < 0:
            LOG.error("Index for register assignment is out of bounds!")
            raise ValueError(to_bit_index, "Out of bounds!", port)
        # If the register index does not have a register associated, add them
        while self.register_count <= register_num:
            if register_num == self.register_count:
                self.add_register(Register.status)
            else:  # Empty registers for empty spots
                self.add_register(Register.none)
        # Update register type if necessary
        if self.register_config[register_num] == "AS_REG_NONE":
            self.modify_register_type(register_num, Register.status)
        elif self.register_config[register_num] == "AS_REG_CONTROL":
            self.modify_register_type(register_num, Register.both)

        # Get or create the register assignment signal
        try:
            reg_signal = self.reg_assign_map_status[register_num]
        except KeyError:
            reg_signal = self.define_signal(
                "s_register_id{}_status".format(register_num),
                data_type="std_logic_vector",
                data_width=Port.DataWidth(31, "downto", 0),
            )
            self._assign_to_register(register_num, reg_signal)

        # Get or create the source signal
        if isinstance(port, GenericSignal):
            source = port
        else:
            self.__update_generics_list__()
            port.glue_signal = self.define_signal_based_on_port(port)
            self.chain.connect(port, port.glue_signal)
            source = port.glue_signal
        # Assign the source signal to the register assignment signal
        reg_signal.assign_to_this_vector(source, to_bit_index)
예제 #19
0
    def assign_register_to_port(
        self, register_num: int, port: Port, from_bit_index: int
    ):
        """! @brief Assign part of a register as a data source to a Port.
        @param register_num  Define the number of the register to assign from
        @param port  The Port to assign the register value to
        @param from_bit_index  The bit offset to assign from.
                               register bit map: (31 downto 0)"""

        # If the register index does not have a register associated, add them
        while self.register_count <= register_num:
            if register_num == self.register_count:
                self.add_register(Register.control)
            else:  # Empty registers for empty spots
                self.add_register(Register.none)

        # Update register type if necessary
        if self.register_config[register_num] == "AS_REG_NONE":
            self.modify_register_type(register_num, Register.control)
        elif self.register_config[register_num] == "AS_REG_STATUS":
            self.modify_register_type(register_num, Register.both)

        # Get or create the register assignment signal
        try:
            reg_signal = self.reg_assign_map_control[register_num]
        except KeyError:
            reg_signal = self.define_signal(
                "s_register_id{}_control".format(register_num),
                data_type="std_logic_vector",
                data_width=Port.DataWidth(31, "downto", 0),
            )
            self._assign_from_register(register_num, reg_signal)

        self.__update_generics_list__()
        if isinstance(port, GenericSignal):
            target = port
        else:
            sig = self.define_signal_based_on_port(port)
            self.chain.connect(port, sig)
            target = sig

        # Assign from the register to the target signal
        reg_signal.assign_from_this_vector(target, from_bit_index)
예제 #20
0
    def __get_data_width__(self, parens: str) -> str:
        if "," in parens:  # For data widths with multiple dimensions
            data_width = []
            for width in parens.split(","):
                data_width.append(self.__get_data_width__(width))
            return [width for width in data_width if width is not None]
        # Determine the "direction" of the data width assignment
        dt_pos = parens.find(" downto ")
        to_pos = parens.find(" to ")
        if dt_pos > -1:
            spliton = "downto"
        elif to_pos > -1:
            spliton = "to"
        else:
            return None

        values = parens.split(spliton, 1)
        value0 = eval_vhdl_expr(values[0].strip().upper(), "data width")
        value1 = eval_vhdl_expr(values[1].strip().upper(), "data width")
        return Port.DataWidth(a=value0, sep=spliton, b=value1)
예제 #21
0
    def __init__(self):
        super().__init__(self.INTERFACE_TYPE_NAME)

        # Ports for arbitration mode
        mem_req = Port("mem_req", direction="out", optional=True)
        mem_req.in_entity = False
        self.add_port(mem_req)
        # This port needs to be set to '1' if not connected!
        mem_req_ack = Port("mem_req_ack", optional=True)
        mem_req_ack.overwrite_rule("sink_missing", "set_value('1')")
        mem_req_ack.in_entity = False
        self.add_port(mem_req_ack)

        # Ports towards AXI interface
        self.add_port(Port("mem_go", direction="out"))
        self.add_port(Port("mem_clr_go"))
        self.add_port(Port("mem_busy"))
        self.add_port(Port("mem_done"))
        self.add_port(Port("mem_error"))
        self.add_port(Port("mem_timeout"))
        self.add_port(Port("mem_rd_req", direction="out"))
        self.add_port(Port("mem_wr_req", direction="out"))
        self.add_port(Port("mem_bus_lock", direction="out"))
        self.add_port(Port("mem_burst", direction="out"))
        self.add_port(
            Port(
                "mem_addr",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(
                    "MEM_ADDRESS_BIT_WIDTH - 1", "downto", 0
                ),
            )
        )
        self.add_port(
            Port(
                "mem_be",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(15, "downto", 0),
            )
        )
        self.add_port(
            Port(
                "mem_xfer_length",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(
                    "BURST_LENGTH_BIT_WIDTH - 1", "downto", 0
                ),
            )
        )
        self.add_port(Port("mem_in_en"))
        self.add_port(
            Port(
                "mem_in_data",
                data_type="std_logic_vector",
                data_width=Port.DataWidth("MEMORY_DATA_WIDTH - 1", "downto", 0),
            )
        )
        self.add_port(Port("mem_out_en"))
        self.add_port(
            Port(
                "mem_out_data",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth("MEMORY_DATA_WIDTH - 1", "downto", 0),
            )
        )
        # This interface usually always connects directly to an AXI Master
        # Unless an Arbiter module manages access to the AXI interface
        self.instantiate_module("AXI_Master")
def __resolve_generic__(data_width: Port.DataWidth,
                        port: Port) -> Port.DataWidth:
    # If data_width.sep is not set, there can't be any generics
    if not data_width.sep:
        return data_width  # No vector? Nothing to do...
    # Grab some resources (port's parent module and generics)
    module = get_parent_module(port)
    gen_strs = as_help.extract_generics(data_width)
    if not gen_strs:
        return data_width  # No generics? Nothing to do...

    # Grab the module group (module's parent) (AsModule does not have signals)
    if getattr(module, "signals", None) is None:
        gmodule = module.parent
        if not gmodule:
            gmodule = module
    else:
        gmodule = module
    # Remove any associated generics that are not found in data_width
    to_remove = []
    for gen in port.generics:
        if gen.code_name not in gen_strs or gen.parent is not module:
            to_remove.append(gen)
    for gen in to_remove:
        port.remove_generic(gen)

    # Make sure all found generics are associated with port
    for gen_str in gen_strs:
        match = False
        # First search in port's generic list
        for gen in port.generics:
            if gen.code_name == gen_str:
                match = True
                break
        if match:
            continue
        # If not found there, search the parent module
        for gen in module.generics:
            if gen.code_name == gen_str:
                port.add_generic(gen)
                break

    # Unpack the data_width
    ndw_a = data_width.a
    ndw_sep = data_width.sep
    ndw_b = data_width.b

    # Substitute any generics with their linked generic in the group module
    to_remove = []
    todo = []  # Here we'll store generic tuples (current, replacement)
    for gen in port.generics:
        val = gen.value
        # Skip generics that have an explicit value set
        # if val and not isinstance(val, Generic):
        #    continue
        # If the linked generic is defined in the group module
        if isinstance(val, Generic) and val.parent is gmodule:
            # We'll need use that generic in place of the generic of the
            # parent module, as that is not available in the group module
            todo.append((gen, val))
        # Else: if this generic is not set in the group module
        elif not gmodule.get_generic(gen.code_name, suppress_error=True):
            # And the generic has a value set (not a linked generic)
            if val and not isinstance(val, Generic):
                # Replace the generic name with that value in data_width
                if not str(data_width.a).isnumeric():
                    ndw_a = ndw_a.replace(gen.code_name, str(val))
                if not str(data_width.b).isnumeric():
                    ndw_b = ndw_b.replace(gen.code_name, str(val))
                # Make sure to remove the generic reference from port
                to_remove.append(gen)
    for gen in to_remove:
        port.remove_generic(gen)

    # Perform the generic substitution
    for gpair in todo:
        # Swap references in port
        port.remove_generic(gpair[0])
        port.add_generic(gpair[1])
        # and generic name strings in data_width
        if not str(data_width.a).isnumeric():
            ndw_a = ndw_a.replace(gpair[0].code_name, gpair[1].code_name)
        if not str(data_width.b).isnumeric():
            ndw_b = ndw_b.replace(gpair[0].code_name, gpair[1].code_name)
    # Re-assemble the data_width tuple and update it for port
    data_width = Port.DataWidth(a=ndw_a, sep=ndw_sep, b=ndw_b)
    # Re-evaluate data_width (resolve math)
    return __resolve_data_width__(data_width, port)
예제 #23
0
    def _build_layer(self):

        config_dict = self.module_config_dicts[self.filter_module_entity]

        # Add and configure filter modules:
        for idx in range(self.filter_module_count):

            modulename = self.name + "_module_" + str(idx)
            filter_module = self.add_module(self.filter_module_entity,
                                            modulename)
            # Configure the filter module
            for param, value in config_dict.items():
                filter_module.set_generic_value(param, value)

            # Select values for this filter module
            if self.operation in self.OPERATIONS_REQUIREING_VALUES:
                lower_bound = idx * self.filters_per_module
                upper_bound = (idx + 1) * self.filters_per_module
                weights = self.weight_values[lower_bound * self.
                                             weights_per_filter:upper_bound *
                                             self.weights_per_filter]
                biases = self.bias_values[lower_bound:upper_bound]
                quant_mults = self.quant_mult_values[lower_bound:upper_bound]
                filter_module.assign_trained_values(weights, biases,
                                                    quant_mults)

            self.filter_modules.append(filter_module)

        total_output_width = self.output_bit_width * self.filter_count
        data_out_inter = Interface(AsStream.INTERFACE_TYPE_NAME,
                                   AsStream(),
                                   default_name="out")
        data_out_inter.direction = "out"

        data_out_port = Port(
            "data",
            "results_data_out",
            direction="out",
            data_type="std_logic_vector",
            data_width=Port.DataWidth(total_output_width - 1, "downto", 0),
        )
        strobe_out_port = Port("strobe", "results_strobe_out", direction="out")
        stall_out_port = Port("stall", "results_stall_out")

        data_out_inter.add_port(data_out_port)
        data_out_inter.add_port(strobe_out_port)
        data_out_inter.add_port(stall_out_port)

        strobe_signal_value = "pipeline_strobe_out_combined and {}".format(
            self.outgoing_strobes_valid_signal.code_name)
        strobe_out_inter_sig = self.define_signal(
            "results_strobe_out_int", fixed_value=strobe_signal_value)

        strobe_out_port.set_glue_signal(strobe_out_inter_sig)
        strobe_out_port.incoming = strobe_out_inter_sig
        strobe_out_inter_sig.outgoing.append(strobe_out_port)

        stall_out_sig = self.define_signal("results_stall_out_int")
        stall_out_port.outgoing.append(stall_out_sig)
        stall_out_sig.incoming.append(stall_out_port)

        self.pipe_manager.get_port("output_stall_in").connect(stall_out_sig)

        self.flush_in_stall = stall_out_sig

        self.result_interface = data_out_inter
        self.result_interface.assign_to(self)
        self.add_interface(self.result_interface)
예제 #24
0
    def __init__(self):
        super().__init__("AXI_Slave_external")

        self.add_port(Port("aclk"))
        self.add_port(Port("aresetn"))
        self.add_port(
            Port(
                "awaddr",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_S_AXI_ADDR_WIDTH - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(
            Port(
                "awprot",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=2, sep="downto", b=0),
            ))
        self.add_port(Port("awvalid"))
        self.add_port(Port("awready", direction="out"))
        self.add_port(
            Port(
                "wdata",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_S_AXI_DATA_WIDTH - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(
            Port(
                "wstrb",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_S_AXI_DATA_WIDTH / 8 - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(Port("wvalid"))
        self.add_port(Port("wready", direction="out"))
        self.add_port(
            Port(
                "bresp",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=1, sep="downto", b=0),
            ))
        self.add_port(Port("bvalid", direction="out"))
        self.add_port(Port("bready"))

        self.add_port(
            Port(
                "araddr",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_S_AXI_ADDR_WIDTH - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(
            Port(
                "arprot",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=2, sep="downto", b=0),
            ))
        self.add_port(Port("arvalid"))
        self.add_port(Port("arready", direction="out"))
        self.add_port(
            Port(
                "rdata",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_S_AXI_DATA_WIDTH - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(
            Port(
                "rresp",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=1, sep="downto", b=0),
            ))
        self.add_port(Port("rvalid", direction="out"))
        self.add_port(Port("rready"))

        self.set_prefix_suffix(new_prefix="s_axi_", new_suffix="")
        self.to_external = True
    def assign_trained_values(self, weights: list, biases: list,
                              quant_mults: list):
        filter_count = self.get_generic("FILTER_COUNT").get_value()
        kernel_size = self.get_generic("KERNEL_SIZE").get_value()
        # Depth of pipeline in module: 4 + (filter_count - 1)
        self.processing_delay += filter_count - 1

        # Generate kernel weight value string
        channel_count = self.get_generic("CHANNEL_COUNT").get_value()
        kernel_str = weights_to_string_for_serial_filter(
            weights, channel_count, filter_count)

        # Calculate quantization BIAS extension from weights
        weights_per_filter = len(weights) // filter_count
        biases = tuple(biases)
        biases_new = []
        for f_idx in range(filter_count):
            biases_new.append(
                calc_extended_quantized_bias(
                    weights[weights_per_filter * f_idx:weights_per_filter *
                            (f_idx + 1)],
                    biases[f_idx],
                ))

        # Convert values to strings
        if filter_count == 1:
            kernel_str = "(0 => " + kernel_str[1:]
            qmult_str = "(0 => {})".format(quant_mults[0])
            biases_str = "(0 => {})".format(biases_new[0])
        else:
            qmult_str = str(tuple(quant_mults))
            biases_str = str(tuple(biases_new))

        kernel_const_name = self.name + "_kernel_values"
        biases_const_name = self.name + "_bias_values"
        quant_mults_const_name = self.name + "_quantization_factors"

        # Create constants for each value type
        kernel_value_const = Constant(
            kernel_const_name,
            kernel_const_name,
            "t_generic_filter_array",
            kernel_str,
            "(0 to {filter_count}, 0 to {channel_count}, 0 to {kernel_values})"
            .format(
                filter_count=filter_count - 1,
                channel_count=channel_count - 1,
                kernel_values=(kernel_size**2) - 1,
            ),
        )
        biases_value_const = Constant(
            biases_const_name,
            biases_const_name,
            "t_integer_array",
            biases_str,
            Port.DataWidth(0, "to", filter_count - 1),
        )
        quant_mult_const = Constant(
            quant_mults_const_name,
            quant_mults_const_name,
            "t_real_array",
            qmult_str,
            Port.DataWidth(0, "to", filter_count - 1),
        )
        self.parent.add_constant(kernel_value_const)
        self.parent.add_constant(biases_value_const)
        self.parent.add_constant(quant_mult_const)

        # Assign constants to the generics
        self.set_generic_value("KERNEL_VALUES", kernel_const_name)
        self.set_generic_value("BIAS_VALUES", biases_const_name)
        self.set_generic_value("QUANTIZATION_MULTIPLIERS",
                               quant_mults_const_name)
예제 #26
0
 def __init__(self):
     super().__init__(self.INTERFACE_TYPE_NAME)
     self.add_port(Port("aclk"))
     self.add_port(Port("areset_n"))
     self.add_port(
         Port(
             "awaddr",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_ADDR_WIDTH - 1", "downto", 0
             ),
         )
     )
     self.add_port(
         Port(
             "awprot",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(2, "downto", 0),
         )
     )
     self.add_port(Port("awvalid"))
     self.add_port(Port("awready", direction="out"))
     self.add_port(
         Port(
             "wdata",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_DATA_WIDTH - 1", "downto", 0
             ),
         )
     )
     self.add_port(
         Port(
             "wstrb",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_DATA_WIDTH / 8 - 1", "downto", 0
             ),
         )
     )
     self.add_port(Port("wvalid"))
     self.add_port(Port("wready", direction="out"))
     self.add_port(
         Port(
             "bresp",
             direction="out",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(1, "downto", 0),
         )
     )
     self.add_port(Port("bvalid", direction="out"))
     self.add_port(
         Port(
             "araddr",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_ADDR_WIDTH - 1", "downto", 0
             ),
         )
     )
     self.add_port(
         Port(
             "arprot",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(2, "downto", 0),
         )
     )
     self.add_port(Port("arvalid"))
     self.add_port(Port("arready", direction="out"))
     self.add_port(
         Port(
             "rdata",
             direction="out",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(
                 "C_S_AXI_DATA_WIDTH - 1", "downto", 0
             ),
         )
     )
     self.add_port(
         Port(
             "rresp",
             data_type="std_logic_vector",
             data_width=Port.DataWidth(1, "downto", 0),
             direction="out",
         )
     )
     self.add_port(Port("rvalid", direction="out"))
     self.add_port(Port("rready"))
     self.set_prefix_suffix("s_axi_", "")
     self.to_external = True
예제 #27
0
 def __get_ports__(self, file_obj) -> int:
     while True:
         # Get the next line with some code in it
         test = self.__peek_next_clean_line__(file_obj)
         # If that line is not a port declaration (no ':'), return
         if ":" not in test:
             return len(self.found_ports)
         # Advance to the next line
         if self.window_module:
             line, tag = self.__next_clean_line__(file_obj,
                                                  get_window_tag=True)
             if tag:
                 tag = tag.strip(" :")
                 try:
                     tag = tag[tag.find("("):tag.find(")") + 1]
                 except IndexError as err:
                     LOG.error(
                         ("VHDLReader: Not a valid tag '%s' in '%s'"
                          " - '%s'"),
                         tag,
                         self.entity_name,
                         str(err),
                     )
                     self.errors.append(
                         self.vhdl_file,
                         "Not a valid 2D Window Tag '{}'!".format(tag),
                     )
         else:
             line = self.__next_clean_line__(file_obj)
         # Clean and split the input
         line = line.strip("\n; ")
         words = line.split(":", 1)
         # Split the part after the ':' on the first whitespace
         params = words[1].strip().split(maxsplit=1)
         # Now we should have this arrangement for the code:
         #  <port name> : <direction> ' ' <data type>[(<data width>)]
         #   words[0]   :   words[1]
         #              :  params[0]  ' ' params[1]  '('
         direction = params[0]
         name = words[0].strip()  # Get the cleaned name
         LOG.debug("Found port '%s' in line '%s'", name, line)
         # If there's a parenthenses, we need to decode the data width
         parens_pos = params[1].find("(")
         if parens_pos > -1:
             # Extract data type and pass the data width definition
             data_type = params[1][:parens_pos]
             parens = params[1][parens_pos:]
             if PIPE_WINDOW_TYPE in data_type:
                 data_width = parens[1:-1]
             else:
                 data_width = self.__get_data_width__(parens)
             LOG.debug("Data width translated as '%s'", data_width)
         else:
             # If no data width definition is present, assume width 1
             data_type = params[1]
             data_width = Port.DataWidth(1, None, None)
         # Instantiate and add a new Port to the found ports list
         port = Port(
             name=name,
             code_name=name,
             direction=direction,
             data_type=data_type,
             data_width=data_width,
         )
         if self.window_module and tag:
             LOG.debug("Found AUTOTAG in '%s' for '%s': '%s'",
                       self.entity_name, name, tag)
             port.set_window_reference(
                 map(str.strip,
                     tag.strip("() ").split(",")))
         self.found_ports.append(port)
예제 #28
0
    def __init__(self):
        super().__init__("AXI_Master_external")

        self.add_port(Port("m_axi_aclk"))
        self.add_port(Port("m_axi_aresetn"))
        self.add_port(Port("m_axi_arready"))
        self.add_port(Port("m_axi_arvalid", direction="out"))
        self.add_port(
            Port(
                "m_axi_araddr",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_M_AXI_ADDR_WIDTH - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(
            Port(
                "m_axi_arlen",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=7, sep="downto", b=0),
            ))
        self.add_port(
            Port(
                "m_axi_arsize",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=2, sep="downto", b=0),
            ))
        self.add_port(
            Port(
                "m_axi_arburst",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=1, sep="downto", b=0),
            ))
        self.add_port(
            Port(
                "m_axi_arprot",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=2, sep="downto", b=0),
            ))
        self.add_port(
            Port(
                "m_axi_arcache",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=3, sep="downto", b=0),
            ))
        self.add_port(Port("m_axi_rready", direction="out"))
        self.add_port(Port("m_axi_rvalid"))
        self.add_port(
            Port(
                "m_axi_rdata",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_M_AXI_DATA_WIDTH - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(
            Port(
                "m_axi_rresp",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=1, sep="downto", b=0),
            ))
        self.add_port(Port("m_axi_rlast"))
        self.add_port(Port("m_axi_awready"))
        self.add_port(Port("m_axi_awvalid", direction="out"))
        self.add_port(
            Port(
                "m_axi_awaddr",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_M_AXI_ADDR_WIDTH - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(
            Port(
                "m_axi_awlen",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=7, sep="downto", b=0),
            ))
        self.add_port(
            Port(
                "m_axi_awsize",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=2, sep="downto", b=0),
            ))
        self.add_port(
            Port(
                "m_axi_awburst",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=1, sep="downto", b=0),
            ))
        self.add_port(
            Port(
                "m_axi_awprot",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=2, sep="downto", b=0),
            ))
        self.add_port(
            Port(
                "m_axi_awcache",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=3, sep="downto", b=0),
            ))
        self.add_port(Port("m_axi_wready"))
        self.add_port(Port("m_axi_wvalid", direction="out"))
        self.add_port(
            Port(
                "m_axi_wdata",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_M_AXI_DATA_WIDTH - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(
            Port(
                "m_axi_wstrb",
                direction="out",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a="C_M_AXI_DATA_WIDTH / 8 - 1",
                                          sep="downto",
                                          b=0),
            ))
        self.add_port(Port("m_axi_wlast", direction="out"))
        self.add_port(Port("m_axi_bready", direction="out"))
        self.add_port(Port("m_axi_bvalid"))
        self.add_port(
            Port(
                "m_axi_bresp",
                data_type="std_logic_vector",
                data_width=Port.DataWidth(a=1, sep="downto", b=0),
            ))
        md_err = Port("md_error", direction="out")
        self.add_port(md_err)

        self.to_external = True
예제 #29
0
    def __get_ports__(self, file_obj) -> int:
        while True:
            # Get the next line with some code in it
            test = self.__peek_next_clean_line__(file_obj)
            # If that line is not a port declaration (no ':'), return
            if ":" not in test:
                return len(self.found_ports)
            # Advance to the next line
            line = self.__next_clean_line__(file_obj)
            # Clean and split the input
            line = line.strip("\n; ")
            words = line.split(":", 1)
            # Split the part after the ':' on the first whitespace
            params = words[1].strip().split(maxsplit=1)
            # Now we should have this arrangement for the code:
            #  <port name> : <direction> ' ' <data type>[(<data width>)]
            #   words[0]   :   words[1]
            #              :  params[0]  ' ' params[1]  '('
            direction = params[0]
            name = words[0].strip()  # Get the cleaned name
            LOG.debug("Found port '%s' in line '%s'", name, line)
            # If there's a parenthenses, we need to decode the data width
            parens_pos = params[1].find("(")
            if parens_pos > -1:
                # Extract data type and pass the data width definition
                data_type = params[1][:parens_pos]
                parens = params[1][parens_pos:]
                data_width = self.__get_data_width__(parens[1:-1])
                LOG.debug("Data width translated as '%s'", data_width)
            else:
                # If no data width definition is present, assume width 1
                data_type = params[1]
                data_width = Port.DataWidth(1, None, None)
            # Instantiate and add a new Port to the found ports list
            port = Port(
                name=name,
                code_name=name,
                direction=direction,
                data_type=data_type,
                data_width=data_width,
            )
            if self.window_module and data_type == PIPE_WINDOW_TYPE:
                if len(data_width) < 3:
                    LOG.error(
                        ("Data type '%s' requires 3 dimensions! "
                         "Instead got: '%s' - in file '%s'"),
                        PIPE_WINDOW_TYPE,
                        parens,
                        self.vhdl_file,
                    )
                else:
                    port.window_config = data_width[:2]
                    port.data_width = data_width[2]
                    LOG.debug(
                        "Found window in '%s' for '%s': '%s'",
                        self.entity_name,
                        name,
                        port.window_config,
                    )
            elif self.window_module and data_type == PIPE_LINE_TYPE:
                if len(data_width) < 2:
                    LOG.error(
                        ("Data type '%s' requires 2 dimensions! "
                         "Instead got: '%s' - in file '%s'"),
                        PIPE_LINE_TYPE,
                        parens,
                        self.vhdl_file,
                    )
                else:
                    port.data_width = data_width[1]
                    port.line_width = data_width[0]
                    LOG.debug(
                        "Found generic line in '%s' for '%s': '%s'",
                        self.entity_name,
                        name,
                        port.line_width,
                    )

            self.found_ports.append(port)