Esempio n. 1
0
def generate_m_axi_ports(
    module: Module,
    port: str,
    arg: str,
    arg_reg: str = '',
) -> Iterator[ast.PortArg]:
    """Generate AXI mmap ports that instantiate given module.

  Args:
      module (Module): Module that needs to be instantiated.
      port (str): Port name in the instantiated module.
      arg (str): Argument name in the instantiating module.
      arg_reg (str, optional): Registered argument name. Defaults to ''.

  Raises:
      ValueError: If the offset port cannot be found in the instantiated module.

  Yields:
      Iterator[ast.PortArg]: PortArgs.
  """
    for suffix in M_AXI_SUFFIXES:
        yield ast.make_port_arg(port=M_AXI_PREFIX + port + suffix,
                                arg=M_AXI_PREFIX + arg + suffix)
    for suffix in '_offset', '_data_V', '_V', '':
        port_name = module.find_port(prefix=port, suffix=suffix)
        if port_name is not None:
            if port_name != port + suffix:
                _logger.warn(
                    f"unexpected offset port `{port_name}' in module"
                    f" `{module.name}'; please double check if this is the "
                    f"offset port for m_axi port `{port}'")
            yield ast.make_port_arg(port=port_name, arg=arg_reg or arg)
            break
    else:
        raise ValueError(f'cannot find offset port for {port}')
Esempio n. 2
0
  def generate_istream_ports(
      self,
      port: str,
      arg: str,
  ) -> Iterator[ast.PortArg]:
    for suffix in ISTREAM_SUFFIXES:
      arg_name = wire_name(arg, suffix)

      # read port
      yield ast.make_port_arg(
          port=self.get_port_of(port, suffix).name,
          arg=arg_name,
      )
      if STREAM_PORT_DIRECTION[suffix] == 'output':
        arg_name = ''

      # peek port
      match = match_array_name(port)
      if match is None:
        peek_port = f'{port}_peek'
      else:
        peek_port = f'{match[0]}_peek[{match[1]}]'
      yield ast.make_port_arg(
          port=self.get_port_of(peek_port, suffix).name,
          arg=arg_name,
      )
Esempio n. 3
0
def generate_async_mmap_ports(
    tag: str, port: str, arg: str,
    instance: tapa.instance.Instance) -> Iterator[ast.PortArg]:
  # TODO: reuse functions that generate i/ostream ports
  prefix = port + '_' + tag
  for suffix in ASYNC_MMAP_SUFFIXES[tag]:
    arg_name = async_mmap_arg_name(
        arg=arg,
        tag=tag,
        suffix=suffix,
    )
    port_name = instance.task.module.find_port(prefix=prefix, suffix=suffix)
    if port_name is not None:
      # Make sure Eot is always 1'b0.
      if suffix == ISTREAM_SUFFIXES[0]:
        arg_name = f"{{1'b0, {arg_name}}}"

      _logger.debug('`%s.%s` is connected to async_mmap port `%s.%s`',
                    instance.name, port_name, arg, tag)
      yield ast.make_port_arg(port=port_name, arg=arg_name)

    # Generate peek ports.
    if ASYNC_MMAP_SUFFIXES[tag] is ISTREAM_SUFFIXES:
      port_name = instance.task.module.find_port(prefix + '_peek', suffix)
      if port_name is not None:
        # Ignore read enable from peek ports.
        if STREAM_PORT_DIRECTION[suffix] == 'input':
          _logger.debug('`%s.%s` is connected to async_mmap port `%s.%s`',
                        instance.name, port_name, arg, tag)
        else:
          arg_name = ''

        yield ast.make_port_arg(port=port_name, arg=arg_name)
Esempio n. 4
0
def generate_handshake_ports(
    instance: tapa.instance.Instance,
    rst_q: Pipeline,
) -> Iterator[ast.PortArg]:
    yield ast.make_port_arg(port=HANDSHAKE_CLK, arg=CLK)
    yield ast.make_port_arg(port=HANDSHAKE_RST_N, arg=rst_q[-1])
    yield ast.make_port_arg(port=HANDSHAKE_START, arg=instance.start)
    for port in HANDSHAKE_OUTPUT_PORTS:
        yield ast.make_port_arg(
            port=port,
            arg="" if instance.is_autorun else wire_name(instance.name, port),
        )
Esempio n. 5
0
 def generate_ostream_ports(
     self,
     port: str,
     arg: str,
 ) -> Iterator[ast.PortArg]:
     for suffix in OSTREAM_SUFFIXES:
         yield ast.make_port_arg(
             port=self.get_port_of(port, suffix).name,
             arg=wire_name(arg, suffix),
         )
Esempio n. 6
0
def generate_peek_ports(verilog, port: str, arg: str) -> Iterator[ast.PortArg]:
    match = match_array_name(port)
    if match is None:
        port = f'{port}_peek_V'
    else:
        port = f'{match[0]}_peek_V_{match[1]}'
    for suffix in verilog.ISTREAM_SUFFIXES:
        if verilog.STREAM_PORT_DIRECTION[suffix] == 'input':
            arg_name = wire_name(arg, suffix)
        else:
            arg_name = ''
        yield ast.make_port_arg(port=port + suffix, arg=arg_name)
