1#=========================================================================
2# VStructuralTranslatorL2.py
3#=========================================================================
4"""Provide SystemVerilog structural translator implementation."""
5
6from textwrap import dedent
7
8from pymtl3.passes.backends.generic.structural.StructuralTranslatorL2 import (
9    StructuralTranslatorL2,
10)
11from pymtl3.passes.rtlir import RTLIRDataType as rdt
12
13from ...util.utility import make_indent, pretty_concat
14from .VStructuralTranslatorL1 import VStructuralTranslatorL1
15
16
17class VStructuralTranslatorL2(
18    VStructuralTranslatorL1, StructuralTranslatorL2 ):
19
20  #-----------------------------------------------------------------------
21  # Data types
22  #-----------------------------------------------------------------------
23
24  def rtlir_tr_packed_array_dtype( s, dtype ):
25    sub_dtype = dtype.get_sub_dtype()
26    if isinstance( sub_dtype, rdt.Vector ):
27      sub_dtype_tr = s.rtlir_tr_vector_dtype( sub_dtype )
28    elif isinstance( sub_dtype, rdt.Struct ):
29      sub_dtype_tr = s.rtlir_tr_struct_dtype( sub_dtype )
30    else:
31      assert False, f"unsupported data type {sub_dtype} in packed array!"
32    dim_str = "".join( f"[{size-1}:0]" for size in dtype.get_dim_sizes() )
33    return {
34      'def' : '',
35      'data_type' : f"{sub_dtype_tr['data_type']}",
36      'packed_type' : f"{dim_str}{sub_dtype_tr['packed_type']}",
37      'unpacked_type' : sub_dtype_tr['unpacked_type'],
38      'ndim' : dtype.get_dim_sizes(),
39      'raw_dtype' : dtype
40    }
41
42  def rtlir_tr_struct_dtype( s, dtype ):
43    dtype_name = dtype.get_name()
44    field_decls = []
45
46    for id_, _dtype in dtype.get_all_properties().items():
47
48      if isinstance( _dtype, rdt.Vector ):
49        tr = s.rtlir_tr_vector_dtype(_dtype)
50      elif isinstance( _dtype, rdt.PackedArray ):
51        tr = s.rtlir_tr_packed_array_dtype(_dtype)
52      elif isinstance( _dtype, rdt.Struct ):
53        tr = s.rtlir_tr_struct_dtype(_dtype)
54      else:
55        assert False, \
56          f'unrecoganized field type {_dtype} of struct {dtype_name}!'
57      field_decls.append(pretty_concat(tr['data_type'], tr['packed_type'], id_, ';'))
58
59    make_indent( field_decls, 1 )
60    field_decl = '\n'.join( field_decls )
61
62    return {
63      'def' : dedent("""\
64        typedef struct packed {{
65        {field_decl}
66        }} {dtype_name};
67        """).format(**locals()),
68      'nbits' : dtype.get_length(),
69      'data_type' : dtype_name,
70      'packed_type' : '',
71      'unpacked_type' : '',
72      'raw_dtype' : dtype
73    }
74
75  #-----------------------------------------------------------------------
76  # Declarations
77  #-----------------------------------------------------------------------
78
79  def gen_array_param( s, n_dim, dtype, array ):
80    if not n_dim and isinstance( dtype, rdt.Struct ):
81      return s.rtlir_tr_struct_instance( dtype, array )
82    else:
83      return super().gen_array_param( n_dim, dtype, array )
84
85  #-----------------------------------------------------------------------
86  # Signal oeprations
87  #-----------------------------------------------------------------------
88
89  def rtlir_tr_packed_index( s, base_signal, index, status ):
90    return s._rtlir_tr_process_unpacked(
91              f'{base_signal}[{index}]',
92              f'{base_signal}{{}}[{index}]',
93              status, ('status', 'unpacked') )
94
95  def rtlir_tr_struct_attr( s, base_signal, attr, status ):
96    return s._rtlir_tr_process_unpacked(
97              f'{base_signal}.{attr}',
98              f'{base_signal}{{}}.{attr}',
99              status, ('status', 'unpacked') )
100
101  def rtlir_tr_struct_instance( s, dtype, struct ):
102    def _gen_packed_array( dtype, n_dim, array ):
103      if not n_dim:
104        if isinstance( dtype, rdt.Vector ):
105          return s.rtlir_tr_literal_number( dtype.nbits, array )
106        elif isinstance( dtype, rdt.Struct ):
107          return s.rtlir_tr_struct_instance( dtype, array )
108        else:
109          assert False, f"unrecognized data type {dtype}!"
110      else:
111        ret = []
112        for i in reversed( range( n_dim[0]) ):
113          ret.append( _gen_packed_array( dtype, n_dim[1:], array[i] ) )
114        if n_dim[0] > 1:
115          cat_str = "{" + ", ".join( ret ) + "}"
116        else:
117          cat_str = ", ".join( ret )
118        return f"{{ {cat_str} }}"
119    ret = []
120    for name, Type in dtype.get_all_properties().items():
121      field = getattr( struct, name )
122      if isinstance( Type, rdt.Vector ):
123        _ret = s.rtlir_tr_literal_number( Type.nbits, field )
124      elif isinstance( Type, rdt.Struct ):
125        _ret = s.rtlir_tr_struct_instance( Type, field )
126      elif isinstance( Type, rdt.PackedArray ):
127        n_dim = Type.get_dim_sizes()
128        sub_dtype = Type.get_sub_dtype()
129        _ret = _gen_packed_array( sub_dtype, n_dim, field )
130      else:
131        assert False, f"unrecognized data type {Type}!"
132      ret.append( _ret )
133    return f"{{ {', '.join(ret)} }}"
134