1#========================================================================= 2# StructuralTranslatorL1.py 3#========================================================================= 4# Author : Peitian Pan 5# Date : March 24, 2019 6"""Provide L1 structural translator.""" 7 8from collections import defaultdict, deque 9 10from pymtl3 import Placeholder 11from pymtl3.passes.rtlir import RTLIRDataType as rdt 12from pymtl3.passes.rtlir import RTLIRType as rt 13from pymtl3.passes.rtlir import StructuralRTLIRSignalExpr as sexp 14from pymtl3.passes.rtlir.structural.StructuralRTLIRGenL1Pass import ( 15 StructuralRTLIRGenL1Pass, 16) 17from pymtl3.passes.rtlir.util.utility import get_component_full_name 18 19from ..BaseRTLIRTranslator import BaseRTLIRTranslator, TranslatorMetadata 20 21 22def gen_connections( top ): 23 """Return a collections of all connections of each instance in the 24 hierarchy whose top is `top`. 25 """ 26 _inst_conns = defaultdict( set ) 27 28 nets = top.get_all_value_nets() 29 adjs = top.get_signal_adjacency_dict() 30 31 for writer, net in nets: 32 S = deque( [ writer ] ) 33 visited = { writer } 34 while S: 35 u = S.pop() 36 writer_host = u.get_host_component() 37 writer_host_parent = writer_host.get_parent_object() 38 for v in adjs[u]: 39 if v not in visited: 40 visited.add( v ) 41 S.append( v ) 42 reader_host = v.get_host_component() 43 reader_host_parent = reader_host.get_parent_object() 44 45 # Four possible cases for the reader and writer signals: 46 # 1. They have the same host component. Both need 47 # to be added to the host component. 48 # 2/3. One's host component is the parent of the other. 49 # Both need to be added to the parent component. 50 # 4. They have the same parent component. 51 # Both need to be added to the parent component. 52 53 if writer_host is reader_host: 54 _inst_conns[writer_host].add( ( u, v ) ) 55 elif writer_host_parent is reader_host: 56 _inst_conns[reader_host].add( ( u, v ) ) 57 elif writer_host is reader_host_parent: 58 _inst_conns[writer_host].add( ( u, v ) ) 59 elif writer_host_parent == reader_host_parent: 60 _inst_conns[writer_host_parent].add( ( u, v ) ) 61 else: 62 raise TypeError( "unexpected connection type!" ) 63 64 return _inst_conns 65 66class StructuralTranslatorL1( BaseRTLIRTranslator ): 67 def __init__( s, top ): 68 super().__init__( top ) 69 # To avoid doing redundant computation, we generate the connections of 70 # the entire hierarchy once and only once here. 71 s.inst_conns = gen_connections( top ) 72 73 def clear( s, tr_top ): 74 super().clear( tr_top ) 75 76 # Set dummy tr_cfgs for testing 77 if not hasattr( s, 'tr_cfgs' ): 78 s.tr_cfgs = None 79 80 # Metadata namespace for RTLIR structural translator and the backend 81 # structural translator 82 s.structural = TranslatorMetadata() 83 s.s_backend = TranslatorMetadata() 84 85 # Generate metadata 86 s.gen_structural_trans_metadata( tr_top ) 87 88 # Data type declaration 89 s.structural.decl_type_vector = {} 90 s.structural.decl_type_array = {} 91 92 #----------------------------------------------------------------------- 93 # gen_structural_trans_metadata 94 #----------------------------------------------------------------------- 95 96 def _get_structural_rtlir_gen_pass( s ): 97 return StructuralRTLIRGenL1Pass 98 99 def gen_structural_trans_metadata( s, tr_top ): 100 tr_top.apply( s._get_structural_rtlir_gen_pass()( s.inst_conns ) ) 101 s.structural.component_no_synthesis_no_clk = {} 102 s.structural.component_no_synthesis_no_reset = {} 103 s._gen_structural_no_clk_reset( tr_top ) 104 105 def _gen_structural_no_clk_reset( s, m ): 106 if s.tr_cfgs: 107 s.structural.component_no_synthesis_no_clk[m] = s.tr_cfgs[m].no_synthesis_no_clk 108 s.structural.component_no_synthesis_no_reset[m] = s.tr_cfgs[m].no_synthesis_no_reset 109 else: 110 s.structural.component_no_synthesis_no_clk[m] = False 111 s.structural.component_no_synthesis_no_reset[m] = False 112 for _m in m.get_child_components(repr): 113 s._gen_structural_no_clk_reset( _m ) 114 115 #----------------------------------------------------------------------- 116 # translate_structural 117 #----------------------------------------------------------------------- 118 119 def translate_structural( s, tr_top ): 120 """Translate structural part of top component under translation. 121 122 This function will only be called once during the whole translation 123 process. 124 """ 125 # Component metadata 126 s.structural.component_is_top = {} 127 s.structural.component_name = {} 128 s.structural.component_file_info = {} 129 s.structural.component_full_name = {} 130 s.structural.component_unique_name = {} 131 s.structural.component_explicit_module_name = {} 132 s.structural.component_no_synthesis = {} 133 134 # Declarations 135 s.structural.decl_ports = {} 136 s.structural.decl_wires = {} 137 s.structural.decl_consts = {} 138 139 # Placeholder 140 s.structural.placeholder_src = {} 141 142 # Connections 143 s.structural.connections = {} 144 s._translate_structural( tr_top ) 145 146 #----------------------------------------------------------------------- 147 # _translate_structural 148 #----------------------------------------------------------------------- 149 150 def _translate_structural( s, m ): 151 """Translate structural part of component m. 152 153 This method will be recursively applied to different components in the 154 hierarchy. 155 """ 156 m_rtype = m.get_metadata( StructuralRTLIRGenL1Pass.rtlir_type ) 157 s.structural.component_is_top[m] = m is s.tr_top 158 s.structural.component_name[m] = m_rtype.get_name() 159 s.structural.component_file_info[m] = m_rtype.get_file_info() 160 s.structural.component_full_name[m] = get_component_full_name(m_rtype) 161 s.structural.component_unique_name[m] = \ 162 s.rtlir_tr_component_unique_name(m_rtype) 163 if s.tr_cfgs: 164 s.structural.component_explicit_module_name[m] = s.tr_cfgs[m].explicit_module_name 165 else: 166 s.structural.component_explicit_module_name[m] = '' 167 if s.tr_cfgs: 168 s.structural.component_no_synthesis[m] = s.tr_cfgs[m].no_synthesis 169 else: 170 s.structural.component_no_synthesis[m] = False 171 172 # Translate declarations of signals 173 s.translate_decls( m ) 174 175 # Translate connections 176 s.translate_connections( m ) 177 178 # Grab the pickled external source generated by PlaceholderPass 179 s.get_placeholder_src( m ) 180 181 #----------------------------------------------------------------------- 182 # get_placeholder_src 183 #----------------------------------------------------------------------- 184 185 def get_placeholder_src( s, m ): 186 if isinstance( m, Placeholder ): 187 s.structural.placeholder_src[m] = s.rtlir_tr_placeholder_src( m ) 188 else: 189 s.structural.placeholder_src[m] = '' 190 191 #----------------------------------------------------------------------- 192 # translate_decls 193 #----------------------------------------------------------------------- 194 195 def translate_decls( s, m ): 196 m_rtype = m.get_metadata( StructuralRTLIRGenL1Pass.rtlir_type ) 197 198 # Ports 199 port_decls = [] 200 for port_id, rtype in m_rtype.get_ports_packed(): 201 if isinstance( rtype, rt.Array ): 202 array_type = rtype 203 port_rtype = rtype.get_sub_type() 204 else: 205 array_type = None 206 port_rtype = rtype 207 port_decls.append( 208 s.rtlir_tr_port_decl( 209 s.rtlir_tr_var_id( port_id ), 210 port_rtype, 211 s.rtlir_tr_unpacked_array_type( array_type ), 212 s.rtlir_data_type_translation( m, port_rtype.get_dtype() ) 213 ) ) 214 s.structural.decl_ports[m] = s.rtlir_tr_port_decls( port_decls ) 215 216 # Wires 217 wire_decls = [] 218 for wire_id, rtype in m_rtype.get_wires_packed(): 219 if isinstance( rtype, rt.Array ): 220 array_type = rtype 221 wire_rtype = rtype.get_sub_type() 222 else: 223 array_type = None 224 wire_rtype = rtype 225 wire_decls.append( 226 s.rtlir_tr_wire_decl( 227 s.rtlir_tr_var_id( wire_id ), 228 wire_rtype, 229 s.rtlir_tr_unpacked_array_type( array_type ), 230 s.rtlir_data_type_translation( m, wire_rtype.get_dtype() ) 231 ) ) 232 s.structural.decl_wires[m] = s.rtlir_tr_wire_decls( wire_decls ) 233 234 # Consts 235 const_decls = [] 236 if hasattr( s, "behavioral" ): 237 used_set = s.behavioral.accessed[m] 238 else: 239 used_set = None 240 241 for const_id, rtype, instance in m.get_metadata( StructuralRTLIRGenL1Pass.consts ): 242 if used_set is None or const_id in used_set: 243 if isinstance( rtype, rt.Array ): 244 array_type = rtype 245 const_rtype = rtype.get_sub_type() 246 else: 247 array_type = None 248 const_rtype = rtype 249 const_decls.append( 250 s.rtlir_tr_const_decl( 251 s.rtlir_tr_var_id( const_id ), 252 const_rtype, 253 s.rtlir_tr_unpacked_array_type( array_type ), 254 s.rtlir_data_type_translation( m, const_rtype.get_dtype() ), 255 instance 256 ) ) 257 s.structural.decl_consts[m] = s.rtlir_tr_const_decls( const_decls ) 258 259 #----------------------------------------------------------------------- 260 # translate_connections 261 #----------------------------------------------------------------------- 262 263 def translate_connections( s, m ): 264 connections = [] 265 _connections = m.get_metadata( StructuralRTLIRGenL1Pass.connections ) 266 for writer, reader in _connections: 267 connections.append( s.rtlir_tr_connection( 268 s.rtlir_signal_expr_translation( writer, m, 'writer' ), 269 s.rtlir_signal_expr_translation( reader, m, 'reader' ) 270 ) ) 271 s.structural.connections[m] = s.rtlir_tr_connections( connections ) 272 273 #----------------------------------------------------------------------- 274 # rtlir_data_type_translation 275 #----------------------------------------------------------------------- 276 277 def rtlir_data_type_translation( s, m, dtype ): 278 """Translate an RTLIR data type into its backend representation.""" 279 if isinstance( dtype, ( rdt.Vector, rdt.Bool ) ): 280 if isinstance( dtype, rdt.Bool ): 281 dtype = rdt.Vector( 1 ) 282 ret = s.rtlir_tr_vector_dtype( dtype ) 283 if dtype not in s.structural.decl_type_vector: 284 s.structural.decl_type_vector[ dtype ] = ret 285 return ret 286 287 else: 288 assert False, f"unsupported RTLIR dtype {dtype} at L1!" 289 290 #----------------------------------------------------------------------- 291 # rtlir_signal_expr_translation 292 #----------------------------------------------------------------------- 293 294 def rtlir_signal_expr_translation( s, expr, m, status = 'intermediate' ): 295 """Translate a signal expression in RTLIR into its backend representation. 296 297 Only the following operations are supported at L1: 298 sexp.CurComp, sexp.CurCompAttr, sexp.BitSelection, sexp.PartSelection, sexp.PortIndex, 299 sexp.WireIndex, sexp.ConstIndex 300 """ 301 if isinstance( expr, sexp.CurComp ): 302 comp_id, comp_rtype = expr.get_component_id(), expr.get_rtype() 303 return s.rtlir_tr_current_comp( comp_id, comp_rtype, status ) 304 305 elif isinstance( expr, sexp.CurCompAttr ): 306 return s.rtlir_tr_current_comp_attr( 307 s.rtlir_signal_expr_translation( expr.get_base(), m ), 308 expr.get_attr(), status ) 309 310 elif isinstance( expr, sexp.PortIndex ): 311 return s.rtlir_tr_port_array_index( 312 s.rtlir_signal_expr_translation( expr.get_base(), m ), 313 expr.get_index(), status ) 314 315 elif isinstance( expr, sexp.WireIndex ): 316 return s.rtlir_tr_wire_array_index( 317 s.rtlir_signal_expr_translation( expr.get_base(), m ), 318 expr.get_index(), status ) 319 320 elif isinstance( expr, sexp.ConstIndex ): 321 return s.rtlir_tr_const_array_index( 322 s.rtlir_signal_expr_translation( expr.get_base(), m ), 323 expr.get_index(), status ) 324 325 elif isinstance( expr, sexp.BitSelection ): 326 base = expr.get_base() 327 assert not isinstance(base, (sexp.PartSelection, sexp.BitSelection)), \ 328 f'bit selection {expr} over bit/part selection {base} is not allowed!' 329 return s.rtlir_tr_bit_selection( 330 s.rtlir_signal_expr_translation( expr.get_base(), m ), expr.get_index(), status ) 331 332 elif isinstance( expr, sexp.PartSelection ): 333 base = expr.get_base() 334 assert not isinstance(base, (sexp.PartSelection, sexp.BitSelection)), \ 335 f'part selection {expr} over bit/part selection {base} is not allowed!' 336 start, stop = expr.get_slice()[0], expr.get_slice()[1] 337 return s.rtlir_tr_part_selection( 338 s.rtlir_signal_expr_translation( expr.get_base(), m ), start, stop, status ) 339 340 elif isinstance( expr, sexp.ConstInstance ): 341 dtype = expr.get_rtype().get_dtype() 342 assert isinstance( dtype, rdt.Vector ), \ 343 f'{dtype} is not supported at L1!' 344 return s.rtlir_tr_literal_number( dtype.get_length(), expr.get_value() ) 345 346 # Other operations are not supported at L1 347 else: 348 assert False, f'{expr} is not supported at L1!' 349 350 #----------------------------------------------------------------------- 351 # Methods to be implemented by the backend translator 352 #----------------------------------------------------------------------- 353 354 # Placeholder 355 def rtlir_tr_placeholder_src( s, m ): 356 raise NotImplementedError() 357 358 # Data types 359 def rtlir_tr_vector_dtype( s, Type ): 360 raise NotImplementedError() 361 362 def rtlir_tr_unpacked_array_type( s, Type ): 363 raise NotImplementedError() 364 365 # Declarations 366 def rtlir_tr_port_decls( s, port_decls ): 367 raise NotImplementedError() 368 369 def rtlir_tr_port_decl( s, id_, rtype, array_type, dtype ): 370 raise NotImplementedError() 371 372 def rtlir_tr_wire_decls( s, wire_decls ): 373 raise NotImplementedError() 374 375 def rtlir_tr_wire_decl( s, id_, Type, array_type, dtype ): 376 raise NotImplementedError() 377 378 def rtlir_tr_const_decls( s, const_decls ): 379 raise NotImplementedError() 380 381 def rtlir_tr_const_decl( s, id_, Type, array_type, dtype, value ): 382 raise NotImplementedError() 383 384 # Connections 385 def rtlir_tr_connections( s, connections ): 386 raise NotImplementedError() 387 388 def rtlir_tr_connection( s, wr_signal, rd_signal ): 389 raise NotImplementedError() 390 391 # Signal operations 392 def rtlir_tr_bit_selection( s, base_signal, index, status ): 393 raise NotImplementedError() 394 395 def rtlir_tr_part_selection( s, base_signal, start, stop, status ): 396 raise NotImplementedError() 397 398 def rtlir_tr_port_array_index( s, base_signal, index, status ): 399 raise NotImplementedError() 400 401 def rtlir_tr_wire_array_index( s, base_signal, index, status ): 402 raise NotImplementedError() 403 404 def rtlir_tr_const_array_index( s, base_signal, index, status ): 405 raise NotImplementedError() 406 407 def rtlir_tr_current_comp_attr( s, base_signal, attr, status ): 408 raise NotImplementedError() 409 410 def rtlir_tr_current_comp( s, comp_id, comp_rtype, status ): 411 raise NotImplementedError() 412 413 # Miscs 414 def rtlir_tr_var_id( s, var_id ): 415 raise NotImplementedError() 416 417 def rtlir_tr_literal_number( s, nbits, value ): 418 raise NotImplementedError() 419 420 def rtlir_tr_component_unique_name( s, c_rtype ): 421 raise NotImplementedError() 422