コード例 #1
0
 def __init__(self, scope, indent: int, createTmpVarFn, constCache=None):
     SerializerCtx.__init__(self,
                            scope,
                            indent,
                            createTmpVarFn,
                            constCache=constCache)
     self._valueWidthRequired = False
コード例 #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
コード例 #3
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)))
コード例 #4
0
    def Operator(cls, op: Operator, ctx: SerializerCtx):
        ops = op.operands
        o = op.operator

        op_str = cls._unaryOps.get(o, None)
        if op_str is not None:
            cancel_parenthesis = op_str[-1] == ")"
            return op_str % (cls._operand(ops[0], 0, op, False,
                                          cancel_parenthesis, ctx))

        op_str = cls._binOps.get(o, None)
        if op_str is not None:
            res_t = op.result._dtype
            if isinstance(res_t, Bits) and res_t != BOOL:
                op0 = cls._as_Bits(ops[0], ctx)
                op1 = cls._as_Bits(ops[1], ctx)
                op = op.operator._evalFn(op0, op1).drivers[0]
            return cls._bin_op(
                op,
                op_str,
                ctx,
                expr_requires_parenthesis=op.operator != AllOps.CONCAT)

        if o == AllOps.CALL:
            return "%s(%s)" % (
                cls.FunctionContainer(ops[0]),
                ", ".join(
                    # operand i does not matter as thy are all in ()
                    map(lambda op: cls._operand(op, 1, o, False, True, ctx),
                        ops[1:])))
        elif o == AllOps.INDEX:
            op0, op1 = ops
            if isinstance(op0,
                          RtlSignalBase) and isResultOfTypeConversion(op0):
                op0 = ctx.createTmpVarFn("tmpTypeConv", op0._dtype)
                op0.def_val = ops[0]

            # if the op0 is not signal or other index index operator it is extracted
            # as tmp variable
            op0_str = cls._operand(op0, 0, op, False, False, ctx)
            op1_str = cls._operand(ops[1], 1, op, False, True, ctx)

            if isinstance(op1._dtype, Bits) and op1._dtype != INT:
                sig = op1._dtype.signed
                if sig is None:
                    op1_str = "UNSIGNED(%s)" % op1_str
                op1_str = "TO_INTEGER(%s)" % op1_str

            return "%s(%s)" % (op0_str, op1_str)
        elif o == AllOps.TERNARY:
            op0 = cls.condAsHdl([ops[0]], True, ctx)
            op1 = cls._operand(ops[1], 1, op, False, False, ctx)
            op2 = cls._operand(ops[2], 2, op, False, False, ctx)
            return "%s WHEN %s ELSE %s" % (op0, op1, op2)
        else:
            raise NotImplementedError("Do not know how to convert %s to vhdl" %
                                      (o))
コード例 #5
0
    def Operator(cls, op: Operator, ctx: SerializerCtx):
        # [TODO] no nested ternary in expressions like
        # ( '1'  WHEN r = f ELSE  '0' ) & "0"
        ops = op.operands
        o = op.operator

        op_str = cls._unaryOps.get(o, None)
        if op_str is not None:
            return op_str % (cls._operand(ops[0], o, ctx))

        op_str = cls._binOps.get(o, None)
        if op_str is not None:
            return op_str % (cls._operand(ops[0], o,
                                          ctx), cls._operand(ops[1], o, ctx))

        if o == AllOps.CALL:
            return "%s(%s)" % (cls.FunctionContainer(ops[0]), ", ".join(
                map(lambda op: cls._operand(op, o, ctx), ops[1:])))
        elif o == AllOps.INDEX:
            assert len(ops) == 2
            o1 = ops[0]
            if isinstance(o1, RtlSignalBase) and isResultOfTypeConversion(o1):
                o1 = ctx.createTmpVarFn("tmpTypeConv", o1._dtype)
                o1.defVal = ops[0]

            return "%s(%s)" % (cls.asHdl(
                o1, ctx).strip(), cls._operand(ops[1], o, ctx))
        elif o == AllOps.TERNARY:
            return " ".join([
                cls._operand(ops[1], o, ctx), "WHEN",
                cls.condAsHdl([ops[0]], True, ctx), "ELSE",
                cls._operand(ops[2], o, ctx)
            ])
        elif o == AllOps.BitsToInt:
            assert len(ops) == 1
            op = cls.asHdl(ops[0], ctx)
            if ops[0]._dtype.signed is None:
                op = "UNSIGNED(%s)" % op
            return "TO_INTEGER(%s)" % op
        elif o == AllOps.IntToBits:
            assert len(ops) == 1
            resT = op.result._dtype
            op_str = cls.asHdl(ops[0], ctx)
            w = resT.bit_length()

            if resT.signed is None:
                return "STD_LOGIC_VECTOR(TO_UNSIGNED(%s, %d))" % (op_str, w)
            elif resT.signed:
                return "TO_UNSIGNED(%s, %d)" % (op_str, w)
            else:
                return "TO_UNSIGNED(%s, %d)" % (op_str, w)
        else:
            raise NotImplementedError("Do not know how to convert %s to vhdl" %
                                      (o))
