def fromPy(self, v, vldMask=None):
        """
        Construct value of this type.
        Delegated on value class for this type
        """
        return self.getValueCls().fromPy(v, self, vldMask=vldMask)

def fromPy ( self , v , vldMask = None ) : return self . getValueCls ( ) . fromPy ( v , self , vldMask = vldMask )

Construct value of this type . Delegated on value class for this type


def auto_cast(self, sigOrVal, toType):
        """
        Cast value or signal of this type to another compatible type.

        :param sigOrVal: instance of signal or value to cast
        :param toType: instance of HdlType to cast into
        """
        if sigOrVal._dtype == toType:
            return sigOrVal

        try:
            c = self._auto_cast_fn
        except AttributeError:
            c = self.get_auto_cast_fn()
            self._auto_cast_fn = c

        return c(self, sigOrVal, toType)

def auto_cast ( self , sigOrVal , toType ) : if sigOrVal . _dtype == toType : return sigOrVal try : c = self . _auto_cast_fn except AttributeError : c = self . get_auto_cast_fn ( ) self . _auto_cast_fn = c return c ( self , sigOrVal , toType )

Cast value or signal of this type to another compatible type .


def reinterpret_cast(self, sigOrVal, toType):
        """
        Cast value or signal of this type to another type of same size.

        :param sigOrVal: instance of signal or value to cast
        :param toType: instance of HdlType to cast into
        """
        try:
            return self.auto_cast(sigOrVal, toType)
        except TypeConversionErr:
            pass

        try:
            r = self._reinterpret_cast_fn
        except AttributeError:
            r = self.get_reinterpret_cast_fn()
            self._reinterpret_cast_fn = r

        return r(self, sigOrVal, toType)

def reinterpret_cast ( self , sigOrVal , toType ) : try : return self . auto_cast ( sigOrVal , toType ) except TypeConversionErr : pass try : r = self . _reinterpret_cast_fn except AttributeError : r = self . get_reinterpret_cast_fn ( ) self . _reinterpret_cast_fn = r return r ( self , sigOrVal , toType )

Cast value or signal of this type to another type of same size .


def walkParams(intf, discovered):
    """
    walk parameter instances on this interface
    """
    for si in intf._interfaces:
        yield from walkParams(si, discovered)

    for p in intf._params:
        if p not in discovered:
            discovered.add(p)
            yield p

def walkParams ( intf , discovered ) : for si in intf . _interfaces : yield from walkParams ( si , discovered ) for p in intf . _params : if p not in discovered : discovered . add ( p ) yield p


def connectPacked(srcPacked, dstInterface, exclude=None):
    """
    Connect 1D vector signal to this structuralized interface

    :param packedSrc: vector which should be connected
    :param dstInterface: structuralized interface where should
        packedSrc be connected to
    :param exclude: sub interfaces of self which should be excluded
    """
    offset = 0
    connections = []
    for i in reversed(list(walkPhysInterfaces(dstInterface))):
        if exclude is not None and i in exclude:
            continue
        sig = i._sig
        t = sig._dtype
        if t == BIT:
            s = srcPacked[offset]
            offset += 1
        else:
            w = t.bit_length()
            s = srcPacked[(w + offset): offset]
            offset += w
        connections.append(sig(s))

    return connections

def connectPacked ( srcPacked , dstInterface , exclude = None ) : offset = 0 connections = [ ] for i in reversed ( list ( walkPhysInterfaces ( dstInterface ) ) ) : if exclude is not None and i in exclude : continue sig = i . _sig t = sig . _dtype if t == BIT : s = srcPacked [ offset ] offset += 1 else : w = t . bit_length ( ) s = srcPacked [ ( w + offset ) : offset ] offset += w connections . append ( sig ( s ) ) return connections


def packIntf(intf, masterDirEqTo=DIRECTION.OUT, exclude=None):
    """
    Concatenate all signals to one big signal, recursively

    :param masterDirEqTo: only signals with this direction are packed
    :param exclude: sequence of signals/interfaces to exclude
    """
    if not intf._interfaces:
        if intf._masterDir == masterDirEqTo:
            return intf._sig
        return None

    res = None
    for i in intf._interfaces:
        if exclude is not None and i in exclude:
            continue

        if i._interfaces:
            if i._masterDir == DIRECTION.IN:
                d = DIRECTION.opposite(masterDirEqTo)
            else:
                d = masterDirEqTo
            s = i._pack(d, exclude=exclude)
        else:
            if i._masterDir == masterDirEqTo:
                s = i._sig
            else:
                s = None

        if s is not None:
            if res is None:
                res = s
            else:
                res = res._concat(s)

    return res

def packIntf ( intf , masterDirEqTo = DIRECTION . OUT , exclude = None ) : if not intf . _interfaces : if intf . _masterDir == masterDirEqTo : return intf . _sig return None res = None for i in intf . _interfaces : if exclude is not None and i in exclude : continue if i . _interfaces : if i . _masterDir == DIRECTION . IN : d = DIRECTION . opposite ( masterDirEqTo ) else : d = masterDirEqTo s = i . _pack ( d , exclude = exclude ) else : if i . _masterDir == masterDirEqTo : s = i . _sig else : s = None if s is not None : if res is None : res = s else : res = res . _concat ( s ) return res

Concatenate all signals to one big signal recursively


def hardcodeRomIntoProcess(cls, rom):
        """
        Due to verilog restrictions it is not posible to use array constants
        and rom memories has to be hardcoded as process
        """
        processes = []
        signals = []
        for e in rom.endpoints:
            assert isinstance(e, Operator) and e.operator == AllOps.INDEX, e
            me, index = e.operands
            assert me is rom

            # construct output of the rom
            romValSig = rom.ctx.sig(rom.name, dtype=e.result._dtype)
            signals.append(romValSig)
            romValSig.hidden = False

            # construct process which will represent content of the rom
            cases = [(toHVal(i), [romValSig(v), ])
                     for i, v in enumerate(rom.defVal.val)]
            statements = [SwitchContainer(index, cases), ]

            for (_, (stm, )) in cases:
                stm.parentStm = statements[0]

            p = HWProcess(rom.name, statements, {index, },
                          {index, }, {romValSig, })
            processes.append(p)

            # override usage of original index operator on rom
            # to use signal generated from this process
            def replaceOrigRomIndexExpr(x):
                if x is e.result:
                    return romValSig
                else:
                    return x
            for _e in e.result.endpoints:
                _e.operands = tuple(map(replaceOrigRomIndexExpr, _e.operands))
                e.result = romValSig

        return processes, signals

def hardcodeRomIntoProcess ( cls , rom ) : processes = [ ] signals = [ ] for e in rom . endpoints : assert isinstance ( e , Operator ) and e . operator == AllOps . INDEX , e me , index = e . operands assert me is rom romValSig = rom . ctx . sig ( rom . name , dtype = e . result . _dtype ) signals . append ( romValSig ) romValSig . hidden = False cases = [ ( toHVal ( i ) , [ romValSig ( v ) , ] ) for i , v in enumerate ( rom . defVal . val ) ] statements = [ SwitchContainer ( index , cases ) , ] for ( _ , ( stm , ) ) in cases : stm . parentStm = statements [ 0 ] p = HWProcess ( rom . name , statements , { index , } , { index , } , { romValSig , } ) processes . append ( p ) def replaceOrigRomIndexExpr ( x ) : if x is e . result : return romValSig else : return x for _e in e . result . endpoints : _e . operands = tuple ( map ( replaceOrigRomIndexExpr , _e . operands ) ) e . result = romValSig return processes , signals


def _toRtl(self, targetPlatform: DummyPlatform):
        """
        synthesize all subunits, make connections between them,
        build entity and component for this unit
        """
        assert not self._wasSynthetised()

        self._targetPlatform = targetPlatform
        if not hasattr(self, "_name"):
            self._name = self._getDefaultName()

        for proc in targetPlatform.beforeToRtl:
            proc(self)

        self._ctx.params = self._buildParams()
        self._externInterf = []

        # prepare subunits
        for u in self._units:
            yield from u._toRtl(targetPlatform)

        for u in self._units:
            subUnitName = u._name
            u._signalsForMyEntity(self._ctx, "sig_" + subUnitName)

        # prepare signals for interfaces
        for i in self._interfaces:
            signals = i._signalsForInterface(self._ctx)
            if i._isExtern:
                self._externInterf.extend(signals)

        for proc in targetPlatform.beforeToRtlImpl:
            proc(self)
        self._loadMyImplementations()
        yield from self._lazyLoaded

        if not self._externInterf:
            raise IntfLvlConfErr(
                "Can not find any external interface for unit %s"
                "- unit without interfaces are not allowed"
                % self._name)

        for proc in targetPlatform.afterToRtlImpl:
            proc(self)

        yield from self._synthetiseContext(self._externInterf)
        self._checkArchCompInstances()

        for proc in targetPlatform.afterToRtl:
            proc(self)

synthesize all subunits make connections between them build entity and component for this unit


def _registerIntfInImpl(self, iName, intf):
        """
        Register interface in implementation phase
        """
        self._registerInterface(iName, intf, isPrivate=True)
        self._loadInterface(intf, False)
        intf._signalsForInterface(self._ctx)

def _registerIntfInImpl ( self , iName , intf ) : self . _registerInterface ( iName , intf , isPrivate = True ) self . _loadInterface ( intf , False ) intf . _signalsForInterface ( self . _ctx )


def tryReduceAnd(sig, val):
    """
    Return sig and val reduced by & operator or None
    if it is not possible to statically reduce expression
    """
    m = sig._dtype.all_mask()
    if val._isFullVld():
        v = val.val
        if v == m:
            return sig
        elif v == 0:
            return val

def tryReduceAnd ( sig , val ) : m = sig . _dtype . all_mask ( ) if val . _isFullVld ( ) : v = val . val if v == m : return sig elif v == 0 : return val


def tryReduceXor(sig, val):
    """
    Return sig and val reduced by ^ operator or None
    if it is not possible to statically reduce expression
    """
    m = sig._dtype.all_mask()
    if not val.vldMask:
        return val

    if val._isFullVld():
        v = val.val
        if v == m:
            return ~sig
        elif v == 0:
            return sig

def tryReduceXor ( sig , val ) : m = sig . _dtype . all_mask ( ) if not val . vldMask : return val if val . _isFullVld ( ) : v = val . val if v == m : return ~ sig elif v == 0 : return sig


def getBaseNameScope(cls):
        """
        Get root of name space
        """
        s = NameScope(False)
        s.setLevel(1)
        s[0].update(cls._keywords_dict)
        return s

def getBaseNameScope ( cls ) : s = NameScope ( False ) s . setLevel ( 1 ) s [ 0 ] . update ( cls . _keywords_dict ) return s