Esempio n. 7
0
def generate_async_mmap_ports(
    tag: str, port: str, arg: str,
    instance: tapa.instance.Instance) -> Iterator[ast.PortArg]:
  prefix = port + '_' + tag + '_V_'
  for suffix in async_mmap_suffixes(tag):
    port_name = instance.task.module.find_port(prefix=prefix, suffix=suffix)
    if port_name is not None:
      yield ast.make_port_arg(
          port=port_name,
          arg=async_mmap_arg_name(
              arg=arg,
              tag=tag,
              suffix=suffix,
          ),
      )
Esempio n. 8
0
 def ports() -> Iterator[ast.PortArg]:
   yield ast.make_port_arg(port='clk', arg=CLK)
   yield ast.make_port_arg(port='reset', arg=rst_q[-1])
   yield from (
       ast.make_port_arg(port=port_name, arg=wire_name(name, arg_suffix))
       for port_name, arg_suffix in zip(FIFO_READ_PORTS, ISTREAM_SUFFIXES))
   yield ast.make_port_arg(port=FIFO_READ_PORTS[-1], arg=TRUE)
   yield from (
       ast.make_port_arg(port=port_name, arg=wire_name(name, arg_suffix))
       for port_name, arg_suffix in zip(FIFO_WRITE_PORTS, OSTREAM_SUFFIXES))
   yield ast.make_port_arg(port=FIFO_WRITE_PORTS[-1], arg=TRUE)
Esempio n. 9
0
File: task.py Progetto: mfkiwl/tapa
    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,
            )
Esempio n. 10
0
    def add_async_mmap_instance(
        self,
        name: str,
        tags: Iterable[str],
        data_width: int,
        addr_width: int = 64,
        buffer_size: Optional[int] = None,
        max_wait_time: int = 3,
        max_burst_len: Optional[int] = None,
        offset_name: str = '',
    ) -> 'Module':
        rst_q = Pipeline(f'{name}__rst', level=self.register_level)
        self.add_pipeline(rst_q, init=ast.Unot(RST_N))

        paramargs = [
            ast.ParamArg(paramname='DataWidth',
                         argname=ast.Constant(data_width)),
            ast.ParamArg(paramname='DataWidthBytesLog',
                         argname=ast.Constant(
                             (data_width // 8 - 1).bit_length())),
        ]
        portargs = [
            ast.make_port_arg(port='clk', arg=CLK),
            ast.make_port_arg(port='rst', arg=rst_q[-1]),
        ]
        paramargs.append(
            ast.ParamArg(paramname='AddrWidth',
                         argname=ast.Constant(addr_width)))
        if buffer_size:
            paramargs.extend(
                (ast.ParamArg(paramname='BufferSize',
                              argname=ast.Constant(buffer_size)),
                 ast.ParamArg(paramname='BufferSizeLog',
                              argname=ast.Constant(
                                  (buffer_size - 1).bit_length()))))
        max_wait_time = max(1, max_wait_time)
        paramargs.append(
            ast.ParamArg(paramname='WaitTimeWidth',
                         argname=ast.Constant(max_wait_time.bit_length())))
        portargs.append(
            ast.make_port_arg(port='max_wait_time',
                              arg="{}'d{}".format(max_wait_time.bit_length(),
                                                  max_wait_time)))
        if max_burst_len is None:
            max_burst_len = max(0, 4096 // data_width - 1)
        paramargs.append(
            ast.ParamArg(paramname='BurstLenWidth',
                         argname=ast.Constant(
                             max(1, max_burst_len.bit_length()))))
        portargs.append(
            ast.make_port_arg(port='max_burst_len',
                              arg="{}'d{}".format(
                                  max(1, max_burst_len.bit_length()),
                                  max_burst_len)))

        for channel, ports in M_AXI_PORTS.items():
            for port, direction in ports:
                portargs.append(
                    ast.make_port_arg(
                        port=f'{M_AXI_PREFIX}{channel}{port}',
                        arg=f'{M_AXI_PREFIX}{name}_{channel}{port}'))

        tags = set(tags)
        for tag in 'read_addr', 'read_data', 'write_addr', 'write_data':
            for suffix in async_mmap_suffixes(tag=tag):
                if tag in tags:
                    arg = async_mmap_arg_name(arg=name, tag=tag, suffix=suffix)
                    if tag.endswith('_addr') and suffix.endswith('_din'):
                        elem_size_bytes_m1 = data_width // 8 - 1
                        arg = "{name} + {{{arg}[{}:0], {}'d0}}".format(
                            addr_width - elem_size_bytes_m1.bit_length() - 1,
                            elem_size_bytes_m1.bit_length(),
                            arg=arg,
                            name=offset_name or name)
                else:
                    if suffix.endswith('_read') or suffix.endswith('_write'):
                        arg = "1'b0"
                    elif suffix.endswith('_din'):
                        arg = "'d0"
                    else:
                        arg = ''
                portargs.append(ast.make_port_arg(port=tag + suffix, arg=arg))

        return self.add_instance(module_name='async_mmap',
                                 instance_name=async_mmap_instance_name(name),
                                 ports=portargs,
                                 params=paramargs)
Esempio n. 11
0
def generate_ostream_ports(port: str, arg: str) -> Iterator[ast.PortArg]:
    for suffix in OSTREAM_SUFFIXES:
        yield ast.make_port_arg(port=fifo_port_name(port, suffix),
                                arg=wire_name(arg, suffix))