Пример #1
0
Файл: core.py Проект: Blaok/tapa
    def _instantiate_children_tasks(
        self,
        task: Task,
        width_table: Dict[str, int],
    ) -> List[ast.Identifier]:
        is_done_signals: List[rtl.Pipeline] = []
        arg_table: Dict[str, rtl.Pipeline] = {}
        async_mmap_args: Dict[Instance.Arg,
                              List[str]] = collections.OrderedDict()

        task.add_m_axi(width_table, self.tcl_files)

        for instance in task.instances:
            child_port_set = set(instance.task.module.ports)

            # add signal delcarations
            for arg in instance.args:
                if arg.cat not in {
                        Instance.Arg.Cat.ISTREAM,
                        Instance.Arg.Cat.OSTREAM,
                }:
                    width = 64  # 64-bit address
                    if arg.cat == Instance.Arg.Cat.SCALAR:
                        width = width_table.get(arg.name, 0)
                        if width == 0:
                            width = int(arg.name.split("'d")[0])
                    q = rtl.Pipeline(
                        name=instance.get_instance_arg(arg.name),
                        level=self.register_level,
                        width=width,
                    )
                    arg_table[arg.name] = q
                    task.module.add_pipeline(q, init=ast.Identifier(arg.name))

                # arg.name is the upper-level name
                # arg.port is the lower-level name

                # check which ports are used for async_mmap
                if arg.cat == Instance.Arg.Cat.ASYNC_MMAP:
                    for tag in rtl.ASYNC_MMAP_SUFFIXES:
                        if set(x.portname
                               for x in rtl.generate_async_mmap_ports(
                                   tag=tag,
                                   port=arg.port,
                                   arg=arg.name,
                                   instance=instance,
                               )) & child_port_set:
                            async_mmap_args.setdefault(arg, []).append(tag)

                # declare wires or forward async_mmap ports
                for tag in async_mmap_args.get(arg, []):
                    if task.is_upper and instance.task.is_lower:
                        task.module.add_signals(
                            rtl.generate_async_mmap_signals(
                                tag=tag,
                                arg=arg.mmap_name,
                                data_width=width_table[arg.name],
                            ))
                    else:
                        task.module.add_ports(
                            rtl.generate_async_mmap_ioports(
                                tag=tag,
                                arg=arg.name,
                                data_width=width_table[arg.name],
                            ))

            # add reset registers
            rst_q = rtl.Pipeline(instance.rst_n, level=self.register_level)
            task.module.add_pipeline(rst_q, init=rtl.RST_N)

            # add start registers
            start_q = rtl.Pipeline(
                f'{instance.start.name}_global',
                level=self.register_level,
            )
            task.module.add_pipeline(start_q, self.start_q[0])

            if instance.is_autorun:
                # autorun modules start when the global start signal is asserted
                task.module.add_logics([
                    ast.Always(
                        sens_list=rtl.CLK_SENS_LIST,
                        statement=ast.make_block(
                            ast.make_if_with_block(
                                cond=ast.Unot(rst_q[-1]),
                                true=ast.NonblockingSubstitution(
                                    left=instance.start,
                                    right=rtl.FALSE,
                                ),
                                false=ast.make_if_with_block(
                                    cond=start_q[-1],
                                    true=ast.NonblockingSubstitution(
                                        left=instance.start,
                                        right=rtl.TRUE,
                                    ),
                                ),
                            )),
                    ),
                ])
            else:
                # set up state
                is_done_q = rtl.Pipeline(
                    f'{instance.is_done.name}',
                    level=self.register_level,
                )
                done_q = rtl.Pipeline(
                    f'{instance.done.name}_global',
                    level=self.register_level,
                )
                task.module.add_pipeline(is_done_q, instance.is_state(STATE10))
                task.module.add_pipeline(done_q, self.done_q[0])

                if_branch = (instance.set_state(STATE00))
                else_branch = ((
                    ast.make_if_with_block(
                        cond=instance.is_state(STATE00),
                        true=ast.make_if_with_block(
                            cond=start_q[-1],
                            true=instance.set_state(STATE01),
                        ),
                    ),
                    ast.make_if_with_block(
                        cond=instance.is_state(STATE01),
                        true=ast.make_if_with_block(
                            cond=instance.ready,
                            true=ast.make_if_with_block(
                                cond=instance.done,
                                true=instance.set_state(STATE10),
                                false=instance.set_state(STATE11),
                            )),
                    ),
                    ast.make_if_with_block(
                        cond=instance.is_state(STATE11),
                        true=ast.make_if_with_block(
                            cond=instance.done,
                            true=instance.set_state(STATE10),
                        ),
                    ),
                    ast.make_if_with_block(
                        cond=instance.is_state(STATE10),
                        true=ast.make_if_with_block(
                            cond=done_q[-1],
                            true=instance.set_state(STATE00),
                        ),
                    ),
                ))
                task.module.add_logics([
                    ast.Always(
                        sens_list=rtl.CLK_SENS_LIST,
                        statement=ast.make_block(
                            ast.make_if_with_block(
                                cond=ast.Unot(rst_q[-1]),
                                true=if_branch,
                                false=else_branch,
                            )),
                    ),
                    ast.Assign(
                        left=instance.start,
                        right=instance.is_state(STATE01),
                    ),
                ])

                is_done_signals.append(is_done_q)

            # insert handshake signals
            task.module.add_signals(instance.handshake_signals)

            # add task module instances
            portargs = list(rtl.generate_handshake_ports(instance, rst_q))
            for arg in instance.args:
                if arg.cat == Instance.Arg.Cat.SCALAR:
                    portargs.append(
                        ast.PortArg(portname=arg.port,
                                    argname=arg_table[arg.name][-1]))
                elif arg.cat == Instance.Arg.Cat.ISTREAM:
                    portargs.extend(
                        instance.task.module.generate_istream_ports(
                            port=arg.port,
                            arg=arg.name,
                        ))
                    portargs.extend(portarg
                                    for portarg in rtl.generate_peek_ports(
                                        rtl, port=arg.port, arg=arg.name)
                                    if portarg.portname in child_port_set)
                elif arg.cat == Instance.Arg.Cat.OSTREAM:
                    portargs.extend(
                        instance.task.module.generate_ostream_ports(
                            port=arg.port,
                            arg=arg.name,
                        ))
                elif arg.cat == Instance.Arg.Cat.MMAP:
                    portargs.extend(
                        rtl.generate_m_axi_ports(
                            module=instance.task.module,
                            port=arg.port,
                            arg=arg.mmap_name,
                            arg_reg=arg_table[arg.name][-1].name,
                        ))
                elif arg.cat == Instance.Arg.Cat.ASYNC_MMAP:
                    for tag in async_mmap_args[arg]:
                        portargs.extend(
                            rtl.generate_async_mmap_ports(
                                tag=tag,
                                port=arg.port,
                                arg=arg.mmap_name,
                                instance=instance,
                            ))

            task.module.add_instance(
                module_name=util.get_module_name(instance.task.name),
                instance_name=instance.name,
                ports=portargs,
            )

        # instantiate async_mmap modules at the upper levels
        if task.is_upper:
            for arg in async_mmap_args:
                task.module.add_async_mmap_instance(
                    name=arg.mmap_name,
                    offset_name=arg_table[arg.name][-1],
                    tags=async_mmap_args[arg],
                    data_width=width_table[arg.name],
                )

        return is_done_signals
Пример #2
0
Файл: core.py Проект: Blaok/tapa
 def get_rtl(self, name: str, prefix: bool = True) -> str:
     return os.path.join(self.rtl_dir,
                         (util.get_module_name(name) if prefix else name) +
                         rtl.RTL_SUFFIX)