def serializationDecision(cls, obj, serializedClasses,
                              serializedConfiguredUnits):
        """
        Decide if this unit should be serialized or not eventually fix name
        to fit same already serialized unit

        :param obj: object to serialize
        :param serializedClasses: dict {unitCls : unitobj}
        :param serializedConfiguredUnits: (unitCls, paramsValues) : unitObj
            where paramsValues are named tuple name:value
        """
        isDeclaration = isinstance(obj, Entity)
        isDefinition = isinstance(obj, Architecture)
        if isDeclaration:
            unit = obj.origin
        elif isDefinition:
            unit = obj.entity.origin
        else:
            return True

        assert isinstance(unit, Unit)
        sd = unit._serializeDecision
        if sd is None:
            return True
        else:
            prevPriv = serializedClasses.get(unit.__class__, None)
            seriazlize, nextPriv = sd(unit, obj, isDeclaration, prevPriv)
            serializedClasses[unit.__class__] = nextPriv
            return seriazlize

def serializationDecision ( cls , obj , serializedClasses , serializedConfiguredUnits ) : isDeclaration = isinstance ( obj , Entity ) isDefinition = isinstance ( obj , Architecture ) if isDeclaration : unit = obj . origin elif isDefinition : unit = obj . entity . origin else : return True assert isinstance ( unit , Unit ) sd = unit . _serializeDecision if sd is None : return True else : prevPriv = serializedClasses . get ( unit . __class__ , None ) seriazlize , nextPriv = sd ( unit , obj , isDeclaration , prevPriv ) serializedClasses [ unit . __class__ ] = nextPriv return seriazlize


def HdlType(cls, typ: HdlType, ctx: SerializerCtx, declaration=False):
        """
        Serialize HdlType instance
        """
        if isinstance(typ, Bits):
            sFn = cls.HdlType_bits
        elif isinstance(typ, HEnum):
            sFn = cls.HdlType_enum
        elif isinstance(typ, HArray):
            sFn = cls.HdlType_array
        elif isinstance(typ, Integer):
            sFn = cls.HdlType_int
        elif isinstance(typ, HBool):
            sFn = cls.HdlType_bool
        else:
            raise NotImplementedError("type declaration is not implemented"
                                      " for type %s"
                                      % (typ.name))

        return sFn(typ, ctx, declaration=declaration)

def
HdlType
(
cls
,
typ
:
HdlType
,
ctx
:
SerializerCtx
,
declaration
=
False
)
:
if
isinstance
(
typ
,
Bits
)
:
sFn
=
cls
.
HdlType_bits
elif
isinstance
(
typ
,
HEnum
)
:
sFn
=
cls
.
HdlType_enum
elif
isinstance
(
typ
,
HArray
)
:
sFn
=
cls
.
HdlType_array
elif
isinstance
(
typ
,
Integer
)
:
sFn
=
cls
.
HdlType_int
elif
isinstance
(
typ
,
HBool
)
:
sFn
=
cls
.
HdlType_bool
else
:
raise
NotImplementedError
(
"type declaration is not implemented"
" for type %s"
%
(
typ
.
name
)
)
return
sFn
(
typ
,
ctx
,
declaration
=
declaration
)


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))

def IfContainer ( cls , ifc : IfContainer , ctx : SerializerCtx ) : 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 : ifFalse = statements else : raise e return cls . ifTmpl . render ( indent = getIndent ( ctx . indent ) , cond = cond , ifTrue = asHdl ( ifTrue ) , elIfs = elIfs , ifFalse = asHdl ( ifFalse ) )


def getBaseCond(c):
    """
    if is negated return original cond and negated flag
    """
    isNegated = False
    try:
        drivers = c.drivers
    except AttributeError:
        return (c, isNegated)

    if len(drivers) == 1:
        d = list(c.drivers)[0]
        if isinstance(d, Operator) and d.operator == AllOps.NOT:
            c = d.operands[0]
            isNegated = True

    return (c, isNegated)

def getBaseCond ( c ) : isNegated = False try : drivers = c . drivers except AttributeError : return ( c , isNegated ) if len ( drivers ) == 1 : d = list ( c . drivers ) [ 0 ] if isinstance ( d , Operator ) and d . operator == AllOps . NOT : c = d . operands [ 0 ] isNegated = True return ( c , isNegated )


def simBitsT(width: int, signed: Union[bool, None]):
    """
    Construct SimBitsT with cache
    """
    k = (width, signed)
    try:
        return __simBitsTCache[k]
    except KeyError:
        t = SimBitsT(width, signed)
        __simBitsTCache[k] = t
        return t

def simBitsT ( width : int , signed : Union [ bool , None ] ) : k = ( width , signed ) try : return __simBitsTCache [ k ] except KeyError : t = SimBitsT ( width , signed ) __simBitsTCache [ k ] = t return t


def getConstName(self, val):
        """
        Get constant name for value
        name of constant is reused if same value was used before
        """
        try:
            return self._cache[val]
        except KeyError:
            if isinstance(val.val, int):
                name = "const_%d_" % val.val
            else:
                name = "const_"

            c = self.nameCheckFn(name, val)
            self._cache[val] = c
            return c

def getConstName ( self , val ) : try : return self . _cache [ val ] except KeyError : if isinstance ( val . val , int ) : name = "const_%d_" % val . val else : name = "const_" c = self . nameCheckFn ( name , val ) self . _cache [ val ] = c return c


def _cut_off_drivers_of(self, sig: RtlSignalBase):
        """
        Cut off statements which are driver of specified signal
        """
        if self.dst is sig:
            self.parentStm = None
            return self
        else:
            return None

def _cut_off_drivers_of ( self , sig : RtlSignalBase ) : if self . dst is sig : self . parentStm = None return self else : return None


def _loadFromArray(self, dtype: HdlType, bitAddr: int) -> int:
        """
        Parse HArray type to this transaction template instance

        :return: address of it's end
        """
        self.itemCnt = evalParam(dtype.size).val
        self.children = TransTmpl(
            dtype.elmType, 0, parent=self, origin=self.origin)
        return bitAddr + self.itemCnt * self.children.bitAddrEnd

def _loadFromArray ( self , dtype : HdlType , bitAddr : int ) -> int : self . itemCnt = evalParam ( dtype . size ) . val self . children = TransTmpl ( dtype . elmType , 0 , parent = self , origin = self . origin ) return bitAddr + self . itemCnt * self . children . bitAddrEnd


def _loadFromHStruct(self, dtype: HdlType, bitAddr: int):
        """
        Parse HStruct type to this transaction template instance

        :return: address of it's end
        """
        for f in dtype.fields:
            t = f.dtype
            origin = f
            isPadding = f.name is None

            if isPadding:
                width = t.bit_length()
                bitAddr += width
            else:
                fi = TransTmpl(t, bitAddr, parent=self, origin=origin)
                self.children.append(fi)
                bitAddr = fi.bitAddrEnd

        return bitAddr

def _loadFromHStruct ( self , dtype : HdlType , bitAddr : int ) : for f in dtype . fields : t = f . dtype origin = f isPadding = f . name is None if isPadding : width = t . bit_length ( ) bitAddr += width else : fi = TransTmpl ( t , bitAddr , parent = self , origin = origin ) self . children . append ( fi ) bitAddr = fi . bitAddrEnd return bitAddr


def _loadFromHType(self, dtype: HdlType, bitAddr: int) -> None:
        """
        Parse any HDL type to this transaction template instance
        """
        self.bitAddr = bitAddr
        childrenAreChoice = False
        if isinstance(dtype, Bits):
            ld = self._loadFromBits
        elif isinstance(dtype, HStruct):
            ld = self._loadFromHStruct
        elif isinstance(dtype, HArray):
            ld = self._loadFromArray
        elif isinstance(dtype, HStream):
            ld = self._loadFromHStream
        elif isinstance(dtype, HUnion):
            ld = self._loadFromUnion
            childrenAreChoice = True
        else:
            raise TypeError("expected instance of HdlType", dtype)

        self.bitAddrEnd = ld(dtype, bitAddr)
        self.childrenAreChoice = childrenAreChoice

def
_loadFromHType
(
self
,
dtype
:
HdlType
,
bitAddr
:
int
)
->
:
self
.
bitAddr
=
bitAddr
childrenAreChoice
=
False
if
isinstance
(
dtype
,
Bits
)
:
ld
=
self
.
_loadFromBits
elif
isinstance
(
dtype
,
HStruct
)
:
ld
=
self
.
_loadFromHStruct
elif
isinstance
(
dtype
,
HArray
)
:
ld
=
self
.
_loadFromArray
elif
isinstance
(
dtype
,
HStream
)
:
ld
=
self
.
_loadFromHStream
elif
isinstance
(
dtype
,
HUnion
)
:
ld
=
self
.
_loadFromUnion
childrenAreChoice
=
True
else
:
raise
TypeError
(
"expected instance of HdlType"
,
dtype
)
self
.
bitAddrEnd
=
ld
(
dtype
,
bitAddr
)
self
.
childrenAreChoice
=
childrenAreChoice


def getItemWidth(self) -> int:
        """
        Only for transactions derived from HArray

        :return: width of item in original array
        """
        if not isinstance(self.dtype, HArray):
            raise TypeError()
        return (self.bitAddrEnd - self.bitAddr) // self.itemCnt

def getItemWidth ( self ) -> int : if not isinstance ( self . dtype , HArray ) : raise TypeError ( ) return ( self . bitAddrEnd - self . bitAddr ) // self . itemCnt


def walkFlatten(self, offset: int=0,
                    shouldEnterFn=_default_shouldEnterFn,
                    otherObjItCtx: ObjIteratorCtx =_DummyIteratorCtx()
                    ) -> Generator[
            Union[Tuple[Tuple[int, int], 'TransTmpl'], 'OneOfTransaction'],
            None, None]:
        """
        Walk fields in instance of TransTmpl

        :param offset: optional offset for all children in this TransTmpl
        :param shouldEnterFn: function (transTmpl) which returns True
            when field should be split on it's children
        :param shouldEnterFn: function(transTmpl) which should return
            (shouldEnter, shouldUse) where shouldEnter is flag that means
            iterator should look inside of this actual object
            and shouldUse flag means that this field should be used
            (=generator should yield it)
        :return: generator of tuples ((startBitAddress, endBitAddress),
            TransTmpl instance)
        """

        t = self.dtype
        base = self.bitAddr + offset
        end = self.bitAddrEnd + offset

        shouldEnter, shouldYield = shouldEnterFn(self)
        if shouldYield:
            yield ((base, end), self)

        if shouldEnter:
            if isinstance(t, Bits):
                pass
            elif isinstance(t, HStruct):
                for ch in self.children:
                    with otherObjItCtx(ch.origin.name):
                        yield from ch.walkFlatten(
                            offset,
                            shouldEnterFn,
                            otherObjItCtx)
            elif isinstance(t, HArray):
                itemSize = (self.bitAddrEnd - self.bitAddr) // self.itemCnt
                for i in range(self.itemCnt):
                    with otherObjItCtx(i):
                        yield from self.children.walkFlatten(
                            base + i * itemSize,
                            shouldEnterFn,
                            otherObjItCtx)
            elif isinstance(t, HUnion):
                yield OneOfTransaction(self, offset, shouldEnterFn,
                                       self.children)
            elif isinstance(t, HStream):
                assert len(self.children) == 1
                yield StreamTransaction(self, offset, shouldEnterFn,
                                        self.children[0])
            else:
                raise TypeError(t)

