def walk_assignments(stm: HdlStatement, dst: RtlSignal)\ ->Generator[Assignment, None, None]: if isinstance(stm, Assignment): if dst is stm.dst: yield stm else: for _stm in stm._iter_stms(): yield from walk_assignments(_stm, dst)
def _count_mux_inputs_for_outputs(stm: HdlStatement, cnt): if isinstance(stm, Assignment): cnt[stm.dst] += 1 else: for _stm in stm._iter_stms(): if isinstance(_stm, Assignment): cnt[_stm.dst] += 1 else: _count_mux_inputs_for_outputs(_stm, cnt)
def walkInputsForSpecificOutput(output_sig: RtlSignalBase, stm: HdlStatement): if output_sig not in stm._outputs: return if isinstance(stm, Assignment): assert stm.dst is output_sig yield from stm._inputs elif isinstance(stm, IfContainer): yield stm.cond for c, _ in stm.elIfs: yield c for _stm in stm._iter_stms(): yield from walkInputsForSpecificOutput(output_sig, _stm) elif isinstance(stm, SwitchContainer): yield stm.switchOn for _stm in stm._iter_stms(): yield from walkInputsForSpecificOutput(output_sig, _stm) else: raise NotImplementedError(stm)
def find_independent_slice_drivers(stm: HdlStatement): if isinstance(stm, Assignment): if stm.indexes and len(stm.indexes) == 1 and isinstance( stm.dst._dtype, Bits): dst = stm.dst for i in stm.indexes: if not isConst(i): return can_directly_replace_with_src_expr = stm.parentStm is None yield (dst, tuple(stm.indexes), can_directly_replace_with_src_expr, stm.src if can_directly_replace_with_src_expr else None) else: for _stm in stm._iter_stms(): yield from find_independent_slice_drivers(_stm)
def extract_part_drivers_stm(stm: HdlStatement, signal_parts: Dict[RtlSignal, List[Tuple[RtlSignal, List[HValue]]]]): if isinstance(stm, Assignment): if stm.indexes and len(stm.indexes) == 1: dst = stm.dst parts = signal_parts.get(dst, None) if parts is None: return False indexes = _format_indexes(stm.indexes) new_dsts, do_remove_stm = parts[indexes] if isinstance(new_dsts, list): assert len(new_dsts) > 1, (dst, new_dsts, stm) assert not do_remove_stm, (dst, new_dsts, stm) # the driven slice was split to multiple sub slices replacement = [] dst_offset = new_dsts[0][-1][1] for i in new_dsts: new_dst = parts[i][0] new_src = stm.src for _i in i: high, low = _i[0] - dst_offset, _i[1] - dst_offset assert high > 0 and low >= 0, dst_offset assert high > low, (dst, stm, (high, low)) new_src = new_src[high:low] a = new_dst(new_src) replacement.append(a) # it has to hav parent statement because it needs to be nested # because otherwise it would not have some overlapping parts driven diferently # inder some condition stm.parentStm._replace_child_statement(stm, replacement, False) elif do_remove_stm: # remove current assignment because we are using src directly assert stm.parentStm is None, stm stm._destroy() else: # rewrite the Assignment instance to use new dst replacement = [ new_dsts(stm.src), ] stm.parentStm._replace_child_statement(stm, replacement, False) return True elif isinstance(stm, (IfContainer, SwitchContainer, HdlStatementBlock)): modified = False for _stm in stm._iter_stms(): modified |= extract_part_drivers_stm(_stm, signal_parts) if modified: assert not stm._enclosed_for, "_enclosed_for is expected not to be initialized yet" outputs = stm._outputs inputs = stm._inputs stm._outputs = UniqList() stm._inputs = UniqList() stm._collect_io() if stm.parentStm is None: for o in outputs: if o not in stm._outputs: o.drivers.remove(stm) for i in inputs: if i not in stm._inputs: i.endpoints.remove(stm) return True else: raise NotImplementedError("Unknown statement ", stm) return False