def ternaryOpsToIf(statements): """Convert all ternary operators to IfContainers""" stms = [] for st in statements: if isinstance(st, Assignment): try: if not isinstance(st.src, RtlSignalBase): raise DoesNotContainsTernary() d = st.src.singleDriver() if not isinstance(d, Operator) or d.operator != AllOps.TERNARY: raise DoesNotContainsTernary() else: ops = d.operands ifc = IfContainer(ops[0], [Assignment(ops[1], st.dst)], [Assignment(ops[2], st.dst)] ) stms.append(ifc) continue except (MultipleDriversErr, DoesNotContainsTernary): pass except NoDriverErr: assert (hasattr(st.src, "_interface") and st.src._interface is not None)\ or st.src.defVal.vldMask, st.src stms.append(st) return stms
def _operand(cls, operand: Union[RtlSignal, Value], operator: OpDefinition, ctx: SerializerCtx): try: isTernaryOp = operand.hidden and operand.drivers[ 0].operator == AllOps.TERNARY except (AttributeError, IndexError): isTernaryOp = False if isTernaryOp: # rewrite ternary operator as if o = ctx.createTmpVarFn("tmpTernary", operand._dtype) cond, ifTrue, ifFalse = operand.drivers[0].operands if_ = If(cond) if_.ifTrue.append( Assignment(ifTrue, o, virtualOnly=True, parentStm=if_)) if_.ifFalse = [] if_.ifFalse.append( Assignment(ifFalse, o, virtualOnly=True, parentStm=if_)) if_._outputs.append(o) for obj in (cond, ifTrue, ifFalse): if isinstance(obj, RtlSignalBase): if_._inputs.append(obj) o.drivers.append(if_) operand = o s = cls.asHdl(operand, ctx) if isinstance(operand, RtlSignalBase): try: o = operand.singleDriver() if o.operator != operator and\ cls.opPrecedence[o.operator] <= cls.opPrecedence[operator]: return "(%s)" % s except Exception: pass return s
def _as_Bits(self, val: Union[RtlSignal, Value]): if val._dtype == BOOL: bit1_t = Bits(1) o = self.createTmpVarFn("tmpBool2std_logic_", bit1_t) ifTrue, ifFalse = bit1_t.from_py(1), bit1_t.from_py(0) if_ = If(val) if_.ifTrue.append(Assignment(ifTrue, o, virtual_only=True, parentStm=if_)) if_.ifFalse = [] if_.ifFalse.append(Assignment(ifFalse, o, virtual_only=True, parentStm=if_)) if_._outputs.append(o) o.drivers.append(if_) return o else: assert isinstance(val._dtype, Bits), val._dtype return val
def __call__(self, source) -> Assignment: """ Create assignment to this signal :attention: it is not call of function it is operator of assignment :return: list of assignments """ if isinstance(source, InterfaceBase): assert source._isAccessible source = source._sig if source is None: source = self._dtype.from_py(None) else: source = toHVal(source, suggestedType=self._dtype) err = False try: source = source._auto_cast(self._dtype) except TypeConversionErr: err = True if err: raise TypeConversionErr( ("Can not connect %r (of type %r) to %r " "(of type %r) due type incompatibility") % (source, source._dtype, self, self._dtype)) tmp = self._getIndexCascade() if tmp: mainSig, indexCascade = tmp self = mainSig else: indexCascade = None # self = self._tryMyIndexToEndpoint() return Assignment(source, self, indexCascade)
def as_hdl_Operator(self, op: Operator): ops = op.operands o = op.operator if o == AllOps.INDEX: assert len(ops) == 2 o0, o1 = ops if o1._dtype == SLICE: # index to .range(x, y) o0_hdl = self.as_hdl_operand(o0, 0, op) o0_hdl = hdl_getattr(o0_hdl, "range") return hdl_call(o0_hdl, [self.as_hdl_Value(o1.val.start), self.as_hdl_Value(o1.val.stop)]) else: return ToHdlAstVerilog_ops.as_hdl_Operator(self, op) elif o in ToHdlAstHwt_ops._cast_ops: assert len(ops) == 1, ops t = self.as_hdl_HdlType(op.result._dtype) return hdl_call( HdlOp(HdlOpType.PARAMETRIZATION, [self.static_cast, t]), [self.as_hdl_Value(ops[0]), ]) elif o == AllOps.CONCAT: isNew, o = self.tmpVars.create_var_cached("tmpConcat_", op.result._dtype, postponed_init=True, extra_args=(AllOps.CONCAT, op.result)) if isNew: o.drivers.append(Assignment(op, o, virtual_only=True)) self.tmpVars.finish_var_init(o) return self.as_hdl(o) else: return ToHdlAstVerilog_ops.as_hdl_Operator(self, op)
def HWProcess(cls, proc, ctx): """ Serialize HWProcess objects """ body = proc.statements extraVars = [] extraVarsSerialized = [] hasToBeVhdlProcess = extraVars or\ arr_any(body, lambda x: isinstance(x, (IfContainer, SwitchContainer, WhileContainer, WaitStm)) or (isinstance(x, Assignment) and x.indexes)) anyIsEventDependnt = arr_any( proc.sensitivityList, lambda s: isinstance(s, Operator)) sensitivityList = sorted( map(lambda s: cls.sensitivityListItem(s, ctx, anyIsEventDependnt), proc.sensitivityList)) if hasToBeVhdlProcess: childCtx = ctx.withIndent() else: childCtx = ctx def createTmpVarFn(suggestedName, dtype): # [TODO] it is better to use RtlSignal s = SignalItem(None, dtype, virtualOnly=True) s.name = childCtx.scope.checkedName(suggestedName, s) s.hidden = False serializedS = cls.SignalItem(s, childCtx, declaration=True) extraVars.append(s) extraVarsSerialized.append(serializedS) return s childCtx.createTmpVarFn = createTmpVarFn statemets = [cls.asHdl(s, childCtx) for s in body] if hasToBeVhdlProcess: proc.name = ctx.scope.checkedName(proc.name, proc) extraVarsInit = [] for s in extraVars: a = Assignment(s.defVal, s, virtualOnly=True) extraVarsInit.append(cls.Assignment(a, childCtx)) return cls.processTmpl.render( indent=getIndent(ctx.indent), name=proc.name, hasToBeVhdlProcess=hasToBeVhdlProcess, extraVars=extraVarsSerialized, sensitivityList=" or ".join(sensitivityList), statements=extraVarsInit + statemets )
def IfContainer(cls, ifc: IfContainer, ctx: SerializerCtx): cond = cls.condAsHdl(ifc.cond, ctx) ifTrue = ifc.ifTrue if ifc.elIfs: # replace elifs with nested if statements ifFalse = [] topIf = IfContainer(ifc.cond, ifc.ifTrue, ifFalse) topIf._inputs = ifc._inputs topIf._outputs = ifc._outputs topIf._sensitivity = ifc._sensitivity for c, stms in ifc.elIfs: _ifFalse = [] lastIf = IfContainer(c, stms, _ifFalse) lastIf._inputs = ifc._inputs lastIf._outputs = ifc._outputs lastIf._sensitivity = ifc._sensitivity ifFalse.append(lastIf) ifFalse = _ifFalse if ifc.ifFalse is None: lastIf.ifFalse = [] else: lastIf.ifFalse = ifc.ifFalse return cls.IfContainer(topIf, ctx) else: ifFalse = ifc.ifFalse if ifFalse is None: ifFalse = [] childCtx = ctx.withIndent() outputInvalidateStms = [] for o in ifc._outputs: # [TODO] look up indexes indexes = None oa = Assignment(o._dtype.from_py(None), o, indexes, virtual_only=True, parentStm=ifc, is_completly_event_dependent=ifc. _is_completly_event_dependent) outputInvalidateStms.append(cls.stmAsHdl(oa, childCtx)) return ifTmpl.render( indent=getIndent(ctx.indent), indentNum=ctx.indent, cond=cond, outputInvalidateStms=outputInvalidateStms, ifTrue=tuple( map(lambda obj: cls.stmAsHdl(obj, childCtx), ifTrue)), ifFalse=tuple( map(lambda obj: cls.stmAsHdl(obj, childCtx), ifFalse)))
def _tmp_var_for_ternary(self, val: RtlSignal): """ Optionaly convert boolean to std_logic_vector """ o = self.createTmpVarFn("tmpTernary_", val._dtype) cond, ifTrue, ifFalse = val.drivers[0].operands if_ = If(cond) if_.ifTrue.append( Assignment(ifTrue, o, virtual_only=True, parentStm=if_)) if_.ifFalse = [] if_.ifFalse.append( Assignment(ifFalse, o, virtual_only=True, parentStm=if_)) if_._outputs.append(o) for obj in (cond, ifTrue, ifFalse): if isinstance(obj, RtlSignalBase): if_._inputs.append(obj) o.drivers.append(if_) return o
def fill_stm_list_with_enclosure(parentStm: Optional[HdlStatement], current_enclosure: Set[RtlSignalBase], statements: List["HdlStatement"], do_enclose_for: List[RtlSignalBase], enclosure: Dict[RtlSignalBase, Union[HValue, RtlSignalBase]])\ -> None: """ Apply enclosure on list of statements (fill all unused code branches with assignments from value specified by enclosure) :param parentStm: optional parent statement where this list is some branch :param current_enclosure: list of signals for which this statement list is enclosed :param statements: list of statements :param do_enclose_for: selected signals for which enclosure should be used :param enclosure: enclosure values for signals :attention: original statements parameter can be modified :return: new statements """ if statements is None: statements = [] for e_sig in do_enclose_for: if e_sig in current_enclosure: continue enclosed = False for stm in statements: if e_sig in stm._outputs: if e_sig not in stm._enclosed_for: stm._fill_enclosure(enclosure) enclosed = True break # any statement was not related with this signal, if not enclosed: e = enclosure[e_sig] a = Assignment(e, e_sig) statements.append(a) if parentStm is not None: a._set_parent_stm(parentStm) return statements
def as_hdl_extraVarsInit(self, extraVars): extraVarsInit = [] for s in extraVars: if isinstance(s.def_val, RtlSignalBase) or s.def_val.vld_mask: a = Assignment(s.def_val, s, virtual_only=True) extraVarsInit.append(self.as_hdl_Assignment(a)) else: assert s.drivers, s for d in s.drivers: extraVarsInit.append(self.as_hdl(d)) return extraVarsInit
def HWProcess(cls, proc: HWProcess, ctx): """ Serialize HWProcess objects """ body = proc.statements extraVars = [] extraVarsSerialized = [] anyIsEventDependnt = arr_any( proc.sensitivityList, lambda s: isinstance(s, Operator)) sensitivityList = sorted( map(lambda s: cls.sensitivityListItem(s, ctx, anyIsEventDependnt), proc.sensitivityList)) hasToBeProcess = arr_any( proc.outputs, lambda x: verilogTypeOfSig(x) == SIGNAL_TYPE.REG ) if hasToBeProcess: childCtx = ctx.withIndent() else: childCtx = ctx def createTmpVarFn(suggestedName, dtype): s = RtlSignal(None, None, dtype, virtual_only=True) s.name = childCtx.scope.checkedName(suggestedName, s) s.hidden = False serializedS = cls.SignalItem(s, childCtx, declaration=True) extraVars.append(s) extraVarsSerialized.append(serializedS) return s childCtx.createTmpVarFn = createTmpVarFn statemets = [cls.asHdl(s, childCtx) for s in body] if hasToBeProcess: proc.name = ctx.scope.checkedName(proc.name, proc) extraVarsInit = [] for s in extraVars: a = Assignment(s.def_val, s, virtual_only=True) extraVarsInit.append(cls.Assignment(a, childCtx)) return cls.processTmpl.render( indent=getIndent(ctx.indent), name=proc.name, hasToBeProcess=hasToBeProcess, extraVars=extraVarsSerialized, sensitivityList=" or ".join(sensitivityList), statements=extraVarsInit + statemets )
def _as_Bits_vec(self, val: Union[RtlSignal, Value]): val = self._as_Bits(val) t = val._dtype if not t.force_vector and t.bit_length() == 1: # std_logic -> std_logic_vector std_logic_vector = Bits(1, signed=t.signed, force_vector=True) o = self.createTmpVarFn("tmp_std_logic2vector_", std_logic_vector) o.drivers.append(Assignment(val, o, virtual_only=True)) return o else: # already a std_logic_vector return val
def __call__( self, source, dst_resolve_fn=lambda x: x._getDestinationSignalForAssignmentToThis() ) -> Assignment: """ Create assignment to this signal :attention: it is not call of function it is operator of assignment :return: list of assignments """ assert not self._const, self if isinstance(source, InterfaceBase): assert source._isAccessible, ( source, "must be a Signal Interface which is accessible in current scope" ) source = source._sig try: requires_type_check = False if source is None: source = self._dtype.from_py(None) else: requires_type_check = True source = toHVal(source, suggestedType=self._dtype) except Exception as e: # simplification of previous exception traceback e_simplified = copy(e) raise e_simplified if requires_type_check: err = False try: source = source._auto_cast(self._dtype) except TypeConversionErr: err = True if err: raise TypeConversionErr( ("Can not connect %r (of type %r) to %r " "(of type %r) due type incompatibility") % (source, source._dtype, self, self._dtype)) try: mainSig, indexCascade = self._getIndexCascade() mainSig = dst_resolve_fn(mainSig) return Assignment(source, mainSig, indexCascade) except Exception as e: # simplification of previous exception traceback e_simplified = copy(e) raise e_simplified
def finish_var_init(self, var: RtlSignal): hdl = self.extraVarsHdl if isinstance(var.def_val, RtlSignalBase) or var.def_val.vld_mask: a = Assignment(var.def_val, var, virtual_only=True) hdl.append(self.toHdlAst.as_hdl_Assignment(a)) else: assert var._const or var.drivers, (var, var.def_val) as_hdl = self.toHdlAst.as_hdl_SignalItem(var, declaration=True) for d in var.drivers: hdl.append(self.toHdlAst.as_hdl(d)) hdl.append(as_hdl)
def __call__(self, source): """ assign to signal which is next value of this register :return: list of assignments """ if isinstance(source, InterfaceBase): source = source._sig if source is None: source = self._dtype.from_py(None) else: source = toHVal(source) source = source._auto_cast(self._dtype) a = Assignment(source, self.next) return [a, ]
def as_hdl_IfContainer_out_invalidate_section(self, outputs: List[RtlSignalBase], parent: IfContainer): outputInvalidateStms = [] for o in outputs: # [TODO] look up indexes indexes = None v = o._dtype.from_py(None) oa = Assignment(v, o, indexes, virtual_only=True, parentStm=parent, is_completly_event_dependent=parent._is_completly_event_dependent) outputInvalidateStms.append(self.as_hdl_Assignment(oa)) if len(outputInvalidateStms) == 1: return outputInvalidateStms[0] else: b = HdlStmBlock() b.body = outputInvalidateStms return b
def as_hdl_Assignment(self, a: Assignment): blocking = False ver_sig_t = verilogTypeOfSig(a.dst) if ver_sig_t in (SIGNAL_TYPE.REG, SIGNAL_TYPE.PORT_REG): evDep = False for driver in a.dst.drivers: if driver._now_is_event_dependent: evDep = True break if not evDep or a.dst.virtual_only: blocking = True elif ver_sig_t in (SIGNAL_TYPE.WIRE, SIGNAL_TYPE.PORT_WIRE): blocking = True else: raise ValueError(ver_sig_t) a = super(ToHdlAstVerilog_statements, self).as_hdl_Assignment(a) a.is_blocking = blocking return a
def __call__(self, source, dst_resolve_fn=lambda x: x. _getDestinationSignalForAssignmentToThis(), exclude=None, fit=False) -> Assignment: """ Create assignment to this signal :attention: it is not call of function it is operator of assignment :return: list of assignments """ assert not self._const, self if exclude is not None and (self in exclude or source in exclude): return [] if self.hidden: try: d = self.singleDriver() except: d = None operator = getattr(d, "operator", None) if operator is not None: assert operator.allowsAssignTo, ( "Assignment to", self, "is not allowed by operator definition") if isinstance(source, InterfaceBase): assert source._isAccessible, ( source, "must be a Signal Interface which is accessible in current scope" ) source = source._sig try: if source is None: requires_type_check = False source = self._dtype.from_py(None) else: requires_type_check = True source = toHVal(source, suggestedType=self._dtype) except Exception as e: # simplification of previous exception traceback e_simplified = copy(e) raise e_simplified if requires_type_check: err = False try: if fit: source = fitTo_t(source, self._dtype) source = source._auto_cast(self._dtype) except TypeConversionErr: err = True if err: raise TypeConversionErr( ("Can not connect %r (of type %r) to %r " "(of type %r) due type incompatibility") % (source, source._dtype, self, self._dtype)) try: mainSig, indexCascade = self._getIndexCascade() mainSig = dst_resolve_fn(mainSig) return Assignment(source, mainSig, indexCascade) except Exception as e: # simplification of previous exception traceback e_simplified = copy(e) raise e_simplified
def HWProcess(cls, proc, ctx): """ Serialize HWProcess objects as VHDL :param scope: name scope to prevent name collisions """ body = proc.statements extraVars = [] extraVarsSerialized = [] hasToBeVhdlProcess = arr_any(body, lambda x: isinstance(x, (IfContainer, SwitchContainer, WhileContainer, WaitStm))) sensitivityList = sorted( map(lambda s: cls.sensitivityListItem(s, ctx), proc.sensitivityList)) if hasToBeVhdlProcess: childCtx = ctx.withIndent() else: childCtx = copy(ctx) def createTmpVarFn(suggestedName, dtype): s = RtlSignal(None, None, dtype, virtualOnly=True) s.name = ctx.scope.checkedName(suggestedName, s) s.hidden = False serializedS = cls.SignalItem(s, childCtx, declaration=True) extraVars.append(s) extraVarsSerialized.append(serializedS) return s childCtx.createTmpVarFn = createTmpVarFn statemets = [cls.asHdl(s, childCtx) for s in body] proc.name = ctx.scope.checkedName(proc.name, proc) extraVarsInit = [] for s in extraVars: if isinstance(s.defVal, RtlSignalBase) or s.defVal.vldMask: a = Assignment(s.defVal, s, virtualOnly=True) extraVarsInit.append(cls.Assignment(a, childCtx)) else: assert s.drivers, s for d in s.drivers: extraVarsInit.append(cls.asHdl(d, childCtx)) _hasToBeVhdlProcess = hasToBeVhdlProcess hasToBeVhdlProcess = extraVars or hasToBeVhdlProcess if hasToBeVhdlProcess and not _hasToBeVhdlProcess: # add indent because we did not added it before because we did not # know t oneIndent = getIndent(1) statemets = list(map(lambda x: oneIndent + x, statemets)) return cls.processTmpl.render( indent=getIndent(ctx.indent), name=proc.name, hasToBeVhdlProcess=hasToBeVhdlProcess, extraVars=extraVarsSerialized, sensitivityList=", ".join(sensitivityList), statements=extraVarsInit + statemets )