def walkFlatten ( self , offset : int = 0 , shouldEnterFn = _default_shouldEnterFn , otherObjItCtx : ObjIteratorCtx = _DummyIteratorCtx ( ) ) -> Generator [ Union [ Tuple [ Tuple [ int , int ] , 'TransTmpl' ] , 'OneOfTransaction' ] , None , None ] : t = self . dtype base = self . bitAddr + offset end = self . bitAddrEnd + offset shouldEnter , shouldYield = shouldEnterFn ( self ) if shouldYield : yield ( ( base , end ) , self ) if shouldEnter : if isinstance ( t , Bits ) : pass elif isinstance ( t , HStruct ) : for ch in self . children : with otherObjItCtx ( ch . origin . name ) : yield from ch . walkFlatten ( offset , shouldEnterFn , otherObjItCtx ) elif isinstance ( t , HArray ) : itemSize = ( self . bitAddrEnd - self . bitAddr ) // self . itemCnt for i in range ( self . itemCnt ) : with otherObjItCtx ( i ) : yield from self . children . walkFlatten ( base + i * itemSize , shouldEnterFn , otherObjItCtx ) elif isinstance ( t , HUnion ) : yield OneOfTransaction ( self , offset , shouldEnterFn , self . children ) elif isinstance ( t , HStream ) : assert len ( self . children ) == 1 yield StreamTransaction ( self , offset , shouldEnterFn , self . children [ 0 ] ) else : raise TypeError ( t )


def signFix(val, width):
    """
    Convert negative int to positive int which has same bits set
    """
    if val > 0:
        msb = 1 << (width - 1)
        if val & msb:
            val -= mask(width) + 1
    return val

def signFix ( val , width ) : if val > 0 : msb = 1 << ( width - 1 ) if val & msb : val -= mask ( width ) + 1 return val


def _merge_with_other_stm(self, other: "IfContainer") -> None:
        """
        Merge other statement to this statement
        """
        merge = self._merge_statement_lists
        newCases = []
        for (c, caseA), (_, caseB) in zip(self.cases, other.cases):
            newCases.append((c, merge(caseA, caseB)))

        self.cases = newCases

        if self.default is not None:
            self.default = merge(self.default, other.default)

        self._on_merge(other)

def _merge_with_other_stm ( self , other : "IfContainer" ) -> None : merge = self . _merge_statement_lists newCases = [ ] for ( c , caseA ) , ( _ , caseB ) in zip ( self . cases , other . cases ) : newCases . append ( ( c , merge ( caseA , caseB ) ) ) self . cases = newCases if self . default is not None : self . default = merge ( self . default , other . default ) self . _on_merge ( other )


def getIndent(indentNum):
    """
    Cached indent getter function
    """
    try:
        return _indentCache[indentNum]
    except KeyError:
        i = "".join([_indent for _ in range(indentNum)])
        _indentCache[indentNum] = i
        return i

def getIndent ( indentNum ) : try : return _indentCache [ indentNum ] except KeyError : i = "" . join ( [ _indent for _ in range ( indentNum ) ] ) _indentCache [ indentNum ] = i return i


def nameAvailabilityCheck(obj, propName, prop):
    """
    Check if not redefining property on obj
    """
    if getattr(obj, propName, None) is not None:
        raise IntfLvlConfErr("%r already has property %s old:%s new:%s" %
                             (obj, propName, repr(getattr(obj, propName)), prop))


def _registerParameter(self, pName, parameter) -> None:
        """
        Register Param object on interface level object
        """
        nameAvailabilityCheck(self, pName, parameter)
        # resolve name in this scope
        try:
            hasName = parameter._name is not None
        except AttributeError:
            hasName = False
        if not hasName:
            parameter._name = pName
        # add name in this scope
        parameter._registerScope(pName, self)

        if parameter.hasGenericName:
            parameter.name = pName

        if parameter._parent is None:
            parameter._parent = self

        self._params.append(parameter)

def _registerParameter ( self , pName , parameter ) -> None : nameAvailabilityCheck ( self , pName , parameter ) try : hasName = parameter . _name is not None except AttributeError : hasName = False if not hasName : parameter . _name = pName parameter . _registerScope ( pName , self ) if parameter . hasGenericName : parameter . name = pName if parameter . _parent is None : parameter . _parent = self self . _params . append ( parameter )


def _updateParamsFrom(self, otherObj:"PropDeclrCollector", updater, exclude:set, prefix:str) -> None:
        """
        Update all parameters which are defined on self from otherObj

        :param otherObj: other object which Param instances should be updated
        :param updater: updater function(self, myParameter, onOtherParameterName, otherParameter)
        :param exclude: iterable of parameter on otherObj object which should be excluded
        :param prefix: prefix which should be added to name of paramters of this object before matching
            parameter name on parent
        """
        excluded = set()
        if exclude is not None:
            exclude = set(exclude)

        for myP in self._params:
            pPName = prefix + myP._scopes[self][1]
            try:
                otherP = getattr(otherObj, pPName)
                if not isinstance(otherP, Param):
                    continue
            except AttributeError:
                continue

            if exclude and otherP in exclude:
                excluded.add(otherP)
                continue
            updater(self, myP, otherP)

        if exclude is not None:
            # assert that what should be excluded really exists
            assert excluded == exclude

def _updateParamsFrom ( self , otherObj : "PropDeclrCollector" , updater , exclude : set , prefix : str ) -> None : excluded = set ( ) if exclude is not None : exclude = set ( exclude ) for myP in self . _params : pPName = prefix + myP . _scopes [ self ] [ 1 ] try : otherP = getattr ( otherObj , pPName ) if not isinstance ( otherP , Param ) : continue except AttributeError : continue if exclude and otherP in exclude : excluded . add ( otherP ) continue updater ( self , myP , otherP ) if exclude is not None : assert excluded == exclude


def _registerUnit(self, uName, unit):
        """
        Register unit object on interface level object
        """
        nameAvailabilityCheck(self, uName, unit)
        assert unit._parent is None
        unit._parent = self
        unit._name = uName
        self._units.append(unit)

def _registerUnit ( self , uName , unit ) : nameAvailabilityCheck ( self , uName , unit ) assert unit . _parent is None unit . _parent = self unit . _name = uName self . _units . append ( unit )


def _registerInterface(self, iName, intf, isPrivate=False):
        """
        Register interface object on interface level object
        """
        nameAvailabilityCheck(self, iName, intf)
        assert intf._parent is None
        intf._parent = self
        intf._name = iName
        intf._ctx = self._ctx

        if isPrivate:
            self._private_interfaces.append(intf)
            intf._isExtern = False
        else:
            self._interfaces.append(intf)
            intf._isExtern = True

def _registerInterface ( self , iName , intf , isPrivate = False ) : nameAvailabilityCheck ( self , iName , intf ) assert intf . _parent is None intf . _parent = self intf . _name = iName intf . _ctx = self . _ctx if isPrivate : self . _private_interfaces . append ( intf ) intf . _isExtern = False else : self . _interfaces . append ( intf ) intf . _isExtern = True


def _registerArray(self, name, items):
        """
        Register array of items on interface level object
        """
        items._parent = self
        items._name = name
        for i, item in enumerate(items):
            setattr(self, "%s_%d" % (name, i), item)

def _registerArray ( self , name , items ) : items . _parent = self items . _name = name for i , item in enumerate ( items ) : setattr ( self , "%s_%d" % ( name , i ) , item )


def singleDriver(self):
        """
        Returns a first driver if signal has only one driver.
        """
        # [TODO] no driver exception
        drv_cnt = len(self.drivers)
        if not drv_cnt:
            raise NoDriverErr(self)
        elif drv_cnt != 1:
            raise MultipleDriversErr(self)

        return self.drivers[0]

def singleDriver ( self ) : drv_cnt = len ( self . drivers ) if not drv_cnt : raise NoDriverErr ( self ) elif drv_cnt != 1 : raise MultipleDriversErr ( self ) return self . drivers [ 0 ]

Returns a first driver if signal has only one driver .


def staticEval(self):
        """
        Recursively statistically evaluate result of this operator
        """
        for o in self.operands:
            o.staticEval()
        self.result._val = self.evalFn()

def staticEval ( self ) : for o in self . operands : o . staticEval ( ) self . result . _val = self . evalFn ( )


def withRes(opDef, operands, resT, outputs=[]):
        """
        Create operator with result signal

        :ivar resT: data type of result signal
        :ivar outputs: iterable of singnals which are outputs
            from this operator
        """
        op = Operator(opDef, operands)
        out = RtlSignal(getCtxFromOps(operands), None, resT)
        out._const = arr_all(op.operands, isConst)
        out.drivers.append(op)
        out.origin = op
        op.result = out
        op.registerSignals(outputs)
        if out._const:
            out.staticEval()
        return out

def withRes ( opDef , operands , resT , outputs = [ ] ) : op = Operator ( opDef , operands ) out = RtlSignal ( getCtxFromOps ( operands ) , None , resT ) out . _const = arr_all ( op . operands , isConst ) out . drivers . append ( op ) out . origin = op op . result = out op . registerSignals ( outputs ) if out . _const : out . staticEval ( ) return out


def withIndent(self, indent=1):
        """
        Create copy of this context with increased indent
        """
        ctx = copy(self)
        ctx.indent += indent
        return ctx

def withIndent ( self , indent = 1 ) : ctx = copy ( self ) ctx . indent += indent return ctx


def _tryConnect(src, unit, intfName):
    """
    Try connect src to interface of specified name on unit.
    Ignore if interface is not present or if it already has driver.
    """
    try:
        dst = getattr(unit, intfName)
    except AttributeError:
        return
    if not dst._sig.drivers:
        connect(src, dst)

def _tryConnect ( src , unit , intfName ) : try : dst = getattr ( unit , intfName ) except AttributeError : return if not dst . _sig . drivers : connect ( src , dst )

Try connect src to interface of specified name on unit . Ignore if interface is not present or if it already has driver .


def propagateClk(obj):
    """
    Propagate "clk" clock signal to all subcomponents
    """
    clk = obj.clk
    for u in obj._units:
        _tryConnect(clk, u, 'clk')

def propagateClk ( obj ) : clk = obj . clk for u in obj . _units : _tryConnect ( clk , u , 'clk' )

Propagate clk clock signal to all subcomponents


def propagateClkRstn(obj):
    """
    Propagate "clk" clock and negative reset "rst_n" signal
    to all subcomponents
    """
    clk = obj.clk
    rst_n = obj.rst_n

    for u in obj._units:
        _tryConnect(clk, u, 'clk')
        _tryConnect(rst_n, u, 'rst_n')
        _tryConnect(~rst_n, u, 'rst')

def propagateClkRstn ( obj ) : clk = obj . clk rst_n = obj . rst_n for u in obj . _units : _tryConnect ( clk , u , 'clk' ) _tryConnect ( rst_n , u , 'rst_n' ) _tryConnect ( ~ rst_n , u , 'rst' )

Propagate clk clock and negative reset rst_n signal to all subcomponents


