Пример #1
0
    def __call__(self, top):
        if not hasattr(top._dag, "all_constraints"):
            raise PassOrderError("all_constraints")

        if hasattr(top, "_sched"):
            raise Exception("Some schedule pass has already been applied!")

        top._sched = PassMetadata()

        # Extract branchiness first
        # Initialize all generated net block to 0 branchiness

        self.meta_block_id = 0
        self.branchiness = {x: 0 for x in top._dag.genblks}
        self.only_loop_at_top = {x: False for x in top._dag.genblks}
        v = CountBranchesLoops()

        # Shunning: since each loop turns into call_assembler_r, a pure-loop
        # update block is basically 0 branchiness and can be inserted anywhere.
        # At the beginning I tried not to put those blocks into any metablock
        # to avoid double call_assembler_r but it just turned out that there
        # is no difference of where you put the call_assembler_r.. Plus,
        # treating loop blocks as normal update block can activate subsequent
        # schedulable 0-branchiness block.

        for blk in top.get_all_update_blocks():
            hostobj = top.get_update_block_host_component(blk)
            if blk in top._dag.blk_greenlet_mapping:
                gblk = top._dag.blk_greenlet_mapping[blk]
                self.branchiness[gblk], self.only_loop_at_top[gblk] = 0, 0
            else:
                self.branchiness[blk], self.only_loop_at_top[blk] = v.enter(
                    hostobj.get_update_block_info(blk)[-1])

        self.schedule_ff(top)

        # Reuse simple's flip schedule
        simple = SimpleSchedulePass()
        simple.schedule_posedge_flip(top)

        self.schedule_intra_cycle(top)

        top._sim = PassMetadata()
        self.create_print_line_trace(top)
        self.create_sim_cycle_count(top)
        self.create_lock_unlock_simulation(top)
        top.lock_in_simulation()

        self.create_sim_eval_comb(top)
        self.create_sim_tick(top)
        self.create_sim_reset(top)
Пример #2
0
    def _gen_metadata(s, m):

        # Create namespace
        if not hasattr(m, '_pass_structural_rtlir_gen'):
            m._pass_structural_rtlir_gen = PassMetadata()

        ns = m._pass_structural_rtlir_gen

        # Generate RTLIR types
        ns.rtlir_type = s.tr_top._rtlir_getter.get_rtlir(m)

        # Generate constants
        ns.consts = []
        rtype = ns.rtlir_type
        const_types = rtype.get_consts_packed()
        for const_name, const_rtype in const_types:
            assert hasattr(m, const_name), \
              f"Internal error: {const_name} is not a member of {m}"
            const_instance = getattr(m, const_name)
            ns.consts.append((const_name, const_rtype, const_instance))

        # Sort connections
        m_conns_set = s.inst_conns[m]
        ordered_conns = [*m.get_connect_order()]
        assert len(ordered_conns) == len(m_conns_set)

        for i, x in enumerate(ordered_conns):
            if x not in m_conns_set:
                x = (x[1], x[0])
                assert x in m_conns_set, "There is a connection missing from "\
                                         "connect_order. Please contact PyMTL developers!"
                ordered_conns[i] = x

        ns.connections = [(gen_signal_expr(m, x[0]), gen_signal_expr(m, x[1]))
                          for x in ordered_conns]
Пример #3
0
  def __call__( self, top ):
    if not hasattr( top._dag, "all_constraints" ):
      raise PassOrderError( "all_constraints" )

    top._sched = PassMetadata()

    top._sched.schedule = self.schedule( top )
Пример #4
0
    def __call__(s, m):
        """ generate RTLIR for all upblks of m """
        if not hasattr(m, '_pass_behavioral_rtlir_gen'):
            m._pass_behavioral_rtlir_gen = PassMetadata()
        m._pass_behavioral_rtlir_gen.rtlir_upblks = {}
        visitor = BehavioralRTLIRGeneratorL3(m)

        upblks = {
            'CombUpblk': get_ordered_upblks(m),
            'SeqUpblk': get_ordered_update_ff(m),
        }
        # Sort the upblks by their name
        upblks['CombUpblk'].sort(key=lambda x: x.__name__)
        upblks['SeqUpblk'].sort(key=lambda x: x.__name__)

        for upblk_type in ('CombUpblk', 'SeqUpblk'):
            for blk in upblks[upblk_type]:
                visitor._upblk_type = upblk_type
                upblk_info = m.get_update_block_info(blk)
                upblk = visitor.enter(blk, upblk_info[-1])
                upblk.is_lambda = upblk_info[0]
                upblk.src = upblk_info[1]
                upblk.lino = upblk_info[2]
                upblk.filename = upblk_info[3]
                m._pass_behavioral_rtlir_gen.rtlir_upblks[blk] = upblk
