Пример #1
0
 def _config(self):
     self.DATA_WIDTH = Param(8)
     self.FORMAT = Param(
         ("AxiS_strFormat"
          ": hex: 0x", AxiS_strFormatItem(TypePath("data"), 'x',
                                          32 // 4), ", dec: ",
          AxiS_strFormatItem(TypePath("data"), 'd',
                             BinToBcd.decadic_deciamls_for_bin(32)),
          " is the value of data from example"))
     self.INPUT_T = Param(HStruct((uint32_t, "data"), ))
     self.ENCODING = Param("utf-8")
Пример #2
0
    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

            isPadding = f.name is None

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

        return bitAddr
Пример #3
0
    def walkFlatten(self, offset: int=0,
                    shouldEnterFn=_default_shouldEnterFn
                    ) -> 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 c in self.children:
                    yield from c.walkFlatten(
                        offset,
                        shouldEnterFn)
            elif isinstance(t, (HArray, HStream)):
                itemSize = (self.bitAddrEnd - self.bitAddr) // self.itemCnt
                for i in range(self.itemCnt):
                    if i == 0:
                        c = self.children
                    else:
                        # spot a new array item
                        c = deepcopy(self.children)
                        assert c.rel_field_path == (0,), c.rel_field_path
                        # replace the index
                        c.rel_field_path = TypePath(i, )
                        
                    yield from c.walkFlatten(
                        base + i * itemSize,
                        shouldEnterFn)

            elif isinstance(t, HUnion):
                yield OneOfTransaction(self, offset, shouldEnterFn,
                                       self.children)
            else:
                raise TypeError(t)
Пример #4
0
 def getFieldPath(self):
     """
     Get field path which specifies the location in original HdlType data type
     """
     path = []
     tmpl = self
     while tmpl is not None:
         path.extend(reversed(tmpl.rel_field_path))
         tmpl = tmpl.parent
     return TypePath(*reversed(path))
Пример #5
0
    def _reg(self,
             name: str,
             dtype: HdlType = BIT,
             def_val: Union[int, None, dict, list] = None,
             clk: Union[RtlSignalBase, None, Tuple[RtlSignalBase,
                                                   OpDefinition]] = None,
             rst: Optional[RtlSignalBase] = None) -> RtlSyncSignal:
        """
        Create RTL FF register in this unit

        :param def_val: s default value of this register,
            if this value is specified reset signal of this component is used
            to generate a reset logic
        :param clk: optional clock signal specification,
            (signal or tuple(signal, edge type (AllOps.RISING_EDGE/FALLING_EDGE)))
        :param rst: optional reset signal specification
        :note: rst/rst_n resolution is done from signal type,
            if it is negated type the reset signal is interpreted as rst_n
        :note: if clk or rst is not specified default signal
            from parent unit instance will be used
        """
        if clk is None:
            clk = getClk(self)

        if def_val is None:
            # if no value is specified reset is not required
            rst = None
        elif rst is None:
            rst = getRst(self)

        if isinstance(dtype, HStruct):
            container = HdlType_to_Interface(dtype)
            container._loadDeclarations()
            flattened_def_val = {}
            _flatten_map(TypePath(), def_val, flattened_def_val)
            for path, intf in container._fieldsToInterfaces.items():
                if isinstance(intf, Signal):
                    _def_val = flattened_def_val.get(path, None)
                    intf._sig = self._reg(
                        "%s_%s" %
                        (name,
                         intf._getFullName(separator_getter=lambda x: "_")),
                        intf._dtype,
                        def_val=_def_val)

            return container
        elif isinstance(dtype, HArray):
            raise NotImplementedError()

        return self._ctx.sig(name,
                             dtype=dtype,
                             clk=clk,
                             syncRst=rst,
                             def_val=def_val)
Пример #6
0
    def _loadFromArray(self, dtype: HdlType, bitAddr: int) -> int:
        """
        Parse HArray type to this transaction template instance

        :return: address of it's end
        """
        self.itemCnt = int(dtype.size)
        self.children = TransTmpl(
            dtype.element_t, 0, parent=self,
            origin=(*self.origin, 0),
            rel_field_path=TypePath(0,)
        )
        return bitAddr + self.itemCnt * self.children.bitAddrEnd
Пример #7
0
    def _loadFromUnion(self, dtype: HdlType, bitAddr: int) -> int:
        """
        Parse HUnion type to this transaction template instance

        :return: address of it's end
        """
        for f in dtype.fields.values():
            ch = TransTmpl(f.dtype, 0, parent=self,
                           origin=(*self.origin, f),
                           rel_field_path=TypePath(f.name,),
                           )
            self.children.append(ch)
        return bitAddr + dtype.bit_length()
Пример #8
0
 def __init__(self,
              structT: HStruct,
              field_path: TypePath,
              instantiateFieldFn,
              masterDir=DIRECTION.OUT,
              loadConfig=True):
     Interface.__init__(self, masterDir=masterDir, loadConfig=loadConfig)
     if not field_path:
         field_path = TypePath()
     else:
         assert isinstance(field_path, TypePath), field_path
     self._field_path = field_path
     self._structT = structT
     self._instantiateFieldFn = instantiateFieldFn
     self._fieldsToInterfaces = {}
Пример #9
0
    def _loadFromHStream(self, dtype: HStream, bitAddr: int) -> int:
        """
        Parse HStream type to this transaction template instance

        :return: address of it's end
        """
        self.children = TransTmpl(
            dtype.element_t, 0, parent=self, origin=self.origin,
            rel_field_path=TypePath(0,))

        if not isinstance(dtype.len_min, int) or dtype.len_min != dtype.len_max:
            raise ValueError("This template is ment only"
                             " for types of constant and finite size")

        self.itemCnt = dtype.len_min
        return bitAddr + dtype.element_t.bit_length() * self.itemCnt
Пример #10
0
    def __init__(self,
                 structT: HStruct,
                 field_path: TypePath,
                 instantiateFieldFn,
                 masterDir=DIRECTION.OUT,
                 loadConfig=True):
        Interface.__init__(self, masterDir=masterDir, loadConfig=loadConfig)
        if not field_path:
            field_path = TypePath()
        else:
            assert isinstance(field_path, TypePath), field_path

        self._field_path = field_path
        self._dtype = structT
        assert self._dtype.fields, "Needs to have at least some mebers (othervise this interface is useless)"
        self._instantiateFieldFn = instantiateFieldFn
        self._fieldsToInterfaces = {}
Пример #11
0
 def __init__(self, dtype: HdlType, bitAddr: int=0,
              parent: Optional['TransTmpl']=None,
              origin: Optional[HStructField]=None,
              rel_field_path: TypePath=TypePath()):
     self.parent = parent
     assert isinstance(dtype, HdlType), dtype
     assert isinstance(rel_field_path, TypePath), rel_field_path
     assert parent is None or isinstance(parent, TransTmpl), parent
     if origin is None:
         origin = (dtype,)
     else:
         assert isinstance(origin, tuple), origin
     self.origin = origin
     self.dtype = dtype
     self.children = []
     self.itemCnt = None
     self.rel_field_path = rel_field_path
     self._loadFromHType(dtype, bitAddr)
Пример #12
0
def axiS_strFormat(parent: Unit, name: str, data_width: int, format_str: str,
                   *args, **kwargs):
    """
    Instanciate an :class:`hwtLib.amba.axis_comp.strformat.AxiS_strFormat` using simplified str.format syntax
    The syntax is allows for an utf-8 string with a variable format groups and several escape sequences
    in addition to normal string escape sequences.

    The escape sequences are (same as :func:`str.format`)

    +=======+=================+
    | char  | escape sequence |
    +=======+=================+
    | {     | {{              |
    +-------+-----------------+
    | }     | }}              |
    +-------+-----------------+

    The syntax for format group is as folowing:

    .. code-block:: text

        {[index/name]:[nuber_of_digits][type]}

    * The index or name specifies the name or the index of the input parameter.
    * The width specifies how mahy digits should the output have.
    * Format types can be found at :class:`hwtLib.amba.axis_comp.strformat.AxiS_strFormatItem`
    * If nuber_of_digits starts with 0 the leading zeros will be used instead of default space char (' ')
    * The sign char is included in nuber_of_digits ('{0:04X}'.format(-1) == '-001')
    * The type is described in :class:`hwtLib.amba.axis_comp.strformat.AxiS_strFormatItem`
    """

    f = AxiS_strFormat()
    f.DATA_WIDTH = data_width

    # construct input t for configuration
    arg_prefix = "arg_"
    while True:
        arg_names = [f"{arg_prefix}{a_i}" for a_i, _ in enumerate(args)]
        if not kwargs:
            break
        else:
            colliding = False
            for a in arg_names:
                if a in kwargs.keys():
                    colliding = True
            if colliding:
                arg_prefix = f"{arg_prefix}0_"
            else:
                break

    in_intf_name_tuples = [
        *zip(args, arg_names),
        *[(a, a_name)
          for a_name, a in sorted(kwargs.items(), key=lambda x: x[0])]
    ]

    format_items = tuple(_parse_format_groups(format_str))
    for fi in format_items:
        if isinstance(fi, str):
            continue
        elif isinstance(fi.member_path[0], int):
            # convert arg index to name in input interface
            fi.member_path = TypePath(arg_names[fi.member_path[0]])

    arg_usage = {}
    for fi in format_items:
        if isinstance(fi, str):
            continue
        usage_cnt = arg_usage.get(fi.member_path, 0) + 1
        arg_usage[fi.member_path] = usage_cnt
        if fi.format_type == 's':
            assert usage_cnt == 1, (
                "string arguments may be used only once as string is consumed")

    for i, (a, a_name) in enumerate(in_intf_name_tuples):
        assert arg_usage.get(TypePath(a_name), 0) > 0, (
            "arg ", i, " named ", a_name, " not used during formating")

    if in_intf_name_tuples:
        struct_members = []
        for a, a_name in in_intf_name_tuples:
            if isinstance(a, AxiStream):
                t = HStream(Bits(8), start_offsets=[0])
            else:
                t = Interface_to_HdlType().apply(a)
            struct_members.append((t, a_name))
        f.INPUT_T = HStruct(*struct_members)
    else:
        f.INPUT_T = None
    f.FORMAT = tuple(format_items)

    # connect inputs
    setattr(parent, name, f)
    for a, a_name in in_intf_name_tuples:
        a_in = getattr(f.data_in, a_name)
        a_in(a)

    return f.data_out
Пример #13
0
def _parse_format_groups(
        f_str: str) -> Generator[Union[str, AxiS_strFormatItem], None, None]:
    _tokens = re.split("([\{\}])", f_str) + [
        None,
    ]
    group_start = None
    current_group_body = None
    tokens = iter(enumerate(_tokens))
    for i, t in tokens:
        if t is None:
            assert group_start is None
            break
        t_next = _tokens[i + 1]
        if group_start is None:
            if t == "{":
                if t_next == "{":
                    # escape of {
                    next(tokens)
                    yield t
                elif t_next == None:
                    raise ValueError(
                        "Group syntax error: missing closing } for { after reading:",
                        tokens[:i + 1])
                else:
                    group_start = i
            elif t == '}':
                if t_next == '}':
                    # escape of }
                    next(tokens)
                    yield t
                else:
                    raise ValueError(
                        "Group syntax error: closing } without { after reading:",
                        _tokens[:i + 1])
            else:
                yield t
        else:
            if t == "{":
                raise ValueError(
                    "Group syntax error: { in a group after reading:",
                    _tokens[:i + 1], ", this group starts at", group_start)
            elif t == "}":
                if not current_group_body:
                    raise ValueError(
                        "Group syntax error: empty group after reading:",
                        _tokens[:i + 1])
                else:
                    f = current_group_body.split(":")
                    name_or_index = f[0]
                    if len(f) == 1:
                        format_type = None
                        digits = None
                    else:
                        assert len(f) == 2, f
                        format_type = f[1]
                        for i, c in enumerate(format_type):
                            if not c.isdigit():
                                break
                        if i > 0:
                            digits = int(format_type[:i])
                        else:
                            digits = None
                        format_type = format_type[i:]
                    if name_or_index.isdigit():
                        name_or_index = int(name_or_index)
                    yield AxiS_strFormatItem(TypePath(name_or_index),
                                             format_type, digits)
                    current_group_body = None
                    group_start = None
            else:
                assert not current_group_body, (
                    "group body has to be in a single string chunk",
                    current_group_body, t)
                current_group_body = t