def propagateClkRst(obj):
    """
    Propagate "clk" clock and reset "rst" signal to all subcomponents
    """
    clk = obj.clk
    rst = obj.rst

    for u in obj._units:
        _tryConnect(clk, u, 'clk')
        _tryConnect(~rst, u, 'rst_n')
        _tryConnect(rst, u, 'rst')

def propagateClkRst ( obj ) : clk = obj . clk rst = obj . rst for u in obj . _units : _tryConnect ( clk , u , 'clk' ) _tryConnect ( ~ rst , u , 'rst_n' ) _tryConnect ( rst , u , 'rst' )

Propagate clk clock and reset rst signal to all subcomponents


def propagateRstn(obj):
    """
    Propagate negative reset "rst_n" signal
    to all subcomponents
    """
    rst_n = obj.rst_n

    for u in obj._units:
        _tryConnect(rst_n, u, 'rst_n')
        _tryConnect(~rst_n, u, 'rst')

def propagateRstn ( obj ) : rst_n = obj . rst_n for u in obj . _units : _tryConnect ( rst_n , u , 'rst_n' ) _tryConnect ( ~ rst_n , u , 'rst' )

Propagate negative reset rst_n signal to all subcomponents


def propagateRst(obj):
    """
    Propagate reset "rst" signal
    to all subcomponents
    """
    rst = obj.rst

    for u in obj._units:
        _tryConnect(~rst, u, 'rst_n')
        _tryConnect(rst, u, 'rst')

def propagateRst ( obj ) : rst = obj . rst for u in obj . _units : _tryConnect ( ~ rst , u , 'rst_n' ) _tryConnect ( rst , u , 'rst' )

Propagate reset rst signal to all subcomponents


def iterBits(sigOrVal: Union[RtlSignal, Value], bitsInOne: int=1,
             skipPadding: bool=True, fillup: bool=False):
    """
    Iterate over bits in vector

    :param sigOrVal: signal or value to iterate over
    :param bitsInOne: number of bits in one part
    :param skipPadding: if true padding is skipped in dense types
    """
    bw = BitWalker(sigOrVal, skipPadding, fillup)
    for _ in range(ceil(sigOrVal._dtype.bit_length() / bitsInOne)):
        yield bw.get(bitsInOne)

    bw.assertIsOnEnd()

def iterBits ( sigOrVal : Union [ RtlSignal , Value ] , bitsInOne : int = 1 , skipPadding : bool = True , fillup : bool = False ) : bw = BitWalker ( sigOrVal , skipPadding , fillup ) for _ in range ( ceil ( sigOrVal . _dtype . bit_length ( ) / bitsInOne ) ) : yield bw . get ( bitsInOne ) bw . assertIsOnEnd ( )


def _serializeExclude_eval(parentUnit, obj, isDeclaration, priv):
    """
    Always decide not to serialize obj

    :param priv: private data for this function first unit of this class
    :return: tuple (do serialize this object, next priv)
    """
    if isDeclaration:
        # prepare entity which will not be serialized
        prepareEntity(obj, parentUnit.__class__.__name__, priv)

    if priv is None:
        priv = parentUnit

    return False, priv

def _serializeExclude_eval ( parentUnit , obj , isDeclaration , priv ) : if isDeclaration : prepareEntity ( obj , parentUnit . __class__ . __name__ , priv ) if priv is None : priv = parentUnit return False , priv


def _serializeOnce_eval(parentUnit, obj, isDeclaration, priv):
    """
    Decide to serialize only first obj of it's class

    :param priv: private data for this function
        (first object with class == obj.__class__)

    :return: tuple (do serialize this object, next priv)
        where priv is private data for this function
        (first object with class == obj.__class__)
    """
    clsName = parentUnit.__class__.__name__

    if isDeclaration:
        obj.name = clsName

    if priv is None:
        priv = parentUnit
    elif isDeclaration:
        # prepare entity which will not be serialized
        prepareEntity(obj, clsName, parentUnit)

    serialize = priv is parentUnit

    return serialize, priv

def _serializeOnce_eval ( parentUnit , obj , isDeclaration , priv ) : clsName = parentUnit . __class__ . __name__ if isDeclaration : obj . name = clsName if priv is None : priv = parentUnit elif isDeclaration : prepareEntity ( obj , clsName , parentUnit ) serialize = priv is parentUnit return serialize , priv

Decide to serialize only first obj of it s class


def _serializeParamsUniq_eval(parentUnit, obj, isDeclaration, priv):
    """
    Decide to serialize only objs with uniq parameters and class

    :param priv: private data for this function
        ({frozen_params: obj})

    :return: tuple (do serialize this object, next priv)
    """

    params = paramsToValTuple(parentUnit)

    if priv is None:
        priv = {}

    if isDeclaration:
        try:
            prevUnit = priv[params]
        except KeyError:
            priv[params] = parentUnit
            return True, priv

        prepareEntity(obj, prevUnit._entity.name, prevUnit)
        return False, priv

    return priv[params] is parentUnit, priv

def _serializeParamsUniq_eval ( parentUnit , obj , isDeclaration , priv ) : params = paramsToValTuple ( parentUnit ) if priv is None : priv = { } if isDeclaration : try : prevUnit = priv [ params ] except KeyError : priv [ params ] = parentUnit return True , priv prepareEntity ( obj , prevUnit . _entity . name , prevUnit ) return False , priv return priv [ params ] is parentUnit , priv


def _getFullName(self):
        """get all name hierarchy separated by '.' """
        name = ""
        tmp = self
        while isinstance(tmp, (InterfaceBase, HObjList)):
            if hasattr(tmp, "_name"):
                n = tmp._name
            else:
                n = ''
            if name == '':
                name = n
            else:
                name = n + '.' + name
            if hasattr(tmp, "_parent"):
                tmp = tmp._parent
            else:
                tmp = None
        return name

def _getFullName ( self ) : name = "" tmp = self while isinstance ( tmp , ( InterfaceBase , HObjList ) ) : if hasattr ( tmp , "_name" ) : n = tmp . _name else : n = '' if name == '' : name = n else : name = n + '.' + name if hasattr ( tmp , "_parent" ) : tmp = tmp . _parent else : tmp = None return name


def _make_association(self, *args, **kwargs):
        """
        Delegate _make_association on items

        :note: doc in :func:`~hwt.synthesizer.interfaceLevel.propDeclCollector._make_association`
        """
        for o in self:
            o._make_association(*args, **kwargs)

def _make_association ( self , * args , ** kwargs ) : for o in self : o . _make_association ( * args , ** kwargs )


def simPrepare(unit: Unit, modelCls: Optional[SimModel]=None,
               targetPlatform=DummyPlatform(),
               dumpModelIn: str=None, onAfterToRtl=None):
    """
    Create simulation model and connect it with interfaces of original unit
    and decorate it with agents

    :param unit: interface level unit which you wont prepare for simulation
    :param modelCls: class of rtl simulation model to run simulation on,
        if is None rtl sim model will be generated from unit
    :param targetPlatform: target platform for this synthes
    :param dumpModelIn: folder to where put sim model files
        (if is None sim model will be constructed only in memory)
    :param onAfterToRtl: callback fn(unit, modelCls) which will be called
        after unit will be synthesised to rtl

    :return: tuple (fully loaded unit with connected sim model,
        connected simulation model,
        simulation processes of agents
        )
    """
    if modelCls is None:
        modelCls = toSimModel(
            unit, targetPlatform=targetPlatform, dumpModelIn=dumpModelIn)
    else:
        # to instantiate hierarchy of unit
        toSimModel(unit)

    if onAfterToRtl:
        onAfterToRtl(unit, modelCls)

    reconnectUnitSignalsToModel(unit, modelCls)
    model = modelCls()
    procs = autoAddAgents(unit)
    return unit, model, procs

def simPrepare ( unit : Unit , modelCls : Optional [ SimModel ] = None , targetPlatform = DummyPlatform ( ) , dumpModelIn : str = None , onAfterToRtl = None ) : if modelCls is None : modelCls = toSimModel ( unit , targetPlatform = targetPlatform , dumpModelIn = dumpModelIn ) else : toSimModel ( unit ) if onAfterToRtl : onAfterToRtl ( unit , modelCls ) reconnectUnitSignalsToModel ( unit , modelCls ) model = modelCls ( ) procs = autoAddAgents ( unit ) return unit , model , procs


def toSimModel(unit, targetPlatform=DummyPlatform(), dumpModelIn=None):
    """
    Create a simulation model for unit

    :param unit: interface level unit which you wont prepare for simulation
    :param targetPlatform: target platform for this synthes
    :param dumpModelIn: folder to where put sim model files
        (otherwise sim model will be constructed only in memory)
    """
    sim_code = toRtl(unit,
                     targetPlatform=targetPlatform,
                     saveTo=dumpModelIn,
                     serializer=SimModelSerializer)
    if dumpModelIn is not None:
        d = os.path.join(os.getcwd(), dumpModelIn)
        dInPath = d in sys.path
        if not dInPath:
            sys.path.insert(0, d)
        if unit._name in sys.modules:
            del sys.modules[unit._name]
        simModule = importlib.import_module(unit._name)

        if not dInPath:
            sys.path.remove(d)
    else:
        simModule = ModuleType('simModule')
        # python supports only ~100 opened brackets
        # it exceded it throws MemoryError: s_push: parser stack overflow
        exec(sim_code, simModule.__dict__)

    return simModule.__dict__[unit._name]

def toSimModel ( unit , targetPlatform = DummyPlatform ( ) , dumpModelIn = None ) : sim_code = toRtl ( unit , targetPlatform = targetPlatform , saveTo = dumpModelIn , serializer = SimModelSerializer ) if dumpModelIn is not None : d = os . path . join ( os . getcwd ( ) , dumpModelIn ) dInPath = d in sys . path if not dInPath : sys . path . insert ( 0 , d ) if unit . _name in sys . modules : del sys . modules [ unit . _name ] simModule = importlib . import_module ( unit . _name ) if not dInPath : sys . path . remove ( d ) else : simModule = ModuleType ( 'simModule' ) exec ( sim_code , simModule . __dict__ ) return simModule . __dict__ [ unit . _name ]


def reconnectUnitSignalsToModel(synthesisedUnitOrIntf, modelCls):
    """
    Reconnect model signals to unit to run simulation with simulation model
    but use original unit interfaces for communication

    :param synthesisedUnitOrIntf: interface where should be signals
        replaced from signals from modelCls
    :param modelCls: simulation model form where signals
        for synthesisedUnitOrIntf should be taken
    """
    obj = synthesisedUnitOrIntf
    subInterfaces = obj._interfaces

    if subInterfaces:
        for intf in subInterfaces:
            # proxies are destroyed on original interfaces and only proxies on
            # array items will remain
            reconnectUnitSignalsToModel(intf, modelCls)
    else:
        # reconnect signal from model
        s = synthesisedUnitOrIntf
        s._sigInside = getattr(modelCls, s._sigInside.name)

def reconnectUnitSignalsToModel ( synthesisedUnitOrIntf , modelCls ) : obj = synthesisedUnitOrIntf subInterfaces = obj . _interfaces if subInterfaces : for intf in subInterfaces : reconnectUnitSignalsToModel ( intf , modelCls ) else : s = synthesisedUnitOrIntf s . _sigInside = getattr ( modelCls , s . _sigInside . name )