コード例 #6
0
    def HWProcess(cls, proc: HWProcess, ctx: SerializerCtx):
        body = proc.statements
        assert body
        proc.name = ctx.scope.checkedName(proc.name, proc)
        sensitivityList = sorted(
            map(cls.sensitivityListItem, proc.sensitivityList))

        childCtx = ctx.withIndent(2)
        _body = "\n".join([cls.stmAsHdl(stm, childCtx) for stm in body])

        return processTmpl.render(hasConditions=arr_any(
            body, lambda stm: not isinstance(stm, Assignment)),
                                  name=proc.name,
                                  sensitivityList=sensitivityList,
                                  stmLines=[_body])
コード例 #7
0
 def _as_Bits(cls, val: Union[RtlSignal, Value], ctx: SerializerCtx):
     if val._dtype == BOOL:
         bit1_t = Bits(1)
         o = ctx.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
コード例 #8
0
ファイル: ops.py プロジェクト: kermit0124/hwt
    def _operand(cls, operand: Union[RtlSignal, Value], i: int,
                 operator: Operator,
                 expr_requires_parenthesis: bool,
                 cancel_parenthesis: bool,
                 ctx: SerializerCtx):

        # [TODO] if operand is concatenation and parent operator
        #        is not concatenation operand should be extracted
        #        as tmp variable
        #        * maybe flatten the concatenations
        if operator.operator != AllOps.CONCAT\
                and cls._operandIsAnotherOperand(operand)\
                and operand.origin.operator == AllOps.CONCAT:
            tmpVar = ctx.createTmpVarFn("tmp_concat_", operand._dtype)
            tmpVar.def_val = operand
            # Assignment(tmpVar, operand, virtual_only=True)
            operand = tmpVar

        oper = operator.operator
        width = None
        if oper not in [AllOps.BitsAsUnsigned, AllOps.BitsAsVec,
                        AllOps.BitsAsSigned] and\
                oper is not AllOps.INDEX and\
                operand._dtype == INT and\
                operator.result is not None and\
                not operator.result._dtype == INT:
            # has to lock width
            for o in operator.operands:
                try:
                    bl = o._dtype.bit_length
                except AttributeError:
                    bl = None
                if bl is not None:
                    width = bl()
                    break

            assert width is not None, (operator, operand)

        s = super()._operand(operand, i, operator,
                             width is not None or expr_requires_parenthesis,
                             width is None and cancel_parenthesis, ctx)
        if width is not None:
            return "%d'%s" % (width, s)
        else:
            return s
コード例 #9
0
 def _tmp_var_for_ternary(cls, val: RtlSignal, ctx: SerializerCtx):
     """
     Optionaly convert boolean to std_logic_vector
     """
     o = ctx.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
コード例 #10
0
ファイル: serializer.py プロジェクト: Ben-401/hwt
    def IfContainer(cls, ifc: IfContainer, ctx: SerializerCtx):
        """
        Srialize IfContainer instance
        """
        childCtx = ctx.withIndent()

        def asHdl(statements):
            return [cls.asHdl(s, childCtx) for s in statements]

        try:
            cond = cls.condAsHdl(ifc.cond, True, ctx)
        except UnsupportedEventOpErr as e:
            cond = None

        if cond is None:
            assert not ifc.elIfs
            assert not ifc.ifFalse
            stmBuff = [cls.asHdl(s, ctx) for s in ifc.ifTrue]
            return "\n".join(stmBuff)

        elIfs = []
        ifTrue = ifc.ifTrue
        ifFalse = ifc.ifFalse
        if ifFalse is None:
            ifFalse = []

        for c, statements in ifc.elIfs:
            try:
                elIfs.append((cls.condAsHdl(c, True, ctx), asHdl(statements)))
            except UnsupportedEventOpErr as e:
                if len(ifc.elIfs) == 1 and not ifFalse:
                    # register expression is in valid format and this
                    # is just register with asynchronous reset or etc...
                    ifFalse = statements
                else:
                    raise e

        return cls.ifTmpl.render(indent=getIndent(ctx.indent),
                                 cond=cond,
                                 ifTrue=asHdl(ifTrue),
                                 elIfs=elIfs,
                                 ifFalse=asHdl(ifFalse))
コード例 #11
0
ファイル: serializer.py プロジェクト: Ben-401/hwt
    def SwitchContainer(cls, sw: SwitchContainer, ctx: SerializerCtx):
        childCtx = ctx.withIndent(1)

        def asHdl(statements):
            return [cls.asHdl(s, childCtx) for s in statements]

        switchOn = cls.condAsHdl(sw.switchOn, False, ctx)

        cases = []
        for key, statements in sw.cases:
            key = cls.asHdl(key, ctx)

            cases.append((key, asHdl(statements)))

        if sw.default:
            cases.append((None, asHdl(sw.default)))

        return cls.switchTmpl.render(indent=getIndent(ctx.indent),
                                     switchOn=switchOn,
                                     cases=cases)
コード例 #12
0
ファイル: serializer.py プロジェクト: Ben-401/hwt
 def getBaseContext(cls):
     return SerializerCtx(cls.getBaseNameScope(), 0, None, None)