Пример #5
0
  def __call__( self, top ):
    if hasattr(top, "sim_reset"):
      raise AttributeError( "Please rename the attribute top.sim_reset")
    if hasattr(top, "print_line_trace"):
      raise AttributeError( "Please modify the attribute top.print_line_trace")
    if not hasattr( top, "_sched" ):
      raise PassOrderError( "_sched" )
    if not hasattr( top._sched, "update_schedule" ):
      raise PassOrderError( "update_schedule" )
    if not hasattr( top._sched, "schedule_ff" ):
      raise PassOrderError( "schedule_ff" )
    if not hasattr( top._sched, "schedule_posedge_flip" ):
      raise PassOrderError( "schedule_posedge_flip" )

    top._sim = PassMetadata()

    self.create_print_line_trace( top )
    self.create_sim_cycle_count( top )
    self.create_lock_unlock_simulation( top )

    top.lock_in_simulation()

    self.create_sim_eval_comb( top )
    self.create_sim_tick( top )
    self.create_sim_reset( top )
Пример #6
0
  def __call__( self, top ):
    if hasattr( top, "config_tracing" ):
      top.config_tracing.check()

      if top.config_tracing.tracing in [ 'text_ascii', 'text_fancy' ]:
        if not hasattr( top, "_tracing" ):
          top._tracing = PassMetadata()
        top._tracing.collect_text_sigs = self.collect_sig_func( top, top._tracing )
Пример #7
0
    def __call__(self, top):
        if not hasattr(top._dag, "all_constraints"):
            raise PassOrderError("all_constraints")

        top._sched = PassMetadata()

        self.meta_schedule(top)
        self.trace_breaking_tick(top)
Пример #8
0
    def __call__(self, top):
        if not hasattr(top._dag, "all_constraints"):
            raise PassOrderError("all_constraints")

        top._sched = PassMetadata()

        self.schedule_intra_cycle(top)
        self.schedule_ff(top)
        self.schedule_posedge_flip(top)
Пример #9
0
    def __call__(self, top):

        if hasattr(top, "config_tracing"):
            top.config_tracing.check()

            if top.config_tracing.tracing != 'none':
                if not hasattr(top, "_tracing"):
                    top._tracing = PassMetadata()
                top._tracing.vcd_func = self.make_vcd_func(top, top._tracing)
Пример #10
0
        def traverse_hierarchy(s, m):

            if hasattr(m, "config_verilog_translate") and m.config_verilog_translate and \
               m.config_verilog_translate.translate:

                if not hasattr(m, '_pass_verilog_translation'):
                    m._pass_verilog_translation = PassMetadata()

                s.translator.translate(m, s.gen_tr_cfgs(m))

                module_name = s.translator._top_module_full_name

                if m.config_verilog_translate.explicit_file_name:
                    fname = m.config_verilog_translate.explicit_file_name
                    if '.v' in fname:
                        filename = fname.split('.v')[0]
                    elif '.sv' in fname:
                        filename = fname.split('.sv')[0]
                    else:
                        filename = fname
                else:
                    filename = module_name

                output_file = filename + '.v'
                temporary_file = filename + '.v.tmp'

                # First write the file to a temporary file
                m._pass_verilog_translation.is_same = False
                with open(temporary_file, 'w') as output:
                    output.write(s.translator.hierarchy.src)
                    output.flush()
                    os.fsync(output)
                    output.close()

                # `is_same` is set if there exists a file that has the same filename as
                # `output_file`, and that file is the same as the temporary file
                if (os.path.exists(output_file)):
                    m._pass_verilog_translation.is_same = \
                        filecmp.cmp( temporary_file, output_file )

                # Rename the temporary file to the output file
                os.rename(temporary_file, output_file)

                # Expose some attributes about the translation process
                m.translated_top_module_name = module_name
                m._translator = s.translator
                m._pass_verilog_translation.translated = True

                m._pass_verilog_translation.translated_filename = output_file
                m._pass_verilog_translation.translated_top_module = module_name

            else:
                for child in m.get_child_components():
                    s.traverse_hierarchy(child)
 def __call__(s, m):
     """Perform type checking on all RTLIR in rtlir_upblks."""
     if not hasattr(m, '_pass_behavioral_rtlir_type_check'):
         m._pass_behavioral_rtlir_type_check = PassMetadata()
     m._pass_behavioral_rtlir_type_check.rtlir_freevars = OrderedDict()
     m._pass_behavioral_rtlir_type_check.rtlir_accessed = set()
     visitor = BehavioralRTLIRTypeCheckVisitorL1(
         m, m._pass_behavioral_rtlir_type_check.rtlir_freevars,
         m._pass_behavioral_rtlir_type_check.rtlir_accessed)
     for blk in m.get_update_blocks():
         visitor.enter(blk, m._pass_behavioral_rtlir_gen.rtlir_upblks[blk])