def simUnitVcd(simModel, stimulFunctions, outputFile=sys.stdout,
               until=100 * Time.ns):
    """
    Syntax sugar
    If outputFile is string try to open it as file

    :return: hdl simulator object
    """
    assert isinstance(simModel, SimModel), \
        "Class of SimModel is required (got %r)" % (simModel)
    if isinstance(outputFile, str):
        d = os.path.dirname(outputFile)
        if d:
            os.makedirs(d, exist_ok=True)
        with open(outputFile, 'w') as f:
            return _simUnitVcd(simModel, stimulFunctions,
                               f, until)
    else:
        return _simUnitVcd(simModel, stimulFunctions,
                           outputFile, until)


def onTWriteCallback__init(self, sim):
        """
        Process for injecting of this callback loop into simulator
        """
        yield from self.onTWriteCallback(sim)
        self.intf.t._sigInside.registerWriteCallback(
            self.onTWriteCallback,
            self.getEnable)
        self.intf.o._sigInside.registerWriteCallback(
            self.onTWriteCallback,
            self.getEnable)

def onTWriteCallback__init ( self , sim ) : yield from self . onTWriteCallback ( sim ) self . intf . t . _sigInside . registerWriteCallback ( self . onTWriteCallback , self . getEnable ) self . intf . o . _sigInside . registerWriteCallback ( self . onTWriteCallback , self . getEnable )


def connectSig(self, signal):
        """
        Connect to port item on subunit
        """
        if self.direction == DIRECTION.IN:
            if self.src is not None:
                raise HwtSyntaxError(
                    "Port %s is already associated with %r"
                    % (self.name, self.src))
            self.src = signal
            signal.endpoints.append(self)

        elif self.direction == DIRECTION.OUT:
            if self.dst is not None:
                raise HwtSyntaxError(
                    "Port %s is already associated with %r"
                    % (self.name, self.dst))
            self.dst = signal
            signal.drivers.append(self)

        else:
            raise NotImplementedError(self)

        signal.hidden = False
        signal.ctx.subUnits.add(self.unit)

def
connectSig
(
self
,
signal
)
:
if
self
.
direction
==
DIRECTION
.
IN
:
if
self
.
src
is
not
:
raise
HwtSyntaxError
(
"Port %s is already associated with %r"
%
(
self
.
name
,
self
.
src
)
)
self
.
src
=
signal
signal
.
endpoints
.
append
(
self
)
elif
self
.
direction
==
DIRECTION
.
OUT
:
if
self
.
dst
is
not
:
raise
HwtSyntaxError
(
"Port %s is already associated with %r"
%
(
self
.
name
,
self
.
dst
)
)
self
.
dst
=
signal
signal
.
drivers
.
append
(
self
)
else
:
raise
NotImplementedError
(
self
)
signal
.
hidden
=
False
signal
.
ctx
.
subUnits
.
add
(
self
.
unit
)


def registerInternSig(self, signal):
        """
        Connect internal signal to port item,
        this connection is used by simulator and only output port items
        will be connected
        """
        if self.direction == DIRECTION.OUT:
            if self.src is not None:
                raise HwtSyntaxError(
                    "Port %s is already associated with %s"
                    % (self.name, str(self.src)))
            self.src = signal

        elif self.direction == DIRECTION.IN:
            if self.dst is not None:
                raise HwtSyntaxError(
                    "Port %s is already associated with %s"
                    % (self.name, str(self.dst)))
            self.dst = signal

        else:
            raise NotImplementedError(self.direction)

def
registerInternSig
(
self
,
signal
)
:
if
self
.
direction
==
DIRECTION
.
OUT
:
if
self
.
src
is
not
:
raise
HwtSyntaxError
(
"Port %s is already associated with %s"
%
(
self
.
name
,
str
(
self
.
src
)
)
)
self
.
src
=
signal
elif
self
.
direction
==
DIRECTION
.
IN
:
if
self
.
dst
is
not
:
raise
HwtSyntaxError
(
"Port %s is already associated with %s"
%
(
self
.
name
,
str
(
self
.
dst
)
)
)
self
.
dst
=
signal
else
:
raise
NotImplementedError
(
self
.
direction
)

Connect internal signal to port item this connection is used by simulator and only output port items will be connected


def connectInternSig(self):
        """
        connet signal from internal side of of this component to this port
        """
        d = self.direction
        if d == DIRECTION.OUT:
            self.src.endpoints.append(self)
        elif d == DIRECTION.IN or d == DIRECTION.INOUT:
            self.dst.drivers.append(self)
        else:
            raise NotImplementedError(d)

def connectInternSig ( self ) : d = self . direction if d == DIRECTION . OUT : self . src . endpoints . append ( self ) elif d == DIRECTION . IN or d == DIRECTION . INOUT : self . dst . drivers . append ( self ) else : raise NotImplementedError ( d )


def getInternSig(self):
        """
        return signal inside unit which has this port
        """
        d = self.direction
        if d == DIRECTION.IN:
            return self.dst
        elif d == DIRECTION.OUT:
            return self.src
        else:
            raise NotImplementedError(d)

def getInternSig ( self ) : d = self . direction if d == DIRECTION . IN : return self . dst elif d == DIRECTION . OUT : return self . src else : raise NotImplementedError ( d )


def isEvDependentOn(sig, process) -> bool:
    """
    Check if hdl process has event depenency on signal
    """
    if sig is None:
        return False

    return process in sig.simFallingSensProcs\
        or process in sig.simRisingSensProcs

def isEvDependentOn ( sig , process ) -> bool : if sig is None : return False return process in sig . simFallingSensProcs or process in sig . simRisingSensProcs


def _add_process(self, proc, priority) -> None:
        """
        Schedule process on actual time with specified priority
        """
        self._events.push(self.now, priority, proc)

def _add_process ( self , proc , priority ) -> None : self . _events . push ( self . now , priority , proc )


def _addHdlProcToRun(self, trigger: SimSignal, proc) -> None:
        """
        Add hdl process to execution queue

        :param trigger: instance of SimSignal
        :param proc: python generator function representing HDL process
        """
        # first process in time has to plan executing of apply values on the
        # end of this time
        if not self._applyValPlaned:
            # (apply on end of this time to minimalize process reevaluation)
            self._scheduleApplyValues()

        if isEvDependentOn(trigger, proc):
            if self.now == 0:
                return  # pass event dependent on startup
            self._seqProcsToRun.append(proc)
        else:
            self._combProcsToRun.append(proc)

def _addHdlProcToRun ( self , trigger : SimSignal , proc ) -> None : if not self . _applyValPlaned : self . _scheduleApplyValues ( ) if isEvDependentOn ( trigger , proc ) : if self . now == 0 : return self . _seqProcsToRun . append ( proc ) else : self . _combProcsToRun . append ( proc )


def _scheduleCombUpdateDoneEv(self) -> Event:
        """
        Schedule combUpdateDoneEv event to let agents know that current
        delta step is ending and values from combinational logic are stable
        """
        assert not self._combUpdateDonePlaned, self.now
        cud = Event(self)
        cud.process_to_wake.append(self.__deleteCombUpdateDoneEv())
        self._add_process(cud, PRIORITY_AGENTS_UPDATE_DONE)
        self._combUpdateDonePlaned = True
        self.combUpdateDoneEv = cud
        return cud

def _scheduleCombUpdateDoneEv ( self ) -> Event : assert not self . _combUpdateDonePlaned , self . now cud = Event ( self ) cud . process_to_wake . append ( self . __deleteCombUpdateDoneEv ( ) ) self . _add_process ( cud , PRIORITY_AGENTS_UPDATE_DONE ) self . _combUpdateDonePlaned = True self . combUpdateDoneEv = cud return cud


def _scheduleApplyValues(self) -> None:
        """
        Apply stashed values to signals
        """
        assert not self._applyValPlaned, self.now
        self._add_process(self._applyValues(), PRIORITY_APPLY_COMB)
        self._applyValPlaned = True

        if self._runSeqProcessesPlaned:
            # if runSeqProcesses is already scheduled
            return

        assert not self._seqProcsToRun and not self._runSeqProcessesPlaned, self.now
        self._add_process(self._runSeqProcesses(), PRIORITY_APPLY_SEQ)
        self._runSeqProcessesPlaned = True

def _scheduleApplyValues ( self ) -> None : assert not self . _applyValPlaned , self . now self . _add_process ( self . _applyValues ( ) , PRIORITY_APPLY_COMB ) self . _applyValPlaned = True if self . _runSeqProcessesPlaned : return assert not self . _seqProcsToRun and not self . _runSeqProcessesPlaned , self . now self . _add_process ( self . _runSeqProcesses ( ) , PRIORITY_APPLY_SEQ ) self . _runSeqProcessesPlaned = True


def _conflictResolveStrategy(self, newValue: set)\
            -> Tuple[Callable[[Value], bool], bool]:
        """
        This functions resolves write conflicts for signal

        :param actionSet: set of actions made by process
        """

        invalidate = False
        resLen = len(newValue)
        if resLen == 3:
            # update for item in array
            val, indexes, isEvDependent = newValue
            return (mkArrayUpdater(val, indexes, invalidate), isEvDependent)
        else:
            # update for simple signal
            val, isEvDependent = newValue
            return (mkUpdater(val, invalidate), isEvDependent)

def _conflictResolveStrategy ( self , newValue : set ) -> Tuple [ Callable [ [ Value ] , bool ] , bool ] : invalidate = False resLen = len ( newValue ) if resLen == 3 : val , indexes , isEvDependent = newValue return ( mkArrayUpdater ( val , indexes , invalidate ) , isEvDependent ) else : val , isEvDependent = newValue return ( mkUpdater ( val , invalidate ) , isEvDependent )


def _runCombProcesses(self) -> None:
        """
        Delta step for combinational processes
        """
        for proc in self._combProcsToRun:
            cont = self._outputContainers[proc]
            proc(self, cont)
            for sigName, sig in cont._all_signals:
                newVal = getattr(cont, sigName)
                if newVal is not None:
                    res = self._conflictResolveStrategy(newVal)
                    # prepare update
                    updater, isEvDependent = res
                    self._valuesToApply.append(
                        (sig, updater, isEvDependent, proc))
                    setattr(cont, sigName, None)
                    # else value is latched

        self._combProcsToRun = UniqList()

def _runCombProcesses ( self ) -> None : for proc in self . _combProcsToRun : cont = self . _outputContainers [ proc ] proc ( self , cont ) for sigName , sig in cont . _all_signals : newVal = getattr ( cont , sigName ) if newVal is not None : res = self . _conflictResolveStrategy ( newVal ) updater , isEvDependent = res self . _valuesToApply . append ( ( sig , updater , isEvDependent , proc ) ) setattr ( cont , sigName , None ) self . _combProcsToRun = UniqList ( )


