def _replace_child_statement(self, stm: HdlStatement, replacement: List[HdlStatement], update_io: bool) -> None: if update_io: raise NotImplementedError() for branch_list in (self.ifTrue, *(elif_stms for _, elif_stms in self.elIfs), self.ifFalse): if branch_list is None: continue try: i = branch_list.index(stm) except ValueError: # not in list continue self.rank -= stm.rank branch_list[i:i + 1] = replacement for rstm in replacement: rstm._set_parent_stm(self) # reset IO because it was shared with this statement stm._destroy() return raise ValueError("Statement", stm, "not found in ", self)
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 tryToMerge(procA: HdlStatementBlock, procB: HdlStatementBlock): """ Try merge procB into procA :raise IncompatibleStructure: if merge is not possible :attention: procA is now result if merge has succeed :return: procA which is now result of merge """ if (checkIfIsTooSimple(procA) or checkIfIsTooSimple(procB) or areSetsIntersets(procA._outputs, procB._sensitivity) or areSetsIntersets(procB._outputs, procA._sensitivity) or not HdlStatement._is_mergable_statement_list( procA.statements, procB.statements)): raise IncompatibleStructure() procA.statements = HdlStatement._merge_statement_lists( procA.statements, procB.statements) procA._outputs.extend(procB._outputs) procA._inputs.extend(procB._inputs) procA._sensitivity.extend(procB._sensitivity) return procA
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 _clean_signal_meta(self): self._sensitivity = None self._ifTrue_enclosed_for = None self._elIfs_enclosed_for = None self._ifFalse_enclosed_for = None HdlStatement._clean_signal_meta(self)
def _clean_signal_meta(self): self._case_enclosed_for = None self._default_enclosed_for = None HdlStatement._clean_signal_meta(self)
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