Пример #12
0
 def __call__(s, tr_top):
     """ generate structural RTLIR for component `tr_top` """
     if not hasattr(tr_top, '_pass_structural_rtlir_gen'):
         tr_top._pass_structural_rtlir_gen = PassMetadata()
     s.tr_top = tr_top
     try:
         s.gen_rtlir_types(tr_top)
         s.gen_constants(tr_top)
         s.sort_connections(tr_top)
     except AssertionError as e:
         msg = '' if not e.args is None else e.args[0]
         raise RTLIRConversionError(tr_top, msg)
Пример #13
0
  def __call__( self, top ):
    top.check()
    top._dag = PassMetadata()

    placeholders = [ x for x in top._dsl.all_named_objects
                     if isinstance( x, Placeholder ) ]

    if placeholders:
      raise LeftoverPlaceholderError( placeholders )

    self._generate_net_blocks( top )
    self._process_value_constraints( top )
    self._process_methods( top )
Пример #14
0
 def __call__(s, m):
     """Perform type checking on all RTLIR in rtlir_upblks."""
     if not hasattr(m, '_pass_behavioral_rtlir_type_check'):
         m._pass_behavioral_rtlir_type_check = PassMetadata()
     m._pass_behavioral_rtlir_type_check.rtlir_freevars = {}
     m._pass_behavioral_rtlir_type_check.rtlir_accessed = set()
     visitor = s.get_visitor_class()(
         m,
         m._pass_behavioral_rtlir_type_check.rtlir_freevars,
         m._pass_behavioral_rtlir_type_check.rtlir_accessed,
         s.tr_top._rtlir_getter,
     )
     for blk in m.get_update_block_order():
         visitor.enter(blk, m._pass_behavioral_rtlir_gen.rtlir_upblks[blk])
Пример #15
0
  def __call__( self, top ):
    if not hasattr( top._dag, "all_constraints" ):
      raise PassOrderError( "all_constraints" )

    if hasattr( top, "_sched" ):
      raise Exception("Some schedule pass has already been applied!")

    top._sched = PassMetadata()

    self.schedule_intra_cycle( top )

    # Reuse simple's ff and flip schedule
    simple = SimpleSchedulePass()
    simple.schedule_ff( top )
    simple.schedule_posedge_flip( top )
Пример #16
0
    def __call__(self, top):
        if not hasattr(top._sched, "schedule"):
            raise PassOrderError("schedule")

        if hasattr(top, "_cl_trace"):
            schedule = top._cl_trace.schedule
        else:
            schedule = top._sched.schedule

        try:
            en = top.text_wave
        except AttributeError:
            return

        if en:
            top._textwave = PassMetadata()
            schedule.append(self.collect_sig_func(top, top._textwave))
Пример #17
0
    def __call__(self, top):

        # Check for dum_vcd flag
        if not hasattr(top, "dump_vcd") or not top.dump_vcd:
            return

        if not hasattr(top._sched, "schedule"):
            raise PassOrderError("schedule")

        if hasattr(top, "_cl_trace"):
            schedule = top._cl_trace.schedule
        else:
            schedule = top._sched.schedule

        top._vcd = PassMetadata()

        schedule.append(self.make_vcd_func(top))