def _runSeqProcesses(self) -> Generator[None, None, None]:
        """
        Delta step for event dependent processes
        """
        updates = []
        for proc in self._seqProcsToRun:
            try:
                outContainer = self._outputContainers[proc]
            except KeyError:
                # processes does not have to have outputs
                outContainer = None

            proc(self, outContainer)

            if outContainer is not None:
                updates.append(outContainer)

        self._seqProcsToRun = UniqList()
        self._runSeqProcessesPlaned = False

        for cont in updates:
            for sigName, sig in cont._all_signals:
                newVal = getattr(cont, sigName)
                if newVal is not None:
                    v = self._conflictResolveStrategy(newVal)
                    updater, _ = v
                    sig.simUpdateVal(self, updater)
                    setattr(cont, sigName, None)
        return
        yield

def _runSeqProcesses ( self ) -> Generator [ None , None , None ] : updates = [ ] for proc in self . _seqProcsToRun : try : outContainer = self . _outputContainers [ proc ] except KeyError : outContainer = None proc ( self , outContainer ) if outContainer is not None : updates . append ( outContainer ) self . _seqProcsToRun = UniqList ( ) self . _runSeqProcessesPlaned = False for cont in updates : for sigName , sig in cont . _all_signals : newVal = getattr ( cont , sigName ) if newVal is not None : v = self . _conflictResolveStrategy ( newVal ) updater , _ = v sig . simUpdateVal ( self , updater ) setattr ( cont , sigName , None ) return yield


def _applyValues(self) -> Generator[None, None, None]:
        """
        Perform delta step by writing stacked values to signals
        """
        va = self._valuesToApply
        self._applyValPlaned = False

        # log if there are items to log
        lav = self.config.logApplyingValues
        if va and lav:
            lav(self, va)
        self._valuesToApply = []

        # apply values to signals, values can overwrite each other
        # but each signal should be driven by only one process and
        # it should resolve value collision
        addSp = self._seqProcsToRun.append
        for s, vUpdater, isEventDependent, comesFrom in va:
            if isEventDependent:
                # now=0 and this was process initialization or async reg
                addSp(comesFrom)
            else:
                # regular combinational process
                s.simUpdateVal(self, vUpdater)

        self._runCombProcesses()

        # processes triggered from simUpdateVal can add new values
        if self._valuesToApply and not self._applyValPlaned:
            self._scheduleApplyValues()

        return
        yield

def _applyValues ( self ) -> Generator [ None , None , None ] : va = self . _valuesToApply self . _applyValPlaned = False lav = self . config . logApplyingValues if va and lav : lav ( self , va ) self . _valuesToApply = [ ] addSp = self . _seqProcsToRun . append for s , vUpdater , isEventDependent , comesFrom in va : if isEventDependent : addSp ( comesFrom ) else : s . simUpdateVal ( self , vUpdater ) self . _runCombProcesses ( ) if self . _valuesToApply and not self . _applyValPlaned : self . _scheduleApplyValues ( ) return yield


def read(self, sig) -> Value:
        """
        Read value from signal or interface
        """
        try:
            v = sig._val
        except AttributeError:
            v = sig._sigInside._val

        return v.clone()

def read ( self , sig ) -> Value : try : v = sig . _val except AttributeError : v = sig . _sigInside . _val return v . clone ( )


def write(self, val, sig: SimSignal)-> None:
        """
        Write value to signal or interface.
        """
        # get target RtlSignal
        try:
            simSensProcs = sig.simSensProcs
        except AttributeError:
            sig = sig._sigInside
            simSensProcs = sig.simSensProcs

        # type cast of input value
        t = sig._dtype

        if isinstance(val, Value):
            v = val.clone()
            v = v._auto_cast(t)
        else:
            v = t.fromPy(val)

        # can not update value in signal directly due singnal proxies
        sig.simUpdateVal(self, lambda curentV: (
            valueHasChanged(curentV, v), v))

        if not self._applyValPlaned:
            if not (simSensProcs or
                    sig.simRisingSensProcs or
                    sig.simFallingSensProcs):
                # signal value was changed but there are no sensitive processes
                # to it because of this _applyValues is never planed
                # and should be
                self._scheduleApplyValues()
            elif (sig._writeCallbacks or
                  sig._writeCallbacksToEn):
                # signal write did not caused any change on any other signal
                # but there are still simulation agets waiting on
                # updateComplete event
                self._scheduleApplyValues()

def write ( self , val , sig : SimSignal ) -> None : try : simSensProcs = sig . simSensProcs except AttributeError : sig = sig . _sigInside simSensProcs = sig . simSensProcs t = sig . _dtype if isinstance ( val , Value ) : v = val . clone ( ) v = v . _auto_cast ( t ) else : v = t . fromPy ( val ) sig . simUpdateVal ( self , lambda curentV : ( valueHasChanged ( curentV , v ) , v ) ) if not self . _applyValPlaned : if not ( simSensProcs or sig . simRisingSensProcs or sig . simFallingSensProcs ) : self . _scheduleApplyValues ( ) elif ( sig . _writeCallbacks or sig . _writeCallbacksToEn ) : self . _scheduleApplyValues ( )


def add_process(self, proc) -> None:
        """
        Add process to events with default priority on current time
        """
        self._events.push(self.now, PRIORITY_NORMAL, proc)

def add_process ( self , proc ) -> None : self . _events . push ( self . now , PRIORITY_NORMAL , proc )


def simUnit(self, synthesisedUnit: Unit, until: float, extraProcesses=[]):
        """
        Run simulation for Unit instance
        """
        beforeSim = self.config.beforeSim
        if beforeSim is not None:
            beforeSim(self, synthesisedUnit)

        add_proc = self.add_process
        for p in extraProcesses:
            add_proc(p(self))

        self._initUnitSignals(synthesisedUnit)
        self.run(until)

def simUnit ( self , synthesisedUnit : Unit , until : float , extraProcesses = [ ] ) : beforeSim = self . config . beforeSim if beforeSim is not None : beforeSim ( self , synthesisedUnit ) add_proc = self . add_process for p in extraProcesses : add_proc ( p ( self ) ) self . _initUnitSignals ( synthesisedUnit ) self . run ( until )


def _mkOp(fn):
    """
    Function to create variadic operator function

    :param fn: function to perform binary operation
    """
    def op(*operands, key=None) -> RtlSignalBase:
        """
        :param operands: variadic parameter of input uperands
        :param key: optional function applied on every operand
            before processing
        """
        assert operands, operands
        top = None
        if key is not None:
            operands = map(key, operands)

        for s in operands:
            if top is None:
                top = s
            else:
                top = fn(top, s)
        return top

    return op

def _mkOp ( fn ) : def op ( * operands , key = None ) -> RtlSignalBase : assert operands , operands top = None if key is not None : operands = map ( key , operands ) for s in operands : if top is None : top = s else : top = fn ( top , s ) return top return op


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 ternaryOpsToIf ( statements ) : 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 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
        )

def
HWProcess
(
cls
,
proc
,
ctx
)
:
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
(
,
,
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
:
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
)


def hash_distance(left_hash, right_hash):
    """Compute the hamming distance between two hashes"""
    if len(left_hash) != len(right_hash):
        raise ValueError('Hamming distance requires two strings of equal length')

    return sum(map(lambda x: 0 if x[0] == x[1] else 1, zip(left_hash, right_hash)))


