1#=========================================================================
2# StructuralRTLIRGenL1Pass.py
3#=========================================================================
4# Author : Shunning Jiang, Peitian Pan
5# Date   : Apr 3, 2019
6"""Provide L1 structural RTLIR generation pass."""
7
8from pymtl3 import MetadataKey
9from pymtl3.passes.PlaceholderConfigs import PlaceholderConfigs
10# from pymtl3.passes.rtlir.RTLIRPass import RTLIRPass
11from pymtl3.passes.rtlir.errors import RTLIRConversionError
12from pymtl3.passes.rtlir.rtype.RTLIRType import RTLIRGetter
13
14from .StructuralRTLIRGenL0Pass import StructuralRTLIRGenL0Pass
15from .StructuralRTLIRSignalExpr import gen_signal_expr
16
17
18class StructuralRTLIRGenL1Pass( StructuralRTLIRGenL0Pass ):
19
20  def __init__( s, inst_conns ):
21    s.inst_conns = inst_conns
22
23  def __call__( s, tr_top ):
24    """ generate structural RTLIR for component `tr_top` """
25    c = s.__class__
26    s.tr_top = tr_top
27    if not tr_top.has_metadata( c.rtlir_getter ):
28      tr_top.set_metadata( c.rtlir_getter, RTLIRGetter(cache=True) )
29
30    try:
31      s._gen_metadata( tr_top )
32    except AssertionError as e:
33      msg = '' if not e.args is None else e.args[0]
34      raise RTLIRConversionError( tr_top, msg )
35
36  def _gen_metadata( s, m ):
37    c = s.__class__
38
39    # Generate RTLIR types
40    rtlir_type = s.tr_top.get_metadata( c.rtlir_getter ).get_rtlir( m )
41    m.set_metadata( c.rtlir_type, rtlir_type )
42
43    # Generate constants
44    consts = []
45    rtype = rtlir_type
46    const_types = rtype.get_consts_packed()
47    for const_name, const_rtype in const_types:
48      assert hasattr(m, const_name), \
49        f"Internal error: {const_name} is not a member of {m}"
50      const_instance = getattr(m, const_name)
51      consts.append( ( const_name, const_rtype, const_instance ) )
52
53    m.set_metadata( c.consts, consts )
54
55    # Sort connections
56    m_conns_set   = s.inst_conns[m]
57    ordered_conns = [ *m.get_connect_order() ]
58
59    # NOTE: this assertion can fail due to connections that
60    # are made outside the component that has them. so i'm removing
61    # this for now until we can figure out a better way to do sanity
62    # check here.
63    # assert len(ordered_conns) == len(m_conns_set)
64
65    for i, x in enumerate(ordered_conns):
66      if x not in m_conns_set:
67        x = (x[1], x[0])
68        assert x in m_conns_set, "There is a connection missing from "\
69                                 "connect_order. Please contact PyMTL developers!"
70        ordered_conns[i] = x
71
72    connections = [ (gen_signal_expr(m, x[0]), gen_signal_expr(m, x[1])) for x in ordered_conns ]
73
74    m.set_metadata( c.connections, connections )
75