Пример #18
0
        def wrap_line_trace(obj):
            if not hasattr(obj, '_ml_trace'):
                obj._ml_trace = PassMetadata()
            obj._ml_trace.line_trace = obj.line_trace

            def wrapped_line_trace(self, *args, **kwargs):
                if self._dsl.param_tree is not None:
                    if self._dsl.param_tree.leaf is not None:
                        if 'line_trace' in self._dsl.param_tree.leaf:
                            # TODO: figure out whether it is necessary to enforce no
                            # positional args.
                            assert len(args) == 0
                            more_args = self._dsl.param_tree.leaf[
                                'line_trace'].items()
                            kwargs.update({x: y for x, y in more_args})
                return self._ml_trace.line_trace(*args, **kwargs)

            obj.line_trace = lambda *args, **kwargs: wrapped_line_trace(
                obj, *args, **kwargs)
Пример #19
0
    def __call__(s, m):
        """ generate RTLIR for all upblks of m """
        if not hasattr(m, '_pass_behavioral_rtlir_gen'):
            m._pass_behavioral_rtlir_gen = PassMetadata()
        m._pass_behavioral_rtlir_gen.rtlir_upblks = {}
        visitor = BehavioralRTLIRGeneratorL4(m)
        upblks = {
            'CombUpblk': list(m.get_update_blocks() - m.get_update_on_edge()),
            'SeqUpblk': list(m.get_update_on_edge())
        }
        # Sort the upblks by their name
        upblks['CombUpblk'].sort(key=lambda x: x.__name__)
        upblks['SeqUpblk'].sort(key=lambda x: x.__name__)

        for upblk_type in ('CombUpblk', 'SeqUpblk'):
            for blk in upblks[upblk_type]:
                visitor._upblk_type = upblk_type
                m._pass_behavioral_rtlir_gen.rtlir_upblks[ blk ] = \
                  visitor.enter( blk, m.get_update_block_ast( blk ) )
Пример #20
0
    def traverse_hierarchy(s, m):

        if hasattr(m, "yosys_translate") and m.yosys_translate:

            if not hasattr(m, '_pass_yosys_translation'):
                m._pass_yosys_translation = PassMetadata()

            s.translator.translate(m)

            module_name = s.translator._top_module_full_name
            output_file = module_name + '.sv'
            temporary_file = module_name + '.sv.tmp'

            # First write the file to a temporary file
            m._pass_yosys_translation.is_same = False
            with open(temporary_file, 'w') as output:
                output.write(s.translator.hierarchy.src)
                output.flush()
                os.fsync(output)
                output.close()

            # `is_same` is set if there exists a file that has the same filename as
            # `output_file`, and that file is the same as the temporary file
            if (os.path.exists(output_file)):
                m._pass_yosys_translation.is_same = \
                    filecmp.cmp( temporary_file, output_file )

            # Rename the temporary file to the output file
            os.rename(temporary_file, output_file)

            m._translator = s.translator
            m._pass_yosys_translation.translated = True

        else:
            for child in m.get_child_components():
                s.traverse_hierarchy(child)
Пример #21
0
 def gen_metadata(s, m):
     if not hasattr(m, '_pass_structural_rtlir_gen'):
         m._pass_structural_rtlir_gen = PassMetadata()
     for child in m.get_child_components():
         s.gen_metadata(child)
Пример #22
0
 def __call__(self, top):
     if not hasattr(top, "_tracing"):
         top._tracing = PassMetadata()
     top._tracing.clear_cl_trace = self.process_component(top)
