1#========================================================================= 2# VStructuralTranslatorL1.py 3#========================================================================= 4"""Provide SystemVerilog structural translator implementation.""" 5 6 7from pymtl3.datatypes import Bits 8from pymtl3.passes.backends.generic.structural.StructuralTranslatorL1 import ( 9 StructuralTranslatorL1, 10) 11from pymtl3.passes.rtlir import RTLIRDataType as rdt 12from pymtl3.passes.rtlir import RTLIRType as rt 13 14from ...errors import VerilogPlaceholderError, VerilogReservedKeywordError 15from ...util.utility import get_component_unique_name, make_indent, pretty_concat 16 17 18class VStructuralTranslatorL1( StructuralTranslatorL1 ): 19 20 def check_decl( s, name, msg ): 21 if s.is_verilog_reserved( name ): 22 raise VerilogReservedKeywordError( name, msg ) 23 24 #----------------------------------------------------------------------- 25 # Placeholder 26 #----------------------------------------------------------------------- 27 28 def rtlir_tr_placeholder_src( s, m ): 29 try: 30 ph_cfg = m.get_metadata( s._placeholder_pass.placeholder_config ) 31 if m is s.tr_top: 32 # If this placeholder is a top level module, use the wrapper 33 # template to support explicit module name. 34 if s.tr_cfgs and s.tr_cfgs[m].explicit_module_name: 35 module_name = s.tr_cfgs[m].explicit_module_name 36 else: 37 module_name = ph_cfg.pickled_top_module 38 s._mangled_placeholder_top_module_name = module_name 39 40 if module_name == ph_cfg.top_module: 41 raise VerilogPlaceholderError(m, 42 f"failed to create wrapper for the given object because the same " 43 f"name {module_name} is used for both the Verilog top module and " 44 f"the wrapper. Please specify a different name through the " 45 f"`explicit_module_name` option of TranslationConfigs.") 46 47 # Read the dependency of the placeholder 48 nlines = ph_cfg.pickled_wrapper_nlines 49 dependency = '\n'.join( ph_cfg.pickled_source.splitlines()[:-nlines] ) 50 51 # Create the placeholder wrapper from the ph_cfg metadata 52 wrapper = ph_cfg.pickled_wrapper_template.format(top_module_name=module_name) 53 54 return dependency + wrapper 55 56 else: 57 # Otherwise use the pickled placeholder source 58 return ph_cfg.pickled_source 59 except (AttributeError, OSError): 60 # Forgot to apply VerilogPlaceholderPass? 61 raise Exception( 62 f"error while translating placeholder {m}:\n" 63 f"- Did you forget to apply the correct PlaceholderPass(e.g. VerilogPlaceholderPass)?" ) 64 65 #----------------------------------------------------------------------- 66 # Data types 67 #----------------------------------------------------------------------- 68 69 def rtlir_tr_vector_dtype( s, dtype ): 70 msb = dtype.get_length() - 1 71 return { 72 'def' : '', 73 'nbits' : dtype.get_length(), 74 'data_type' : 'logic', 75 'packed_type' : f'[{msb}:0]', 76 'unpacked_type' : '', 77 'raw_dtype' : dtype 78 } 79 80 def rtlir_tr_unpacked_array_type( s, Type ): 81 if Type is None: 82 return { 'def' : '', 'unpacked_type' : '', 'n_dim':[] } 83 else: 84 array_dim = "".join( f"[0:{size-1}]" for size in Type.get_dim_sizes() ) 85 return { 86 'def' : '', 87 'unpacked_type' : array_dim, 88 'n_dim' : Type.get_dim_sizes() 89 } 90 91 #----------------------------------------------------------------------- 92 # Declarations 93 #----------------------------------------------------------------------- 94 95 def rtlir_tr_port_decls( s, port_decls ): 96 make_indent( port_decls, 1 ) 97 return ',\n'.join( port_decls ) 98 99 def rtlir_tr_port_decl( s, id_, Type, array_type, dtype ): 100 _dtype = Type.get_dtype() 101 direction = Type.get_direction() 102 if direction == 'input': 103 direction += ' ' 104 if array_type: 105 template = "Note: port {id_} has data type {_dtype}" 106 else: 107 n_dim = array_type['n_dim'] 108 template = "Note: {n_dim} array of ports {id_} has data type {_dtype}" 109 s.check_decl( id_, template.format( **locals() ) ) 110 return pretty_concat( direction, dtype['data_type'], dtype['packed_type'], 111 id_, array_type['unpacked_type'] ) 112 113 def rtlir_tr_wire_decls( s, wire_decls ): 114 make_indent( wire_decls, 1 ) 115 return '\n'.join( wire_decls ) 116 117 def rtlir_tr_wire_decl( s, id_, Type, array_type, dtype ): 118 _dtype = Type.get_dtype() 119 if array_type: 120 template = "Note: wire {id_} has data type {_dtype}" 121 else: 122 n_dim = array_type['n_dim'] 123 template = "Note: {n_dim} array of wires {id_} has data type {_dtype}" 124 s.check_decl( id_, template.format( **locals() ) ) 125 return pretty_concat( dtype['data_type'], dtype['packed_type'], 126 id_, array_type['unpacked_type'], ';' ) 127 128 def rtlir_tr_const_decls( s, const_decls ): 129 make_indent( const_decls, 1 ) 130 return '\n'.join( const_decls ) 131 132 def gen_array_param( s, n_dim, dtype, array ): 133 if not n_dim: 134 if isinstance( dtype, rdt.Vector ): 135 return s._literal_number( dtype.get_length(), array ) 136 else: 137 assert False, f'{array} is not an integer or a BitStruct!' 138 else: 139 ret = [] 140 for _idx, idx in enumerate( range( n_dim[0] ) ): 141 ret.append( s.gen_array_param( n_dim[1:], dtype, array[idx] ) ) 142 return f"'{{ {', '.join(ret)} }}" 143 144 def rtlir_tr_const_decl( s, id_, Type, array_type, dtype, value ): 145 _dtype = Type.get_dtype() 146 if array_type: 147 template = "Note: constant {id_} has data type {_dtype}" 148 else: 149 n_dim = array_type['n_dim'] 150 template = "Note: {n_dim} array of constants {id_} has data type {_dtype}" 151 s.check_decl( id_, template.format( **locals() ) ) 152 _dtype = pretty_concat(dtype['data_type'], dtype['packed_type'], id_, array_type['unpacked_type']) 153 _value = s.gen_array_param( array_type['n_dim'], dtype['raw_dtype'], value ) 154 155 return f'localparam {_dtype} = {_value};' 156 157 #----------------------------------------------------------------------- 158 # Connections 159 #----------------------------------------------------------------------- 160 161 def rtlir_tr_connections( s, connections ): 162 make_indent( connections, 1 ) 163 return '\n'.join( connections ) 164 165 def rtlir_tr_connection( s, wr_signal, rd_signal ): 166 return f'assign {rd_signal} = {wr_signal};' 167 168 #----------------------------------------------------------------------- 169 # Signal operations 170 #----------------------------------------------------------------------- 171 172 def rtlir_tr_bit_selection( s, base_signal, index, status ): 173 # Bit selection 174 return s._rtlir_tr_process_unpacked( 175 f'{base_signal}[{index}]', 176 f'{base_signal}{{}}[{index}]', 177 status, ('status', 'unpacked') ) 178 179 def rtlir_tr_part_selection( s, base_signal, start, stop, status ): 180 # Part selection 181 return s._rtlir_tr_process_unpacked( 182 f'{base_signal}[{stop-1}:{start}]', 183 f'{base_signal}{{}}[{stop-1}:{start}]', 184 status, ('status', 'unpacked') ) 185 186 def rtlir_tr_port_array_index( s, base_signal, index, status ): 187 return s._rtlir_tr_process_unpacked( 188 f'{base_signal}[{index}]', 189 f'{base_signal}{{}}[{index}]', 190 status, ('status', 'unpacked') ) 191 192 def rtlir_tr_wire_array_index( s, base_signal, index, status ): 193 return f'{base_signal}[{index}]' 194 195 def rtlir_tr_const_array_index( s, base_signal, index, status ): 196 return f'{base_signal}[{index}]' 197 198 def rtlir_tr_current_comp_attr( s, base_signal, attr, status ): 199 return f'{attr}' 200 201 def rtlir_tr_current_comp( s, comp_id, comp_rtype, status ): 202 return '' 203 204 def _rtlir_tr_process_unpacked( s, signal, signal_tplt, status, enable ): 205 if (status in ('reader', 'writer') and 'status' in enable) or \ 206 (s._rtlir_tr_unpacked_q and 'unpacked' in enable): 207 ret = signal_tplt.format(''.join( 208 [f'[{i}]' for i in list(s._rtlir_tr_unpacked_q)])) 209 s._rtlir_tr_unpacked_q.clear() 210 return ret 211 else: 212 return signal 213 214 #----------------------------------------------------------------------- 215 # Miscs 216 #----------------------------------------------------------------------- 217 218 def rtlir_tr_var_id( s, var_id ): 219 return var_id.replace( '[', '__' ).replace( ']', '' ) 220 221 def _literal_number( s, nbits, value ): 222 return f"{nbits}'d{int(value)}" 223 224 def rtlir_tr_literal_number( s, nbits, value ): 225 return s._literal_number( nbits, value ) 226 227 def rtlir_tr_component_unique_name( s, c_rtype ): 228 return get_component_unique_name( c_rtype ) 229