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
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), ], )
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
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))
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"
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)
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
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__()
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)
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
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 = []
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
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
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)
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)
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)
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)
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)
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)
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
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)
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
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)