Beispiel #1
0
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
Beispiel #2
0
    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
Beispiel #3
0
 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
Beispiel #4
0
    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)
Beispiel #5
0
    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)
Beispiel #6
0
    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
        )
Beispiel #7
0
    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)))
Beispiel #8
0
 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
Beispiel #9
0
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
Beispiel #10
0
 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
Beispiel #11
0
    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
        )
Beispiel #12
0
 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
Beispiel #13
0
    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
Beispiel #14
0
    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)
Beispiel #15
0
    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, ]
Beispiel #16
0
    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
Beispiel #17
0
    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
Beispiel #18
0
    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
Beispiel #19
0
    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
        )