Пример #23
0
    def __call__(self, top):
        if not top._dsl.constructed:
            raise VerilogImportError(
                top,
                f"please elaborate design {top} before applying the TBGen pass!"
            )

        top._tbgen = PassMetadata()
        top._tbgen.tbgen_hooks = []

        tbgen_components = []

        def traverse_hierarchy(m):
            if hasattr(m, 'verilog_tbgen') and hasattr(m, '_ports'):
                tbgen_components.append((m, m.verilog_tbgen))
            else:
                for child in m.get_child_components():
                    traverse_hierarchy(child)

        traverse_hierarchy(top)

        for x, case_name in tbgen_components:

            signal_decls = []
            task_assign_strs = []
            task_signal_decls = []
            task_check_strs = []
            dut_signal_decls = []

            py_signal_order = []

            for pname, vname, port, is_ifc in x._ports:
                if vname == "reset" or vname == "clk":
                    continue

                # Prepare for generating strings
                if isinstance(port, rt.Port): direction = port.get_direction()
                elif isinstance(port, rt.Array):
                    direction = port.get_sub_type().get_direction()
                else:
                    raise Exception(f"unrecognized direction {d}!")

                p_n_dim, p_rtype = get_rtype(port)
                dtype = p_rtype.get_dtype()
                if isinstance(dtype, rdt.Vector): nbits = dtype.get_length()
                elif isinstance(dtype, rdt.Struct):
                    nbits = get_nbits(dtype.get_class())
                else:
                    raise Exception(f"unrecognized data type {d}!")

                # signal_decls
                signal_decl_indices = " ".join([f"[0:{d-1}]" for d in p_n_dim])
                signal_decls.append(
                    f"logic [{nbits-1}:0] {vname} {signal_decl_indices}")

                # dut_signal_decls

                if p_n_dim:
                    # https://sutherland-hdl.com/papers/2013-SNUG-SV_Synthesizable-SystemVerilog_paper.pdf
                    # chapter 5.2.3
                    dut_signal_decls.append(
                        f".{vname}({{ >> {{ {vname} }} }})")
                else:
                    dut_signal_decls.append(f".{vname}({vname})")

                Q = deque([(vname, vname, p_n_dim)])
                tot = 0  # This is to keep the same order as pname list
                while Q:
                    name, mangled_name, indices = Q.popleft()
                    if not indices:
                        pyname = pname[tot]
                        if direction == "input":
                            task_signal_decls.append(
                                f"input logic [{nbits-1}:0] inp_{mangled_name}"
                            )
                            task_assign_strs.append(
                                f"{name} = inp_{mangled_name}")
                        else:  # output
                            task_signal_decls.append(
                                f"input logic [{nbits-1}:0] ref_{mangled_name}"
                            )
                            task_check_strs.append(
                                f"`CHECK(lineno, {name}, ref_{mangled_name}, \"{pyname} ({name} in Verilog)\")"
                            )
                        tot += 1
                        py_signal_order.append(pyname)
                    else:
                        for i in range(indices[0]):
                            Q.append((f"{name}[{i}]", f"{mangled_name}__{i}",
                                      indices[1:]))

            dut_name = x._ip_cfg.translated_top_module

            with open(f"{dut_name}_{case_name}_tb.v", 'w') as output:
                output.write(
                    tb_template.format(
                        args_strs=",".join(
                            [f"a{i}" for i in range(len(task_signal_decls))]),
                        harness_name=dut_name + "_tb",
                        signal_decls=";\n  ".join(
                            signal_decls
                        ),  # logic [31:0] xxx [0:3]; -- unpacked array
                        task_signal_decls=",\n    ".join(
                            task_signal_decls
                        ),  # input logic [31:0] in__x;input logic [31:0] ref_y; -- unpacked ports
                        task_assign_strs=";\n    ".join(
                            task_assign_strs),  # x = in__x; -- unpacked
                        task_check_strs=";\n    ".join(
                            task_check_strs
                        ),  # ERR( lineno, 'x', x, ref_x ) -- unpacked
                        dut_name=dut_name,
                        dut_clk_decl='.clk(clk)' if x._ph_cfg.has_clk else '',
                        dut_reset_decl='.reset(reset)'
                        if x._ph_cfg.has_reset else '',
                        dut_signal_decls=",\n    ".join(
                            dut_signal_decls
                        ),  # logic [31:0] xxx, -- packed array, # .x(x), -- packed array
                        cases_file_name=f"{dut_name}_{case_name}_tb.v.cases",
                    ))

            case_file = open(f"{dut_name}_{case_name}_tb.v.cases", "w")
            top._tbgen.tbgen_hooks.append(
                self.gen_hook_func(top, x, py_signal_order, case_file))
Пример #24
0
 def visit_placeholder(s, m):
     if not hasattr(m, '_placeholder_meta'):
         m._placeholder_meta = PassMetadata()