def average_hash(image_path, hash_size=8):
    """ Compute the average hash of the given image. """
    with open(image_path, 'rb') as f:
        # Open the image, resize it and convert it to black & white.
        image = Image.open(f).resize((hash_size, hash_size), Image.ANTIALIAS).convert('L')
        pixels = list(image.getdata())

    avg = sum(pixels) / len(pixels)

    # Compute the hash based on each pixels value compared to the average.
    bits = "".join(map(lambda pixel: '1' if pixel > avg else '0', pixels))
    hashformat = "0{hashlength}x".format(hashlength=hash_size ** 2 // 4)
    return int(bits, 2).__format__(hashformat)

def average_hash ( image_path , hash_size = 8 ) : with open ( image_path , 'rb' ) as f : image = Image . open ( f ) . resize ( ( hash_size , hash_size ) , Image . ANTIALIAS ) . convert ( 'L' ) pixels = list ( image . getdata ( ) ) avg = sum ( pixels ) / len ( pixels ) bits = "" . join ( map ( lambda pixel : '1' if pixel > avg else '0' , pixels ) ) hashformat = "0{hashlength}x" . format ( hashlength = hash_size ** 2 // 4 ) return int ( bits , 2 ) . __format__ ( hashformat )

Compute the average hash of the given image .


def distance(image_path, other_image_path):
    """ Compute the hamming distance between two images"""
    image_hash = average_hash(image_path)
    other_image_hash = average_hash(other_image_path)

    return hash_distance(image_hash, other_image_hash)


def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the Vizio media player platform."""
    host = config.get(CONF_HOST)
    token = config.get(CONF_ACCESS_TOKEN)
    name = config.get(CONF_NAME)
    volume_step = config.get(CONF_VOLUME_STEP)
    device_type = config.get(CONF_DEVICE_CLASS)
    device = VizioDevice(host, token, name, volume_step, device_type)
    if device.validate_setup() is False:
        _LOGGER.error("Failed to set up Vizio platform, "
                      "please check if host and API key are correct")
        return
    elif (token is None or token == "") and device_type == "tv":
        _LOGGER.error("Failed to set up Vizio platform, "
                      "if device_class is 'tv' then an auth_token needs "
                      "to be provided, otherwise if device_class is "
                      "'soundbar' then add the right device_class to config")
        return

    if config.get(CONF_SUPPRESS_WARNING):
        from requests.packages import urllib3
        _LOGGER.warning("InsecureRequestWarning is disabled "
                        "because of Vizio platform configuration")
        urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    add_entities([device], True)

Set up the Vizio media player platform .


def update(self):
        """Retrieve latest state of the device."""
        is_on = self._device.get_power_state()

        if is_on:
            self._state = STATE_ON

            volume = self._device.get_current_volume()
            if volume is not None:
                self._volume_level = float(volume) / self._max_volume

            input_ = self._device.get_current_input()
            if input_ is not None:
                self._current_input = input_.meta_name

            inputs = self._device.get_inputs()
            if inputs is not None:
                self._available_inputs = [input_.name for input_ in inputs]

        else:
            if is_on is None:
                self._state = None
            else:
                self._state = STATE_OFF

            self._volume_level = None
            self._current_input = None
            self._available_inputs = None

def update ( self ) : is_on = self . _device . get_power_state ( ) if is_on : self . _state = STATE_ON volume = self . _device . get_current_volume ( ) if volume is not None : self . _volume_level = float ( volume ) / self . _max_volume input_ = self . _device . get_current_input ( ) if input_ is not None : self . _current_input = input_ . meta_name inputs = self . _device . get_inputs ( ) if inputs is not None : self . _available_inputs = [ input_ . name for input_ in inputs ] else : if is_on is None : self . _state = None else : self . _state = STATE_OFF self . _volume_level = None self . _current_input = None self . _available_inputs = None


def mute_volume(self, mute):
        """Mute the volume."""
        if mute:
            self._device.mute_on()
        else:
            self._device.mute_off()

def mute_volume ( self , mute ) : if mute : self . _device . mute_on ( ) else : self . _device . mute_off ( )


def volume_up(self):
        """Increasing volume of the device."""
        self._volume_level += self._volume_step / self._max_volume
        self._device.vol_up(num=self._volume_step)

def volume_up ( self ) : self . _volume_level += self . _volume_step / self . _max_volume self . _device . vol_up ( num = self . _volume_step )


def volume_down(self):
        """Decreasing volume of the device."""
        self._volume_level -= self._volume_step / self._max_volume
        self._device.vol_down(num=self._volume_step)

def volume_down ( self ) : self . _volume_level -= self . _volume_step / self . _max_volume self . _device . vol_down ( num = self . _volume_step )


def set_volume_level(self, volume):
        """Set volume level."""
        if self._volume_level is not None:
            if volume > self._volume_level:
                num = int(self._max_volume * (volume - self._volume_level))
                self._volume_level = volume
                self._device.vol_up(num=num)
            elif volume < self._volume_level:
                num = int(self._max_volume * (self._volume_level - volume))
                self._volume_level = volume
                self._device.vol_down(num=num)

def set_volume_level ( self , volume ) : if self . _volume_level is not None : if volume > self . _volume_level : num = int ( self . _max_volume * ( volume - self . _volume_level ) ) self . _volume_level = volume self . _device . vol_up ( num = num ) elif volume < self . _volume_level : num = int ( self . _max_volume * ( self . _volume_level - volume ) ) self . _volume_level = volume self . _device . vol_down ( num = num )


def reset(self):
        '''Restores the starting position.'''
        self.piece_bb = [
                BB_VOID,                       # NONE
                BB_RANK_C | BB_RANK_G,         # PAWN
                BB_A1 | BB_I1 | BB_A9 | BB_I9, # LANCE
                BB_A2 | BB_A8 | BB_I2 | BB_I8, # KNIGHT
                BB_A3 | BB_A7 | BB_I3 | BB_I7, # SILVER
                BB_A4 | BB_A6 | BB_I4 | BB_I6, # GOLD
                BB_B2 | BB_H8,                 # BISHOP
                BB_B8 | BB_H2,                 # ROOK
                BB_A5 | BB_I5,                 # KING
                BB_VOID,                       # PROM_PAWN
                BB_VOID,                       # PROM_LANCE
                BB_VOID,                       # PROM_KNIGHT
                BB_VOID,                       # PROM_SILVER
                BB_VOID,                       # PROM_BISHOP
                BB_VOID,                       # PROM_ROOK
        ]

        self.pieces_in_hand = [collections.Counter(), collections.Counter()]

        self.occupied = Occupied(BB_RANK_G | BB_H2 | BB_H8 | BB_RANK_I, BB_RANK_A | BB_B2 | BB_B8 | BB_RANK_C)

        self.king_squares = [I5, A5]
        self.pieces = [NONE for i in SQUARES]

        for i in SQUARES:
            mask = BB_SQUARES[i]
            for piece_type in PIECE_TYPES:
                if mask & self.piece_bb[piece_type]:
                    self.pieces[i] = piece_type

        self.turn = BLACK
        self.move_number = 1
        self.captured_piece_stack = collections.deque()
        self.move_stack = collections.deque()
        self.incremental_zobrist_hash = self.board_zobrist_hash(DEFAULT_RANDOM_ARRAY)
        self.transpositions = collections.Counter((self.zobrist_hash(), ))

def reset ( self ) : self . piece_bb = [ BB_VOID , BB_RANK_C | BB_RANK_G , BB_A1 | BB_I1 | BB_A9 | BB_I9 , BB_A2 | BB_A8 | BB_I2 | BB_I8 , BB_A3 | BB_A7 | BB_I3 | BB_I7 , BB_A4 | BB_A6 | BB_I4 | BB_I6 , BB_B2 | BB_H8 , BB_B8 | BB_H2 , BB_A5 | BB_I5 , BB_VOID , BB_VOID , BB_VOID , BB_VOID , BB_VOID , BB_VOID , ] self . pieces_in_hand = [ collections . Counter ( ) , collections . Counter ( ) ] self . occupied = Occupied ( BB_RANK_G | BB_H2 | BB_H8 | BB_RANK_I , BB_RANK_A | BB_B2 | BB_B8 | BB_RANK_C ) self . king_squares = [ I5 , A5 ] self . pieces = [ NONE for i in SQUARES ] for i in SQUARES : mask = BB_SQUARES [ i ] for piece_type in PIECE_TYPES : if mask & self . piece_bb [ piece_type ] : self . pieces [ i ] = piece_type self . turn = BLACK self . move_number = 1 self . captured_piece_stack = collections . deque ( ) self . move_stack = collections . deque ( ) self . incremental_zobrist_hash = self . board_zobrist_hash ( DEFAULT_RANDOM_ARRAY ) self . transpositions = collections . Counter ( ( self . zobrist_hash ( ) , ) )


def piece_at(self, square):
        '''Gets the piece at the given square.'''
        mask = BB_SQUARES[square]
        color = int(bool(self.occupied[WHITE] & mask))

        piece_type = self.piece_type_at(square)
        if piece_type:
            return Piece(piece_type, color)

def piece_at ( self , square ) : mask = BB_SQUARES [ square ] color = int ( bool ( self . occupied [ WHITE ] & mask ) ) piece_type = self . piece_type_at ( square ) if piece_type : return Piece ( piece_type , color )


def remove_piece_at(self, square, into_hand=False):
        '''Removes a piece from the given square if present.'''
        piece_type = self.piece_type_at(square)

        if piece_type == NONE:
            return

        if into_hand:
            self.add_piece_into_hand(piece_type, self.turn)

        mask = BB_SQUARES[square]

        self.piece_bb[piece_type] ^= mask

        color = int(bool(self.occupied[WHITE] & mask))

        self.pieces[square] = NONE
        self.occupied.ixor(mask, color, square)

        # Update incremental zobrist hash.
        if color == BLACK:
            piece_index = (piece_type - 1) * 2
        else:
            piece_index = (piece_type - 1) * 2 + 1
        self.incremental_zobrist_hash ^= DEFAULT_RANDOM_ARRAY[81 * piece_index + 9 * rank_index(square) + file_index(square)]

def remove_piece_at ( self , square , into_hand = False ) : piece_type = self . piece_type_at ( square ) if piece_type == NONE : return if into_hand : self . add_piece_into_hand ( piece_type , self . turn ) mask = BB_SQUARES [ square ] self . piece_bb [ piece_type ] ^= mask color = int ( bool ( self . occupied [ WHITE ] & mask ) ) self . pieces [ square ] = NONE self . occupied . ixor ( mask , color , square ) if color == BLACK : piece_index = ( piece_type - 1 ) * 2 else : piece_index = ( piece_type - 1 ) * 2 + 1 self . incremental_zobrist_hash ^= DEFAULT_RANDOM_ARRAY [ 81 * piece_index + 9 * rank_index ( square ) + file_index ( square ) ]

Removes a piece from the given square if present .


def set_piece_at(self, square, piece, from_hand=False, into_hand=False):
        '''Sets a piece at the given square. An existing piece is replaced.'''
        if from_hand:
            self.remove_piece_from_hand(piece.piece_type, self.turn)

        self.remove_piece_at(square, into_hand)

        self.pieces[square] = piece.piece_type

        mask = BB_SQUARES[square]

        piece_type = piece.piece_type

        self.piece_bb[piece_type] |= mask

        if piece_type == KING:
            self.king_squares[piece.color] = square

        self.occupied.ixor(mask, piece.color, square)

        # Update incremental zorbist hash.
        if piece.color == BLACK:
            piece_index = (piece.piece_type - 1) * 2
        else:
            piece_index = (piece.piece_type - 1) * 2 + 1
        self.incremental_zobrist_hash ^= DEFAULT_RANDOM_ARRAY[81 * piece_index + 9 * rank_index(square) + file_index(square)]

def set_piece_at ( self , square , piece , from_hand = False , into_hand = False ) : if from_hand : self . remove_piece_from_hand ( piece . piece_type , self . turn ) self . remove_piece_at ( square , into_hand ) self . pieces [ square ] = piece . piece_type mask = BB_SQUARES [ square ] piece_type = piece . piece_type self . piece_bb [ piece_type ] |= mask if piece_type == KING : self . king_squares [ piece . color ] = square self . occupied . ixor ( mask , piece . color , square ) if piece . color == BLACK : piece_index = ( piece . piece_type - 1 ) * 2 else : piece_index = ( piece . piece_type - 1 ) * 2 + 1 self . incremental_zobrist_hash ^= DEFAULT_RANDOM_ARRAY [ 81 * piece_index + 9 * rank_index ( square ) + file_index ( square ) ]

Sets a piece at the given square . An existing piece is replaced .


def is_suicide_or_check_by_dropping_pawn(self, move):
        '''
        Checks if the given move would move would leave the king in check or
        put it into check.
        '''

        self.push(move)
        is_suicide = self.was_suicide()
        is_check_by_dropping_pawn = self.was_check_by_dropping_pawn(move)
        self.pop()
        return is_suicide or is_check_by_dropping_pawn

def is_suicide_or_check_by_dropping_pawn ( self , move ) : self . push ( move ) is_suicide = self . was_suicide ( ) is_check_by_dropping_pawn = self . was_check_by_dropping_pawn ( move ) self . pop ( ) return is_suicide or is_check_by_dropping_pawn

Checks if the given move would move would leave the king in check or put it into check .


def was_suicide(self):
        '''
        Checks if the king of the other side is attacked. Such a position is not
        valid and could only be reached by an illegal move.
        '''
        return self.is_attacked_by(self.turn, self.king_squares[self.turn ^ 1])

def was_suicide ( self ) : return self . is_attacked_by ( self . turn , self . king_squares [ self . turn ^ 1 ] )

Checks if the king of the other side is attacked . Such a position is not valid and could only be reached by an illegal move .


def is_game_over(self):
        '''
        Checks if the game is over due to checkmate, stalemate or
        fourfold repetition.
        '''

        # Stalemate or checkmate.
        try:
            next(self.generate_legal_moves().__iter__())
        except StopIteration:
            return True

        # Fourfold repetition.
        if self.is_fourfold_repetition():
            return True

        return False

def is_game_over ( self ) : try : next ( self . generate_legal_moves ( ) . __iter__ ( ) ) except StopIteration : return True if self . is_fourfold_repetition ( ) : return True return False

Checks if the game is over due to checkmate stalemate or fourfold repetition .


def is_checkmate(self):
        '''Checks if the current position is a checkmate.'''
        if not self.is_check():
            return False

        try:
            next(self.generate_legal_moves().__iter__())
            return False
        except StopIteration:
            return True

def is_checkmate ( self ) : if not self . is_check ( ) : return False try : next ( self . generate_legal_moves ( ) . __iter__ ( ) ) return False except StopIteration : return True

Checks if the current position is a checkmate .


def is_fourfold_repetition(self):
        '''
        a game is ended if a position occurs for the fourth time
        on consecutive alternating moves.
        '''
        zobrist_hash = self.zobrist_hash()

        # A minimum amount of moves must have been played and the position
        # in question must have appeared at least four times.
        if self.transpositions[zobrist_hash] < 4:
            return False

        return True

def is_fourfold_repetition ( self ) : zobrist_hash = self . zobrist_hash ( ) if self . transpositions [ zobrist_hash ] < 4 : return False return True

a game is ended if a position occurs for the fourth time on consecutive alternating moves .


def pop(self):
        '''
        Restores the previous position and returns the last move from the stack.
        '''
        move = self.move_stack.pop()

        # Update transposition table.
        self.transpositions.subtract((self.zobrist_hash(), ))

        # Decrement move number.
        self.move_number -= 1

        # Restore state.
        captured_piece_type = self.captured_piece_stack.pop()
        captured_piece_color = self.turn

        # On a null move simply swap the turn.
        if not move:
            self.turn ^= 1
            return move

        # Restore the source square.
        piece_type = self.piece_type_at(move.to_square)
        if move.promotion:
            piece_type = PIECE_PROMOTED.index(piece_type)

        if move.from_square is None:
            self.add_piece_into_hand(piece_type, self.turn ^ 1)
        else:
            self.set_piece_at(move.from_square, Piece(piece_type, self.turn ^ 1))

        # Restore target square.
        if captured_piece_type:
            self.remove_piece_from_hand(captured_piece_type, captured_piece_color ^ 1)
            self.set_piece_at(move.to_square, Piece(captured_piece_type, captured_piece_color))
        else:
            self.remove_piece_at(move.to_square)

        # Swap turn.
        self.turn ^= 1

        return move

def pop ( self ) : move = self . move_stack . pop ( ) self . transpositions . subtract ( ( self . zobrist_hash ( ) , ) ) self . move_number -= 1 captured_piece_type = self . captured_piece_stack . pop ( ) captured_piece_color = self . turn if not move : self . turn ^= 1 return move piece_type = self . piece_type_at ( move . to_square ) if move . promotion : piece_type = PIECE_PROMOTED . index ( piece_type ) if move . from_square is None : self . add_piece_into_hand ( piece_type , self . turn ^ 1 ) else : self . set_piece_at ( move . from_square , Piece ( piece_type , self . turn ^ 1 ) ) if captured_piece_type : self . remove_piece_from_hand ( captured_piece_type , captured_piece_color ^ 1 ) self . set_piece_at ( move . to_square , Piece ( captured_piece_type , captured_piece_color ) ) else : self . remove_piece_at ( move . to_square ) self . turn ^= 1 return move

Restores the previous position and returns the last move from the stack .


def sfen(self):
        '''
        Gets an SFEN representation of the current position.
        '''
        sfen = []
        empty = 0

        # Position part.
        for square in SQUARES:
            piece = self.piece_at(square)

            if not piece:
                empty += 1
            else:
                if empty:
                    sfen.append(str(empty))
                    empty = 0
                sfen.append(piece.symbol())

            if BB_SQUARES[square] & BB_FILE_1:
                if empty:
                    sfen.append(str(empty))
                    empty = 0

                if square != I1:
                    sfen.append('/')

        sfen.append(' ')

        # Side to move.
        if self.turn == WHITE:
            sfen.append('w')
        else:
            sfen.append('b')

        sfen.append(' ')

        # Pieces in hand
        pih_len = 0
        for color in COLORS:
            p = self.pieces_in_hand[color]
            pih_len += len(p)
            for piece_type in sorted(p.keys(), reverse=True):
                if p[piece_type] >= 1:
                    if p[piece_type] > 1:
                        sfen.append(str(p[piece_type]))
                    piece = Piece(piece_type, color)
                    sfen.append(piece.symbol())
        if pih_len == 0:
            sfen.append('-')

        sfen.append(' ')

        # Move count
        sfen.append(str(self.move_number))

        return ''.join(sfen)

def
sfen
(
self
)
:
sfen
=
[
]
empty
=
0
for
square
in
SQUARES
:
piece
=
self
.
piece_at
(
square
)
if
not
piece
:
empty
+=
1
else
:
if
empty
:
sfen
.
append
(
str
(
empty
)
)
empty
=
0
sfen
.
append
(
piece
.
symbol
(
)
)
if
BB_SQUARES
[
square
]
&
BB_FILE_1
:
if
empty
:
sfen
.
append
(
str
(
empty
)
)
empty
=
0
if
square
!=
I1
:
sfen
.
append
(
'/'
)
sfen
.
append
(
' '
)
if
self
.
turn
==
WHITE
:
sfen
.
append
(
'w'
)
else
:
sfen
.
append
(
'b'
)
sfen
.
append
(
' '
)
pih_len
=
0
for
color
in
COLORS
:
p
=
self
.
pieces_in_hand
[
color
]
pih_len
+=
len
(
p
)
for
piece_type
in
sorted
(
p
.
keys
(
)
,
reverse
=
True
)
:
if
p
[
piece_type
]
>=
1
:
if
p
[
piece_type
]
>
1
:
sfen
.
append
(
str
(
p
[
piece_type
]
)
)
piece
=
Piece
(
piece_type
,
color
)
sfen
.
append
(
piece
.
symbol
(
)
)
if
pih_len
==
0
:
sfen
.
append
(
'-'
)
sfen
.
append
(
' '
)
sfen
.
append
(
str
(
self
.
move_number
)
)
return
''
.
join
(
sfen
)

Gets an SFEN representation of the current position .


def push_usi(self, usi):
        '''
        Parses a move in standard coordinate notation, makes the move and puts
        it on the the move stack.
        Raises `ValueError` if neither legal nor a null move.
        Returns the move.
        '''
        move = Move.from_usi(usi)
        self.push(move)
        return move

def push_usi ( self , usi ) : move = Move . from_usi ( usi ) self . push ( move ) return move

Parses a move in standard coordinate notation makes the move and puts it on the the move stack . Raises ValueError if neither legal nor a null move . Returns the move .


def zobrist_hash(self, array=None):
        '''
        Returns a Zobrist hash of the current position.
        '''
        # Hash in the board setup.
        zobrist_hash = self.board_zobrist_hash(array)

        if array is None:
            array = DEFAULT_RANDOM_ARRAY

        if self.turn == WHITE:
            zobrist_hash ^= array[2268]

        # pieces in hand pattern is
        # 19 * 5 * 5 * 5 * 5 * 3 * 3 = 106875 < pow(2, 17)
        # just checking black side is okay in normal state
        i = (
                self.pieces_in_hand[BLACK][ROOK] * 35625 +
                self.pieces_in_hand[BLACK][BISHOP] * 11875 +
                self.pieces_in_hand[BLACK][GOLD] * 2375 +
                self.pieces_in_hand[BLACK][SILVER] * 475 +
                self.pieces_in_hand[BLACK][KNIGHT] * 95 +
                self.pieces_in_hand[BLACK][LANCE] * 19 +
                self.pieces_in_hand[BLACK][PAWN])
        bit = bit_scan(i)
        while bit != -1 and bit is not None:
            zobrist_hash ^= array[2269 + bit]
            bit = bit_scan(i, bit + 1)

        return zobrist_hash

def zobrist_hash ( self , array = None ) : zobrist_hash = self . board_zobrist_hash ( array ) if array is None : array = DEFAULT_RANDOM_ARRAY if self . turn == WHITE : zobrist_hash ^= array [ 2268 ] i = ( self . pieces_in_hand [ BLACK ] [ ROOK ] * 35625 + self . pieces_in_hand [ BLACK ] [ BISHOP ] * 11875 + self . pieces_in_hand [ BLACK ] [ GOLD ] * 2375 + self . pieces_in_hand [ BLACK ] [ SILVER ] * 475 + self . pieces_in_hand [ BLACK ] [ KNIGHT ] * 95 + self . pieces_in_hand [ BLACK ] [ LANCE ] * 19 + self . pieces_in_hand [ BLACK ] [ PAWN ] ) bit = bit_scan ( i ) while bit != - 1 and bit is not None : zobrist_hash ^= array [ 2269 + bit ] bit = bit_scan ( i , bit + 1 ) return zobrist_hash

Returns a Zobrist hash of the current position .


def symbol(self):
        '''
        Gets the symbol `p`, `l`, `n`, etc.
        '''
        if self.color == BLACK:
            return PIECE_SYMBOLS[self.piece_type].upper()
        else:
            return PIECE_SYMBOLS[self.piece_type]

def symbol ( self ) : if self . color == BLACK : return PIECE_SYMBOLS [ self . piece_type ] . upper ( ) else : return PIECE_SYMBOLS [ self . piece_type ]


def from_symbol(cls, symbol):
        '''
        Creates a piece instance from a piece symbol.
        Raises `ValueError` if the symbol is invalid.
        '''
        if symbol.lower() == symbol:
            return cls(PIECE_SYMBOLS.index(symbol), WHITE)
        else:
            return cls(PIECE_SYMBOLS.index(symbol.lower()), BLACK)

def from_symbol ( cls , symbol ) : if symbol . lower ( ) == symbol : return cls ( PIECE_SYMBOLS . index ( symbol ) , WHITE ) else : return cls ( PIECE_SYMBOLS . index ( symbol . lower ( ) ) , BLACK )

Creates a piece instance from a piece symbol . Raises ValueError if the symbol is invalid .


def usi(self):
        '''
        Gets an USI string for the move.
        For example a move from 7A to 8A would be `7a8a` or `7a8a+` if it is
        a promotion.
        '''
        if self:
            if self.drop_piece_type:
                return '{0}*{1}'.format(PIECE_SYMBOLS[self.drop_piece_type].upper(), SQUARE_NAMES[self.to_square])
            else:
                return SQUARE_NAMES[self.from_square] + SQUARE_NAMES[self.to_square] + \
                       ('+' if self.promotion else '')
        else:
            return '0000'

def usi ( self ) : if self : if self . drop_piece_type : return '{0}*{1}' . format ( PIECE_SYMBOLS [ self . drop_piece_type ] . upper ( ) , SQUARE_NAMES [ self . to_square ] ) else : return SQUARE_NAMES [ self . from_square ] + SQUARE_NAMES [ self . to_square ] + ( '+' if self . promotion else '' ) else : return '0000'

Gets an USI string for the move . For example a move from 7A to 8A would be 7a8a or 7a8a + if it is a promotion .


def from_usi(cls, usi):
        '''
        Parses an USI string.
        Raises `ValueError` if the USI string is invalid.
        '''
        if usi == '0000':
            return cls.null()
        elif len(usi) == 4:
            if usi[1] == '*':
                piece = Piece.from_symbol(usi[0])
                return cls(None, SQUARE_NAMES.index(usi[2:4]), False, piece.piece_type)
            else:
                return cls(SQUARE_NAMES.index(usi[0:2]), SQUARE_NAMES.index(usi[2:4]))
        elif len(usi) == 5 and usi[4] == '+':
            return cls(SQUARE_NAMES.index(usi[0:2]), SQUARE_NAMES.index(usi[2:4]), True)
        else:
            raise ValueError('expected usi string to be of length 4 or 5')

Parses an USI string . Raises ValueError if the USI string is invalid .