def handshake_signals(self) -> Iterator[Union[ast.Wire, ast.Reg]]: """All handshake signals used for this instance. Yields: Union[ast.Wire, ast.Reg] of signals. """ if self.is_autorun: yield ast.Reg(name=self.start.name, width=None) else: yield ast.Wire(name=self.start.name, width=None) yield ast.Reg(name=self.state.name, width=ast.make_width(2)) yield from (ast.Wire(name=rtl.wire_name(self.name, suffix), width=None) for suffix in rtl.HANDSHAKE_OUTPUT_PORTS)
def generate_async_mmap_signals(tag: str, arg: str, data_width: int) -> Iterator[ast.Wire]: for suffix in ASYNC_MMAP_SUFFIXES[tag]: yield ast.Wire( name=async_mmap_arg_name(arg=arg, tag=tag, suffix=suffix), width=async_mmap_width( tag=tag, suffix=suffix, data_width=data_width, ), )
def convert_axis_to_fifo(self, axis_name: str) -> str: assert len(self.get_fifo_directions(axis_name)) == 1, \ "axis interfaces should have one direction" direction_axis = { 'consumed_by': 'produced_by', 'produced_by': 'consumed_by', }[self.get_fifo_directions(axis_name)[0]] data_width = self.ports[axis_name].width # add FIFO registerings to provide timing isolation fifo_name = 'tapa_fifo_' + axis_name self.module.add_fifo_instance(name=fifo_name, width=data_width+1, depth=2) # add FIFO's wires for suffix in rtl.STREAM_PORT_DIRECTION: wire_name = rtl.wire_name(fifo_name, suffix) wire_width = rtl.get_stream_width(suffix, data_width) self.module.add_signals([ast.Wire(name=wire_name, width=wire_width)]) # add constant outputs for AXIS output ports if direction_axis == 'consumed_by': for axis_suffix, bit in rtl.AXIS_CONSTANTS.items(): port_name = self.module.find_port(axis_name, axis_suffix) width = rtl.get_axis_port_width_int(axis_suffix, data_width) self.module.add_logics([ ast.Assign(left=ast.Identifier(port_name), right=ast.IntConst("%d'b%s"%(width, str(bit)*width)))]) # connect the FIFO to the AXIS interface for suffix in self.get_fifo_suffixes(direction_axis): wire_name = rtl.wire_name(fifo_name, suffix) offset = 0 for axis_suffix in rtl.STREAM_TO_AXIS[suffix]: port_name = self.module.find_port(axis_name, axis_suffix) width = rtl.get_axis_port_width_int(axis_suffix, data_width) if len(rtl.STREAM_TO_AXIS[suffix]) > 1: wire = ast.Partselect(ast.Identifier(wire_name), ast.IntConst(str(offset + width - 1)), ast.IntConst(str(offset))) else: wire = ast.Identifier(wire_name) self.assign_directional( ast.Identifier(port_name), wire, rtl.STREAM_PORT_DIRECTION[suffix]) offset += width return fifo_name
def _connect_fifos(self, task: Task) -> None: _logger.debug(" connecting %s's children tasks", task.name) for fifo_name in task.fifos: for direction in task.get_fifo_directions(fifo_name): task_name, _, fifo_port = task.get_connection_to( fifo_name, direction) for suffix in task.get_fifo_suffixes(direction): # declare wires for FIFOs wire_name = rtl.wire_name(fifo_name, suffix) wire_width = self.get_task(task_name).module.get_port_of( fifo_port, suffix).width wire = ast.Wire(name=wire_name, width=wire_width) task.module.add_signals([wire]) if task.is_fifo_external(fifo_name): task.connect_fifo_externally(fifo_name, task.name == self.top)
def _connect_fifos(self, task: Task) -> None: _logger.debug(" connecting %s's children tasks", task.name) for fifo_name, fifo in task.fifos.items(): directions = { 'consumed_by': rtl.ISTREAM_SUFFIXES, 'produced_by': rtl.OSTREAM_SUFFIXES } for direction, suffixes in directions.items(): # skip if not in this direction if direction not in fifo: continue task_name, _, fifo_port = task.get_fifo_port( fifo_name, direction) child_ports = self.get_task(task_name).module.ports for suffix in suffixes: # declare wires for FIFOs wire_name = rtl.wire_name(fifo_name, suffix) wire_width = child_ports[rtl.fifo_port_name( fifo_port, suffix)].width wire = ast.Wire(name=wire_name, width=wire_width) task.module.add_signals([wire]) # if this FIFO is not declared, connect it directly to ports if 'depth' not in fifo: port_name = rtl.fifo_port_name(fifo_name, suffix) port_direction = rtl.STREAM_PORT_DIRECTION[suffix] if port_direction == 'input': task.module.add_logics([ ast.Assign(left=ast.Identifier(wire_name), right=ast.Identifier(port_name)) ]) elif port_direction == 'output': task.module.add_logics([ ast.Assign(left=ast.Identifier(port_name), right=ast.Identifier(wire_name)) ])
def add_m_axi( self, width_table: Dict[str, int], tcl_files: Dict[str, str], ) -> None: for arg_name, (m_axi_id_width, args) in self.mmaps.items(): # add m_axi ports to the arg list self.module.add_m_axi( name=arg_name, data_width=width_table[arg_name], id_width=m_axi_id_width or None, ) if len(args) == 1: continue # add AXI interconnect if necessary assert len(args) <= 16, f'too many ports connected to {arg_name}' assert m_axi_id_width is not None s_axi_id_width = max( arg.instance.task.get_id_width(arg.port) or 0 for arg in args) portargs = [ ast.make_port_arg(port='INTERCONNECT_ACLK', arg=rtl.HANDSHAKE_CLK), ast.make_port_arg( port='INTERCONNECT_ARESETN', arg=rtl.HANDSHAKE_RST_N, ), ast.make_port_arg(port='M00_AXI_ACLK', arg=rtl.HANDSHAKE_CLK), ast.make_port_arg(port='M00_AXI_ARESET_OUT_N', arg=''), ] for axi_chan, axi_ports in rtl.M_AXI_PORTS.items(): for axi_port, direction in axi_ports: m_axi_arg = f'{rtl.M_AXI_PREFIX}{arg_name}_{axi_chan}{axi_port}' if axi_port == 'ID' and direction == 'input': m_axi_arg = ( f"{{{s_axi_id_width + 4 - m_axi_id_width}'d0, " f"{m_axi_arg}}}") portargs.append( ast.make_port_arg( port=f'M00_AXI_{axi_chan}{axi_port}', arg=m_axi_arg, )) for idx, arg in enumerate(args): portargs += ( ast.make_port_arg(port=f'S{idx:02d}_AXI_ACLK', arg=rtl.HANDSHAKE_CLK), ast.make_port_arg(port=f'S{idx:02d}_AXI_ARESET_OUT_N', arg=''), ) wires = [] for axi_chan, axi_ports in rtl.M_AXI_PORTS.items(): for axi_port, _ in axi_ports: wire_name = (f'{rtl.M_AXI_PREFIX}{arg.mmap_name}_' f'{axi_chan}{axi_port}') wires.append( ast.Wire( name=wire_name, width=rtl.get_m_axi_port_width( port=axi_port, data_width=width_table[arg_name], id_width=arg.instance.task.get_id_width( arg.port), ))) portargs.append( ast.make_port_arg( port=f'S{idx:02d}_AXI_{axi_chan}{axi_port}', arg=wire_name, )) self.module.add_signals(wires) data_width = max(width_table[arg_name], 32) assert data_width in {32, 64, 128, 256, 512, 1024} module_name = (f'axi_interconnect_{data_width}b_' f'{s_axi_id_width}t_x{len(args)}') s_axi_data_width = ' \\\n '.join( f'CONFIG.S{idx:02d}_AXI_DATA_WIDTH {data_width}' for idx in range(len(args))) s_axi_read_acceptance = ' \\\n '.join( f'CONFIG.S{idx:02d}_AXI_READ_ACCEPTANCE 16' for idx in range(len(args))) s_axi_write_acceptance = ' \\\n '.join( f'CONFIG.S{idx:02d}_AXI_WRITE_ACCEPTANCE 16' for idx in range(len(args))) tcl_files.setdefault( module_name, f'''\ create_ip \\ -name axi_interconnect \\ -vendor xilinx.com \\ -library ip \\ -version 1.7 \\ -module_name {module_name} set_property -dict [list \\ CONFIG.AXI_ADDR_WIDTH 64 \\ CONFIG.NUM_SLAVE_PORTS {len(args)} \\ CONFIG.THREAD_ID_WIDTH {s_axi_id_width} \\ CONFIG.INTERCONNECT_DATA_WIDTH {data_width} \\ CONFIG.M00_AXI_DATA_WIDTH {data_width} \\ {s_axi_data_width} \\ CONFIG.M00_AXI_READ_ISSUING 16 \\ {s_axi_read_acceptance} \\ CONFIG.M00_AXI_WRITE_ISSUING 16 \\ {s_axi_write_acceptance} \\ ] [get_ips {module_name}] set_property generate_synth_checkpoint false [get_files {module_name}.xci] generate_target {{synthesis simulation}} [get_files {module_name}.xci] ''') self.module.add_instance( module_name=module_name, instance_name=f'{module_name}__{arg_name}', ports=portargs, )
def signals(self) -> Iterator[Union[ast.Reg, ast.Wire, ast.Pragma]]: yield ast.Wire(name=self[0].name, width=self._width) for x in self[1:]: yield ast.Pragma(ast.PragmaEntry('dont_touch = "yes"')) yield ast.Reg(name=x.name, width=self._width)
def signals(self) -> Iterator[Union[ast.Reg, ast.Wire, ast.Pragma]]: yield ast.Wire(name=self[0].name, width=self._width) for x in self[1:]: yield ast.Pragma(ast.PragmaEntry('shreg_extract = "no"')) yield ast.Reg(name=x.name, width=self._width)