def _fill_enclosure(self, enclosure: Dict[RtlSignalBase, HdlStatement]) -> None: """ :attention: enclosure has to be discoverd first use _discover_enclosure() method """ select = [] outputs = self._outputs for e in enclosure.keys(): if e in outputs: select.append(e) for (_, stms), e in zip(self.cases, self._case_enclosed_for): fill_stm_list_with_enclosure(self, e, stms, select, enclosure) e.update(select) t = self.switchOn._dtype default_required = len(self.cases) < t.domain_size() if self.default is not None or default_required: self.default = fill_stm_list_with_enclosure( self, self._default_enclosed_for, self.default, select, enclosure) self._default_enclosed_for.update(select) self._enclosed_for.update(select)
def _fill_enclosure(self, enclosure: Dict[RtlSignalBase, Union[HValue, RtlSignalBase]]) -> None: enc = [] outputs = self._outputs for e in sorted(enclosure.keys(), key=RtlSignal_sort_key): if e in outputs and e not in self._enclosed_for: enc.append(e) if not enc: return fill_stm_list_with_enclosure(self, self._ifTrue_enclosed_for, self.ifTrue, enc, enclosure) for (_, stms), e in zip(self.elIfs, self._elIfs_enclosed_for): fill_stm_list_with_enclosure(self, e, stms, enc, enclosure) self.ifFalse = fill_stm_list_with_enclosure(self, self._ifFalse_enclosed_for, self.ifFalse, enc, enclosure) self._enclosed_for.update(enc)
def _statements_to_HWProcesses(_statements, tryToSolveCombLoops)\ -> Generator[HWProcess, None, None]: assert _statements # try to simplify statements proc_statements = [] for _stm in _statements: stms, _ = _stm._try_reduce() proc_statements.extend(stms) outputs = UniqList() _inputs = UniqList() sensitivity = UniqList() enclosed_for = set() for _stm in proc_statements: seen = set() _stm._discover_sensitivity(seen) _stm._discover_enclosure() outputs.extend(_stm._outputs) _inputs.extend(_stm._inputs) sensitivity.extend(_stm._sensitivity) enclosed_for.update(_stm._enclosed_for) enclosure_values = {} for sig in outputs: # inject nopVal if needed if sig._useNopVal: n = sig._nopVal enclosure_values[sig] = n if enclosure_values: do_enclose_for = list(where(outputs, lambda o: o in enclosure_values)) fill_stm_list_with_enclosure(None, enclosed_for, proc_statements, do_enclose_for, enclosure_values) if proc_statements: for o in outputs: assert not o.hidden, o seen = set() inputs = UniqList() for i in _inputs: inputs.extend(i._walk_public_drivers(seen)) intersect = outputs.intersection_set(sensitivity) if intersect: if not tryToSolveCombLoops: raise HwtSyntaxError( "Combinational loop on signal(s)", intersect) # try to solve combinational loops by separating drivers of signals # from statements for sig in intersect: proc_statements, proc_stms_select = cut_off_drivers_of( sig, proc_statements) yield from _statements_to_HWProcesses(proc_stms_select, False) if proc_statements: yield from _statements_to_HWProcesses(proc_statements, False) else: name = name_for_process(outputs) yield HWProcess("assig_process_" + name, proc_statements, sensitivity, inputs, outputs) else: assert not outputs # this can happen e.g. when If does not contains any Assignment pass
def _statements_to_HdlStatementBlocks(_statements, tryToSolveCombLoops)\ -> Generator[HdlStatementBlock, None, None]: assert _statements # try to simplify statements proc_statements = [] for _stm in _statements: _stm._clean_signal_meta() stms, _ = _stm._try_reduce() proc_statements.extend(stms) if not proc_statements: return outputs = UniqList() _inputs = UniqList() sensitivity = UniqList() enclosed_for = set() _proc_statements = [] for _stm in proc_statements: seen = set() _stm._discover_sensitivity(seen) _stm._discover_enclosure() if _stm._outputs: # remove a statement entirely if it has no ouput # (empty if statment or something similar) # simulation only processes should not be processed by this function # and process should always drive something, unless it is useless outputs.extend(_stm._outputs) _inputs.extend(_stm._inputs) sensitivity.extend(_stm._sensitivity) enclosed_for.update(_stm._enclosed_for) _proc_statements.append(_stm) proc_statements = _proc_statements if not proc_statements: # this can happen e.g. when If does not contains any Assignment return sensitivity_recompute = False enclosure_recompute = False enclosure_values = {} for sig in outputs: # inject nop_val if needed if sig._nop_val is not NO_NOPVAL and sig not in enclosed_for: enclosure_recompute = True n = sig._nop_val enclosure_values[sig] = n if not isinstance(n, Value): _inputs.append(n) sensitivity_recompute = True if enclosure_recompute: # we have some enclosure values, try fill missing code branches with # this values do_enclose_for = [o for o in outputs if o in enclosure_values] fill_stm_list_with_enclosure(None, enclosed_for, proc_statements, do_enclose_for, enclosure_values) if enclosure_recompute or sensitivity_recompute: for _stm in proc_statements: _stm._clean_signal_meta() seen = set() _stm._discover_sensitivity(seen) _stm._discover_enclosure() if sensitivity_recompute: sensitivity = UniqList() for _stm in proc_statements: sensitivity.extend(_stm._sensitivity) for o in outputs: assert not o.hidden, o seen = set() inputs = UniqList() for i in _inputs: inputs.extend(i._walk_public_drivers(seen)) intersect = outputs.intersection_set(sensitivity) if intersect: # there is a combinational loop inside a single process which # can not be solved by separation of statments in process if not tryToSolveCombLoops: raise HwtSyntaxError( "Combinational loop on signal(s)", intersect) # try to solve combinational loops by separating drivers of signals # from statements for sig in intersect: proc_statements, proc_stms_select = cut_off_drivers_of( sig, proc_statements) yield from _statements_to_HdlStatementBlocks(proc_stms_select, False) if proc_statements: yield from _statements_to_HdlStatementBlocks(proc_statements, False) else: # no combinational loops, wrap current statemetns to a process instance name = name_for_process(outputs) yield HdlStatementBlock("assig_process_" + name, proc_statements, sensitivity, inputs, outputs)